Skip to content

Commit

Permalink
Fixes for gevent 24.10.+
Browse files Browse the repository at this point in the history
  • Loading branch information
arcivanov committed Oct 29, 2024
1 parent 94e7667 commit 8b1c397
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 124 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ jobs:
- '3.11'
- '3.10'
- '3.9'
- '3.8'
- '3.7'
- 'pypy-3.8'
- 'pypy-3.9'
- 'pypy-3.10'
with-venv:
- 'true'
- 'false'
Expand Down
2 changes: 1 addition & 1 deletion .idea/geventmp.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ Supported Platforms
All claims of support may not be real at all. You're welcome to experiment. See warnings on top.

* Linux and Darwin.
* CPython 3.7, 3.8, 3.9, 3.10, 3.11, 3.12
* PyPy 3.8, 3.9
* CPython 3.9, 3.10, 3.11, 3.12, 3.13
* PyPy 3.9, 3.10

Known Issues
============
Expand Down
4 changes: 1 addition & 3 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

@init
def set_properties(project):
project.set_property_if_unset("gevent_version", ">=1.3.0")
project.set_property_if_unset("gevent_version", ">=24.10.0")

project.depends_on("gevent", project.get_property("gevent_version"))

Expand Down Expand Up @@ -77,8 +77,6 @@ def set_properties(project):

project.set_property("distutils_classifiers", [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand Down
134 changes: 20 additions & 114 deletions src/main/python/geventmp/monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,118 +16,28 @@
import sys
from importlib import import_module

import gevent
import pkg_resources
from gevent.monkey import __call_module_hook, _notify_patch, saved, _NONE

GEVENT_PRE_15a3 = False
GEVENT_SAVED_MODULE_SETTINGS = "_gevent_saved_patch_all_module_settings"
gevent_ver = pkg_resources.parse_version(gevent.__version__)
if gevent_ver < pkg_resources.parse_version("1.5a3"):
GEVENT_PRE_15a3 = True
GEVENT_SAVED_MODULE_SETTINGS = "_gevent_saved_patch_all"


def patch_item(module, attr, newitem, _patch_module=False):
olditem = getattr(module, attr, _NONE)
if olditem is not _NONE:
saved.setdefault(module.__name__, {}).setdefault(attr, olditem)
setattr(module, attr, newitem)
if _patch_module:
if olditem is not None and newitem is not None:
try:
newitem.__module__ = olditem.__module__
except (TypeError, AttributeError):
pass


def patch_module(target_module, source_module, items=None,
_warnings=None,
_notify_will_subscribers=True,
_notify_did_subscribers=True,
_call_hooks=True,
_patch_module=False):
"""
patch_module(target_module, source_module, items=None)
Replace attributes in *target_module* with the attributes of the
same name in *source_module*.
The *source_module* can provide some attributes to customize the process:
* ``__implements__`` is a list of attribute names to copy; if not present,
the *items* keyword argument is mandatory.
* ``_gevent_will_monkey_patch(target_module, items, warn, **kwargs)``
* ``_gevent_did_monkey_patch(target_module, items, warn, **kwargs)``
These two functions in the *source_module* are called *if* they exist,
before and after copying attributes, respectively. The "will" function
may modify *items*. The value of *warn* is a function that should be called
with a single string argument to issue a warning to the user. If the "will"
function raises :exc:`gevent.events.DoNotPatch`, no patching will be done. These functions
are called before any event subscribers or plugins.
:keyword list items: A list of attribute names to replace. If
not given, this will be taken from the *source_module* ``__implements__``
attribute.
:return: A true value if patching was done, a false value if patching was canceled.
.. versionadded:: 1.3b1
"""
from gevent import events

if items is None:
items = getattr(source_module, '__implements__', None)
if items is None:
raise AttributeError('%r does not have __implements__' % source_module)

try:
if _call_hooks:
__call_module_hook(source_module, 'will', target_module, items, _warnings)
if _notify_will_subscribers:
_notify_patch(
events.GeventWillPatchModuleEvent(target_module.__name__, source_module,
target_module, items),
_warnings)
except events.DoNotPatch:
return False

for attr in items:
patch_item(target_module, attr, getattr(source_module, attr),
_patch_module=_patch_module)

if _call_hooks:
__call_module_hook(source_module, 'did', target_module, items, _warnings)

if _notify_did_subscribers:
# We allow turning off the broadcast of the 'did' event for the benefit
# of our internal functions which need to do additional work (besides copying
# attributes) before their patch can be considered complete.
_notify_patch(
events.GeventDidPatchModuleEvent(target_module.__name__, source_module,
target_module)
)

return True


def _patch_module(name,
items=None,
_warnings=None,
_patch_kwargs=None,
_notify_will_subscribers=True,
_notify_did_subscribers=True,
_call_hooks=True,
_patch_module=False,
_package_prefix='gevent.'):
from gevent.monkey.api import patch_module

gevent_module = import_module(_package_prefix + name)
module_name = getattr(gevent_module, '__target__', name)
target_module = import_module(module_name)
target_module_name = getattr(gevent_module, '__target__', name)
target_module = import_module(target_module_name)

patch_module(target_module, gevent_module, items=items,
_warnings=_warnings,
_warnings=_warnings, _patch_kwargs=_patch_kwargs,
_notify_will_subscribers=_notify_will_subscribers,
_notify_did_subscribers=_notify_did_subscribers,
_call_hooks=_call_hooks,
_patch_module=_patch_module)
_call_hooks=_call_hooks)

# On Python 2, the `futures` package will install
# a bunch of modules with the same name as those from Python 3,
Expand All @@ -138,6 +48,7 @@ def _patch_module(name,
# Be sure to keep the original states matching also.

alternate_names = getattr(gevent_module, '__alternate_targets__', ())
from gevent.monkey._state import saved # TODO: Add apis for these use cases.
for alternate_name in alternate_names:
alternate_module = sys.modules.get(alternate_name)
if alternate_module is not None and alternate_module is not target_module:
Expand All @@ -146,27 +57,22 @@ def _patch_module(name,
_warnings=_warnings,
_notify_will_subscribers=False,
_notify_did_subscribers=False,
_call_hooks=False,
_patch_module=_patch_module)
saved[alternate_name] = saved[module_name]
_call_hooks=False)
saved[alternate_name] = saved[target_module_name]

return gevent_module, target_module


def _patch_mp(will_patch_all):
from gevent.monkey._state import saved
geventmp_arg = will_patch_all.will_patch_module("geventmp")
if geventmp_arg is None or geventmp_arg:
_patch_module("_mp.3._mp_spawn", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_util", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_connection", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_synchronize", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_popen_fork", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_popen_spawn_posix", _patch_module=True, _package_prefix='geventmp.')
_patch_module("_mp.3._mp_forkserver", _patch_module=True, _package_prefix='geventmp.')
if sys.version_info >= (3, 8):
# See https://bugs.python.org/issue36867
_patch_module("_mp.3._mp_resource_tracker", _patch_module=True, _package_prefix='geventmp.')
else:
_patch_module("_mp.3._mp_sem_tracker", _patch_module=True, _package_prefix='geventmp.')

saved[GEVENT_SAVED_MODULE_SETTINGS]["geventmp"] = True
_patch_module("_mp.3._mp_spawn", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_util", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_connection", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_synchronize", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_popen_fork", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_popen_spawn_posix", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_forkserver", _package_prefix='geventmp.')
_patch_module("_mp.3._mp_resource_tracker", _package_prefix='geventmp.')
saved[GEVENT_SAVED_MODULE_SETTINGS]["geventmp"] = True

0 comments on commit 8b1c397

Please sign in to comment.