From 6b6092f533f0e4787b8564c4fad6ec6d1018af0d Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Fri, 15 May 2020 19:27:54 -0600 Subject: [PATCH] bpo-39075: types.SimpleNamespace no longer sorts attributes in its repr (GH-19430) --- Doc/library/types.rst | 6 ++++-- Lib/test/test_types.py | 6 +++--- .../next/Library/2020-04-07-23-44-06.bpo-39075.hgck3j.rst | 2 ++ Objects/namespaceobject.c | 2 -- 4 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-04-07-23-44-06.bpo-39075.hgck3j.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index cdddb46783a..79acdf4499a 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -355,8 +355,7 @@ Additional Utility Classes and Functions self.__dict__.update(kwargs) def __repr__(self): - keys = sorted(self.__dict__) - items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys) + items = (f"{k}={v!r}" for k, v in self.__dict__.items()) return "{}({})".format(type(self).__name__, ", ".join(items)) def __eq__(self, other): @@ -368,6 +367,9 @@ Additional Utility Classes and Functions .. versionadded:: 3.3 + .. versionchanged:: 3.9 + Attribute order in the repr changed from alphabetical to insertion (like + ``dict``). .. function:: DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 28ebfb6e603..49dc5bf40e3 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1262,8 +1262,8 @@ def test_repr(self): ns2._y = 5 name = "namespace" - self.assertEqual(repr(ns1), "{name}(w=3, x=1, y=2)".format(name=name)) - self.assertEqual(repr(ns2), "{name}(_y=5, x='spam')".format(name=name)) + self.assertEqual(repr(ns1), "{name}(x=1, y=2, w=3)".format(name=name)) + self.assertEqual(repr(ns2), "{name}(x='spam', _y=5)".format(name=name)) def test_equal(self): ns1 = types.SimpleNamespace(x=1) @@ -1312,7 +1312,7 @@ def test_recursive_repr(self): ns3.spam = ns2 name = "namespace" repr1 = "{name}(c='cookie', spam={name}(...))".format(name=name) - repr2 = "{name}(spam={name}(spam={name}(...), x=1))".format(name=name) + repr2 = "{name}(spam={name}(x=1, spam={name}(...)))".format(name=name) self.assertEqual(repr(ns1), repr1) self.assertEqual(repr(ns2), repr2) diff --git a/Misc/NEWS.d/next/Library/2020-04-07-23-44-06.bpo-39075.hgck3j.rst b/Misc/NEWS.d/next/Library/2020-04-07-23-44-06.bpo-39075.hgck3j.rst new file mode 100644 index 00000000000..c447a191f07 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-04-07-23-44-06.bpo-39075.hgck3j.rst @@ -0,0 +1,2 @@ +The repr for :class:`types.SimpleNamespace` is now insertion ordered rather +than alphabetical. diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index 29141a81d71..fa37ed250d3 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -91,8 +91,6 @@ namespace_repr(PyObject *ns) keys = PyDict_Keys(d); if (keys == NULL) goto error; - if (PyList_Sort(keys) != 0) - goto error; keys_iter = PyObject_GetIter(keys); if (keys_iter == NULL)