mirror of https://github.com/python/cpython.git
[3.13] gh-117398: Add datetime C-API type check test for subinterpreters (gh-120463)
Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters.
(cherry picked from commit 50a389565a
, AKA gh-119604)
Co-authored-by: neonene <53406459+neonene@users.noreply.github.com>
This commit is contained in:
parent
e0f4dd8ec5
commit
15c3d0013d
|
@ -13,6 +13,7 @@
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
import unittest
|
import unittest
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
@ -38,6 +39,10 @@
|
||||||
import _testcapi
|
import _testcapi
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_testcapi = None
|
_testcapi = None
|
||||||
|
try:
|
||||||
|
import _interpreters
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
_interpreters = None
|
||||||
|
|
||||||
# Needed by test_datetime
|
# Needed by test_datetime
|
||||||
import _strptime
|
import _strptime
|
||||||
|
@ -6798,6 +6803,42 @@ def test_datetime_from_timestamp(self):
|
||||||
|
|
||||||
self.assertEqual(dt_orig, dt_rt)
|
self.assertEqual(dt_orig, dt_rt)
|
||||||
|
|
||||||
|
def test_type_check_in_subinterp(self):
|
||||||
|
script = textwrap.dedent(f"""
|
||||||
|
if {_interpreters is None}:
|
||||||
|
import _testcapi as module
|
||||||
|
module.test_datetime_capi()
|
||||||
|
else:
|
||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
fullname = '_testcapi_datetime'
|
||||||
|
origin = importlib.util.find_spec('_testcapi').origin
|
||||||
|
loader = importlib.machinery.ExtensionFileLoader(fullname, origin)
|
||||||
|
spec = importlib.util.spec_from_loader(fullname, loader)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
|
def run(type_checker, obj):
|
||||||
|
if not type_checker(obj, True):
|
||||||
|
raise TypeError(f'{{type(obj)}} is not C API type')
|
||||||
|
|
||||||
|
import _datetime
|
||||||
|
run(module.datetime_check_date, _datetime.date.today())
|
||||||
|
run(module.datetime_check_datetime, _datetime.datetime.now())
|
||||||
|
run(module.datetime_check_time, _datetime.time(12, 30))
|
||||||
|
run(module.datetime_check_delta, _datetime.timedelta(1))
|
||||||
|
run(module.datetime_check_tzinfo, _datetime.tzinfo())
|
||||||
|
""")
|
||||||
|
if _interpreters is None:
|
||||||
|
ret = support.run_in_subinterp(script)
|
||||||
|
self.assertEqual(ret, 0)
|
||||||
|
else:
|
||||||
|
for name in ('isolated', 'legacy'):
|
||||||
|
with self.subTest(name):
|
||||||
|
config = _interpreters.new_config(name).__dict__
|
||||||
|
ret = support.run_in_subinterp_with_config(script, **config)
|
||||||
|
self.assertEqual(ret, 0)
|
||||||
|
|
||||||
|
|
||||||
def load_tests(loader, standard_tests, pattern):
|
def load_tests(loader, standard_tests, pattern):
|
||||||
standard_tests.addTest(ZoneInfoCompleteTest())
|
standard_tests.addTest(ZoneInfoCompleteTest())
|
||||||
|
|
|
@ -1788,7 +1788,7 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config):
|
||||||
config['gil'] = 'shared'
|
config['gil'] = 'shared'
|
||||||
elif gil == 2:
|
elif gil == 2:
|
||||||
config['gil'] = 'own'
|
config['gil'] = 'own'
|
||||||
else:
|
elif not isinstance(gil, str):
|
||||||
raise NotImplementedError(gil)
|
raise NotImplementedError(gil)
|
||||||
config = types.SimpleNamespace(**config)
|
config = types.SimpleNamespace(**config)
|
||||||
return _testinternalcapi.run_in_subinterp_with_config(code, config)
|
return _testinternalcapi.run_in_subinterp_with_config(code, config)
|
||||||
|
|
|
@ -22,11 +22,18 @@ test_datetime_capi(PyObject *self, PyObject *args)
|
||||||
test_run_counter++;
|
test_run_counter++;
|
||||||
PyDateTime_IMPORT;
|
PyDateTime_IMPORT;
|
||||||
|
|
||||||
if (PyDateTimeAPI) {
|
if (PyDateTimeAPI == NULL) {
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// The following C API types need to outlive interpreters, since the
|
||||||
|
// borrowed references to them can be held by users without being updated.
|
||||||
|
assert(!PyType_HasFeature(PyDateTimeAPI->DateType, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
assert(!PyType_HasFeature(PyDateTimeAPI->TimeType, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
assert(!PyType_HasFeature(PyDateTimeAPI->DateTimeType, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
assert(!PyType_HasFeature(PyDateTimeAPI->DeltaType, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
assert(!PyType_HasFeature(PyDateTimeAPI->TZInfoType, Py_TPFLAGS_HEAPTYPE));
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Functions exposing the C API type checking for testing */
|
/* Functions exposing the C API type checking for testing */
|
||||||
#define MAKE_DATETIME_CHECK_FUNC(check_method, exact_method) \
|
#define MAKE_DATETIME_CHECK_FUNC(check_method, exact_method) \
|
||||||
|
@ -479,3 +486,38 @@ _PyTestCapi_Init_DateTime(PyObject *mod)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Test module for subinterpreters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
_testcapi_datetime_exec(PyObject *mod)
|
||||||
|
{
|
||||||
|
if (test_datetime_capi(NULL, NULL) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyModuleDef_Slot _testcapi_datetime_slots[] = {
|
||||||
|
{Py_mod_exec, _testcapi_datetime_exec},
|
||||||
|
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
|
||||||
|
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
|
||||||
|
{0, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct PyModuleDef _testcapi_datetime_module = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
.m_name = "_testcapi_datetime",
|
||||||
|
.m_size = 0,
|
||||||
|
.m_methods = test_methods,
|
||||||
|
.m_slots = _testcapi_datetime_slots,
|
||||||
|
};
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit__testcapi_datetime(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&_testcapi_datetime_module);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue