Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start testing on Python 3.13 #27

Merged
merged 2 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,18 @@ jobs:
# - windows-latest
# - macos-latest
python-version:
- '3.13'
- '3.12'
- '3.11'
- '3.10'
- '3.9'
- '3.8'
- '3.7'
- 'pypy-3.8'
- 'pypy-3.9'
- 'pypy-3.10'
with-venv:
- 'true'
- 'false'
env:
DEPLOY_PYTHONS: "3.11"
DEPLOY_PYTHONS: "3.12"
DEPLOY_OSES: "Linux"
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
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