From 2f9495665372e8f07b4f0ca0aeabf608166b832f Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Sun, 12 Jun 2016 20:26:31 +0100 Subject: [PATCH 1/5] Depend on subprocess32 on posix systems for python27 And use it in plase of subprocess on posix systems. --- lib/matplotlib/compat/subprocess.py | 14 ++++++++++++-- setup.py | 1 + setupext.py | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index 9b5b516a68c2..a7e63a464986 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -5,6 +5,8 @@ 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 +17,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'] 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..8d2aacc01bc1 100755 --- a/setupext.py +++ b/setupext.py @@ -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 ( + "subprocess was not found. It is an optional dependency" + " for for python versions prior to 3.2 that 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" From 67d26aa3bca4acc88ea57927f72df82964b8ef2f Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Sun, 12 Jun 2016 21:45:04 +0100 Subject: [PATCH 2/5] Remove no longer needed workaround for subprocess pre 2.7 --- lib/matplotlib/compat/subprocess.py | 47 +++-------------------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index a7e63a464986..788116b03fe7 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -31,61 +31,24 @@ __all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError'] + if hasattr(subprocess, 'Popen'): Popen = subprocess.Popen # Assume that it also has the other constants. 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 From 5accdc92b973afe61d0a4dc7dd384c0c036b53d3 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Sun, 12 Jun 2016 21:51:01 +0100 Subject: [PATCH 3/5] No longer relevant comment --- lib/matplotlib/compat/subprocess.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index 788116b03fe7..be36f7aef5d5 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -1,8 +1,6 @@ """ 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 From 4b36ce4dd47674622e87b63370c4b45dc51199d6 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Sun, 10 Jul 2016 21:05:42 +0100 Subject: [PATCH 4/5] Fix comments --- lib/matplotlib/compat/subprocess.py | 1 - setupext.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index be36f7aef5d5..8cb0f845a650 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -29,7 +29,6 @@ __all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError'] - if hasattr(subprocess, 'Popen'): Popen = subprocess.Popen # Assume that it also has the other constants. diff --git a/setupext.py b/setupext.py index 8d2aacc01bc1..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: @@ -1409,8 +1409,8 @@ def check(self): import subprocess32 except ImportError: return ( - "subprocess was not found. It is an optional dependency" - " for for python versions prior to 3.2 that improves" + "subprocess32 was not found. It used " + " for Python versions prior to 3.2 to improves" " functionality on Linux and OSX") return "using subprocess32" From c4d126f906f2971bbf8e70e7946260e7fc1eb8e6 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Tue, 12 Jul 2016 09:08:31 +0100 Subject: [PATCH 5/5] compat/subprocess is now pep8 complient --- lib/matplotlib/tests/test_coding_standards.py | 1 - 1 file changed, 1 deletion(-) 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',