https://github.com/python/cpython/commit/116caab464af216d30f0b938703ab65fd2cf5edf
commit: 116caab464af216d30f0b938703ab65fd2cf5edf
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-13T12:53:48+03:00
summary:
gh-78526: Add tests for PEP 468 and PEP 520 (GH-155387)
Test that the order of keyword arguments and the order of class attribute
definitions are preserved.
files:
M Lib/test/test_call.py
M Lib/test/test_class.py
diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index 1e42356be21ddd..76f1c351e15908 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -47,6 +47,54 @@ def fn(**kw):
self.assertIsInstance(res, dict)
self.assertEqual(list(res.items()), expected)
+ def test_kwargs_order_preserved(self):
+ # PEP 468: Preserving Keyword Argument Order
+ def fn(**kw):
+ return list(kw)
+
+ self.assertEqual(fn(b=1, a=2, c=3), ['b', 'a', 'c'])
+ self.assertEqual(fn(c=3, a=2, b=1), ['c', 'a', 'b'])
+ # Unpacked mappings are merged in place, keeping their own order.
+ self.assertEqual(fn(z=0, **{'x': 1, 'a': 2}, y=3),
+ ['z', 'x', 'a', 'y'])
+ self.assertEqual(fn(**{'b': 1}, **{'a': 2}), ['b', 'a'])
+ # Named parameters are removed from **kwargs without reordering
+ # the rest.
+ def fn2(a, c=None, **kw):
+ return list(kw)
+
+ self.assertEqual(fn2(d=1, a=2, b=3, c=4, e=5), ['d', 'b', 'e'])
+
+ def test_kwargs_order_preserved_in_methods(self):
+ # PEP 468: Preserving Keyword Argument Order
+ class C:
+ def __init__(self, **kw):
+ self.init_kw = list(kw)
+
+ def meth(self, **kw):
+ return list(kw)
+
+ @classmethod
+ def cmeth(cls, **kw):
+ return list(kw)
+
+ @staticmethod
+ def smeth(**kw):
+ return list(kw)
+
+ c = C(b=1, a=2, c=3)
+ self.assertEqual(c.init_kw, ['b', 'a', 'c'])
+ self.assertEqual(c.meth(b=1, a=2, c=3), ['b', 'a', 'c'])
+ self.assertEqual(C.cmeth(b=1, a=2, c=3), ['b', 'a', 'c'])
+ self.assertEqual(C.smeth(b=1, a=2, c=3), ['b', 'a', 'c'])
+
+ def test_kwargs_order_preserved_in_c_functions(self):
+ # PEP 468: Preserving Keyword Argument Order
+ self.assertEqual(list(dict(b=1, a=2, c=3)), ['b', 'a', 'c'])
+ self.assertEqual(list(dict(**{'b': 1}, a=2)), ['b', 'a'])
+ self.assertEqual(list(collections.OrderedDict(b=1, a=2, c=3)),
+ ['b', 'a', 'c'])
+
def test_frames_are_popped_after_failed_calls(self):
# GH-93252: stuff blows up if we don't pop the new frame after
# recovering from failed calls:
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index e07efd26966945..7bd6d966e8536b 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -1052,5 +1052,65 @@ def __init__(self):
self.fail("MemoryError was not raised during deallocation")
self.fail("the dictionary was not cleared")
+class DefinitionOrderTests(unittest.TestCase):
+ # PEP 520: Preserving Class Attribute Definition Order
+
+ @staticmethod
+ def defined_names(namespace):
+ # Skip the names added by the compiler, like __firstlineno__.
+ return [name for name in namespace if not name.startswith('__')]
+
+ def test_definition_order(self):
+ class C:
+ b = 1
+ a = 2
+ def m(self): pass
+ @staticmethod
+ def s(): pass
+ z = 3
+
+ self.assertEqual(self.defined_names(C.__dict__),
+ ['b', 'a', 'm', 's', 'z'])
+
+ def test_definition_order_redefinition(self):
+ class C:
+ b = 1
+ a = 2
+ b = 3
+
+ self.assertEqual(self.defined_names(C.__dict__), ['b', 'a'])
+ self.assertEqual(C.b, 3)
+
+ def test_definition_order_after_deletion(self):
+ class C:
+ a = 1
+ b = 2
+ del a
+ a = 3
+
+ self.assertEqual(self.defined_names(C.__dict__), ['b', 'a'])
+
+ def test_definition_order_in_namespace(self):
+ namespaces = []
+ class Meta(type):
+ def __new__(mcls, name, bases, namespace, **kwds):
+ namespaces.append(list(namespace))
+ return super().__new__(mcls, name, bases, namespace, **kwds)
+
+ class C(metaclass=Meta):
+ b = 1
+ a = 2
+ def m(self): pass
+
+ self.assertEqual(self.defined_names(namespaces[0]), ['b', 'a', 'm'])
+
+ def test_prepare_preserves_order(self):
+ namespace = type.__prepare__('C', ())
+ namespace['b'] = 1
+ namespace['a'] = 2
+ namespace['b'] = 3
+ self.assertEqual(list(namespace), ['b', 'a'])
+
+
if __name__ == '__main__':
unittest.main()
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]