diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2016-09-05 21:50:11 (GMT) |
---|---|---|
committer | Eric Snow <ericsnowcurrently@gmail.com> | 2016-09-05 21:50:11 (GMT) |
commit | 92a6c170e6897ee98c36a3a9087b1a7d3e054d2b (patch) | |
tree | 59cbc717ac59e802529bc3ad4e61de161b66ac68 /Lib/test | |
parent | 45659861380a9cd9e41ea002d4de92519ffb3422 (diff) | |
download | cpython-92a6c170e6897ee98c36a3a9087b1a7d3e054d2b.zip cpython-92a6c170e6897ee98c36a3a9087b1a7d3e054d2b.tar.gz cpython-92a6c170e6897ee98c36a3a9087b1a7d3e054d2b.tar.bz2 |
Issue #24254: Preserve class attribute definition order.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_builtin.py | 192 | ||||
-rw-r--r-- | Lib/test/test_metaclass.py | 11 | ||||
-rw-r--r-- | Lib/test/test_pydoc.py | 8 | ||||
-rw-r--r-- | Lib/test/test_sys.py | 2 | ||||
-rw-r--r-- | Lib/test/test_types.py | 22 |
5 files changed, 229 insertions, 6 deletions
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7741a79..486f445 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -16,8 +16,10 @@ import traceback import types import unittest import warnings +from collections import OrderedDict from operator import neg -from test.support import TESTFN, unlink, run_unittest, check_warnings +from test.support import (TESTFN, unlink, run_unittest, check_warnings, + cpython_only) from test.support.script_helper import assert_python_ok try: import pty, signal @@ -1778,6 +1780,194 @@ class TestType(unittest.TestCase): A.__doc__ = doc self.assertEqual(A.__doc__, doc) + def test_type_definition_order_nonempty(self): + class Spam: + b = 1 + c = 3 + a = 2 + d = 4 + eggs = 2 + e = 5 + b = 42 + + self.assertEqual(Spam.__definition_order__, + ('__module__', '__qualname__', + 'b', 'c', 'a', 'd', 'eggs', 'e')) + + def test_type_definition_order_empty(self): + class Empty: + pass + + self.assertEqual(Empty.__definition_order__, + ('__module__', '__qualname__')) + + def test_type_definition_order_on_instance(self): + class Spam: + a = 2 + b = 1 + c = 3 + with self.assertRaises(AttributeError): + Spam().__definition_order__ + + def test_type_definition_order_set_to_None(self): + class Spam: + a = 2 + b = 1 + c = 3 + Spam.__definition_order__ = None + self.assertEqual(Spam.__definition_order__, None) + + def test_type_definition_order_set_to_tuple(self): + class Spam: + a = 2 + b = 1 + c = 3 + Spam.__definition_order__ = ('x', 'y', 'z') + self.assertEqual(Spam.__definition_order__, ('x', 'y', 'z')) + + def test_type_definition_order_deleted(self): + class Spam: + a = 2 + b = 1 + c = 3 + del Spam.__definition_order__ + self.assertEqual(Spam.__definition_order__, None) + + def test_type_definition_order_set_to_bad_type(self): + class Spam: + a = 2 + b = 1 + c = 3 + Spam.__definition_order__ = 42 + self.assertEqual(Spam.__definition_order__, 42) + + def test_type_definition_order_builtins(self): + self.assertEqual(object.__definition_order__, None) + self.assertEqual(type.__definition_order__, None) + self.assertEqual(dict.__definition_order__, None) + self.assertEqual(type(None).__definition_order__, None) + + def test_type_definition_order_dunder_names_included(self): + class Dunder: + VAR = 3 + def __init__(self): + pass + + self.assertEqual(Dunder.__definition_order__, + ('__module__', '__qualname__', + 'VAR', '__init__')) + + def test_type_definition_order_only_dunder_names(self): + class DunderOnly: + __xyz__ = None + def __init__(self): + pass + + self.assertEqual(DunderOnly.__definition_order__, + ('__module__', '__qualname__', + '__xyz__', '__init__')) + + def test_type_definition_order_underscore_names(self): + class HalfDunder: + __whether_to_be = True + or_not_to_be__ = False + + self.assertEqual(HalfDunder.__definition_order__, + ('__module__', '__qualname__', + '_HalfDunder__whether_to_be', 'or_not_to_be__')) + + def test_type_definition_order_with_slots(self): + class Slots: + __slots__ = ('x', 'y') + a = 1 + b = 2 + + self.assertEqual(Slots.__definition_order__, + ('__module__', '__qualname__', + '__slots__', 'a', 'b')) + + def test_type_definition_order_overwritten_None(self): + class OverwrittenNone: + __definition_order__ = None + a = 1 + b = 2 + c = 3 + + self.assertEqual(OverwrittenNone.__definition_order__, None) + + def test_type_definition_order_overwritten_tuple(self): + class OverwrittenTuple: + __definition_order__ = ('x', 'y', 'z') + a = 1 + b = 2 + c = 3 + + self.assertEqual(OverwrittenTuple.__definition_order__, + ('x', 'y', 'z')) + + def test_type_definition_order_overwritten_bad_item(self): + with self.assertRaises(TypeError): + class PoorlyOverwritten: + __definition_order__ = ('a', 2, 'c') + a = 1 + b = 2 + c = 3 + + def test_type_definition_order_overwritten_bad_type(self): + with self.assertRaises(TypeError): + class PoorlyOverwritten: + __definition_order__ = ['a', 2, 'c'] + a = 1 + b = 2 + c = 3 + + def test_type_definition_order_metaclass(self): + class Meta(type): + SPAM = 42 + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.assertEqual(Meta.__definition_order__, + ('__module__', '__qualname__', + 'SPAM', '__init__')) + + def test_type_definition_order_OrderedDict(self): + class Meta(type): + def __prepare__(self, *args, **kwargs): + return OrderedDict() + + class WithODict(metaclass=Meta): + x='y' + + self.assertEqual(WithODict.__definition_order__, + ('__module__', '__qualname__', 'x')) + + class Meta(type): + def __prepare__(self, *args, **kwargs): + class ODictSub(OrderedDict): + pass + return ODictSub() + + class WithODictSub(metaclass=Meta): + x='y' + + self.assertEqual(WithODictSub.__definition_order__, + ('__module__', '__qualname__', 'x')) + + @cpython_only + def test_type_definition_order_cpython(self): + # some implementations will have an ordered-by-default dict. + + class Meta(type): + def __prepare__(self, *args, **kwargs): + return {} + + class NotOrdered(metaclass=Meta): + x='y' + + self.assertEqual(NotOrdered.__definition_order__, None) + def test_bad_args(self): with self.assertRaises(TypeError): type() diff --git a/Lib/test/test_metaclass.py b/Lib/test/test_metaclass.py index e6fe20a..4db792e 100644 --- a/Lib/test/test_metaclass.py +++ b/Lib/test/test_metaclass.py @@ -180,7 +180,7 @@ Use a metaclass that doesn't derive from type. meta: C () ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)] kw: [] - >>> type(C) is dict + >>> type(C) is types._DefaultClassNamespaceType True >>> print(sorted(C.items())) [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)] @@ -211,8 +211,11 @@ And again, with a __prepare__ attribute. The default metaclass must define a __prepare__() method. - >>> type.__prepare__() - {} + >>> ns = type.__prepare__() + >>> type(ns) is types._DefaultClassNamespaceType + True + >>> list(ns) == [] + True >>> Make sure it works with subclassing. @@ -248,7 +251,9 @@ Test failures in looking up the __prepare__ method work. """ +from collections import OrderedDict import sys +import types # Trace function introduces __locals__ which causes various tests to fail. if hasattr(sys, 'gettrace') and sys.gettrace(): diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 4998597..527234b 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -427,6 +427,7 @@ class PydocDocTest(unittest.TestCase): expected_html = expected_html_pattern % ( (mod_url, mod_file, doc_loc) + expected_html_data_docstrings) + self.maxDiff = None self.assertEqual(result, expected_html) @unittest.skipIf(sys.flags.optimize >= 2, @@ -473,13 +474,18 @@ class PydocDocTest(unittest.TestCase): def test_non_str_name(self): # issue14638 # Treat illegal (non-str) name like no name + # Definition order is set to None so it looks the same in both + # cases. class A: + __definition_order__ = None __name__ = 42 class B: pass adoc = pydoc.render_doc(A()) bdoc = pydoc.render_doc(B()) - self.assertEqual(adoc.replace("A", "B"), bdoc) + self.maxDiff = None + expected = adoc.replace("A", "B") + self.assertEqual(bdoc, expected) def test_not_here(self): missing_module = "test.i_am_not_here" diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 4435d69..3131f36 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1084,7 +1084,7 @@ class SizeofTest(unittest.TestCase): check((1,2,3), vsize('') + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2n15Pl4Pn9Pn11PIP' + fmt = 'P2n15Pl4Pn9Pn11PIPP' if hasattr(sys, 'getcounts'): fmt += '3n2P' s = vsize(fmt) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index a202196..e5e110f 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -825,6 +825,28 @@ class ClassCreationTests(unittest.TestCase): self.assertEqual(C.y, 1) self.assertEqual(C.z, 2) + def test_new_class_deforder(self): + C = types.new_class("C") + self.assertEqual(C.__definition_order__, tuple()) + + Meta = self.Meta + def func(ns): + ns["x"] = 0 + D = types.new_class("D", (), {"metaclass": Meta, "z": 2}, func) + self.assertEqual(D.__definition_order__, ('y', 'z', 'x')) + + def func(ns): + ns["__definition_order__"] = None + ns["x"] = 0 + D = types.new_class("D", (), {"metaclass": Meta, "z": 2}, func) + self.assertEqual(D.__definition_order__, None) + + def func(ns): + ns["__definition_order__"] = ('a', 'b', 'c') + ns["x"] = 0 + D = types.new_class("D", (), {"metaclass": Meta, "z": 2}, func) + self.assertEqual(D.__definition_order__, ('a', 'b', 'c')) + # Many of the following tests are derived from test_descr.py def test_prepare_class(self): # Basic test of metaclass derivation |