Skip to content

Commit

Permalink
closes bpo-36188: Clean up 'unbound' method left-overs. (GH-12169)
Browse files Browse the repository at this point in the history
Methods are always bound, and `__self__` can no longer be `NULL`
(`method_new()` and `PyMethod_New()` both explicitly check for this).

Moreover, once a bound method is bound, it *stays* bound and won't be re-bound
to something else, so the section in the datamodel that talks about accessing
an methods in a different descriptor-binding context doesn't apply any more in
Python 3.
  • Loading branch information
mjpieters authored and benjaminp committed Mar 5, 2019
1 parent 0983fcd commit b727239
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 24 deletions.
6 changes: 0 additions & 6 deletions Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -578,12 +578,6 @@ Callable types
to be bound. The new method's :attr:`__func__` attribute is the original
function object.

When a user-defined method object is created by retrieving another method
object from a class or instance, the behaviour is the same as for a
function object, except that the :attr:`__func__` attribute of the new
instance is not the original method object but its :attr:`__func__`
attribute.

When an instance method object is created by retrieving a class method
object from a class or instance, its :attr:`__self__` attribute is the
class itself, and its :attr:`__func__` attribute is the function object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cleaned up left-over vestiges of Python 2 unbound method handling in method objects and documentation.
Patch by Martijn Pieters
21 changes: 3 additions & 18 deletions Objects/classobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,7 @@ static Py_hash_t
method_hash(PyMethodObject *a)
{
Py_hash_t x, y;
if (a->im_self == NULL)
x = _Py_HashPointer(Py_None);
else
x = _Py_HashPointer(a->im_self);
x = _Py_HashPointer(a->im_self);
y = PyObject_Hash(a->im_func);
if (y == -1)
return -1;
Expand All @@ -294,11 +291,6 @@ method_call(PyObject *method, PyObject *args, PyObject *kwargs)
PyObject *self, *func;

self = PyMethod_GET_SELF(method);
if (self == NULL) {
PyErr_BadInternalCall();
return NULL;
}

func = PyMethod_GET_FUNCTION(method);

return _PyObject_Call_Prepend(func, self, args, kwargs);
Expand All @@ -307,15 +299,8 @@ method_call(PyObject *method, PyObject *args, PyObject *kwargs)
static PyObject *
method_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
{
/* Don't rebind an already bound method of a class that's not a base
class of cls. */
if (PyMethod_GET_SELF(meth) != NULL) {
/* Already bound */
Py_INCREF(meth);
return meth;
}
/* Bind it to obj */
return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj);
Py_INCREF(meth);
return meth;
}

PyTypeObject PyMethod_Type = {
Expand Down

0 comments on commit b727239

Please sign in to comment.