Update test_time from v3.14.3

This commit is contained in:
CPython Developers authored and Jeong, YunWon committed 2026-02-11 16:57:51 +09:00
1 parent 38562d4bce
commit abec3606cf
3 files changed
+231 -118

No files matched your search

+1 -1
View File
@@ -1519,7 +1519,7 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
# bpo-41260: The parameter was named "fmt" in the pure python impl.
t.strftime(format="%f")
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON; chrono fallback on Windows")
def test_strftime_trailing_percent(self):
# bpo-35066: Make sure trailing '%' doesn't cause datetime's strftime to
# complain. Different libcs have different handling of trailing
-1
View File
@@ -614,7 +614,6 @@ class TestSupport(unittest.TestCase):
self.check_print_warning("a\nb",
'Warning -- a\nWarning -- b\n')
@unittest.expectedFailureIf(sys.platform != "win32", "TODO: RUSTPYTHON; no has_strftime_extensions yet")
def test_has_strftime_extensions(self):
if sys.platform == "win32":
self.assertFalse(support.has_strftime_extensions)
+230 -116
View File
@@ -2,7 +2,6 @@ from test import support
from test.support import warnings_helper
import decimal
import enum
import locale
import math
import platform
import sys
@@ -14,8 +13,12 @@ try:
import _testcapi
except ImportError:
_testcapi = None
try:
import _testinternalcapi
except ImportError:
_testinternalcapi = None
from test.support import skip_if_buggy_ucrt_strfptime
from test.support import skip_if_buggy_ucrt_strfptime, SuppressCrashReport
# Max year is only limited by the size of C int.
SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
@@ -38,6 +41,10 @@ class _PyTime(enum.IntEnum):
# Round away from zero
ROUND_UP = 3
# _PyTime_t is int64_t
PyTime_MIN = -2 ** 63
PyTime_MAX = 2 ** 63 - 1
# Rounding modes supported by PyTime
ROUNDING_MODES = (
# (PyTime rounding method, decimal rounding method)
@@ -109,6 +116,7 @@ class TimeTestCase(unittest.TestCase):
'need time.pthread_getcpuclockid()')
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
@unittest.skipIf(support.is_emscripten, "Fails to find clock")
def test_pthread_getcpuclockid(self):
clk_id = time.pthread_getcpuclockid(threading.get_ident())
self.assertTrue(type(clk_id) is int)
@@ -150,13 +158,32 @@ class TimeTestCase(unittest.TestCase):
self.assertEqual(int(time.mktime(time.localtime(self.t))),
int(self.t))
def test_sleep(self):
def test_sleep_exceptions(self):
self.assertRaises(TypeError, time.sleep, [])
self.assertRaises(TypeError, time.sleep, "a")
self.assertRaises(TypeError, time.sleep, complex(0, 0))
self.assertRaises(ValueError, time.sleep, -2)
self.assertRaises(ValueError, time.sleep, -1)
time.sleep(1.2)
self.assertRaises(ValueError, time.sleep, -0.1)
# Improved exception #81267
with self.assertRaises(TypeError) as errmsg:
time.sleep([])
self.assertIn("integer or float", str(errmsg.exception))
def test_sleep(self):
for value in [-0.0, 0, 0.0, 1e-100, 1e-9, 1e-6, 1, 1.2]:
with self.subTest(value=value):
time.sleep(value)
def test_epoch(self):
# bpo-43869: Make sure that Python use the same Epoch on all platforms:
# January 1, 1970, 00:00:00 (UTC).
epoch = time.gmtime(0)
# Only test the date and time, ignore other gmtime() members
self.assertEqual(tuple(epoch)[:6], (1970, 1, 1, 0, 0, 0), epoch)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_strftime(self):
tt = time.gmtime(self.t)
for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
@@ -169,8 +196,46 @@ class TimeTestCase(unittest.TestCase):
self.fail('conversion specifier: %r failed.' % format)
self.assertRaises(TypeError, time.strftime, b'%S', tt)
# embedded null character
self.assertRaises(ValueError, time.strftime, '%S\0', tt)
def test_strftime_invalid_format(self):
tt = time.gmtime(self.t)
with SuppressCrashReport():
for i in range(1, 128):
format = ' %' + chr(i)
with self.subTest(format=format):
try:
time.strftime(format, tt)
except ValueError as exc:
self.assertEqual(str(exc), 'Invalid format string')
# TODO: RUSTPYTHON; chrono fallback on Windows does not preserve surrogates
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_strftime_special(self):
tt = time.gmtime(self.t)
s1 = time.strftime('%c', tt)
s2 = time.strftime('%B', tt)
# gh-52551, gh-78662: Unicode strings should pass through strftime,
# independently from locale.
self.assertEqual(time.strftime('\U0001f40d', tt), '\U0001f40d')
self.assertEqual(time.strftime('\U0001f4bb%c\U0001f40d%B', tt), f'\U0001f4bb{s1}\U0001f40d{s2}')
self.assertEqual(time.strftime('%c\U0001f4bb%B\U0001f40d', tt), f'{s1}\U0001f4bb{s2}\U0001f40d')
# Lone surrogates should pass through.
self.assertEqual(time.strftime('\ud83d', tt), '\ud83d')
self.assertEqual(time.strftime('\udc0d', tt), '\udc0d')
self.assertEqual(time.strftime('\ud83d%c\udc0d%B', tt), f'\ud83d{s1}\udc0d{s2}')
self.assertEqual(time.strftime('%c\ud83d%B\udc0d', tt), f'{s1}\ud83d{s2}\udc0d')
self.assertEqual(time.strftime('%c\udc0d%B\ud83d', tt), f'{s1}\udc0d{s2}\ud83d')
# Surrogate pairs should not recombine.
self.assertEqual(time.strftime('\ud83d\udc0d', tt), '\ud83d\udc0d')
self.assertEqual(time.strftime('%c\ud83d\udc0d%B', tt), f'{s1}\ud83d\udc0d{s2}')
# Surrogate-escaped bytes should not recombine.
self.assertEqual(time.strftime('\udcf0\udc9f\udc90\udc8d', tt), '\udcf0\udc9f\udc90\udc8d')
self.assertEqual(time.strftime('%c\udcf0\udc9f\udc90\udc8d%B', tt), f'{s1}\udcf0\udc9f\udc90\udc8d{s2}')
# gh-124531: The null character should not terminate the format string.
self.assertEqual(time.strftime('\0', tt), '\0')
self.assertEqual(time.strftime('\0'*1000, tt), '\0'*1000)
self.assertEqual(time.strftime('\0%c\0%B', tt), f'\0{s1}\0{s2}')
self.assertEqual(time.strftime('%c\0%B\0', tt), f'{s1}\0{s2}\0')
def _bounds_checking(self, func):
# Make sure that strftime() checks the bounds of the various parts
@@ -229,8 +294,8 @@ class TimeTestCase(unittest.TestCase):
self.assertRaises(ValueError, func,
(1900, 1, 1, 0, 0, 0, 0, 367, -1))
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono on Windows rejects month=0/day=0 and raises wrong error type
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_strftime_bounding_check(self):
self._bounds_checking(lambda tup: time.strftime('', tup))
@@ -247,8 +312,8 @@ class TimeTestCase(unittest.TestCase):
except ValueError:
pass
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono on Windows does not handle month=0/day=0 in struct_time
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_default_values_for_zero(self):
# Make sure that using all zeros uses the proper default
# values. No test for daylight savings since strftime() does
@@ -259,8 +324,8 @@ class TimeTestCase(unittest.TestCase):
result = time.strftime("%Y %m %d %H %M %S %w %j", (2000,)+(0,)*8)
self.assertEqual(expected, result)
# TODO: RUSTPYTHON
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono %Z on Windows not compatible with strptime
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
@skip_if_buggy_ucrt_strfptime
def test_strptime(self):
# Should be able to go round-trip from strftime to strptime without
@@ -270,6 +335,8 @@ class TimeTestCase(unittest.TestCase):
'j', 'm', 'M', 'p', 'S',
'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
format = '%' + directive
if directive == 'd':
format += ',%Y' # Avoid GH-70647.
strf_output = time.strftime(format, tt)
try:
time.strptime(strf_output, format)
@@ -286,14 +353,20 @@ class TimeTestCase(unittest.TestCase):
# check that this doesn't chain exceptions needlessly (see #17572)
with self.assertRaises(ValueError) as e:
time.strptime('', '%D')
self.assertIs(e.exception.__suppress_context__, True)
# additional check for IndexError branch (issue #19545)
self.assertTrue(e.exception.__suppress_context__)
# additional check for stray % branch
with self.assertRaises(ValueError) as e:
time.strptime('19', '%Y %')
self.assertIs(e.exception.__suppress_context__, True)
time.strptime('%', '%')
self.assertTrue(e.exception.__suppress_context__)
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
def test_strptime_leap_year(self):
# GH-70647: warns if parsing a format with a day and no year.
with self.assertWarnsRegex(DeprecationWarning,
r'.*day of month without a year.*'):
time.strptime('02-07 18:28', '%m-%d %H:%M')
# TODO: RUSTPYTHON; chrono on Windows cannot handle month=0/big years
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_asctime(self):
time.asctime(time.gmtime(self.t))
@@ -309,13 +382,13 @@ class TimeTestCase(unittest.TestCase):
self.assertRaises(TypeError, time.asctime, ())
self.assertRaises(TypeError, time.asctime, (0,) * 10)
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono on Windows rejects month=0/day=0
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_asctime_bounding_check(self):
self._bounds_checking(time.asctime)
# TODO: RUSTPYTHON
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono on Windows formats negative years differently
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_ctime(self):
t = time.mktime((1973, 9, 16, 1, 3, 52, 0, 0, -1))
self.assertEqual(time.ctime(t), 'Sun Sep 16 01:03:52 1973')
@@ -415,8 +488,6 @@ class TimeTestCase(unittest.TestCase):
for unreasonable in -1e200, 1e200:
self.assertRaises(OverflowError, func, unreasonable)
# TODO: RUSTPYTHON, TypeError: unexpected type NoneType
@unittest.expectedFailure
def test_ctime_without_arg(self):
# Not sure how to check the values, since the clock could tick
# at any time. Make sure these are at least accepted and
@@ -424,8 +495,6 @@ class TimeTestCase(unittest.TestCase):
time.ctime()
time.ctime(None)
# TODO: RUSTPYTHON, TypeError: unexpected type NoneType
@unittest.expectedFailure
def test_gmtime_without_arg(self):
gt0 = time.gmtime()
gt1 = time.gmtime(None)
@@ -433,8 +502,6 @@ class TimeTestCase(unittest.TestCase):
t1 = time.mktime(gt1)
self.assertAlmostEqual(t1, t0, delta=0.2)
# TODO: RUSTPYTHON, TypeError: unexpected type NoneType
@unittest.expectedFailure
def test_localtime_without_arg(self):
lt0 = time.localtime()
lt1 = time.localtime(None)
@@ -469,8 +536,6 @@ class TimeTestCase(unittest.TestCase):
pass
self.assertEqual(time.strftime('%Z', tt), tzname)
# TODO: RUSTPYTHON
@unittest.skipIf(sys.platform == "win32", "Implement get_clock_info for Windows.")
def test_monotonic(self):
# monotonic() should not go backward
times = [time.monotonic() for n in range(100)]
@@ -497,6 +562,12 @@ class TimeTestCase(unittest.TestCase):
def test_perf_counter(self):
time.perf_counter()
@unittest.skipIf(
support.is_wasi, "process_time not available on WASI"
)
@unittest.skipIf(
support.is_emscripten, "process_time present but doesn't exclude sleep"
)
def test_process_time(self):
# process_time() should not include time spend during a sleep
start = time.process_time()
@@ -512,7 +583,7 @@ class TimeTestCase(unittest.TestCase):
def test_thread_time(self):
if not hasattr(time, 'thread_time'):
if sys.platform.startswith(('linux', 'win')):
if sys.platform.startswith(('linux', 'android', 'win')):
self.fail("time.thread_time() should be available on %r"
% (sys.platform,))
else:
@@ -520,11 +591,10 @@ class TimeTestCase(unittest.TestCase):
# thread_time() should not include time spend during a sleep
start = time.thread_time()
time.sleep(0.100)
time.sleep(0.200)
stop = time.thread_time()
# use 20 ms because thread_time() has usually a resolution of 15 ms
# on Windows
self.assertLess(stop - start, 0.020)
# gh-143528: use 100 ms to support slow CI
self.assertLess(stop - start, 0.100)
info = time.get_clock_info('thread_time')
self.assertTrue(info.monotonic)
@@ -572,8 +642,9 @@ class TimeTestCase(unittest.TestCase):
'perf_counter',
'process_time',
'time',
'thread_time',
]
if hasattr(time, 'thread_time'):
clocks.append('thread_time')
for name in clocks:
with self.subTest(name=name):
@@ -592,17 +663,8 @@ class TimeTestCase(unittest.TestCase):
class TestLocale(unittest.TestCase):
def setUp(self):
self.oldloc = locale.setlocale(locale.LC_ALL)
def tearDown(self):
locale.setlocale(locale.LC_ALL, self.oldloc)
@support.run_with_locale('LC_ALL', 'fr_FR', '')
def test_bug_3061(self):
try:
tmp = locale.setlocale(locale.LC_ALL, "fr_FR")
except locale.Error:
self.skipTest('could not set locale.LC_ALL to fr_FR')
# This should not cause an exception
time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
@@ -613,8 +675,6 @@ class _TestAsctimeYear:
def yearstr(self, y):
return time.asctime((y,) + (0,) * 8).split()[-1]
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
def test_large_year(self):
# Check that it doesn't crash for year > 9999
self.assertEqual(self.yearstr(12345), '12345')
@@ -627,15 +687,17 @@ class _TestStrftimeYear:
# assumes year >= 1900, so it does not specify the number
# of digits.
# TODO: RUSTPYTHON
# if time.strftime('%Y', (1,) + (0,) * 8) == '0001':
# _format = '%04d'
# else:
# _format = '%d'
if time.strftime('%Y', (1,) + (0,) * 8) == '0001':
_format = '%04d'
else:
_format = '%d'
def yearstr(self, y):
return time.strftime('%Y', (y,) + (0,) * 8)
@unittest.skipUnless(
support.has_strftime_extensions, "requires strftime extension"
)
def test_4dyear(self):
# Check that we can return the zero padded value.
if self._format == '%04d':
@@ -646,8 +708,7 @@ class _TestStrftimeYear:
self.test_year('%04d', func=year4d)
def skip_if_not_supported(y):
msg = "strftime() is limited to [1; 9999] with Visual Studio"
# Check that it doesn't crash for year > 9999
msg = f"strftime() does not support year {y} on this platform"
try:
time.strftime('%Y', (y,) + (0,) * 8)
except ValueError:
@@ -670,8 +731,6 @@ class _TestStrftimeYear:
class _Test4dYear:
_format = '%d'
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
def test_year(self, fmt=None, func=None):
fmt = fmt or self._format
func = func or self.yearstr
@@ -688,8 +747,6 @@ class _Test4dYear:
self.assertEqual(self.yearstr(TIME_MAXYEAR).lstrip('+'), str(TIME_MAXYEAR))
self.assertRaises(OverflowError, self.yearstr, TIME_MAXYEAR + 1)
# TODO: RUSTPYTHON, ValueError: invalid struct_time parameter
@unittest.expectedFailure
def test_negative(self):
self.assertEqual(self.yearstr(-1), self._format % -1)
self.assertEqual(self.yearstr(-1234), '-1234')
@@ -704,32 +761,54 @@ class _Test4dYear:
class TestAsctime4dyear(_TestAsctimeYear, _Test4dYear, unittest.TestCase):
pass
# TODO: RUSTPYTHON; chrono on Windows cannot handle month=0/day=0 in struct_time
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_year(self, *args, **kwargs):
return super().test_year(*args, **kwargs)
# class TestStrftime4dyear(_TestStrftimeYear, _Test4dYear, unittest.TestCase):
# pass
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_large_year(self):
return super().test_large_year()
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_negative(self):
return super().test_negative()
class TestStrftime4dyear(_TestStrftimeYear, _Test4dYear, unittest.TestCase):
# TODO: RUSTPYTHON; chrono on Windows cannot handle month=0/day=0 in struct_time
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_year(self, *args, **kwargs):
return super().test_year(*args, **kwargs)
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_large_year(self):
return super().test_large_year()
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
def test_negative(self):
return super().test_negative()
class TestPytime(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
# TODO: RUSTPYTHON; chrono %Z on Windows gives offset instead of timezone name
@unittest.expectedFailureIf(sys.platform == "win32", "TODO: RUSTPYTHON")
@skip_if_buggy_ucrt_strfptime
@unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support")
def test_localtime_timezone(self):
# Get the localtime and examine it for the offset and zone.
lt = time.localtime()
self.assertTrue(hasattr(lt, "tm_gmtoff"))
self.assertTrue(hasattr(lt, "tm_zone"))
self.assertHasAttr(lt, "tm_gmtoff")
self.assertHasAttr(lt, "tm_zone")
# See if the offset and zone are similar to the module
# attributes.
if lt.tm_gmtoff is None:
self.assertTrue(not hasattr(time, "timezone"))
self.assertNotHasAttr(time, "timezone")
else:
self.assertEqual(lt.tm_gmtoff, -[time.timezone, time.altzone][lt.tm_isdst])
if lt.tm_zone is None:
self.assertTrue(not hasattr(time, "tzname"))
self.assertNotHasAttr(time, "tzname")
else:
self.assertEqual(lt.tm_zone, time.tzname[lt.tm_isdst])
@@ -748,18 +827,14 @@ class TestPytime(unittest.TestCase):
self.assertEqual(new_lt9, lt)
self.assertEqual(new_lt.tm_gmtoff, lt.tm_gmtoff)
self.assertEqual(new_lt9.tm_zone, lt.tm_zone)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support")
def test_strptime_timezone(self):
t = time.strptime("UTC", "%Z")
self.assertEqual(t.tm_zone, 'UTC')
t = time.strptime("+0500", "%z")
self.assertEqual(t.tm_gmtoff, 5 * 3600)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support")
def test_short_times(self):
@@ -772,7 +847,8 @@ class TestPytime(unittest.TestCase):
self.assertIs(lt.tm_zone, None)
@unittest.skipIf(_testcapi is None, 'need the _testcapi module')
@unittest.skipIf(_testcapi is None, 'need the _testinternalcapi module')
@unittest.skipIf(_testinternalcapi is None, 'need the _testinternalcapi module')
class CPyTimeTestCase:
"""
Base class to test the C _PyTime_t API.
@@ -780,7 +856,7 @@ class CPyTimeTestCase:
OVERFLOW_SECONDS = None
def setUp(self):
from _testcapi import SIZEOF_TIME_T
from _testinternalcapi import SIZEOF_TIME_T
bits = SIZEOF_TIME_T * 8 - 1
self.time_t_min = -2 ** bits
self.time_t_max = 2 ** bits - 1
@@ -859,7 +935,7 @@ class CPyTimeTestCase:
# test rounding
ns_timestamps = self._rounding_values(use_float)
valid_values = convert_values(ns_timestamps)
for time_rnd, decimal_rnd in ROUNDING_MODES :
for time_rnd, decimal_rnd in ROUNDING_MODES:
with decimal.localcontext() as context:
context.rounding = decimal_rnd
@@ -908,36 +984,36 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase):
OVERFLOW_SECONDS = math.ceil((2**63 + 1) / SEC_TO_NS)
def test_FromSeconds(self):
from _testcapi import PyTime_FromSeconds
from _testinternalcapi import _PyTime_FromSeconds
# PyTime_FromSeconds() expects a C int, reject values out of range
# _PyTime_FromSeconds() expects a C int, reject values out of range
def c_int_filter(secs):
return (_testcapi.INT_MIN <= secs <= _testcapi.INT_MAX)
self.check_int_rounding(lambda secs, rnd: PyTime_FromSeconds(secs),
self.check_int_rounding(lambda secs, rnd: _PyTime_FromSeconds(secs),
lambda secs: secs * SEC_TO_NS,
value_filter=c_int_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(TypeError):
PyTime_FromSeconds(float('nan'))
_PyTime_FromSeconds(float('nan'))
def test_FromSecondsObject(self):
from _testcapi import PyTime_FromSecondsObject
from _testinternalcapi import _PyTime_FromSecondsObject
self.check_int_rounding(
PyTime_FromSecondsObject,
_PyTime_FromSecondsObject,
lambda secs: secs * SEC_TO_NS)
self.check_float_rounding(
PyTime_FromSecondsObject,
_PyTime_FromSecondsObject,
lambda ns: self.decimal_round(ns * SEC_TO_NS))
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
PyTime_FromSecondsObject(float('nan'), time_rnd)
_PyTime_FromSecondsObject(float('nan'), time_rnd)
def test_AsSecondsDouble(self):
from _testcapi import PyTime_AsSecondsDouble
@@ -952,11 +1028,6 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase):
float_converter,
NS_TO_SEC)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(TypeError):
PyTime_AsSecondsDouble(float('nan'))
def create_decimal_converter(self, denominator):
denom = decimal.Decimal(denominator)
@@ -967,7 +1038,7 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase):
return converter
def test_AsTimeval(self):
from _testcapi import PyTime_AsTimeval
from _testinternalcapi import _PyTime_AsTimeval
us_converter = self.create_decimal_converter(US_TO_NS)
@@ -984,35 +1055,78 @@ class TestCPyTime(CPyTimeTestCase, unittest.TestCase):
else:
seconds_filter = self.time_t_filter
self.check_int_rounding(PyTime_AsTimeval,
self.check_int_rounding(_PyTime_AsTimeval,
timeval_converter,
NS_TO_SEC,
value_filter=seconds_filter)
@unittest.skipUnless(hasattr(_testcapi, 'PyTime_AsTimespec'),
'need _testcapi.PyTime_AsTimespec')
@unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimespec'),
'need _testinternalcapi._PyTime_AsTimespec')
def test_AsTimespec(self):
from _testcapi import PyTime_AsTimespec
from _testinternalcapi import _PyTime_AsTimespec
def timespec_converter(ns):
return divmod(ns, SEC_TO_NS)
self.check_int_rounding(lambda ns, rnd: PyTime_AsTimespec(ns),
self.check_int_rounding(lambda ns, rnd: _PyTime_AsTimespec(ns),
timespec_converter,
NS_TO_SEC,
value_filter=self.time_t_filter)
def test_AsMilliseconds(self):
from _testcapi import PyTime_AsMilliseconds
@unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimeval_clamp'),
'need _testinternalcapi._PyTime_AsTimeval_clamp')
def test_AsTimeval_clamp(self):
from _testinternalcapi import _PyTime_AsTimeval_clamp
self.check_int_rounding(PyTime_AsMilliseconds,
if sys.platform == 'win32':
from _testcapi import LONG_MIN, LONG_MAX
tv_sec_max = LONG_MAX
tv_sec_min = LONG_MIN
else:
tv_sec_max = self.time_t_max
tv_sec_min = self.time_t_min
for t in (PyTime_MIN, PyTime_MAX):
ts = _PyTime_AsTimeval_clamp(t, _PyTime.ROUND_CEILING)
with decimal.localcontext() as context:
context.rounding = decimal.ROUND_CEILING
us = self.decimal_round(decimal.Decimal(t) / US_TO_NS)
tv_sec, tv_usec = divmod(us, SEC_TO_US)
if tv_sec_max < tv_sec:
tv_sec = tv_sec_max
tv_usec = 0
elif tv_sec < tv_sec_min:
tv_sec = tv_sec_min
tv_usec = 0
self.assertEqual(ts, (tv_sec, tv_usec))
@unittest.skipUnless(hasattr(_testinternalcapi, '_PyTime_AsTimespec_clamp'),
'need _testinternalcapi._PyTime_AsTimespec_clamp')
def test_AsTimespec_clamp(self):
from _testinternalcapi import _PyTime_AsTimespec_clamp
for t in (PyTime_MIN, PyTime_MAX):
ts = _PyTime_AsTimespec_clamp(t)
tv_sec, tv_nsec = divmod(t, NS_TO_SEC)
if self.time_t_max < tv_sec:
tv_sec = self.time_t_max
tv_nsec = 0
elif tv_sec < self.time_t_min:
tv_sec = self.time_t_min
tv_nsec = 0
self.assertEqual(ts, (tv_sec, tv_nsec))
def test_AsMilliseconds(self):
from _testinternalcapi import _PyTime_AsMilliseconds
self.check_int_rounding(_PyTime_AsMilliseconds,
self.create_decimal_converter(MS_TO_NS),
NS_TO_SEC)
def test_AsMicroseconds(self):
from _testcapi import PyTime_AsMicroseconds
from _testinternalcapi import _PyTime_AsMicroseconds
self.check_int_rounding(PyTime_AsMicroseconds,
self.check_int_rounding(_PyTime_AsMicroseconds,
self.create_decimal_converter(US_TO_NS),
NS_TO_SEC)
@@ -1026,13 +1140,13 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase):
OVERFLOW_SECONDS = 2 ** 64
def test_object_to_time_t(self):
from _testcapi import pytime_object_to_time_t
from _testinternalcapi import _PyTime_ObjectToTime_t
self.check_int_rounding(pytime_object_to_time_t,
self.check_int_rounding(_PyTime_ObjectToTime_t,
lambda secs: secs,
value_filter=self.time_t_filter)
self.check_float_rounding(pytime_object_to_time_t,
self.check_float_rounding(_PyTime_ObjectToTime_t,
self.decimal_round,
value_filter=self.time_t_filter)
@@ -1052,36 +1166,36 @@ class TestOldPyTime(CPyTimeTestCase, unittest.TestCase):
return converter
def test_object_to_timeval(self):
from _testcapi import pytime_object_to_timeval
from _testinternalcapi import _PyTime_ObjectToTimeval
self.check_int_rounding(pytime_object_to_timeval,
self.check_int_rounding(_PyTime_ObjectToTimeval,
lambda secs: (secs, 0),
value_filter=self.time_t_filter)
self.check_float_rounding(pytime_object_to_timeval,
self.check_float_rounding(_PyTime_ObjectToTimeval,
self.create_converter(SEC_TO_US),
value_filter=self.time_t_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
pytime_object_to_timeval(float('nan'), time_rnd)
_PyTime_ObjectToTimeval(float('nan'), time_rnd)
def test_object_to_timespec(self):
from _testcapi import pytime_object_to_timespec
from _testinternalcapi import _PyTime_ObjectToTimespec
self.check_int_rounding(pytime_object_to_timespec,
self.check_int_rounding(_PyTime_ObjectToTimespec,
lambda secs: (secs, 0),
value_filter=self.time_t_filter)
self.check_float_rounding(pytime_object_to_timespec,
self.check_float_rounding(_PyTime_ObjectToTimespec,
self.create_converter(SEC_TO_NS),
value_filter=self.time_t_filter)
# test nan
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaises(ValueError):
pytime_object_to_timespec(float('nan'), time_rnd)
_PyTime_ObjectToTimespec(float('nan'), time_rnd)
@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
class TestTimeWeaklinking(unittest.TestCase):
@@ -1107,11 +1221,11 @@ class TestTimeWeaklinking(unittest.TestCase):
if mac_ver >= (10, 12):
for name in clock_names:
self.assertTrue(hasattr(time, name), f"time.{name} is not available")
self.assertHasAttr(time, name)
else:
for name in clock_names:
self.assertFalse(hasattr(time, name), f"time.{name} is available")
self.assertNotHasAttr(time, name)
if __name__ == "__main__":