cpython: 9e5bc3d38de8 (original) (raw)

--- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1700,6 +1700,10 @@ class defining the method. Metaclasses ^^^^^^^^^^^ +.. index::

+ By default, classes are constructed using :func:type. The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace). @@ -1730,6 +1734,8 @@ When a class definition is executed, the Determining the appropriate metaclass ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. index::

The appropriate metaclass for a class definition is determined as follows: @@ -1751,6 +1757,9 @@ that criterion, then the class definitio Preparing the class namespace ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. index::

+ Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a __prepare__ attribute, it is called as namespace = metaclass.__prepare__(name, bases, **kwds) (where the @@ -1768,6 +1777,9 @@ is initialised as an empty ordered mappi Executing the class body ^^^^^^^^^^^^^^^^^^^^^^^^ +.. index::

+ The class body is executed (approximately) as exec(body, globals(), namespace). The key difference from a normal call to :func:exec is that lexical scoping allows the class body (including @@ -1777,12 +1789,19 @@ class definition occurs inside a functio However, even when the class definition occurs inside the function, methods defined inside the class still cannot see names defined at the class scope. Class variables must be accessed through the first parameter of instance or -class methods, and cannot be accessed at all from static methods. - +class methods, or through the implicit lexically scoped __class__ reference +described in the next section. + +.. _class-object-creation: Creating the class object ^^^^^^^^^^^^^^^^^^^^^^^^^ +.. index::

+ + Once the class namespace has been populated by executing the class body, the class object is created by calling metaclass(name, bases, namespace, **kwds) (the additional keywords @@ -1796,6 +1815,26 @@ created by the compiler if any methods i lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method. +.. impl-detail:: +

+When using the default metaclass :class:type, or any metaclass that ultimately +calls type.__new__, the following additional customisation steps are +invoked after creating the class object: + +* first, type.__new__ collects all of the descriptors in the class

--- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -351,6 +351,11 @@ whenever a new subclass is created:: class Plugin2(PluginBase): pass +In order to allow zero-argument :func:super calls to work correctly from +:meth:~object.__init_subclass__ implementations, custom metaclasses must +ensure that the new __classcell__ namespace entry is propagated to +type.__new__ (as described in :ref:class-object-creation). + .. seealso:: :pep:487 -- Simpler customization of class creation @@ -2235,6 +2240,11 @@ Changes in the Python API on a ZipFile created with mode 'r' will raise a :exc:ValueError. Previously, a :exc:RuntimeError was raised in those scenarios. +* when custom metaclasses are combined with zero-argument :func:super or

--- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -239,6 +239,7 @@ def _write_atomic(path, data, mode=0o666

Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL)

Python 3.6b1 3377 (set class cell from type.new #23722)

Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257)

+# Python 3.6rc1 3379 (more thorough class validation #23722) #

MAGIC must change whenever the bytecode emitted by the compiler may no

longer be understood by older implementations of the eval loop (usually

@@ -247,7 +248,7 @@ def _write_atomic(path, data, mode=0o666

Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array

in PC/launcher.c must also be updated.

-MAGIC_NUMBER = (3378).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3379).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = 'pycache'

--- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -1,7 +1,9 @@ -"""Unit tests for new super() implementation.""" +"""Unit tests for zero-argument super() & related machinery.""" import sys import unittest +import warnings +from test.support import check_warnings class A: @@ -144,6 +146,8 @@ class TestSuper(unittest.TestCase): self.assertIs(X.f(), X) def test___class___new(self):

class Meta(type): @@ -161,6 +165,7 @@ class TestSuper(unittest.TestCase): self.assertIs(test_class, A) def test___class___delayed(self):

class Meta(type): @@ -169,10 +174,14 @@ class TestSuper(unittest.TestCase): test_namespace = namespace return None

self.assertIs(A, None) @@ -180,6 +189,7 @@ class TestSuper(unittest.TestCase): self.assertIs(B.f(), B) def test___class___mro(self):

class Meta(type): @@ -195,34 +205,105 @@ class TestSuper(unittest.TestCase): self.assertIs(test_class, A)

+

+

+

+

+

+

+

-

def test_obscure_super_errors(self): def f():

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ What's New in Python 3.7.0 alpha 1 Core and Builtins ----------------- +- Issue #23722: Rather than silently producing a class that doesn't support

--- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2687,9 +2687,16 @@ type_new(PyTypeObject *metatype, PyObjec else type->tp_free = PyObject_Del;

--- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -54,8 +54,8 @@ const char *Py_FileSystemDefaultEncodeEr static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) {

--- a/Python/compile.c +++ b/Python/compile.c @@ -1967,8 +1967,9 @@ compiler_class(struct compiler *c, stmt_ compiler_exit_scope(c); return 0; }

@@ -1983,6 +1984,7 @@ compiler_class(struct compiler *c, stmt_ assert(i == 0); ADDOP_I(c, LOAD_CLOSURE, i);

@@ -1992,9 +1994,11 @@ compiler_class(struct compiler *c, stmt_ Py_DECREF(str); } else {

--- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -242,7 +242,7 @@ const unsigned char _Py_M__importlib_ext 101,95,97,116,111,109,105,99,106,0,0,0,115,26,0,0, 0,0,5,16,1,6,1,26,1,2,3,14,1,20,1,16, 1,14,1,2,1,14,1,14,1,6,1,114,58,0,0,0,

};