Windows: Use 32-bit distribution of python
This commit is contained in:
127
python/gevent/_patcher.py
Normal file
127
python/gevent/_patcher.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# Copyright 2018 gevent. See LICENSE for details.
|
||||
|
||||
# Portions of the following are inspired by code from eventlet. I
|
||||
# believe they are distinct enough that no eventlet copyright would
|
||||
# apply (they are not a copy or substantial portion of the eventlot
|
||||
# code).
|
||||
|
||||
# Added in gevent 1.3a2. Not public in that release.
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
from gevent._compat import PY3
|
||||
from gevent._compat import iteritems
|
||||
from gevent._compat import imp_acquire_lock
|
||||
from gevent._compat import imp_release_lock
|
||||
|
||||
|
||||
from gevent.builtins import __import__ as _import
|
||||
|
||||
|
||||
MAPPING = {
|
||||
'gevent.local': '_threading_local',
|
||||
'gevent.socket': 'socket',
|
||||
'gevent.select': 'select',
|
||||
'gevent.ssl': 'ssl',
|
||||
'gevent.thread': '_thread' if PY3 else 'thread',
|
||||
'gevent.subprocess': 'subprocess',
|
||||
'gevent.os': 'os',
|
||||
'gevent.threading': 'threading',
|
||||
'gevent.builtins': 'builtins' if PY3 else '__builtin__',
|
||||
'gevent.signal': 'signal',
|
||||
'gevent.time': 'time',
|
||||
'gevent.queue': 'queue' if PY3 else 'Queue',
|
||||
}
|
||||
|
||||
_PATCH_PREFIX = '__g_patched_module_'
|
||||
|
||||
class _SysModulesPatcher(object):
|
||||
|
||||
def __init__(self, importing):
|
||||
self._saved = {}
|
||||
self.importing = importing
|
||||
self.green_modules = {
|
||||
stdlib_name: importlib.import_module(gevent_name)
|
||||
for gevent_name, stdlib_name
|
||||
in iteritems(MAPPING)
|
||||
}
|
||||
self.orig_imported = frozenset(sys.modules)
|
||||
|
||||
def _save(self):
|
||||
for modname in self.green_modules:
|
||||
self._saved[modname] = sys.modules.get(modname, None)
|
||||
|
||||
self._saved[self.importing] = sys.modules.get(self.importing, None)
|
||||
# Anything we've already patched regains its original name during this
|
||||
# process
|
||||
for mod_name, mod in iteritems(sys.modules):
|
||||
if mod_name.startswith(_PATCH_PREFIX):
|
||||
orig_mod_name = mod_name[len(_PATCH_PREFIX):]
|
||||
self._saved[mod_name] = sys.modules.get(orig_mod_name, None)
|
||||
self.green_modules[orig_mod_name] = mod
|
||||
|
||||
def _replace(self):
|
||||
# Cover the target modules so that when you import the module it
|
||||
# sees only the patched versions
|
||||
for name, mod in iteritems(self.green_modules):
|
||||
sys.modules[name] = mod
|
||||
|
||||
def _restore(self):
|
||||
for modname, mod in iteritems(self._saved):
|
||||
if mod is not None:
|
||||
sys.modules[modname] = mod
|
||||
else:
|
||||
try:
|
||||
del sys.modules[modname]
|
||||
except KeyError:
|
||||
pass
|
||||
# Anything from the same package tree we imported this time
|
||||
# needs to be saved so we can restore it later, and so it doesn't
|
||||
# leak into the namespace.
|
||||
pkg_prefix = self.importing.split('.', 1)[0]
|
||||
for modname, mod in list(iteritems(sys.modules)):
|
||||
if (modname not in self.orig_imported
|
||||
and modname != self.importing
|
||||
and not modname.startswith(_PATCH_PREFIX)
|
||||
and modname.startswith(pkg_prefix)):
|
||||
sys.modules[_PATCH_PREFIX + modname] = mod
|
||||
del sys.modules[modname]
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
try:
|
||||
self._restore()
|
||||
finally:
|
||||
imp_release_lock()
|
||||
|
||||
def __enter__(self):
|
||||
imp_acquire_lock()
|
||||
self._save()
|
||||
self._replace()
|
||||
|
||||
|
||||
def import_patched(module_name):
|
||||
"""
|
||||
Import *module_name* with gevent monkey-patches active,
|
||||
and return the greened module.
|
||||
|
||||
Any sub-modules that were imported by the package are also
|
||||
saved.
|
||||
|
||||
"""
|
||||
patched_name = _PATCH_PREFIX + module_name
|
||||
if patched_name in sys.modules:
|
||||
return sys.modules[patched_name]
|
||||
|
||||
|
||||
# Save the current module state, and restore on exit,
|
||||
# capturing desirable changes in the modules package.
|
||||
with _SysModulesPatcher(module_name):
|
||||
sys.modules.pop(module_name, None)
|
||||
|
||||
module = _import(module_name, {}, {}, module_name.split('.')[:-1])
|
||||
sys.modules[patched_name] = module
|
||||
|
||||
return module
|
||||
Reference in New Issue
Block a user