aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/_patcher.py
diff options
context:
space:
mode:
authorJames Taylor <user234683@users.noreply.github.com>2018-09-14 19:32:27 -0700
committerJames Taylor <user234683@users.noreply.github.com>2018-09-14 19:32:27 -0700
commit4212164e91ba2f49583cf44ad623a29b36db8f77 (patch)
tree47aefe3c0162f03e0c823b43873356f69c1cd636 /python/gevent/_patcher.py
parent6ca20ff7010f2bafc7fefcb8cad982be27a8aeae (diff)
downloadyt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.tar.lz
yt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.tar.xz
yt-local-4212164e91ba2f49583cf44ad623a29b36db8f77.zip
Windows: Use 32-bit distribution of python
Diffstat (limited to 'python/gevent/_patcher.py')
-rw-r--r--python/gevent/_patcher.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/python/gevent/_patcher.py b/python/gevent/_patcher.py
new file mode 100644
index 0000000..2ced50c
--- /dev/null
+++ b/python/gevent/_patcher.py
@@ -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