mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Update test_time from v3.14.3
This commit is contained in:
1 parent
38562d4bce
commit
abec3606cf
3 files changed
+231
-118
No files matched your search
Vendored
+1
-1
@@ -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
|
||||
|
||||
Vendored
-1
@@ -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)
|
||||
|
||||
Vendored
+230
-116
@@ -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__":
|
||||
|
||||
Reference in new issue
Block a user