diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index 9b5b516a68c2..8cb0f845a650 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -1,10 +1,10 @@ """ A replacement wrapper around the subprocess module, with a number of work-arounds: -- Provides the check_output function (which subprocess only provides from Python - 2.7 onwards). - Provides a stub implementation of subprocess members on Google App Engine (which are missing in subprocess). +- Use subprocess32, backport from python 3.2 on Linux/Mac work-around for + https://github.com/matplotlib/matplotlib/issues/5314 Instead of importing subprocess, other modules should use this as follows: @@ -15,8 +15,16 @@ from __future__ import absolute_import # Required to import subprocess from __future__ import print_function - -import subprocess +import os +import sys +if os.name == 'posix' and sys.version_info[:2] < (3, 2): + # work around for https://github.com/matplotlib/matplotlib/issues/5314 + try: + import subprocess32 as subprocess + except ImportError: + import subprocess +else: + import subprocess __all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError'] @@ -27,55 +35,17 @@ PIPE = subprocess.PIPE STDOUT = subprocess.STDOUT CalledProcessError = subprocess.CalledProcessError + check_output = subprocess.check_output else: # In restricted environments (such as Google App Engine), these are # non-existent. Replace them with dummy versions that always raise OSError. def Popen(*args, **kwargs): raise OSError("subprocess.Popen is not supported") + + def check_output(*args, **kwargs): + raise OSError("subprocess.check_output is not supported") PIPE = -1 STDOUT = -2 # There is no need to catch CalledProcessError. These stubs cannot raise # it. None in an except clause will simply not match any exceptions. CalledProcessError = None - - -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 = Popen(stdout=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 - - -# python2.7's subprocess provides a check_output method -if hasattr(subprocess, 'check_output'): - check_output = subprocess.check_output -else: - check_output = _check_output diff --git a/lib/matplotlib/tests/test_coding_standards.py b/lib/matplotlib/tests/test_coding_standards.py index 529591fddf18..81d30682097e 100644 --- a/lib/matplotlib/tests/test_coding_standards.py +++ b/lib/matplotlib/tests/test_coding_standards.py @@ -217,7 +217,6 @@ def test_pep8_conformance_installed_files(): 'tests/test_subplots.py', 'tests/test_tightlayout.py', 'tests/test_triangulation.py', - 'compat/subprocess.py', 'backends/__init__.py', 'backends/backend_agg.py', 'backends/backend_cairo.py', diff --git a/setup.py b/setup.py index 5fdc01d1a3f1..4b4038a7d306 100644 --- a/setup.py +++ b/setup.py @@ -70,6 +70,7 @@ setupext.Six(), setupext.Dateutil(), setupext.FuncTools32(), + setupext.Subprocess32(), setupext.Pytz(), setupext.Cycler(), setupext.Tornado(), diff --git a/setupext.py b/setupext.py index 514ab795eefa..af4b1989af16 100755 --- a/setupext.py +++ b/setupext.py @@ -1386,8 +1386,8 @@ def check(self): import functools32 except ImportError: return ( - "functools32 was not found. It is required for for" - "python versions prior to 3.2") + "functools32 was not found. It is required for" + "Python versions prior to 3.2") return "using functools32" else: @@ -1400,6 +1400,30 @@ def get_install_requires(self): return [] +class Subprocess32(SetupPackage): + name = "subprocess32" + + def check(self): + if sys.version_info[:2] < (3, 2): + try: + import subprocess32 + except ImportError: + return ( + "subprocess32 was not found. It used " + " for Python versions prior to 3.2 to improves" + " functionality on Linux and OSX") + + return "using subprocess32" + else: + return "Not required" + + def get_install_requires(self): + if sys.version_info[:2] < (3, 2) and os.name == 'posix': + return ['subprocess32'] + else: + return [] + + class Tornado(OptionalPackage): name = "tornado"
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: