From 82e9adba6f8a8eae91aa524b5a25d898eb95e5c1 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 17 Sep 2021 18:24:04 -0500 Subject: [PATCH 1/3] Correct error: __setname__ is not only for descriptors --- Doc/reference/datamodel.rst | 14 +++++++------- Objects/typeobject.c | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index fd78c7ef3c86fa..4725345862872f 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2133,15 +2133,15 @@ current call is identified based on the first argument passed to the method. Failing to do so will result in a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately -calls ``type.__new__``, the following additional customisation steps are +calls ``type.__new__``, the following additional customization steps are invoked after creating the class object: -* first, ``type.__new__`` collects all of the descriptors in the class - namespace that define a :meth:`~object.__set_name__` method; -* second, all of these ``__set_name__`` methods are called with the class - being defined and the assigned name of that particular descriptor; -* finally, the :meth:`~object.__init_subclass__` hook is called on the - immediate parent of the new class in its method resolution order. +1) The ``type.__new__`` method collects all of the attribute in the class + namespace that define a :meth:`~object.__set_name__` method; +2) All of these ``__set_name__`` methods are called with the class + being defined and the assigned name of that particular attribute; +3) The :meth:`~object.__init_subclass__` hook is called on the + immediate parent of the new class in its method resolution order. After the class object is created, it is passed to the class decorators included in the class definition (if any) and the resulting object is bound diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ec274a025de30c..a81d071e31d23b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -8458,7 +8458,8 @@ update_all_slots(PyTypeObject* type) } -/* Call __set_name__ on all descriptors in a newly generated type */ +/* Call __set_name__ on all attributes (including descriptors) + in a newly generated type */ static int type_new_set_names(PyTypeObject *type) { From b586645898e673058fac482034f8a0f6b4b106a4 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 17 Sep 2021 19:53:04 -0500 Subject: [PATCH 2/3] Move __set_name__ docs to correct section. Repair broken example. --- Doc/reference/datamodel.rst | 49 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 4725345862872f..7b422f0e5e42f6 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1774,28 +1774,6 @@ class' :attr:`~object.__dict__`. Called to delete the attribute on an instance *instance* of the owner class. -.. method:: object.__set_name__(self, owner, name) - - Called at the time the owning class *owner* is created. The - descriptor has been assigned to *name*. - - .. note:: - - :meth:`__set_name__` is only called implicitly as part of the - :class:`type` constructor, so it will need to be called explicitly with - the appropriate parameters when a descriptor is added to a class after - initial creation:: - - class A: - pass - descr = custom_descriptor() - A.attr = descr - descr.__set_name__(A, 'attr') - - See :ref:`class-object-creation` for more details. - - .. versionadded:: 3.6 - The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module as specifying the class where this object was defined (setting this appropriately can assist in runtime introspection of dynamic class attributes). @@ -1984,6 +1962,33 @@ class defining the method. .. versionadded:: 3.6 +When a class is created, :meth:`type.__new__` scans the class variables +and makes callbacks to those with a :meth:`__set_name__` hook. + +.. method:: object.__set_name__(self, owner, name) + + Automatically called at the time the owning class *owner* is + created. The object has been assigned to *name* in that class:: + + class A: + x = C() # Automatically calls: x.__set_name__(A, 'x') + + If the class variable is assigned after the class is created, + :meth:`__set_name__` will not be called automatically. + If needed, :meth:`__set_name__` can be called directly:: + + class A: + pass + + c = C() + A.x = c # The hook is not called + c.__set_name__(A, 'x') # Manually invoke the hook + + See :ref:`class-object-creation` for more details. + + .. versionadded:: 3.6 + + .. _metaclasses: Metaclasses From cec70b52080737fd550d5ad84723144bcf1184a3 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 17 Sep 2021 22:55:48 -0500 Subject: [PATCH 3/3] Grammar fixes --- Doc/reference/datamodel.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 7b422f0e5e42f6..181e445bb7bc6e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2141,9 +2141,9 @@ When using the default metaclass :class:`type`, or any metaclass that ultimately calls ``type.__new__``, the following additional customization steps are invoked after creating the class object: -1) The ``type.__new__`` method collects all of the attribute in the class +1) The ``type.__new__`` method collects all of the attributes in the class namespace that define a :meth:`~object.__set_name__` method; -2) All of these ``__set_name__`` methods are called with the class +2) Those ``__set_name__`` methods are called with the class being defined and the assigned name of that particular attribute; 3) The :meth:`~object.__init_subclass__` hook is called on the immediate parent of the new class in its method resolution order.