Skip to content

Commit

Permalink
Merge pull request #4932 from doloopwhile/bugfix/4917-decoding-stdout…
Browse files Browse the repository at this point in the history
…-of-shell

Vendor Update - stdout and stderr of shell should be decoded with system encoding
  • Loading branch information
pfmoore authored Mar 1, 2018
2 parents 3b7dd50 + 916e7f3 commit 01a555e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 43 deletions.
2 changes: 1 addition & 1 deletion news/distro.vendor
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Upgraded distro to 1.0.4.
Upgraded distro to 1.2.0.
85 changes: 44 additions & 41 deletions src/pip/_vendor/distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@
import subprocess


if not sys.platform.startswith('linux'):
raise ImportError('Unsupported platform: {0}'.format(sys.platform))

_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc')
_OS_RELEASE_BASENAME = 'os-release'

Expand Down Expand Up @@ -511,6 +508,21 @@ def distro_release_attr(attribute):
return _distro.distro_release_attr(attribute)


class cached_property(object):
"""A version of @property which caches the value. On access, it calls the
underlying function and sets the value in `__dict__` so future accesses
will not re-call the property.
"""
def __init__(self, f):
self._fname = f.__name__
self._f = f

def __get__(self, obj, owner):
assert obj is not None, 'call {} on an instance'.format(self._fname)
ret = obj.__dict__[self._fname] = self._f(obj)
return ret


class LinuxDistribution(object):
"""
Provides information about a Linux distribution.
Expand Down Expand Up @@ -576,6 +588,9 @@ def __init__(self,
`distro release file`_ that is actually used as a data source. The
empty string if no distro release file is used as a data source.
* ``include_lsb`` (bool): The result of the ``include_lsb`` parameter.
This controls whether the lsb information will be loaded.
Raises:
* :py:exc:`IOError`: Some I/O issue with an os-release file or distro
Expand All @@ -591,26 +606,20 @@ def __init__(self,
self.os_release_file = os_release_file or \
os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME)
self.distro_release_file = distro_release_file or '' # updated later
self._os_release_info = self._get_os_release_info()
self._lsb_release_info = self._get_lsb_release_info() \
if include_lsb else {}
self._distro_release_info = self._get_distro_release_info()
self.include_lsb = include_lsb

def __repr__(self):
"""Return repr of all info
"""
return \
"LinuxDistribution(" \
"os_release_file={0!r}, " \
"distro_release_file={1!r}, " \
"_os_release_info={2!r}, " \
"_lsb_release_info={3!r}, " \
"_distro_release_info={4!r})".format(
self.os_release_file,
self.distro_release_file,
self._os_release_info,
self._lsb_release_info,
self._distro_release_info)
"os_release_file={self.os_release_file!r}, " \
"distro_release_file={self.distro_release_file!r}, " \
"include_lsb={self.include_lsb!r}, " \
"_os_release_info={self._os_release_info!r}, " \
"_lsb_release_info={self._lsb_release_info!r}, " \
"_distro_release_info={self._distro_release_info!r})".format(
self=self)

def linux_distribution(self, full_distribution_name=True):
"""
Expand Down Expand Up @@ -835,7 +844,8 @@ def distro_release_attr(self, attribute):
"""
return self._distro_release_info.get(attribute, '')

def _get_os_release_info(self):
@cached_property
def _os_release_info(self):
"""
Get the information items from the specified os-release file.
Expand Down Expand Up @@ -907,34 +917,24 @@ def _parse_os_release_content(lines):
pass
return props

def _get_lsb_release_info(self):
@cached_property
def _lsb_release_info(self):
"""
Get the information items from the lsb_release command output.
Returns:
A dictionary containing all information items.
"""
cmd = 'lsb_release -a'
process = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
stdout, stderr = stdout.decode('utf-8'), stderr.decode('utf-8')
code = process.returncode
if code == 0:
content = stdout.splitlines()
return self._parse_lsb_release_content(content)
elif code == 127: # Command not found
if not self.include_lsb:
return {}
else:
if sys.version_info[:2] >= (3, 5):
raise subprocess.CalledProcessError(code, cmd, stdout, stderr)
elif sys.version_info[:2] >= (2, 7):
raise subprocess.CalledProcessError(code, cmd, stdout)
elif sys.version_info[:2] == (2, 6):
raise subprocess.CalledProcessError(code, cmd)
with open(os.devnull, 'w') as devnull:
try:
cmd = ('lsb_release', '-a')
stdout = subprocess.check_output(cmd, stderr=devnull)
except OSError: # Command not found
return {}
content = stdout.decode(sys.getfilesystemencoding()).splitlines()
return self._parse_lsb_release_content(content)

@staticmethod
def _parse_lsb_release_content(lines):
Expand All @@ -952,7 +952,6 @@ def _parse_lsb_release_content(lines):
"""
props = {}
for line in lines:
line = line.decode('utf-8') if isinstance(line, bytes) else line
kv = line.strip('\n').split(':', 1)
if len(kv) != 2:
# Ignore lines without colon.
Expand All @@ -961,7 +960,8 @@ def _parse_lsb_release_content(lines):
props.update({k.replace(' ', '_').lower(): v.strip()})
return props

def _get_distro_release_info(self):
@cached_property
def _distro_release_info(self):
"""
Get the information items from the specified distro release file.
Expand Down Expand Up @@ -1001,6 +1001,9 @@ def _get_distro_release_info(self):
'fedora-release',
'gentoo-release',
'mageia-release',
'mandrake-release',
'mandriva-release',
'mandrivalinux-release',
'manjaro-release',
'oracle-release',
'redhat-release',
Expand Down
2 changes: 1 addition & 1 deletion src/pip/_vendor/vendor.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
appdirs==1.4.3
distlib==0.2.6
distro==1.0.4
distro==1.2.0
html5lib==1.0b10
six==1.11.0
colorama==0.3.9
Expand Down

0 comments on commit 01a555e

Please sign in to comment.