diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 62d8806b75d9db0..08778eb9355c5f3 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -1019,6 +1019,8 @@ def test_detach_materialized_dict_no_memory(self): import test.support import _testcapi + set_nomemory = _testcapi.set_nomemory # eagerly load the function + class A: def __init__(self): self.a = 1 @@ -1026,7 +1028,7 @@ def __init__(self): a = A() d = a.__dict__ with test.support.catch_unraisable_exception() as ex: - _testcapi.set_nomemory(0, 1) + set_nomemory(0, 1) del a assert ex.unraisable.exc_type is MemoryError try: diff --git a/Lib/test/test_structseq.py b/Lib/test/test_structseq.py index 74506fc54de50e7..96aa3b337369bc5 100644 --- a/Lib/test/test_structseq.py +++ b/Lib/test/test_structseq.py @@ -6,7 +6,7 @@ import textwrap import time import unittest -from test.support import script_helper +from test.support import import_helper, script_helper class StructSeqTest(unittest.TestCase): @@ -48,6 +48,105 @@ def test_repr(self): self.assertIn("st_ino=", rep) self.assertIn("st_dev=", rep) + def test_repr_with_unnamed_fields(self): + # gh-154387: each unnamed field is shown at its own index rather than + # borrowing a neighbour's name. Unnamed fields need not be contiguous or + # trailing. + _testcapi = import_helper.import_module("_testcapi") + cls = _testcapi.structseq_newtype_interspersed_unnamed() + self.assertEqual(cls.n_fields, 5) + self.assertEqual(cls.n_sequence_fields, 4) + self.assertEqual(cls.n_unnamed_fields, 2) + self.assertEqual(cls.__match_args__, ("first", "third")) + + t1 = cls(range(5)) + self.assertEqual(repr(t1), + "_testcapi.Interspersed(first=0, =1, third=2, " + "=3)") + # Only the visible fields form the tuple; the hidden "fifth" is excluded. + self.assertEqual(tuple(t1), (0, 1, 2, 3)) + self.assertEqual(len(t1), 4) + # Named fields are accessible by attribute, including the hidden one. + self.assertEqual(t1.first, 0) + self.assertEqual(t1.third, 2) + self.assertEqual(t1.fifth, 4) + + t2 = cls(range(4)) + self.assertEqual(repr(t2), + "_testcapi.Interspersed(first=0, =1, third=2, " + "=3)") + # Only the visible fields form the tuple; the hidden "fifth" is excluded. + self.assertEqual(tuple(t2), (0, 1, 2, 3)) + self.assertEqual(len(t2), 4) + # Named fields are accessible by attribute, including the hidden one. + # The hidden "fifth" is not set, so it returns None. + self.assertEqual(t2.first, 0) + self.assertEqual(t2.third, 2) + self.assertIsNone(t2.fifth) + + def test_os_stat_result_has_custom_repr(self): + # gh-154387: os.stat_result has a custom repr (statresult_repr) showing + # the float times st_atime/st_mtime/st_ctime by name, not the unnamed + # integer slots with generic "". + self.assertEqual(os.stat_result.n_sequence_fields, 10) + self.assertEqual(os.stat_result.n_unnamed_fields, 3) + + # All fields supplied: st_atime/st_mtime/st_ctime are the float slots. + r1 = os.stat_result(range(os.stat_result.n_fields)) + rep = repr(r1) + self.assertEqual(rep, + "os.stat_result(st_mode=0, st_ino=1, st_dev=2, st_nlink=3, " + "st_uid=4, st_gid=5, st_size=6, st_atime=10, st_mtime=11, " + "st_ctime=12)") + self.assertNotIn("