From cd4c1cf5cfc966d394a8b084acd43a00ea24cda3 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sun, 28 Apr 2019 01:09:08 -0700 Subject: [PATCH 1/5] bpo-36743: __get__ is sometimes called without the owner argument --- Doc/reference/datamodel.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index d1702ccb641767..41effa4cac5e22 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1620,12 +1620,13 @@ class' :attr:`~object.__dict__`. .. method:: object.__get__(self, instance, owner) - Called to get the attribute of the owner class (class attribute access) or of an - instance of that class (instance attribute access). *owner* is always the owner - class, while *instance* is the instance that the attribute was accessed through, - or ``None`` when the attribute is accessed through the *owner*. This method - should return the (computed) attribute value or raise an :exc:`AttributeError` - exception. + Called to get the attribute of the owner class (class attribute access) or + of an instance of that class (instance attribute access). The optional + *owner* argument is the owner class, while *instance* is the instance that + the attribute was accessed through, or ``None`` when the attribute is + accessed through the *owner*. Note that callers are allowed to omit the + *owner* argument when it isn't needed. This method should return the + (computed) attribute value or raise an :exc:`AttributeError` exception. .. method:: object.__set__(self, instance, value) From 755f766a99514299be35e9a9b549ed764c4bacbd Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 28 Aug 2019 22:45:22 -0700 Subject: [PATCH 2/5] Clarify caller and callee responsibilities in practice --- Doc/reference/datamodel.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 41effa4cac5e22..2661a3948a1f0f 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1618,16 +1618,23 @@ refers to the attribute whose name is the key of the property in the owner class' :attr:`~object.__dict__`. -.. method:: object.__get__(self, instance, owner) +.. method:: object.__get__(self, instance, owner=None) Called to get the attribute of the owner class (class attribute access) or of an instance of that class (instance attribute access). The optional *owner* argument is the owner class, while *instance* is the instance that the attribute was accessed through, or ``None`` when the attribute is - accessed through the *owner*. Note that callers are allowed to omit the - *owner* argument when it isn't needed. This method should return the - (computed) attribute value or raise an :exc:`AttributeError` exception. + accessed through the *owner*. + This method should return the computed attribute value or raise an + :exc:`AttributeError` exception. + + :PEP:`252` specifies that :meth:`__get__` is callable with one or two + arguments. Python's own built-in descriptors support this specification; + however, it is likely that some third-party tools have descriptors + that require both arguments. Python's own :meth:`__getattribute__` + implementation always passes in both arguments whether they are required + or not. .. method:: object.__set__(self, instance, value) From 325e6c4ed17a26277f6f9762780f0b3cc16096c3 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 28 Aug 2019 22:54:35 -0700 Subject: [PATCH 3/5] Fix standard library descriptors that unnecessarily required a cls argument to __get__ --- Lib/_pyio.py | 2 +- Lib/functools.py | 6 +++--- Lib/unittest/mock.py | 2 +- Tools/demo/eiffel.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 40e0c9f9e2c66b..27447e0b6a15f1 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -283,7 +283,7 @@ def _open_code_with_warning(path): class DocDescriptor: """Helper for builtins.open.__doc__ """ - def __get__(self, obj, typ): + def __get__(self, obj, typ=None): return ( "open(file, mode='r', buffering=-1, encoding=None, " "errors=None, newline=None, closefd=True)\n\n" + diff --git a/Lib/functools.py b/Lib/functools.py index 9495fbe56eba39..f87d9c571873ad 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -383,7 +383,7 @@ def _method(cls_or_self, /, *args, **keywords): _method._partialmethod = self return _method - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): get = getattr(self.func, "__get__", None) result = None if get is not None: @@ -888,7 +888,7 @@ def register(self, cls, method=None): """ return self.dispatcher.register(cls, func=method) - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): def _method(*args, **kwargs): method = self.dispatcher.dispatch(args[0].__class__) return method.__get__(obj, cls)(*args, **kwargs) @@ -926,7 +926,7 @@ def __set_name__(self, owner, name): f"({self.attrname!r} and {name!r})." ) - def __get__(self, instance, owner): + def __get__(self, instance, owner=None): if instance is None: return self if self.attrname is None: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 298b41e0d7e4dd..e56e4414d5d351 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2770,7 +2770,7 @@ class PropertyMock(Mock): def _get_child_mock(self, /, **kwargs): return MagicMock(**kwargs) - def __get__(self, obj, obj_type): + def __get__(self, obj, obj_type=None): return self() def __set__(self, obj, val): self(val) diff --git a/Tools/demo/eiffel.py b/Tools/demo/eiffel.py index 736abea81738c8..a76c2324dd6a67 100755 --- a/Tools/demo/eiffel.py +++ b/Tools/demo/eiffel.py @@ -78,7 +78,7 @@ def __init__(self, func, pre, post): self.__name__ = func.__name__ self.__doc__ = func.__doc__ - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): return EiffelMethodWrapper(obj, self) def callmethod(self, inst, args, kwargs): From 5434a7670327c0553d88bc892ec0694dc7f4d581 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 28 Aug 2019 23:23:28 -0700 Subject: [PATCH 4/5] bpo-12077: Cross-reference __set__ to the data descriptor docs --- Doc/reference/datamodel.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 2661a3948a1f0f..d92ac61965ffdd 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1641,6 +1641,9 @@ class' :attr:`~object.__dict__`. Called to set the attribute on an instance *instance* of the owner class to a new value, *value*. + Note, adding :meth:`__set__` or :meth:`__delete__` changes the kind of + descriptor to a "data descriptor". See :ref:`invoking descriptors` for + more details. .. method:: object.__delete__(self, instance) From f31255879b48ce949b10b3e50944bba065c8f5f8 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 29 Aug 2019 00:06:20 -0700 Subject: [PATCH 5/5] Fix reference link --- Doc/reference/datamodel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index d92ac61965ffdd..8813f57587f01a 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1642,7 +1642,7 @@ class' :attr:`~object.__dict__`. new value, *value*. Note, adding :meth:`__set__` or :meth:`__delete__` changes the kind of - descriptor to a "data descriptor". See :ref:`invoking descriptors` for + descriptor to a "data descriptor". See :ref:`descriptor-invocation` for more details. .. method:: object.__delete__(self, instance) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy