Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
92a6c170
Commit
92a6c170
authored
Sep 05, 2016
by
Eric Snow
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #24254: Preserve class attribute definition order.
parent
45659861
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
568 additions
and
189 deletions
+568
-189
Doc/library/inspect.rst
Doc/library/inspect.rst
+188
-179
Doc/library/types.rst
Doc/library/types.rst
+12
-0
Doc/reference/compound_stmts.rst
Doc/reference/compound_stmts.rst
+11
-0
Doc/reference/datamodel.rst
Doc/reference/datamodel.rst
+8
-1
Doc/whatsnew/3.6.rst
Doc/whatsnew/3.6.rst
+26
-0
Include/object.h
Include/object.h
+2
-0
Include/odictobject.h
Include/odictobject.h
+4
-0
Lib/test/test_builtin.py
Lib/test/test_builtin.py
+191
-1
Lib/test/test_metaclass.py
Lib/test/test_metaclass.py
+8
-3
Lib/test/test_pydoc.py
Lib/test/test_pydoc.py
+7
-1
Lib/test/test_sys.py
Lib/test/test_sys.py
+1
-1
Lib/test/test_types.py
Lib/test/test_types.py
+22
-0
Lib/types.py
Lib/types.py
+4
-1
Lib/typing.py
Lib/typing.py
+1
-0
Misc/NEWS
Misc/NEWS
+2
-0
Objects/odictobject.c
Objects/odictobject.c
+15
-0
Objects/typeobject.c
Objects/typeobject.c
+65
-1
Python/bltinmodule.c
Python/bltinmodule.c
+1
-1
No files found.
Doc/library/inspect.rst
View file @
92a6c170
...
@@ -34,185 +34,190 @@ provided as convenient choices for the second argument to :func:`getmembers`.
...
@@ -34,185 +34,190 @@ 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 |
| | | attributes, in the order |
| | | in which they were |
| | | defined (if known) |
+-----------+----------------------+---------------------------+
| method | __doc__ | documentation string |
| method | __doc__ | documentation string |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __name__ | name with which this |
| | __name__ | name with which this |
| | | method was defined |
| | | method was defined |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __qualname__ | qualified name |
| | __qualname__ | qualified name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __func__ | function object |
| | __func__ | function object |
| | | containing implementation |
| | | containing implementation |
| | | of method |
| | | of method |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __self__ | instance to which this |
| | __self__ | instance to which this |
| | | method is bound, or |
| | | method is bound, or |
| | | ``None`` |
| | | ``None`` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| function | __doc__ | documentation string |
| function | __doc__ | documentation string |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __name__ | name with which this |
| | __name__ | name with which this |
| | | function was defined |
| | | function was defined |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __qualname__ | qualified name |
| | __qualname__ | qualified name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __code__ | code object containing |
| | __code__ | code object containing |
| | | compiled function |
| | | compiled function |
| | | :term:`bytecode` |
| | | :term:`bytecode` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __defaults__ | tuple of any default |
| | __defaults__ | tuple of any default |
| | | values for positional or |
| | | values for positional or |
| | | keyword parameters |
| | | keyword parameters |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __kwdefaults__ | mapping of any default |
| | __kwdefaults__ | mapping of any default |
| | | values for keyword-only |
| | | values for keyword-only |
| | | parameters |
| | | parameters |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __globals__ | global namespace in which |
| | __globals__ | global namespace in which |
| | | this function was defined |
| | | this function was defined |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __annotations__ | mapping of parameters |
| | __annotations__ | mapping of parameters |
| | | names to annotations; |
| | | names to annotations; |
| | | ``"return"`` key is |
| | | ``"return"`` key is |
| | | reserved for return |
| | | reserved for return |
| | | annotations. |
| | | annotations. |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| traceback | tb_frame | frame object at this |
| traceback | tb_frame | frame object at this |
| | | level |
| | | level |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | tb_lasti | index of last attempted |
| | tb_lasti | index of last attempted |
| | | instruction in bytecode |
| | | instruction in bytecode |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | tb_lineno | current line number in |
| | tb_lineno | current line number in |
| | | Python source code |
| | | Python source code |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | tb_next | next inner traceback |
| | tb_next | next inner traceback |
| | | object (called by this |
| | | object (called by this |
| | | level) |
| | | level) |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| frame | f_back | next outer frame object |
| frame | f_back | next outer frame object |
| | | (this frame's caller) |
| | | (this frame's caller) |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_builtins | builtins namespace seen |
| | f_builtins | builtins namespace seen |
| | | by this frame |
| | | by this frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_code | code object being |
| | f_code | code object being |
| | | executed in this frame |
| | | executed in this frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_globals | global namespace seen by |
| | f_globals | global namespace seen by |
| | | this frame |
| | | this frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_lasti | index of last attempted |
| | f_lasti | index of last attempted |
| | | instruction in bytecode |
| | | instruction in bytecode |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_lineno | current line number in |
| | f_lineno | current line number in |
| | | Python source code |
| | | Python source code |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_locals | local namespace seen by |
| | f_locals | local namespace seen by |
| | | this frame |
| | | this frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_restricted | 0 or 1 if frame is in |
| | f_restricted | 0 or 1 if frame is in |
| | | restricted execution mode |
| | | restricted execution mode |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | f_trace | tracing function for this |
| | f_trace | tracing function for this |
| | | frame, or ``None`` |
| | | frame, or ``None`` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| code | co_argcount | number of arguments (not |
| code | co_argcount | number of arguments (not |
| | | including \* or \*\* |
| | | including \* or \*\* |
| | | args) |
| | | args) |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_code | string of raw compiled |
| | co_code | string of raw compiled |
| | | bytecode |
| | | bytecode |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_consts | tuple of constants used |
| | co_consts | tuple of constants used |
| | | in the bytecode |
| | | in the bytecode |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_filename | name of file in which |
| | co_filename | name of file in which |
| | | this code object was |
| | | this code object was |
| | | created |
| | | created |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_firstlineno | number of first line in |
| | co_firstlineno | number of first line in |
| | | Python source code |
| | | Python source code |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_flags | bitmap: 1=optimized ``|`` |
| | co_flags | bitmap: 1=optimized ``|`` |
| | | 2=newlocals ``|`` 4=\*arg |
| | | 2=newlocals ``|`` 4=\*arg |
| | | ``|`` 8=\*\*arg |
| | | ``|`` 8=\*\*arg |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_lnotab | encoded mapping of line |
| | co_lnotab | encoded mapping of line |
| | | numbers to bytecode |
| | | numbers to bytecode |
| | | indices |
| | | indices |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_name | name with which this code |
| | co_name | name with which this code |
| | | object was defined |
| | | object was defined |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_names | tuple of names of local |
| | co_names | tuple of names of local |
| | | variables |
| | | variables |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_nlocals | number of local variables |
| | co_nlocals | number of local variables |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_stacksize | virtual machine stack |
| | co_stacksize | virtual machine stack |
| | | space required |
| | | space required |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | co_varnames | tuple of names of |
| | co_varnames | tuple of names of |
| | | arguments and local |
| | | arguments and local |
| | | variables |
| | | variables |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| generator | __name__ | name |
| generator | __name__ | name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __qualname__ | qualified name |
| | __qualname__ | qualified name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | gi_frame | frame |
| | gi_frame | frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | gi_running | is the generator running? |
| | gi_running | is the generator running? |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | gi_code | code |
| | gi_code | code |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | gi_yieldfrom | object being iterated by |
| | gi_yieldfrom | object being iterated by |
| | | ``yield from``, or |
| | | ``yield from``, or |
| | | ``None`` |
| | | ``None`` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| coroutine | __name__ | name |
| coroutine | __name__ | name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __qualname__ | qualified name |
| | __qualname__ | qualified name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | cr_await | object being awaited on, |
| | cr_await | object being awaited on, |
| | | or ``None`` |
| | | or ``None`` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | cr_frame | frame |
| | cr_frame | frame |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | cr_running | is the coroutine running? |
| | cr_running | is the coroutine running? |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | cr_code | code |
| | cr_code | code |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| builtin | __doc__ | documentation string |
| builtin | __doc__ | documentation string |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __name__ | original name of this |
| | __name__ | original name of this |
| | | function or method |
| | | function or method |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __qualname__ | qualified name |
| | __qualname__ | qualified name |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
| | __self__ | instance to which a |
| | __self__ | instance to which a |
| | | method is bound, or |
| | | method is bound, or |
| | | ``None`` |
| | | ``None`` |
+-----------+-----------------+---------------------------+
+-----------+-----------------
-----
+---------------------------+
.. versionchanged:: 3.5
.. versionchanged:: 3.5
...
@@ -221,6 +226,10 @@ attributes:
...
@@ -221,6 +226,10 @@ 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])
...
...
Doc/library/types.rst
View file @
92a6c170
...
@@ -53,8 +53,20 @@ Dynamic Type Creation
...
@@ -53,8 +53,20 @@ 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
The default value for the ``namespace`` element of the returned
tuple has changed from :func:`dict`. Now an insertion-order-
preserving mapping is used when the metaclass does not have a
``__prepare__`` method,
.. seealso::
.. seealso::
:ref:`metaclasses`
:ref:`metaclasses`
...
...
Doc/reference/compound_stmts.rst
View file @
92a6c170
...
@@ -632,6 +632,17 @@ list for the base classes and the saved local namespace for the attribute
...
@@ -632,6 +632,17 @@ list for the base classes and the saved local namespace for the attribute
dictionary. The class name is bound to this class object in the original local
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
in the ``__definition_order__`` attribute on the new class. If that order
is not known then the attribute is set to :const:`None`. The class body
may include a ``__definition_order__`` attribute. In that case it is used
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>`.
Classes can also be decorated: just like when decorating functions, ::
Classes can also be decorated: just like when decorating functions, ::
...
...
Doc/reference/datamodel.rst
View file @
92a6c170
...
@@ -1750,7 +1750,14 @@ as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the
...
@@ -1750,7 +1750,14 @@ as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the
additional keyword arguments, if any, come from the class definition).
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 :func:`dict` instance.
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::
...
...
Doc/whatsnew/3.6.rst
View file @
92a6c170
...
@@ -92,6 +92,7 @@ Windows improvements:
...
@@ -92,6 +92,7 @@ Windows improvements:
:pep:`4XX` - Python Virtual Environments
:pep:`4XX` - Python Virtual Environments
PEP written by Carl Meyer
PEP written by Carl Meyer
.. XXX PEP 520: :ref:`Preserving Class Attribute Definition Order<whatsnew-deforder>`
New Features
New Features
============
============
...
@@ -271,6 +272,31 @@ Example of fatal error on buffer overflow using
...
@@ -271,6 +272,31 @@ Example of fatal error on buffer overflow using
(Contributed by Victor Stinner in :issue:`26516` and :issue:`26564`.)
(Contributed by Victor Stinner in :issue:`26516` and :issue:`26564`.)
.. _whatsnew-deforder:
PEP 520: Preserving Class Attribute Definition Order
----------------------------------------------------
Attributes in a class definition body have a natural ordering: the same
order in which the names appear in the source. This order is now
preserved in the new class's ``__definition_order__`` attribute. It is
a tuple of the attribute names, in the order in which they appear in
the class definition body.
For types that don't have a definition (e.g. builtins), or the attribute
order could not be determined, ``__definition_order__`` is ``None``.
Also, the effective default class *execution* namespace (returned from
``type.__prepare__()``) is now an insertion-order-preserving mapping.
For CPython, it is now ``collections.OrderedDict``. Note that the
class namespace, ``cls.__dict__``, is unchanged.
.. seealso::
:pep:`520` - Preserving Class Attribute Definition Order
PEP written and implemented by Eric Snow.
Other Language Changes
Other Language Changes
======================
======================
...
...
Include/object.h
View file @
92a6c170
...
@@ -421,6 +421,8 @@ typedef struct _typeobject {
...
@@ -421,6 +421,8 @@ 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
;
...
...
Include/odictobject.h
View file @
92a6c170
...
@@ -28,6 +28,10 @@ PyAPI_FUNC(PyObject *) PyODict_New(void);
...
@@ -28,6 +28,10 @@ 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) \
...
...
Lib/test/test_builtin.py
View file @
92a6c170
...
@@ -16,8 +16,10 @@ import traceback
...
@@ -16,8 +16,10 @@ 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
...
@@ -1778,6 +1780,194 @@ class TestType(unittest.TestCase):
...
@@ -1778,6 +1780,194 @@ 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
()
...
...
Lib/test/test_metaclass.py
View file @
92a6c170
...
@@ -180,7 +180,7 @@ Use a metaclass that doesn't derive from type.
...
@@ -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
dict
>>> type(C) is
types._DefaultClassNamespaceType
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,8 +211,11 @@ And again, with a __prepare__ attribute.
...
@@ -211,8 +211,11 @@ And again, with a __prepare__ attribute.
The default metaclass must define a __prepare__() method.
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.
Make sure it works with subclassing.
...
@@ -248,7 +251,9 @@ Test failures in looking up the __prepare__ method work.
...
@@ -248,7 +251,9 @@ 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
():
...
...
Lib/test/test_pydoc.py
View file @
92a6c170
...
@@ -427,6 +427,7 @@ class PydocDocTest(unittest.TestCase):
...
@@ -427,6 +427,7 @@ 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
,
...
@@ -473,13 +474,18 @@ class PydocDocTest(unittest.TestCase):
...
@@ -473,13 +474,18 @@ 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
.
assertEqual
(
adoc
.
replace
(
"A"
,
"B"
),
bdoc
)
self
.
maxDiff
=
None
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"
...
...
Lib/test/test_sys.py
View file @
92a6c170
...
@@ -1084,7 +1084,7 @@ class SizeofTest(unittest.TestCase):
...
@@ -1084,7 +1084,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
=
'P2n15Pl4Pn9Pn11PIP'
fmt
=
'P2n15Pl4Pn9Pn11PIP
P
'
if
hasattr
(
sys
,
'getcounts'
):
if
hasattr
(
sys
,
'getcounts'
):
fmt
+=
'3n2P'
fmt
+=
'3n2P'
s
=
vsize
(
fmt
)
s
=
vsize
(
fmt
)
...
...
Lib/test/test_types.py
View file @
92a6c170
...
@@ -825,6 +825,28 @@ class ClassCreationTests(unittest.TestCase):
...
@@ -825,6 +825,28 @@ 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
...
...
Lib/types.py
View file @
92a6c170
...
@@ -25,8 +25,11 @@ CoroutineType = type(_c)
...
@@ -25,8 +25,11 @@ 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
...
@@ -85,7 +88,7 @@ def prepare_class(name, bases=(), kwds=None):
...
@@ -85,7 +88,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
=
{}
ns
=
_DefaultClassNamespaceType
()
return
meta
,
ns
,
kwds
return
meta
,
ns
,
kwds
def
_calculate_meta
(
meta
,
bases
):
def
_calculate_meta
(
meta
,
bases
):
...
...
Lib/typing.py
View file @
92a6c170
...
@@ -1301,6 +1301,7 @@ class _ProtocolMeta(GenericMeta):
...
@@ -1301,6 +1301,7 @@ 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
...
...
Misc/NEWS
View file @
92a6c170
...
@@ -49,6 +49,8 @@ Core and Builtins
...
@@ -49,6 +49,8 @@ Core and Builtins
potentially have caused off-by-one-ulp results on platforms with
potentially have caused off-by-one-ulp results on platforms with
unreliable ldexp implementations.
unreliable ldexp implementations.
- Issue #24254: Make class definition namespace ordered by default.
- Issue #27662: Fix an overflow check in ``List_New``: the original code was
- Issue #27662: Fix an overflow check in ``List_New``: the original code was
checking against ``Py_SIZE_MAX`` instead of the correct upper bound of
checking against ``Py_SIZE_MAX`` instead of the correct upper bound of
``Py_SSIZE_T_MAX``. Patch by Xiang Zhang.
``Py_SSIZE_T_MAX``. Patch by Xiang Zhang.
...
...
Objects/odictobject.c
View file @
92a6c170
...
@@ -1762,6 +1762,21 @@ PyODict_DelItem(PyObject *od, PyObject *key)
...
@@ -1762,6 +1762,21 @@ 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)
...
...
Objects/typeobject.c
View file @
92a6c170
...
@@ -48,6 +48,7 @@ static size_t method_cache_collisions = 0;
...
@@ -48,6 +48,7 @@ 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__
);
...
@@ -488,6 +489,23 @@ type_set_module(PyTypeObject *type, PyObject *value, void *context)
...
@@ -488,6 +489,23 @@ 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
)
{
{
...
@@ -834,6 +852,8 @@ static PyGetSetDef type_getsets[] = {
...
@@ -834,6 +852,8 @@ 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
},
...
@@ -2351,6 +2371,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
...
@@ -2351,6 +2371,7 @@ 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
;
...
@@ -2559,6 +2580,48 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
...
@@ -2559,6 +2580,48 @@ 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__.
...
@@ -3073,6 +3136,7 @@ type_dealloc(PyTypeObject *type)
...
@@ -3073,6 +3136,7 @@ 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 *.
*/
*/
...
@@ -3115,7 +3179,7 @@ type_subclasses(PyTypeObject *type, PyObject *args_ignored)
...
@@ -3115,7 +3179,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
PyDict_New
();
return
Py
O
Dict_New
();
}
}
/*
/*
...
...
Python/bltinmodule.c
View file @
92a6c170
...
@@ -145,7 +145,7 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
...
@@ -145,7 +145,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
=
PyDict_New
();
ns
=
Py
O
Dict_New
();
}
}
else
{
else
{
Py_DECREF
(
meta
);
Py_DECREF
(
meta
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment