summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-08-29 02:02:51 -0700
committerRaymond Hettinger <rhettinger@users.noreply.github.com>2019-08-29 02:02:51 -0700
commitc71ae1a45bd6e6d0f5aebc470b35f5a7dc0d8078 (patch)
tree1e89af5c38142e19f260f1490423baa9ecf1f32e
parent0d45d50e421b46b56195821580c3760b43813106 (diff)
downloadcpython-git-c71ae1a45bd6e6d0f5aebc470b35f5a7dc0d8078.tar.gz
bpo-36743: __get__ is sometimes called without the owner argument (GH-12992) (GH-15589)
(cherry picked from commit 0dac68f1e593c11612ed54af9edb865d398f3b05) Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
-rw-r--r--Doc/reference/datamodel.rst25
-rw-r--r--Lib/_pyio.py2
-rw-r--r--Lib/functools.py6
-rw-r--r--Lib/unittest/mock.py2
-rwxr-xr-xTools/demo/eiffel.py2
5 files changed, 24 insertions, 13 deletions
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index d1702ccb64..8813f57587 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -1618,21 +1618,32 @@ 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). *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*.
+ 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)
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:`descriptor-invocation` for
+ more details.
.. method:: object.__delete__(self, instance)
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 650109295f..eb4e6620fc 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -281,7 +281,7 @@ except AttributeError:
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 64d120182b..a674a685df 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -400,7 +400,7 @@ class partialmethod(object):
_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:
@@ -905,7 +905,7 @@ class singledispatchmethod:
"""
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)
@@ -943,7 +943,7 @@ class cached_property:
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 7ab6812591..4c76f53f38 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -2806,7 +2806,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 736abea817..a76c2324dd 100755
--- a/Tools/demo/eiffel.py
+++ b/Tools/demo/eiffel.py
@@ -78,7 +78,7 @@ class EiffelDescriptor:
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):