mirror of https://github.com/python/cpython
[3.13] gh-71587: Drop local reference cache to `_strptime` module in `_datetime` (gh-120424)
The _strptime module object was cached in a static local variable (in the datetime.strptime() implementation). That's a problem when it crosses isolation boundaries, such as reinitializing the runtme or between interpreters. This change fixes the problem by dropping the static variable, instead always relying on the normal sys.modules cache (via PyImport_Import()).
(cherry picked from commit 127c1d2771
, AKA gh-120224)
Co-authored-by: neonene <53406459+neonene@users.noreply.github.com>
This commit is contained in:
parent
8e5caa72c2
commit
0041087aa1
|
@ -776,6 +776,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_showwarnmsg));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_showwarnmsg));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_shutdown));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_shutdown));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_slotnames));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_slotnames));
|
||||||
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime_datetime));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_strptime_datetime));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_swappedbytes_));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_swappedbytes_));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_type_));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_type_));
|
||||||
|
|
|
@ -265,6 +265,7 @@ struct _Py_global_strings {
|
||||||
STRUCT_FOR_ID(_showwarnmsg)
|
STRUCT_FOR_ID(_showwarnmsg)
|
||||||
STRUCT_FOR_ID(_shutdown)
|
STRUCT_FOR_ID(_shutdown)
|
||||||
STRUCT_FOR_ID(_slotnames)
|
STRUCT_FOR_ID(_slotnames)
|
||||||
|
STRUCT_FOR_ID(_strptime)
|
||||||
STRUCT_FOR_ID(_strptime_datetime)
|
STRUCT_FOR_ID(_strptime_datetime)
|
||||||
STRUCT_FOR_ID(_swappedbytes_)
|
STRUCT_FOR_ID(_swappedbytes_)
|
||||||
STRUCT_FOR_ID(_type_)
|
STRUCT_FOR_ID(_type_)
|
||||||
|
|
|
@ -774,6 +774,7 @@ extern "C" {
|
||||||
INIT_ID(_showwarnmsg), \
|
INIT_ID(_showwarnmsg), \
|
||||||
INIT_ID(_shutdown), \
|
INIT_ID(_shutdown), \
|
||||||
INIT_ID(_slotnames), \
|
INIT_ID(_slotnames), \
|
||||||
|
INIT_ID(_strptime), \
|
||||||
INIT_ID(_strptime_datetime), \
|
INIT_ID(_strptime_datetime), \
|
||||||
INIT_ID(_swappedbytes_), \
|
INIT_ID(_swappedbytes_), \
|
||||||
INIT_ID(_type_), \
|
INIT_ID(_type_), \
|
||||||
|
|
|
@ -636,6 +636,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
|
||||||
string = &_Py_ID(_slotnames);
|
string = &_Py_ID(_slotnames);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
_PyUnicode_InternInPlace(interp, &string);
|
_PyUnicode_InternInPlace(interp, &string);
|
||||||
|
string = &_Py_ID(_strptime);
|
||||||
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
|
_PyUnicode_InternInPlace(interp, &string);
|
||||||
string = &_Py_ID(_strptime_datetime);
|
string = &_Py_ID(_strptime_datetime);
|
||||||
assert(_PyUnicode_CheckConsistency(string, 1));
|
assert(_PyUnicode_CheckConsistency(string, 1));
|
||||||
_PyUnicode_InternInPlace(interp, &string);
|
_PyUnicode_InternInPlace(interp, &string);
|
||||||
|
|
|
@ -404,6 +404,15 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
|
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
|
||||||
self.assertEqual(out, '9\n' * INIT_LOOPS)
|
self.assertEqual(out, '9\n' * INIT_LOOPS)
|
||||||
|
|
||||||
|
def test_datetime_reset_strptime(self):
|
||||||
|
code = (
|
||||||
|
"import datetime;"
|
||||||
|
"d = datetime.datetime.strptime('2000-01-01', '%Y-%m-%d');"
|
||||||
|
"print(d.strftime('%Y%m%d'))"
|
||||||
|
)
|
||||||
|
out, err = self.run_embedded_interpreter("test_repeated_init_exec", code)
|
||||||
|
self.assertEqual(out, '20000101\n' * INIT_LOOPS)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
|
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
|
||||||
class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix crash in C version of :meth:`datetime.datetime.strptime` when called again
|
||||||
|
on the restarted interpreter.
|
|
@ -5511,19 +5511,19 @@ datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_strptime(PyObject *cls, PyObject *args)
|
datetime_strptime(PyObject *cls, PyObject *args)
|
||||||
{
|
{
|
||||||
static PyObject *module = NULL;
|
PyObject *string, *format, *result;
|
||||||
PyObject *string, *format;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format))
|
if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
PyObject *module = PyImport_Import(&_Py_ID(_strptime));
|
||||||
if (module == NULL) {
|
if (module == NULL) {
|
||||||
module = PyImport_ImportModule("_strptime");
|
return NULL;
|
||||||
if (module == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return PyObject_CallMethodObjArgs(module, &_Py_ID(_strptime_datetime),
|
result = PyObject_CallMethodObjArgs(module, &_Py_ID(_strptime_datetime),
|
||||||
cls, string, format, NULL);
|
cls, string, format, NULL);
|
||||||
|
Py_DECREF(module);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return new datetime from date/datetime and time arguments. */
|
/* Return new datetime from date/datetime and time arguments. */
|
||||||
|
|
|
@ -434,7 +434,6 @@ Modules/_ctypes/_ctypes.c CreateSwappedType swapped_suffix -
|
||||||
Modules/_ctypes/_ctypes.c - _unpickle -
|
Modules/_ctypes/_ctypes.c - _unpickle -
|
||||||
Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype array_cache -
|
Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype array_cache -
|
||||||
Modules/_cursesmodule.c - ModDict -
|
Modules/_cursesmodule.c - ModDict -
|
||||||
Modules/_datetimemodule.c datetime_strptime module -
|
|
||||||
|
|
||||||
## state
|
## state
|
||||||
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
|
Modules/_ctypes/_ctypes.c - _ctypes_ptrtype_cache -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Reference in New Issue