Open garyvdm opened 2 years ago
I bisected to here:
a918589578a2a807396c5f6afab7b59ab692c642 is the first bad commit commit a918589578a2a807396c5f6afab7b59ab692c642 Author: Michael J. Sullivan sully@msully.net Date: Wed May 4 21:00:21 2022 -0700
bpo-46764: Fix wrapping bound method with @classmethod (#31367)
cc @rhettinger
Having stumbled across this in a Django app where I was using Field.contribute_to_class
to add some extra functionality to models that I couldn't change directly, I experimented with a few different workarounds with very little success.
Eventually I decided the easiest solution was an explicit decorator, and this is what I'm using now (in the very specific cases where I need to ensure the old behavior is maintained:
class partialmethod_with_self(partialmethod):
def __get__(self, obj, cls=None):
return self._make_unbound_method().__get__(obj, cls)
This works in my case, and it should be backwards-compatible as well (I tested against 3.11 and 3.9.2).
Is this behavior change documented anywhere? Will it ever be fixed? Is it considered as a bug at all by the python devs?
I am also being hit by this problem in the context of django (and the contribute_to_class
pattern). This basically boils down to this snippet (works fine until 3.10, errors out in 3.11 and 3.12):
from functools import partialmethod
class A:
@classmethod
def f1(cls, self, value):
self.value = value
class B:
def __init__(self):
self.value = None
setattr(B, 'set_value_true', partialmethod(A.f1, True))
b = B()
b.set_value_true()
print(b.value)
Bug report
The behavior of
partialmethod
changed in python3.11. This caused a library that I use testsuite to fail.Here is a minimal use case that demonstrates this:
In python3.10, this prints
True
. In python3.11 it errors with:The arguments passed to
Wrapper.set_state_wrap
are: python3.10:wrapper, cell, True
python3.11:cell, True
So
partialmethod
is forgetting thatset_state_wrap
is a method ofwrapper
, and it needs to pass that in as the first arg.I know that the way that they are using
partialmethod
here is not how it is intended to be used, and feels wrong. However this change is behavior if intended should be documented.Your environment