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

Add Support for Python 3.12 and drop Python 2 Support #18

Merged
merged 3 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
38 changes: 8 additions & 30 deletions plone/reload/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,17 @@
_marker = object()
MOD_TIMES = dict()

from importlib.util import cache_from_source, source_from_cache

try:
# Py3
from imp import cache_from_source, source_from_cache

def _cache_from_source(path):
if '__pycache__' in path:
return path
return cache_from_source(path)

def _source_from_cache(path):
if '__pycache__' in path:
return source_from_cache(path)
def _cache_from_source(path):
if '__pycache__' in path:
return path
return cache_from_source(path)

except ImportError:
# Py2
def _cache_from_source(path):
if path.endswith('pyc') or path.endswith('pyo'):
cache = path
else:
cache = path + 'c'
if os.path.isfile(cache):
path = cache
return path

def _source_from_cache(path):
source = path
if path.endswith('pyc') or path.endswith('pyo'):
source = path[:-1]
if os.path.isfile(source):
path = source
return path
def _source_from_cache(path):
if '__pycache__' in path:
return source_from_cache(path)
return path


def in_search_path(path):
Expand Down
46 changes: 18 additions & 28 deletions plone/reload/xreload.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@
"""

import marshal
import imp
import importlib
import sys
import types
import inspect

import six
from six.moves import reload_module
from importlib import reload as reload_module
import zope.component

# from zope.interface.interface import Specification
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# from zope.interface.interface import Specification


CLASS_STATICS = frozenset(["__dict__", "__doc__", "__module__", "__weakref__"])

Expand Down Expand Up @@ -60,34 +61,24 @@ def reload(self):
if pkgname:
# We're not reloading the package, only the module in it
pkg = sys.modules[pkgname]
path = pkg.__path__ # Search inside the package
else:
# Search the top-level module path
pkg = None
path = None # Make find_module() uses the default search path
# Find the module; may raise ImportError
(stream, filename, (suffix, mode, kind)) = imp.find_module(
modname, path)
# Turn it into a code object
try:
# Is it Python source code or byte code read from a file?
# XXX Could handle frozen modules, zip-import modules
if kind not in (imp.PY_COMPILED, imp.PY_SOURCE):
# Fall back to built-in reload()
return reload_module(self.mod)
if kind == imp.PY_SOURCE:
package_name = pkg.__name__ if pkg else None
specs = importlib.util.find_spec(self.mod.__name__, package=package_name)
filename = specs.origin
if specs.has_location:
with open(filename, 'rb') as stream:
source = stream.read()
# PeterB: if we don't strip the source code and add newline we
# get a SyntaxError even if `python $filename` is perfectly
# happy.
source = source.strip() + '\n'
source = source.strip() + b'\n'
code = compile(source, filename, "exec")
else:
# I have no idea how to test this one
code = marshal.load(stream) # pragma NO COVER
finally:
if stream:
stream.close()
else:
# Fall back to built-in reload()
return reload_module(self.mod)

# Execute the code im a temporary namespace; if this fails, no changes
tmpns = {'__name__': '%s.%s' % (pkgname, modname),
'__file__': filename,
Expand Down Expand Up @@ -168,13 +159,12 @@ def _update_scope(oldscope, newscope):

def _update_function(oldfunc, newfunc):
"""Update a function object."""
if _closure_changed(six.get_function_closure(oldfunc),
six.get_function_closure(newfunc)):
if _closure_changed(oldfunc.__closure__,
newfunc.__closure__):
raise ClosureChanged()
setattr(oldfunc, six._func_code, six.get_function_code(newfunc))
setattr(oldfunc, six._func_defaults, six.get_function_defaults(newfunc))
_update_scope(six.get_function_globals(oldfunc),
six.get_function_globals(newfunc))
setattr(oldfunc, "__code__", newfunc.__code__)
setattr(oldfunc, "__defaults__", newfunc.__defaults__)
_update_scope(oldfunc.__globals__, newfunc.__globals__)
# XXX What else?
return oldfunc

Expand Down