mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
[3.13] gh-120782: Update internal type cache when reloading datetime (GH-120829) (#120855)
* [3.13] gh-120782: Update internal type cache when reloading datetime When reloading _datetime module, the single-phase version did not invoke the PyInit__datetime function, whereas the current multi-phase version updates the static types through the module init. The outdated static type cache in the interpreter state needs to be invalidated at the end of reloading the multi-phase module.
This commit is contained in:
parent
85971492b7
commit
2c3aa527fd
3 changed files with 39 additions and 20 deletions
|
@ -52,25 +52,6 @@ except ImportError:
|
|||
pass
|
||||
#
|
||||
|
||||
# This is copied from test_import/__init__.py.
|
||||
def no_rerun(reason):
|
||||
"""Skip rerunning for a particular test.
|
||||
|
||||
WARNING: Use this decorator with care; skipping rerunning makes it
|
||||
impossible to find reference leaks. Provide a clear reason for skipping the
|
||||
test using the 'reason' parameter.
|
||||
"""
|
||||
def deco(func):
|
||||
_has_run = False
|
||||
def wrapper(self):
|
||||
nonlocal _has_run
|
||||
if _has_run:
|
||||
self.skipTest(reason)
|
||||
func(self)
|
||||
_has_run = True
|
||||
return wrapper
|
||||
return deco
|
||||
|
||||
pickle_loads = {pickle.loads, pickle._loads}
|
||||
|
||||
pickle_choices = [(pickle, pickle, proto)
|
||||
|
@ -6420,7 +6401,6 @@ class IranTest(ZoneInfoTest):
|
|||
|
||||
|
||||
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
|
||||
@no_rerun("the encapsulated datetime C API does not support reloading")
|
||||
class CapiTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Since the C API is not present in the _Pure tests, skip all tests
|
||||
|
@ -6889,6 +6869,38 @@ class ExtensionModuleTests(unittest.TestCase):
|
|||
""")
|
||||
script_helper.assert_python_ok('-c', script)
|
||||
|
||||
def test_update_type_cache(self):
|
||||
# gh-120782
|
||||
script = textwrap.dedent("""
|
||||
import sys
|
||||
for i in range(5):
|
||||
import _datetime
|
||||
assert _datetime.date.max > _datetime.date.min
|
||||
assert _datetime.time.max > _datetime.time.min
|
||||
assert _datetime.datetime.max > _datetime.datetime.min
|
||||
assert _datetime.timedelta.max > _datetime.timedelta.min
|
||||
assert _datetime.date.__dict__["min"] is _datetime.date.min
|
||||
assert _datetime.date.__dict__["max"] is _datetime.date.max
|
||||
assert _datetime.date.__dict__["resolution"] is _datetime.date.resolution
|
||||
assert _datetime.time.__dict__["min"] is _datetime.time.min
|
||||
assert _datetime.time.__dict__["max"] is _datetime.time.max
|
||||
assert _datetime.time.__dict__["resolution"] is _datetime.time.resolution
|
||||
assert _datetime.datetime.__dict__["min"] is _datetime.datetime.min
|
||||
assert _datetime.datetime.__dict__["max"] is _datetime.datetime.max
|
||||
assert _datetime.datetime.__dict__["resolution"] is _datetime.datetime.resolution
|
||||
assert _datetime.timedelta.__dict__["min"] is _datetime.timedelta.min
|
||||
assert _datetime.timedelta.__dict__["max"] is _datetime.timedelta.max
|
||||
assert _datetime.timedelta.__dict__["resolution"] is _datetime.timedelta.resolution
|
||||
assert _datetime.timezone.__dict__["min"] is _datetime.timezone.min
|
||||
assert _datetime.timezone.__dict__["max"] is _datetime.timezone.max
|
||||
assert _datetime.timezone.__dict__["utc"] is _datetime.timezone.utc
|
||||
assert isinstance(_datetime.timezone.min, _datetime.tzinfo)
|
||||
assert isinstance(_datetime.timezone.max, _datetime.tzinfo)
|
||||
assert isinstance(_datetime.timezone.utc, _datetime.tzinfo)
|
||||
del sys.modules['_datetime']
|
||||
""")
|
||||
script_helper.assert_python_ok('-c', script)
|
||||
|
||||
|
||||
def load_tests(loader, standard_tests, pattern):
|
||||
standard_tests.addTest(ZoneInfoCompleteTest())
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix wrong references of the :mod:`datetime` types after reloading the module.
|
|
@ -7339,6 +7339,12 @@ _datetime_exec(PyObject *module)
|
|||
static_assert(DI100Y == 25 * DI4Y - 1, "DI100Y");
|
||||
assert(DI100Y == days_before_year(100+1));
|
||||
|
||||
if (reloading) {
|
||||
for (size_t i = 0; i < Py_ARRAY_LENGTH(capi_types); i++) {
|
||||
PyType_Modified(capi_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (set_current_module(interp, module) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue