Issue #24254: Drop cls.__definition_order__.

This commit is contained in:
Eric Snow 2016-09-08 15:11:11 -07:00
parent 7f730cf01d
commit 4f29e75289
16 changed files with 193 additions and 533 deletions

View File

@ -34,190 +34,185 @@ provided as convenient choices for the second argument to :func:`getmembers`.
They also help you determine when you can expect to find the following special They also help you determine when you can expect to find the following special
attributes: attributes:
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| Type | Attribute | Description | | Type | Attribute | Description |
+===========+======================+===========================+ +===========+=================+===========================+
| module | __doc__ | documentation string | | module | __doc__ | documentation string |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __file__ | filename (missing for | | | __file__ | filename (missing for |
| | | built-in modules) | | | | built-in modules) |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| class | __doc__ | documentation string | | class | __doc__ | documentation string |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __name__ | name with which this | | | __name__ | name with which this |
| | | class was defined | | | | class was defined |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __qualname__ | qualified name | | | __qualname__ | qualified name |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __module__ | name of module in which | | | __module__ | name of module in which |
| | | this class was defined | | | | this class was defined |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __definition_order__ | the names of the class's | | method | __doc__ | documentation string |
| | | attributes, in the order | +-----------+-----------------+---------------------------+
| | | in which they were | | | __name__ | name with which this |
| | | defined (if known) | | | | method was defined |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| method | __doc__ | documentation string | | | __qualname__ | qualified name |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __name__ | name with which this | | | __func__ | function object |
| | | method was defined | | | | containing implementation |
+-----------+----------------------+---------------------------+ | | | of method |
| | __qualname__ | qualified name | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | __self__ | instance to which this |
| | __func__ | function object | | | | method is bound, or |
| | | containing implementation | | | | ``None`` |
| | | of method | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | function | __doc__ | documentation string |
| | __self__ | instance to which this | +-----------+-----------------+---------------------------+
| | | method is bound, or | | | __name__ | name with which this |
| | | ``None`` | | | | function was defined |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| function | __doc__ | documentation string | | | __qualname__ | qualified name |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __name__ | name with which this | | | __code__ | code object containing |
| | | function was defined | | | | compiled function |
+-----------+----------------------+---------------------------+ | | | :term:`bytecode` |
| | __qualname__ | qualified name | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | __defaults__ | tuple of any default |
| | __code__ | code object containing | | | | values for positional or |
| | | compiled function | | | | keyword parameters |
| | | :term:`bytecode` | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | __kwdefaults__ | mapping of any default |
| | __defaults__ | tuple of any default | | | | values for keyword-only |
| | | values for positional or | | | | parameters |
| | | keyword parameters | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | __globals__ | global namespace in which |
| | __kwdefaults__ | mapping of any default | | | | this function was defined |
| | | values for keyword-only | +-----------+-----------------+---------------------------+
| | | parameters | | | __annotations__ | mapping of parameters |
+-----------+----------------------+---------------------------+ | | | names to annotations; |
| | __globals__ | global namespace in which | | | | ``"return"`` key is |
| | | this function was defined | | | | reserved for return |
+-----------+----------------------+---------------------------+ | | | annotations. |
| | __annotations__ | mapping of parameters | +-----------+-----------------+---------------------------+
| | | names to annotations; | | traceback | tb_frame | frame object at this |
| | | ``"return"`` key is | | | | level |
| | | reserved for return | +-----------+-----------------+---------------------------+
| | | annotations. | | | tb_lasti | index of last attempted |
+-----------+----------------------+---------------------------+ | | | instruction in bytecode |
| traceback | tb_frame | frame object at this | +-----------+-----------------+---------------------------+
| | | level | | | tb_lineno | current line number in |
+-----------+----------------------+---------------------------+ | | | Python source code |
| | tb_lasti | index of last attempted | +-----------+-----------------+---------------------------+
| | | instruction in bytecode | | | tb_next | next inner traceback |
+-----------+----------------------+---------------------------+ | | | object (called by this |
| | tb_lineno | current line number in | | | | level) |
| | | Python source code | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | frame | f_back | next outer frame object |
| | tb_next | next inner traceback | | | | (this frame's caller) |
| | | object (called by this | +-----------+-----------------+---------------------------+
| | | level) | | | f_builtins | builtins namespace seen |
+-----------+----------------------+---------------------------+ | | | by this frame |
| frame | f_back | next outer frame object | +-----------+-----------------+---------------------------+
| | | (this frame's caller) | | | f_code | code object being |
+-----------+----------------------+---------------------------+ | | | executed in this frame |
| | f_builtins | builtins namespace seen | +-----------+-----------------+---------------------------+
| | | by this frame | | | f_globals | global namespace seen by |
+-----------+----------------------+---------------------------+ | | | this frame |
| | f_code | code object being | +-----------+-----------------+---------------------------+
| | | executed in this frame | | | f_lasti | index of last attempted |
+-----------+----------------------+---------------------------+ | | | instruction in bytecode |
| | f_globals | global namespace seen by | +-----------+-----------------+---------------------------+
| | | this frame | | | f_lineno | current line number in |
+-----------+----------------------+---------------------------+ | | | Python source code |
| | f_lasti | index of last attempted | +-----------+-----------------+---------------------------+
| | | instruction in bytecode | | | f_locals | local namespace seen by |
+-----------+----------------------+---------------------------+ | | | this frame |
| | f_lineno | current line number in | +-----------+-----------------+---------------------------+
| | | Python source code | | | f_restricted | 0 or 1 if frame is in |
+-----------+----------------------+---------------------------+ | | | restricted execution mode |
| | f_locals | local namespace seen by | +-----------+-----------------+---------------------------+
| | | this frame | | | f_trace | tracing function for this |
+-----------+----------------------+---------------------------+ | | | frame, or ``None`` |
| | f_restricted | 0 or 1 if frame is in | +-----------+-----------------+---------------------------+
| | | restricted execution mode | | code | co_argcount | number of arguments (not |
+-----------+----------------------+---------------------------+ | | | including \* or \*\* |
| | f_trace | tracing function for this | | | | args) |
| | | frame, or ``None`` | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | co_code | string of raw compiled |
| code | co_argcount | number of arguments (not | | | | bytecode |
| | | including \* or \*\* | +-----------+-----------------+---------------------------+
| | | args) | | | co_consts | tuple of constants used |
+-----------+----------------------+---------------------------+ | | | in the bytecode |
| | co_code | string of raw compiled | +-----------+-----------------+---------------------------+
| | | bytecode | | | co_filename | name of file in which |
+-----------+----------------------+---------------------------+ | | | this code object was |
| | co_consts | tuple of constants used | | | | created |
| | | in the bytecode | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | co_firstlineno | number of first line in |
| | co_filename | name of file in which | | | | Python source code |
| | | this code object was | +-----------+-----------------+---------------------------+
| | | created | | | co_flags | bitmap: 1=optimized ``|`` |
+-----------+----------------------+---------------------------+ | | | 2=newlocals ``|`` 4=\*arg |
| | co_firstlineno | number of first line in | | | | ``|`` 8=\*\*arg |
| | | Python source code | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | co_lnotab | encoded mapping of line |
| | co_flags | bitmap: 1=optimized ``|`` | | | | numbers to bytecode |
| | | 2=newlocals ``|`` 4=\*arg | | | | indices |
| | | ``|`` 8=\*\*arg | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | co_name | name with which this code |
| | co_lnotab | encoded mapping of line | | | | object was defined |
| | | numbers to bytecode | +-----------+-----------------+---------------------------+
| | | indices | | | co_names | tuple of names of local |
+-----------+----------------------+---------------------------+ | | | variables |
| | co_name | name with which this code | +-----------+-----------------+---------------------------+
| | | object was defined | | | co_nlocals | number of local variables |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | co_names | tuple of names of local | | | co_stacksize | virtual machine stack |
| | | variables | | | | space required |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | co_nlocals | number of local variables | | | co_varnames | tuple of names of |
+-----------+----------------------+---------------------------+ | | | arguments and local |
| | co_stacksize | virtual machine stack | | | | variables |
| | | space required | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | generator | __name__ | name |
| | co_varnames | tuple of names of | +-----------+-----------------+---------------------------+
| | | arguments and local | | | __qualname__ | qualified name |
| | | variables | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | gi_frame | frame |
| generator | __name__ | name | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | gi_running | is the generator running? |
| | __qualname__ | qualified name | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | gi_code | code |
| | gi_frame | frame | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | gi_yieldfrom | object being iterated by |
| | gi_running | is the generator running? | | | | ``yield from``, or |
+-----------+----------------------+---------------------------+ | | | ``None`` |
| | gi_code | code | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | coroutine | __name__ | name |
| | gi_yieldfrom | object being iterated by | +-----------+-----------------+---------------------------+
| | | ``yield from``, or | | | __qualname__ | qualified name |
| | | ``None`` | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | cr_await | object being awaited on, |
| coroutine | __name__ | name | | | | or ``None`` |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __qualname__ | qualified name | | | cr_frame | frame |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | cr_await | object being awaited on, | | | cr_running | is the coroutine running? |
| | | or ``None`` | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | cr_code | code |
| | cr_frame | frame | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | builtin | __doc__ | documentation string |
| | cr_running | is the coroutine running? | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+ | | __name__ | original name of this |
| | cr_code | code | | | | function or method |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| builtin | __doc__ | documentation string | | | __qualname__ | qualified name |
+-----------+----------------------+---------------------------+ +-----------+-----------------+---------------------------+
| | __name__ | original name of this | | | __self__ | instance to which a |
| | | function or method | | | | method is bound, or |
+-----------+----------------------+---------------------------+ | | | ``None`` |
| | __qualname__ | qualified name | +-----------+-----------------+---------------------------+
+-----------+----------------------+---------------------------+
| | __self__ | instance to which a |
| | | method is bound, or |
| | | ``None`` |
+-----------+----------------------+---------------------------+
.. versionchanged:: 3.5 .. versionchanged:: 3.5
@ -226,10 +221,6 @@ attributes:
The ``__name__`` attribute of generators is now set from the function The ``__name__`` attribute of generators is now set from the function
name, instead of the code name, and it can now be modified. name, instead of the code name, and it can now be modified.
.. versionchanged:: 3.6
Add ``__definition_order__`` to classes.
.. function:: getmembers(object[, predicate]) .. function:: getmembers(object[, predicate])

View File

@ -53,19 +53,13 @@ Dynamic Type Creation
in *kwds* argument with any ``'metaclass'`` entry removed. If no *kwds* in *kwds* argument with any ``'metaclass'`` entry removed. If no *kwds*
argument is passed in, this will be an empty dict. argument is passed in, this will be an empty dict.
.. impl-detail::
CPython uses :class:`collections.OrderedDict` for the default
namespace.
.. versionadded:: 3.3 .. versionadded:: 3.3
.. versionchanged:: 3.6 .. versionchanged:: 3.6
The default value for the ``namespace`` element of the returned The default value for the ``namespace`` element of the returned
tuple has changed from :func:`dict`. Now an insertion-order- tuple has changed. Now an insertion-order-preserving mapping is
preserving mapping is used when the metaclass does not have a used when the metaclass does not have a ``__prepare__`` method,
``__prepare__`` method,
.. seealso:: .. seealso::

View File

@ -634,15 +634,9 @@ dictionary. The class name is bound to this class object in the original local
namespace. namespace.
The order in which attributes are defined in the class body is preserved The order in which attributes are defined in the class body is preserved
in the ``__definition_order__`` attribute on the new class. If that order in the new class's ``__dict__``. Note that this is reliable only right
is not known then the attribute is set to :const:`None`. The class body after the class is created and only for classes that were defined using
may include a ``__definition_order__`` attribute. In that case it is used the definition syntax.
directly. The value must be a tuple of identifiers or ``None``, otherwise
:exc:`TypeError` will be raised when the class statement is executed.
.. versionchanged:: 3.6
Add ``__definition_order__`` to classes.
Class creation can be customized heavily using :ref:`metaclasses <metaclasses>`. Class creation can be customized heavily using :ref:`metaclasses <metaclasses>`.

View File

@ -1752,13 +1752,6 @@ additional keyword arguments, if any, come from the class definition).
If the metaclass has no ``__prepare__`` attribute, then the class namespace If the metaclass has no ``__prepare__`` attribute, then the class namespace
is initialised as an empty ordered mapping. is initialised as an empty ordered mapping.
.. impl-detail::
In CPython the default is :class:`collections.OrderedDict`.
.. versionchanged:: 3.6
Defaults to :class:`collections.OrderedDict` instead of :func:`dict`.
.. seealso:: .. seealso::
:pep:`3115` - Metaclasses in Python 3000 :pep:`3115` - Metaclasses in Python 3000

View File

@ -421,8 +421,6 @@ typedef struct _typeobject {
destructor tp_finalize; destructor tp_finalize;
PyObject *tp_deforder;
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
/* these must be last and never explicitly initialized */ /* these must be last and never explicitly initialized */
Py_ssize_t tp_allocs; Py_ssize_t tp_allocs;

View File

@ -28,10 +28,6 @@ PyAPI_FUNC(PyObject *) PyODict_New(void);
PyAPI_FUNC(int) PyODict_SetItem(PyObject *od, PyObject *key, PyObject *item); PyAPI_FUNC(int) PyODict_SetItem(PyObject *od, PyObject *key, PyObject *item);
PyAPI_FUNC(int) PyODict_DelItem(PyObject *od, PyObject *key); PyAPI_FUNC(int) PyODict_DelItem(PyObject *od, PyObject *key);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyODict_KeysAsTuple(PyObject *od);
#endif
/* wrappers around PyDict* functions */ /* wrappers around PyDict* functions */
#define PyODict_GetItem(od, key) PyDict_GetItem((PyObject *)od, key) #define PyODict_GetItem(od, key) PyDict_GetItem((PyObject *)od, key)
#define PyODict_GetItemWithError(od, key) \ #define PyODict_GetItemWithError(od, key) \

View File

@ -16,10 +16,8 @@ import traceback
import types import types
import unittest import unittest
import warnings import warnings
from collections import OrderedDict
from operator import neg 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 from test.support.script_helper import assert_python_ok
try: try:
import pty, signal import pty, signal
@ -1780,194 +1778,6 @@ class TestType(unittest.TestCase):
A.__doc__ = doc A.__doc__ = doc
self.assertEqual(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): def test_bad_args(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
type() type()

View File

@ -180,7 +180,7 @@ Use a metaclass that doesn't derive from type.
meta: C () meta: C ()
ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)] ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)]
kw: [] kw: []
>>> type(C) is types._DefaultClassNamespaceType >>> type(C) is dict
True True
>>> print(sorted(C.items())) >>> print(sorted(C.items()))
[('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)] [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('a', 42), ('b', 24)]
@ -211,11 +211,8 @@ And again, with a __prepare__ attribute.
The default metaclass must define a __prepare__() method. The default metaclass must define a __prepare__() method.
>>> ns = type.__prepare__() >>> type.__prepare__()
>>> type(ns) is types._DefaultClassNamespaceType {}
True
>>> list(ns) == []
True
>>> >>>
Make sure it works with subclassing. Make sure it works with subclassing.
@ -251,9 +248,7 @@ Test failures in looking up the __prepare__ method work.
""" """
from collections import OrderedDict
import sys import sys
import types
# Trace function introduces __locals__ which causes various tests to fail. # Trace function introduces __locals__ which causes various tests to fail.
if hasattr(sys, 'gettrace') and sys.gettrace(): if hasattr(sys, 'gettrace') and sys.gettrace():

View File

@ -427,7 +427,6 @@ class PydocDocTest(unittest.TestCase):
expected_html = expected_html_pattern % ( expected_html = expected_html_pattern % (
(mod_url, mod_file, doc_loc) + (mod_url, mod_file, doc_loc) +
expected_html_data_docstrings) expected_html_data_docstrings)
self.maxDiff = None
self.assertEqual(result, expected_html) self.assertEqual(result, expected_html)
@unittest.skipIf(sys.flags.optimize >= 2, @unittest.skipIf(sys.flags.optimize >= 2,
@ -474,18 +473,13 @@ class PydocDocTest(unittest.TestCase):
def test_non_str_name(self): def test_non_str_name(self):
# issue14638 # issue14638
# Treat illegal (non-str) name like no name # Treat illegal (non-str) name like no name
# Definition order is set to None so it looks the same in both
# cases.
class A: class A:
__definition_order__ = None
__name__ = 42 __name__ = 42
class B: class B:
pass pass
adoc = pydoc.render_doc(A()) adoc = pydoc.render_doc(A())
bdoc = pydoc.render_doc(B()) bdoc = pydoc.render_doc(B())
self.maxDiff = None self.assertEqual(adoc.replace("A", "B"), bdoc)
expected = adoc.replace("A", "B")
self.assertEqual(bdoc, expected)
def test_not_here(self): def test_not_here(self):
missing_module = "test.i_am_not_here" missing_module = "test.i_am_not_here"

View File

@ -1085,7 +1085,7 @@ class SizeofTest(unittest.TestCase):
check((1,2,3), vsize('') + 3*self.P) check((1,2,3), vsize('') + 3*self.P)
# type # type
# static type: PyTypeObject # static type: PyTypeObject
fmt = 'P2n15Pl4Pn9Pn11PIPP' fmt = 'P2n15Pl4Pn9Pn11PIP'
if hasattr(sys, 'getcounts'): if hasattr(sys, 'getcounts'):
fmt += '3n2P' fmt += '3n2P'
s = vsize(fmt) s = vsize(fmt)

View File

@ -825,28 +825,6 @@ class ClassCreationTests(unittest.TestCase):
self.assertEqual(C.y, 1) self.assertEqual(C.y, 1)
self.assertEqual(C.z, 2) 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 # Many of the following tests are derived from test_descr.py
def test_prepare_class(self): def test_prepare_class(self):
# Basic test of metaclass derivation # Basic test of metaclass derivation

View File

@ -25,11 +25,8 @@ CoroutineType = type(_c)
_c.close() # Prevent ResourceWarning _c.close() # Prevent ResourceWarning
class _C: class _C:
_nsType = type(locals())
def _m(self): pass def _m(self): pass
MethodType = type(_C()._m) MethodType = type(_C()._m)
# In CPython, this should end up as OrderedDict.
_DefaultClassNamespaceType = _C._nsType
BuiltinFunctionType = type(len) BuiltinFunctionType = type(len)
BuiltinMethodType = type([].append) # Same as BuiltinFunctionType BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
@ -88,7 +85,7 @@ def prepare_class(name, bases=(), kwds=None):
if hasattr(meta, '__prepare__'): if hasattr(meta, '__prepare__'):
ns = meta.__prepare__(name, bases, **kwds) ns = meta.__prepare__(name, bases, **kwds)
else: else:
ns = _DefaultClassNamespaceType() ns = {}
return meta, ns, kwds return meta, ns, kwds
def _calculate_meta(meta, bases): def _calculate_meta(meta, bases):

View File

@ -1301,7 +1301,6 @@ class _ProtocolMeta(GenericMeta):
if (not attr.startswith('_abc_') and if (not attr.startswith('_abc_') and
attr != '__abstractmethods__' and attr != '__abstractmethods__' and
attr != '_is_protocol' and attr != '_is_protocol' and
attr != '__definition_order__' and
attr != '__dict__' and attr != '__dict__' and
attr != '__args__' and attr != '__args__' and
attr != '__slots__' and attr != '__slots__' and

View File

@ -1765,21 +1765,6 @@ PyODict_DelItem(PyObject *od, PyObject *key)
return _PyDict_DelItem_KnownHash(od, key, hash); return _PyDict_DelItem_KnownHash(od, key, hash);
} }
PyObject *
_PyODict_KeysAsTuple(PyObject *od) {
Py_ssize_t i = 0;
_ODictNode *node;
PyObject *keys = PyTuple_New(PyODict_Size(od));
if (keys == NULL)
return NULL;
_odict_FOREACH((PyODictObject *)od, node) {
Py_INCREF(_odictnode_KEY(node));
PyTuple_SET_ITEM(keys, i, _odictnode_KEY(node));
i++;
}
return keys;
}
/* ------------------------------------------- /* -------------------------------------------
* The OrderedDict views (keys/values/items) * The OrderedDict views (keys/values/items)

View File

@ -48,7 +48,6 @@ static size_t method_cache_collisions = 0;
_Py_IDENTIFIER(__abstractmethods__); _Py_IDENTIFIER(__abstractmethods__);
_Py_IDENTIFIER(__class__); _Py_IDENTIFIER(__class__);
_Py_IDENTIFIER(__delitem__); _Py_IDENTIFIER(__delitem__);
_Py_IDENTIFIER(__definition_order__);
_Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(__dict__);
_Py_IDENTIFIER(__doc__); _Py_IDENTIFIER(__doc__);
_Py_IDENTIFIER(__getattribute__); _Py_IDENTIFIER(__getattribute__);
@ -489,23 +488,6 @@ type_set_module(PyTypeObject *type, PyObject *value, void *context)
return _PyDict_SetItemId(type->tp_dict, &PyId___module__, value); return _PyDict_SetItemId(type->tp_dict, &PyId___module__, value);
} }
static PyObject *
type_deforder(PyTypeObject *type, void *context)
{
if (type->tp_deforder == NULL)
Py_RETURN_NONE;
Py_INCREF(type->tp_deforder);
return type->tp_deforder;
}
static int
type_set_deforder(PyTypeObject *type, PyObject *value, void *context)
{
Py_XINCREF(value);
Py_XSETREF(type->tp_deforder, value);
return 0;
}
static PyObject * static PyObject *
type_abstractmethods(PyTypeObject *type, void *context) type_abstractmethods(PyTypeObject *type, void *context)
{ {
@ -852,8 +834,6 @@ static PyGetSetDef type_getsets[] = {
{"__qualname__", (getter)type_qualname, (setter)type_set_qualname, NULL}, {"__qualname__", (getter)type_qualname, (setter)type_set_qualname, NULL},
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
{"__module__", (getter)type_module, (setter)type_set_module, NULL}, {"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__definition_order__", (getter)type_deforder,
(setter)type_set_deforder, NULL},
{"__abstractmethods__", (getter)type_abstractmethods, {"__abstractmethods__", (getter)type_abstractmethods,
(setter)type_set_abstractmethods, NULL}, (setter)type_set_abstractmethods, NULL},
{"__dict__", (getter)type_dict, NULL, NULL}, {"__dict__", (getter)type_dict, NULL, NULL},
@ -2371,7 +2351,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
goto error; goto error;
} }
/* Copy the definition namespace into a new dict. */
dict = PyDict_Copy(orig_dict); dict = PyDict_Copy(orig_dict);
if (dict == NULL) if (dict == NULL)
goto error; goto error;
@ -2580,48 +2559,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
if (qualname != NULL && PyDict_DelItem(dict, PyId___qualname__.object) < 0) if (qualname != NULL && PyDict_DelItem(dict, PyId___qualname__.object) < 0)
goto error; goto error;
/* Set tp_deforder to the extracted definition order, if any. */
type->tp_deforder = _PyDict_GetItemId(dict, &PyId___definition_order__);
if (type->tp_deforder != NULL) {
Py_INCREF(type->tp_deforder);
// Due to subclass lookup, __definition_order__ can't be in __dict__.
if (_PyDict_DelItemId(dict, &PyId___definition_order__) != 0) {
goto error;
}
if (type->tp_deforder != Py_None) {
Py_ssize_t numnames;
if (!PyTuple_Check(type->tp_deforder)) {
PyErr_SetString(PyExc_TypeError,
"__definition_order__ must be a tuple or None");
goto error;
}
// Make sure they are identifers.
numnames = PyTuple_Size(type->tp_deforder);
for (i = 0; i < numnames; i++) {
PyObject *name = PyTuple_GET_ITEM(type->tp_deforder, i);
if (name == NULL) {
goto error;
}
if (!PyUnicode_Check(name) || !PyUnicode_IsIdentifier(name)) {
PyErr_Format(PyExc_TypeError,
"__definition_order__ must "
"contain only identifiers, got '%s'",
name);
goto error;
}
}
}
}
else if (PyODict_Check(orig_dict)) {
type->tp_deforder = _PyODict_KeysAsTuple(orig_dict);
if (type->tp_deforder == NULL)
goto error;
}
/* Set tp_doc to a copy of dict['__doc__'], if the latter is there /* Set tp_doc to a copy of dict['__doc__'], if the latter is there
and is a string. The __doc__ accessor will first look for tp_doc; and is a string. The __doc__ accessor will first look for tp_doc;
if that fails, it will still look into __dict__. if that fails, it will still look into __dict__.
@ -3136,7 +3073,6 @@ type_dealloc(PyTypeObject *type)
Py_XDECREF(type->tp_mro); Py_XDECREF(type->tp_mro);
Py_XDECREF(type->tp_cache); Py_XDECREF(type->tp_cache);
Py_XDECREF(type->tp_subclasses); Py_XDECREF(type->tp_subclasses);
Py_XDECREF(type->tp_deforder);
/* A type's tp_doc is heap allocated, unlike the tp_doc slots /* A type's tp_doc is heap allocated, unlike the tp_doc slots
* of most other objects. It's okay to cast it to char *. * of most other objects. It's okay to cast it to char *.
*/ */
@ -3179,7 +3115,7 @@ type_subclasses(PyTypeObject *type, PyObject *args_ignored)
static PyObject * static PyObject *
type_prepare(PyObject *self, PyObject *args, PyObject *kwds) type_prepare(PyObject *self, PyObject *args, PyObject *kwds)
{ {
return PyODict_New(); return PyDict_New();
} }
/* /*

View File

@ -147,7 +147,7 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
if (prep == NULL) { if (prep == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear(); PyErr_Clear();
ns = PyODict_New(); ns = PyDict_New();
} }
else { else {
Py_DECREF(meta); Py_DECREF(meta);