8000 bpo-36743: __get__ is sometimes called without the owner argument (#1… · python/cpython@0dac68f · GitHub
[go: up one dir, main page]

Skip to content

Commit 0dac68f

Browse files
authored
bpo-36743: __get__ is sometimes called without the owner argument (#12992)
1 parent 84125fe commit 0dac68f

File tree

5 files changed

+24
-13
lines changed

5 files changed

+24
-13
lines changed

Doc/reference/datamodel.rst

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,21 +1618,32 @@ refers to the attribute whose name is the key of the property in the owner
16181618
class' :attr:`~object.__dict__`.
16191619

16201620

1621-
.. method:: object.__get__(self, instance, owner)
1621+
.. method:: object.__get__(self, instance, owner=None)
16221622

1623-
Called to get the attribute of the owner class (class attribute access) or of an
1624-
instance of that class (instance attribute access). *owner* is always the owner
1625-
class, while *instance* is the instance that the attribute was accessed through,
1626-
or ``None`` when the attribute is accessed through the *owner*. This method
1627-
should return the (computed) attribute value or raise an :exc:`AttributeError`
1628-
exception.
1623+
Called to get the attribute of the owner class (class attribute access) or
1624+
of an instance of that class (instance attribute access). The optional
1625+
*owner* argument is the owner class, while *instance* is the instance that
1626+
the attribute was accessed through, or ``None`` when the attribute is
1627+
accessed through the *owner*.
16291628

1629+
This method should return the computed attribute value or raise an
1630+
:exc:`AttributeError` exception.
1631+
1632+
:PEP:`252` specifies that :meth:`__get__` is callable with one or two
1633+
arguments. Python's own built-in descriptors support this specification;
1634+
however, it is likely that some third-party tools have descriptors
1635+
that require both arguments. Python's own :meth:`__getattribute__`
1636+
implementation always passes in both arguments whether they are required
1637+
or not.
16301638

16311639
.. method:: object.__set__(self, instance, value)
16321640

16331641
Called to set the attribute on an instance *instance* of the owner class to a
16341642
new value, *value*.
16351643

1644+
Note, adding :meth:`__set__` or :meth:`__delete__` changes the kind of
1645+
descriptor to a "data descriptor". See :ref:`descriptor-invocation` for
1646+
more details.
16361647

16371648
.. method:: object.__delete__(self, instance)
16381649

Lib/_pyio.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def _open_code_with_warning(path):
283283
class DocDescriptor:
284284
"""Helper for builtins.open.__doc__
285285
"""
286-
def __get__(self, obj, typ):
286+
def __get__(self, obj, typ=None):
287287
return (
288288
"open(file, mode='r', buffering=-1, encoding=None, "
289289
"errors=None, newline=None, closefd=True)\n\n" +

Lib/functools.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ def _method(cls_or_self, /, *args, **keywords):
383383
_method._partialmethod = self
384384
return _method
385385

386-
def __get__(self, obj, cls):
386+
def __get__(self, obj, cls=None):
387387
get = getattr(self.func, "__get__", None)
388388
result = None
389389
if get is not None:
@@ -888,7 +888,7 @@ def register(self, cls, method=None):
888888
"""
889889
return self.dispatcher.register(cls, func=method)
890890

891< EDBE code class="diff-text syntax-highlighted-line deletion">-
def __get__(self, obj, cls):
891+
def __get__(self, obj, cls=None):
892892
def _method(*args, **kwargs):
893893
method = self.dispatcher.dispatch(args[0].__class__)
894894
return method.__get__(obj, cls)(*args, **kwargs)
@@ -926,7 +926,7 @@ def __set_name__(self, owner, name):
926926
f"({self.attrname!r} and {name!r})."
927927
)
928928

929-
def __get__(self, instance, owner):
929+
def __get__(self, instance, owner=None):
930930
if instance is None:
931931
return self
932932
if self.attrname is None:

Lib/unittest/mock.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2804,7 +2804,7 @@ class PropertyMock(Mock):
28042804
def _get_child_mock(self, /, **kwargs):
28052805
return MagicMock(**kwargs)
28062806

2807-
def __get__(self, obj, obj_type):
2807+
def __get__(self, obj, obj_type=None):
28082808
return self()
28092809
def __set__(self, obj, val):
28102810
self(val)

Tools/demo/eiffel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def __init__(self, func, pre, post):
7878
self.__name__ = func.__name__
7979
self.__doc__ = func.__doc__
8080

81-
def __get__(self, obj, cls):
81+
def __get__(self, obj, cls=None):
8282
return EiffelMethodWrapper(obj, self)
8383

8484
def callmethod(self, inst, args, kwargs):

0 commit comments

Comments
 (0)
0