Issue 20786: inspect.getargspec() returns wrong answer with property.delete() (original) (raw)
The Python builtin property() historically does not allow inspect.getargspec to be called on any of get(), set(), or delete(). As of 3.4, it seems that this call now succeeds. However the answer it gives for delete() seems to be incorrect. Below illustrates that property.delete() accepts two arguments "self" and "instance" but inspect is giving a misleading answer:
import inspect
userland descriptor
class Descriptor(object): def get(self, instance, owner): if instance is None: return self def set(self, instance, value): pass def delete(self, instance): pass
class with property + userland descriptor
class X(object): @property def foo(self): pass @foo.deleter def foo(self): pass
bar = Descriptor()
property.delete and Descriptor.delete both accept two arguments:
property.delete(X.foo, X()) Descriptor.delete(X.bar, X())
on all versions, userland delete produces 'self', 'instance' for args
assert inspect.getargspec(Descriptor.delete) == (['self', 'instance'], None, None, None)
try: # but on python 3.4, it returns ['instance'] insp = inspect.getargspec(property.delete) assert insp == (['self', 'instance'], None, None, None), insp except TypeError as e: # on all other python versions, raises # <slot wrapper '__delete__' of 'property' objects> is not a Python function print("Exception: %s" % e)
for context, we are currently creating wrappers around these methods in SQLAlchemy, and in the case of property dunders, we expect that exception and catch it. So when the exception doesn't happen, we assume the answer is correct, but in this case it's not - the answer getargspec() gives us cannot be used to create a correct wrapper unless there's some other detail I'm missing. hence this is backwards incompatible.
Larry, I think the problem is that
>>> property.__delete__.__text_signature__
'(instance, /)'
but should be something like '($self, instance, /)'.
What do you think?