Skip to content

Commit db47683

Browse files
committed
Make tests generic
1 parent 29c45a3 commit db47683

2 files changed

Lines changed: 87 additions & 83 deletions

File tree

Lib/test/datetimetester.py

Lines changed: 59 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -7155,49 +7155,75 @@ def test_datetime_from_timestamp(self):
71557155

71567156
self.assertEqual(dt_orig, dt_rt)
71577157

7158-
def test_type_check_in_subinterp(self):
7158+
def assert_python_ok_in_subinterp(self, script,
7159+
setup='_testcapi.test_datetime_capi()',
7160+
mainsetup='_testcapi.test_datetime_capi()',
7161+
config='isolated'):
71597162
# iOS requires the use of the custom framework loader,
71607163
# not the ExtensionFileLoader.
71617164
if sys.platform == "ios":
71627165
extension_loader = "AppleFrameworkLoader"
71637166
else:
71647167
extension_loader = "ExtensionFileLoader"
71657168

7166-
script = textwrap.dedent(f"""
7169+
maincode = textwrap.dedent(f'''
7170+
import textwrap
7171+
from test import support
7172+
7173+
subcode = textwrap.dedent("""
7174+
if {_interpreters is None}:
7175+
import _testcapi
7176+
else:
7177+
import importlib.machinery
7178+
import importlib.util
7179+
fullname = '_testcapi_datetime'
7180+
origin = importlib.util.find_spec('_testcapi').origin
7181+
loader = importlib.machinery.{extension_loader}(fullname, origin)
7182+
spec = importlib.util.spec_from_loader(fullname, loader)
7183+
_testcapi = importlib.util.module_from_spec(spec)
7184+
spec.loader.exec_module(_testcapi)
7185+
7186+
$SETUP$
7187+
$SCRIPT$
7188+
""")
7189+
7190+
import _testcapi
7191+
$MAINSETUP$
7192+
71677193
if {_interpreters is None}:
7168-
import _testcapi as module
7169-
module.test_datetime_capi()
7194+
ret = support.run_in_subinterp(subcode)
71707195
else:
7171-
import importlib.machinery
7172-
import importlib.util
7173-
fullname = '_testcapi_datetime'
7174-
origin = importlib.util.find_spec('_testcapi').origin
7175-
loader = importlib.machinery.{extension_loader}(fullname, origin)
7176-
spec = importlib.util.spec_from_loader(fullname, loader)
7177-
module = importlib.util.module_from_spec(spec)
7178-
spec.loader.exec_module(module)
7179-
module.test_datetime_capi()
7196+
import _interpreters
7197+
config = _interpreters.new_config('{config}').__dict__
7198+
ret = support.run_in_subinterp_with_config(subcode, **config)
7199+
7200+
assert ret == 0
7201+
7202+
''').replace('$MAINSETUP$', mainsetup)
7203+
maincode = maincode.replace('$SETUP$', textwrap.indent(setup, '\x20'*4))
7204+
maincode = maincode.replace('$SCRIPT$', textwrap.indent(script, '\x20'*4))
7205+
7206+
res = script_helper.assert_python_ok('-c', maincode)
7207+
return res
71807208

7209+
def test_type_check_in_subinterp(self):
7210+
script = textwrap.dedent(f"""
71817211
def run(type_checker, obj):
71827212
if not type_checker(obj, True):
71837213
raise TypeError(f'{{type(obj)}} is not C API type')
71847214
71857215
import _datetime
7186-
run(module.datetime_check_date, _datetime.date.today())
7187-
run(module.datetime_check_datetime, _datetime.datetime.now())
7188-
run(module.datetime_check_time, _datetime.time(12, 30))
7189-
run(module.datetime_check_delta, _datetime.timedelta(1))
7190-
run(module.datetime_check_tzinfo, _datetime.tzinfo())
7216+
run(_testcapi.datetime_check_date, _datetime.date.today())
7217+
run(_testcapi.datetime_check_datetime, _datetime.datetime.now())
7218+
run(_testcapi.datetime_check_time, _datetime.time(12, 30))
7219+
run(_testcapi.datetime_check_delta, _datetime.timedelta(1))
7220+
run(_testcapi.datetime_check_tzinfo, _datetime.tzinfo())
71917221
""")
7192-
if _interpreters is None:
7193-
ret = support.run_in_subinterp(script)
7194-
self.assertEqual(ret, 0)
7195-
else:
7196-
for name in ('isolated', 'legacy'):
7197-
with self.subTest(name):
7198-
config = _interpreters.new_config(name).__dict__
7199-
ret = support.run_in_subinterp_with_config(script, **config)
7200-
self.assertEqual(ret, 0)
7222+
self.assert_python_ok_in_subinterp(script, mainsetup='')
7223+
if _interpreters is not None:
7224+
with self.subTest('legacy'):
7225+
self.assert_python_ok_in_subinterp(script, mainsetup='',
7226+
config='legacy')
72017227

72027228

72037229
class ExtensionModuleTests(unittest.TestCase):
@@ -7284,6 +7310,7 @@ def gen():
72847310
try:
72857311
yield
72867312
finally:
7313+
# Exceptions are ignored here
72877314
assert not sys.modules
72887315
td = _datetime.timedelta(days=1)
72897316
assert td.days == 1
@@ -7315,55 +7342,9 @@ def gen():
73157342
res = script_helper.assert_python_ok('-c', script)
73167343
self.assertFalse(res.err)
73177344

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-
73647345
def test_static_type_at_shutdown3(self):
73657346
script = textwrap.dedent("""
7366-
timedelta = module.get_delta_type()
7347+
timedelta = _testcapi.get_capi_types()['timedelta']
73677348
73687349
def gen():
73697350
try:
@@ -7374,19 +7355,18 @@ def gen():
73747355
it = gen()
73757356
next(it)
73767357
""")
7377-
res = self.run_script_132413(script)
7358+
res = CapiTest.assert_python_ok_in_subinterp(self, script, setup='')
73787359
self.assertIn(b'ImportError: sys.meta_path is None', res.err)
73797360

73807361
def test_static_type_before_shutdown(self):
73817362
script = textwrap.dedent(f"""
73827363
import sys
73837364
assert '_datetime' not in sys.modules
7384-
timedelta = module.get_delta_type()
7365+
timedelta = _testcapi.get_capi_types()['timedelta']
73857366
timedelta(days=1)
73867367
assert '_datetime' in sys.modules
73877368
""")
7388-
res = self.run_script_132413(script)
7389-
self.assertFalse(res.err)
7369+
CapiTest.assert_python_ok_in_subinterp(self, script, setup='')
73907370

73917371
def test_remain_only_one_module(self):
73927372
script = textwrap.dedent("""
@@ -7403,8 +7383,7 @@ def test_remain_only_one_module(self):
74037383
gc.collect()
74047384
assert len(ws) == 1
74057385
""")
7406-
res = script_helper.assert_python_ok('-c', script)
7407-
self.assertFalse(res.err)
7386+
script_helper.assert_python_ok('-c', script)
74087387

74097388
@unittest.skipIf(not support.Py_DEBUG, "Debug builds only")
74107389
def test_no_leak(self):

Modules/_testcapi/datetime.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,34 @@ test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj)
454454
}
455455

456456
static PyObject *
457-
get_delta_type(PyObject *self, PyObject *args)
457+
get_capi_types(PyObject *self, PyObject *args)
458458
{
459-
return PyDateTimeAPI ? Py_NewRef(PyDateTimeAPI->DeltaType) : Py_None;
459+
if (PyDateTimeAPI == NULL) {
460+
Py_RETURN_NONE;
461+
}
462+
PyObject *dict = PyDict_New();
463+
if (dict == NULL) {
464+
return NULL;
465+
}
466+
if (PyDict_SetItemString(dict, "date", PyDateTimeAPI->DateType) < 0) {
467+
goto error;
468+
}
469+
if (PyDict_SetItemString(dict, "time", PyDateTimeAPI->TimeType) < 0) {
470+
goto error;
471+
}
472+
if (PyDict_SetItemString(dict, "datetime", PyDateTimeAPI->DateTimeType) < 0) {
473+
goto error;
474+
}
475+
if (PyDict_SetItemString(dict, "timedelta", PyDateTimeAPI->DeltaType) < 0) {
476+
goto error;
477+
}
478+
if (PyDict_SetItemString(dict, "tzinfo", PyDateTimeAPI->TZInfoType) < 0) {
479+
goto error;
480+
}
481+
return dict;
482+
error:
483+
Py_DECREF(dict);
484+
return NULL;
460485
}
461486

462487
static PyMethodDef test_methods[] = {
@@ -475,11 +500,11 @@ static PyMethodDef test_methods[] = {
475500
{"get_datetime_fromdateandtimeandfold", get_datetime_fromdateandtimeandfold, METH_VARARGS},
476501
{"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS},
477502
{"get_delta_fromdsu", get_delta_fromdsu, METH_VARARGS},
478-
{"get_delta_type", get_delta_type, METH_NOARGS},
479503
{"get_time_fromtime", get_time_fromtime, METH_VARARGS},
480504
{"get_time_fromtimeandfold", get_time_fromtimeandfold, METH_VARARGS},
481505
{"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS},
482506
{"get_timezones_offset_zero", get_timezones_offset_zero, METH_NOARGS},
507+
{"get_capi_types", get_capi_types, METH_NOARGS},
483508
{"make_timezones_capi", make_timezones_capi, METH_NOARGS},
484509
{"test_datetime_capi", test_datetime_capi, METH_NOARGS},
485510
{NULL},

0 commit comments

Comments
 (0)