Skip to content

Commit 022d4e8

Browse files
committed
Make tests realistic by using subinterp
1 parent 6880f34 commit 022d4e8

File tree

3 files changed

+69
-24
lines changed

3 files changed

+69
-24
lines changed

Lib/test/datetimetester.py

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7176,6 +7176,7 @@ def test_type_check_in_subinterp(self):
71767176
spec = importlib.util.spec_from_loader(fullname, loader)
71777177
module = importlib.util.module_from_spec(spec)
71787178
spec.loader.exec_module(module)
7179+
module.test_datetime_capi()
71797180
71807181
def run(type_checker, obj):
71817182
if not type_checker(obj, True):
@@ -7314,38 +7315,77 @@ def gen():
73147315
res = script_helper.assert_python_ok('-c', script)
73157316
self.assertFalse(res.err)
73167317

7318+
def run_script_132413(self, script):
7319+
# iOS requires the use of the custom framework loader,
7320+
# not the ExtensionFileLoader.
7321+
if sys.platform == "ios":
7322+
extension_loader = "AppleFrameworkLoader"
7323+
else:
7324+
extension_loader = "ExtensionFileLoader"
7325+
7326+
main_interp_script = textwrap.dedent(f'''
7327+
import textwrap
7328+
from test import support
7329+
7330+
sub_script = textwrap.dedent("""
7331+
if {_interpreters is None}:
7332+
import _testcapi as module
7333+
else:
7334+
import importlib.machinery
7335+
import importlib.util
7336+
fullname = '_testcapi_datetime'
7337+
origin = importlib.util.find_spec('_testcapi').origin
7338+
loader = importlib.machinery.{extension_loader}(fullname, origin)
7339+
spec = importlib.util.spec_from_loader(fullname, loader)
7340+
module = importlib.util.module_from_spec(spec)
7341+
spec.loader.exec_module(module)
7342+
7343+
# Skip calling test_datetime_capi()
7344+
$REPLACE_ME$
7345+
""")
7346+
7347+
import _testcapi
7348+
_testcapi.test_datetime_capi()
7349+
7350+
if {_interpreters is None}:
7351+
ret = support.run_in_subinterp(sub_script)
7352+
else:
7353+
import _interpreters
7354+
config = _interpreters.new_config('isolated').__dict__
7355+
ret = support.run_in_subinterp_with_config(sub_script, **config)
7356+
7357+
assert ret == 0
7358+
7359+
''').replace('$REPLACE_ME$', textwrap.indent(script, '\x20'*4))
7360+
7361+
res = script_helper.assert_python_ok('-c', main_interp_script)
7362+
return res
7363+
73177364
def test_static_type_at_shutdown3(self):
73187365
script = textwrap.dedent("""
7319-
import gc
7320-
import sys
7321-
from _datetime import timedelta
7322-
del sys.modules['_datetime']
7323-
gc.collect()
7366+
timedelta = module.get_delta_type()
73247367
73257368
def gen():
7326-
try:
7327-
yield
7328-
finally:
7329-
timedelta(days=1)
7369+
try:
7370+
yield
7371+
finally:
7372+
timedelta(days=1)
73307373
73317374
it = gen()
73327375
next(it)
7333-
""")
7334-
res = script_helper.assert_python_ok('-c', script)
7376+
""")
7377+
res = self.run_script_132413(script)
73357378
self.assertIn(b'ImportError: sys.meta_path is None', res.err)
73367379

73377380
def test_static_type_before_shutdown(self):
7338-
script = textwrap.dedent("""
7339-
import gc
7381+
script = textwrap.dedent(f"""
73407382
import sys
7341-
from _datetime import timedelta
7342-
del sys.modules['_datetime']
7343-
gc.collect()
7344-
7383+
assert '_datetime' not in sys.modules
7384+
timedelta = module.get_delta_type()
73457385
timedelta(days=1)
73467386
assert '_datetime' in sys.modules
7347-
""")
7348-
res = script_helper.assert_python_ok('-c', script)
7387+
""")
7388+
res = self.run_script_132413(script)
73497389
self.assertFalse(res.err)
73507390

73517391
def test_module_free(self):
@@ -7356,7 +7396,7 @@ def test_module_free(self):
73567396
ws = weakref.WeakSet()
73577397
for _ in range(3):
73587398
import _datetime
7359-
td = _datetime.timedelta
7399+
timedelta = _datetime.timedelta
73607400
ws.add(_datetime)
73617401
del sys.modules['_datetime']
73627402
del _datetime

Modules/_datetimemodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ _get_current_state(PyObject **p_mod)
155155
PyObject *mod = PyImport_ImportModule("_datetime");
156156
if (mod == NULL) {
157157
assert(_Py_IsInterpreterFinalizing(interp));
158-
/* It is not preferable to reload the module implicitly here. */
158+
/* We do not take care of the unlikely case. */
159159
return NULL;
160160
}
161161
st = get_module_state(mod);

Modules/_testcapi/datetime.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,12 @@ test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj)
453453
return Py_BuildValue("(iii)", days, seconds, microseconds);
454454
}
455455

456+
static PyObject *
457+
get_delta_type(PyObject *self, PyObject *args)
458+
{
459+
return PyDateTimeAPI ? Py_NewRef(PyDateTimeAPI->DeltaType) : Py_None;
460+
}
461+
456462
static PyMethodDef test_methods[] = {
457463
{"PyDateTime_DATE_GET", test_PyDateTime_DATE_GET, METH_O},
458464
{"PyDateTime_DELTA_GET", test_PyDateTime_DELTA_GET, METH_O},
@@ -469,6 +475,7 @@ static PyMethodDef test_methods[] = {
469475
{"get_datetime_fromdateandtimeandfold", get_datetime_fromdateandtimeandfold, METH_VARARGS},
470476
{"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS},
471477
{"get_delta_fromdsu", get_delta_fromdsu, METH_VARARGS},
478+
{"get_delta_type", get_delta_type, METH_NOARGS},
472479
{"get_time_fromtime", get_time_fromtime, METH_VARARGS},
473480
{"get_time_fromtimeandfold", get_time_fromtimeandfold, METH_VARARGS},
474481
{"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS},
@@ -495,9 +502,7 @@ _PyTestCapi_Init_DateTime(PyObject *mod)
495502
static int
496503
_testcapi_datetime_exec(PyObject *mod)
497504
{
498-
if (test_datetime_capi(NULL, NULL) == NULL) {
499-
return -1;
500-
}
505+
// Call test_datetime_capi() in each test.
501506
return 0;
502507
}
503508

0 commit comments

Comments
 (0)