Commit 9f687e5e authored by Jason Madden's avatar Jason Madden

It might be simple to make subprocess more-or-less work under Windows/Py3....

It might be simple to make subprocess more-or-less work under Windows/Py3. First step is to import the moved names from the right place. Fixes #668. Fixes #669.
parent 7c716778
# Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details. # Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
# pylint: disable=redefined-outer-name
""" """
Make the standard library cooperative. Make the standard library cooperative.
...@@ -15,8 +16,9 @@ patching to certain modules, but most programs will want to use the ...@@ -15,8 +16,9 @@ patching to certain modules, but most programs will want to use the
default values as they receive the most wide-spread testing. default values as they receive the most wide-spread testing.
Patching *should be done as early as possible* in the lifecycle of the Patching *should be done as early as possible* in the lifecycle of the
program. For example, the main module (the one that tests against ``__main__`` program. For example, the main module (the one that tests against
or is otherwise the first imported) should begin with this code:: ``__main__`` or is otherwise the first imported) should begin with
this code, ideally before any other imports::
from gevent import monkey from gevent import monkey
monkey.patch_all() monkey.patch_all()
...@@ -44,7 +46,6 @@ Sometimes it is useful to run existing python scripts or modules that ...@@ -44,7 +46,6 @@ Sometimes it is useful to run existing python scripts or modules that
were not built to be gevent aware under gevent. To do so, this module were not built to be gevent aware under gevent. To do so, this module
can be run as the main module, passing the script and its arguments. can be run as the main module, passing the script and its arguments.
For details, see the :func:`main` function. For details, see the :func:`main` function.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import print_function from __future__ import print_function
...@@ -52,15 +53,17 @@ import sys ...@@ -52,15 +53,17 @@ import sys
__all__ = [ __all__ = [
'patch_all', 'patch_all',
'patch_socket', 'patch_builtins',
'patch_ssl', 'patch_dns',
'patch_os', 'patch_os',
'patch_time',
'patch_select', 'patch_select',
'patch_thread', 'patch_signal',
'patch_socket',
'patch_ssl',
'patch_subprocess', 'patch_subprocess',
'patch_sys', 'patch_sys',
'patch_signal', 'patch_thread',
'patch_time',
# query functions # query functions
'get_original', 'get_original',
'is_module_patched', 'is_module_patched',
...@@ -78,6 +81,10 @@ else: ...@@ -78,6 +81,10 @@ else:
string_types = __builtin__.basestring string_types = __builtin__.basestring
PY3 = False PY3 = False
if sys.platform.startswith("win"):
WIN = True
else:
WIN = False
# maps module name -> attribute name -> original item # maps module name -> attribute name -> original item
# e.g. "time" -> "sleep" -> built-in function sleep # e.g. "time" -> "sleep" -> built-in function sleep
...@@ -406,16 +413,30 @@ def patch_select(aggressive=True): ...@@ -406,16 +413,30 @@ def patch_select(aggressive=True):
def patch_subprocess(): def patch_subprocess():
"""Replace :func:`subprocess.call`, :func:`subprocess.check_call`, """
:func:`subprocess.check_output` and :class:`subprocess.Popen` with cooperative versions.""" Replace :func:`subprocess.call`, :func:`subprocess.check_call`,
:func:`subprocess.check_output` and :class:`subprocess.Popen` with
:mod:`cooperative versions <gevent.subprocess>`.
.. note::
On Windows under Python 3, the API support may not completely match
the standard library.
"""
patch_module('subprocess') patch_module('subprocess')
def patch_builtins(): def patch_builtins():
"""Make the builtin __import__ function greenlet safe under Python 2""" """
# https://github.com/gevent/gevent/issues/108 Make the builtin __import__ function `greenlet safe`_ under Python 2.
# Note that this is only needed in Python 2; under Python 3 (at least the versions
# we support) import locks are not global, they're per-module. .. note::
This does nothing under Python 3 as it is not necessary. Python 3 features
improved import locks that are per-module, not global.
.. _greenlet safe: https://github.com/gevent/gevent/issues/108
"""
if sys.version_info[:2] < (3, 3): if sys.version_info[:2] < (3, 3):
patch_module('builtins') patch_module('builtins')
......
...@@ -62,6 +62,7 @@ __extra__ = [ ...@@ -62,6 +62,7 @@ __extra__ = [
'pywintypes', 'pywintypes',
'list2cmdline', 'list2cmdline',
'_subprocess', '_subprocess',
'_winapi',
# Python 2.5 does not have _subprocess, so we don't use it # Python 2.5 does not have _subprocess, so we don't use it
# XXX We don't run on Py 2.5 anymore; can/could/should we use _subprocess? # XXX We don't run on Py 2.5 anymore; can/could/should we use _subprocess?
'WAIT_OBJECT_0', 'WAIT_OBJECT_0',
...@@ -114,27 +115,29 @@ if sys.version_info[:2] <= (2, 6): ...@@ -114,27 +115,29 @@ if sys.version_info[:2] <= (2, 6):
__implements__.remove('check_output') __implements__.remove('check_output')
__extra__.append('check_output') __extra__.append('check_output')
_subprocess = getattr(__subprocess__, '_subprocess', None) # In Python 3 on Windows, a lot of the functions previously
# in _subprocess moved to _winapi
_NONE = object() _NONE = object()
_subprocess = getattr(__subprocess__, '_subprocess', _NONE)
_winapi = getattr(__subprocess__, '_winapi', _NONE)
for name in __extra__[:]: _attr_resolution_order = [__subprocess__, _subprocess, _winapi]
for name in list(__extra__):
if name in globals(): if name in globals():
continue continue
value = _NONE value = _NONE
try: for place in _attr_resolution_order:
value = getattr(__subprocess__, name) value = getattr(place, name, _NONE)
except AttributeError: if value is not _NONE:
if _subprocess is not None: break
try:
value = getattr(_subprocess, name)
except AttributeError:
pass
if value is _NONE: if value is _NONE:
__extra__.remove(name) __extra__.remove(name)
else: else:
globals()[name] = value globals()[name] = value
del _attr_resolution_order
__all__ = __implements__ + __imports__ __all__ = __implements__ + __imports__
...@@ -742,7 +745,7 @@ class Popen(object): ...@@ -742,7 +745,7 @@ class Popen(object):
env, env,
cwd, cwd,
startupinfo) startupinfo)
except pywintypes.error as e: except IOError as e: # From 2.6 on, pywintypes.error was defined as IOError
# Translate pywintypes.error to WindowsError, which is # Translate pywintypes.error to WindowsError, which is
# a subclass of OSError. FIXME: We should really # a subclass of OSError. FIXME: We should really
# translate errno using _sys_errlist (or similar), but # translate errno using _sys_errlist (or similar), but
......
...@@ -90,17 +90,25 @@ if sys.platform == 'win32': ...@@ -90,17 +90,25 @@ if sys.platform == 'win32':
FAILING_TESTS.append('test_ftplib.py') FAILING_TESTS.append('test_ftplib.py')
if PY3: if PY3:
# Lets see how close we get
#FAILING_TESTS += [
# We don't have an implementation of subprocess
# on PY3/Windows...
#'test__subprocess_poll.py',
# Therefore we don't monkey-patch it by default because
# it breaks subprocess completely
#'test_subprocess.py',
#]
# XXX need investigating # XXX need investigating
FAILING_TESTS += [ FAILING_TESTS += [
'test__example_portforwarder.py', 'test__example_portforwarder.py',
'test__socket_ex.py', 'test__socket_ex.py',
'test__examples.py', 'test__examples.py',
'test_subprocess.py',
'test__issue600.py', 'test__issue600.py',
'test__subprocess.py', 'test__subprocess.py',
'test_threading_2.py', 'test_threading_2.py',
'FLAKY test__api_timeout.py', 'FLAKY test__api_timeout.py',
'test__subprocess_poll.py',
'test__example_udp_client.py' 'test__example_udp_client.py'
] ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment