From b5b6a14d286fbb6099df3a7a32bfe3d8b354c0c3 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 29 Dec 2017 12:20:57 -0500 Subject: [PATCH 1/5] Regain Python 2.6 support --- distro.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/distro.py b/distro.py index 39bfce79..41074579 100755 --- a/distro.py +++ b/distro.py @@ -518,7 +518,7 @@ def __init__(self, f): self._f = f def __get__(self, obj, owner): - assert obj is not None, 'call {} on an instance'.format(self._fname) + assert obj is not None, 'call {0} on an instance'.format(self._fname) ret = obj.__dict__[self._fname] = self._f(obj) return ret @@ -917,6 +917,14 @@ def _parse_os_release_content(lines): pass return props + def check_output(*args, **kwargs): + """Run command with arguments and return its output as a byte string. + + Same as subprocess.check_output(), but works before Python 2.7.""" + + p = subprocess.Popen(stdout=subprocess.PIPE, *args, **kwargs) + return p.communicate()[0].strip() + @cached_property def _lsb_release_info(self): """ @@ -930,7 +938,7 @@ def _lsb_release_info(self): with open(os.devnull, 'w') as devnull: try: cmd = ('lsb_release', '-a') - stdout = subprocess.check_output(cmd, stderr=devnull) + stdout = check_output(cmd, stderr=devnull) except OSError: # Command not found return {} content = stdout.decode(sys.getfilesystemencoding()).splitlines() From cb5c331e82c41f7b6b44f2634a9dc962c6fe9940 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 29 Dec 2017 12:31:45 -0500 Subject: [PATCH 2/5] Flake8 fix --- distro.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distro.py b/distro.py index 41074579..1ce1b31e 100755 --- a/distro.py +++ b/distro.py @@ -938,7 +938,7 @@ def _lsb_release_info(self): with open(os.devnull, 'w') as devnull: try: cmd = ('lsb_release', '-a') - stdout = check_output(cmd, stderr=devnull) + stdout = self.check_output(cmd, stderr=devnull) except OSError: # Command not found return {} content = stdout.decode(sys.getfilesystemencoding()).splitlines() From 85c30b8b6149d7983684e4b5a81687b3e75ca725 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 29 Dec 2017 12:42:55 -0500 Subject: [PATCH 3/5] Don't use auxiliary function --- distro.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/distro.py b/distro.py index 1ce1b31e..71bc823e 100755 --- a/distro.py +++ b/distro.py @@ -917,14 +917,6 @@ def _parse_os_release_content(lines): pass return props - def check_output(*args, **kwargs): - """Run command with arguments and return its output as a byte string. - - Same as subprocess.check_output(), but works before Python 2.7.""" - - p = subprocess.Popen(stdout=subprocess.PIPE, *args, **kwargs) - return p.communicate()[0].strip() - @cached_property def _lsb_release_info(self): """ @@ -938,7 +930,7 @@ def _lsb_release_info(self): with open(os.devnull, 'w') as devnull: try: cmd = ('lsb_release', '-a') - stdout = self.check_output(cmd, stderr=devnull) + stdout = subprocess.Popen(cmd, stderr=devnull).communicate()[0] except OSError: # Command not found return {} content = stdout.decode(sys.getfilesystemencoding()).splitlines() From 4b9c61c5346cf22fe4d89d8b24d335862b720ecf Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 29 Dec 2017 13:04:52 -0500 Subject: [PATCH 4/5] Steal check_output code from Python 2.7 --- distro.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/distro.py b/distro.py index 71bc823e..4e323574 100755 --- a/distro.py +++ b/distro.py @@ -917,6 +917,42 @@ def _parse_os_release_content(lines): pass return props + def _check_output(*popenargs, **kwargs): + r"""Run command with arguments and return its output as a byte string. + + If the exit code was non-zero it raises a CalledProcessError. The + CalledProcessError object will have the return code in the returncode + attribute and output in the output attribute. + + The arguments are the same as for the Popen constructor. Example: + + >>> check_output(["ls", "-l", "/dev/null"]) + 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' + + The stdout argument is not allowed as it is used internally. + To capture standard error in the result, use stderr=STDOUT. + + >>> check_output(["/bin/sh", "-c", + ... "ls -l non_existent_file ; exit 0"], + ... stderr=STDOUT) + 'ls: non_existent_file: No such file or directory\n' + """ + if 'stdout' in kwargs: + raise ValueError( + 'stdout argument not allowed, it will be overridden.' + ) + process = subprocess.Popen( + stdout=subprocess.PIPE, *popenargs, **kwargs + ) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise subprocess.CalledProcessError(retcode, cmd, output=output) + return output + @cached_property def _lsb_release_info(self): """ @@ -930,7 +966,7 @@ def _lsb_release_info(self): with open(os.devnull, 'w') as devnull: try: cmd = ('lsb_release', '-a') - stdout = subprocess.Popen(cmd, stderr=devnull).communicate()[0] + stdout = self._check_output(cmd, stderr=devnull) except OSError: # Command not found return {} content = stdout.decode(sys.getfilesystemencoding()).splitlines() From dee319437c273b0bc5da188b7c0ba2895dbe6f77 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 29 Dec 2017 13:14:48 -0500 Subject: [PATCH 5/5] Revert #197 --- distro.py | 64 +++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/distro.py b/distro.py index 4e323574..f8fb6611 100755 --- a/distro.py +++ b/distro.py @@ -917,42 +917,6 @@ def _parse_os_release_content(lines): pass return props - def _check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. - - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. - - The arguments are the same as for the Popen constructor. Example: - - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. - - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError( - 'stdout argument not allowed, it will be overridden.' - ) - process = subprocess.Popen( - stdout=subprocess.PIPE, *popenargs, **kwargs - ) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd, output=output) - return output - @cached_property def _lsb_release_info(self): """ @@ -961,16 +925,26 @@ def _lsb_release_info(self): Returns: A dictionary containing all information items. """ - if not self.include_lsb: + cmd = ['lsb_release', '-a'] + process = subprocess.Popen( + cmd, + 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 return {} - with open(os.devnull, 'w') as devnull: - try: - cmd = ('lsb_release', '-a') - stdout = self._check_output(cmd, stderr=devnull) - except OSError: # Command not found - return {} - content = stdout.decode(sys.getfilesystemencoding()).splitlines() - return self._parse_lsb_release_content(content) + 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) @staticmethod def _parse_lsb_release_content(lines):