classification
Title: inspect.getargspec() returns wrong answer with property.__delete__()
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: larry, ncoghlan, python-dev, yselivanov, zzzeek
Priority: release blocker Keywords:

Created on 2014-02-26 22:10 by zzzeek, last changed 2014-03-17 06:31 by python-dev. This issue is now closed.

Messages (8)
msg212313 - (view) Author: mike bayer (zzzeek) * Date: 2014-02-26 22:10
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)
msg212314 - (view) Author: mike bayer (zzzeek) * Date: 2014-02-26 22:14
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.
msg212315 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-02-26 22:27
Larry, I think the problem is that

    >>> property.__delete__.__text_signature__
    '(instance, /)'

but should be something like '($self, instance, /)'.

What do you think?
msg212453 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-02-28 16:02
Larry, Nick, what do you think?
I'd like this to be fixed in 3.4.0...
msg212557 - (view) Author: mike bayer (zzzeek) * Date: 2014-03-02 15:11
see also http://bugs.python.org/issue20828 as it seems like there might be a bigger pattern here (not sure).
msg212564 - (view) Author: Roundup Robot (python-dev) Date: 2014-03-02 17:25
New changeset c9861ec8754c by Yury Selivanov in branch 'default':
Issue #20786: Fix signatures for dict.__delitem__ and property.__delete__
http://hg.python.org/cpython/rev/c9861ec8754c
msg212566 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-03-02 17:31
Mike, this is now fixed. I've created an issue for tracking of getting this fix in 3.4.0: #20829.

Thanks for finding this bug!
msg213828 - (view) Author: Roundup Robot (python-dev) Date: 2014-03-17 06:31
New changeset 7ad0e19cc682 by Yury Selivanov in branch '3.4':
Issue #20786: Fix signatures for dict.__delitem__ and property.__delete__
http://hg.python.org/cpython/rev/7ad0e19cc682
History
Date User Action Args
2014-03-17 06:31:07python-devsetmessages: + msg213828
2014-03-02 17:31:27yselivanovsetmessages: + msg212566
2014-03-02 17:26:57yselivanovsetstatus: open -> closed
resolution: fixed
2014-03-02 17:25:37python-devsetnosy: + python-dev
messages: + msg212564
2014-03-02 15:11:14zzzeeksetmessages: + msg212557
2014-02-28 16:02:03yselivanovsetmessages: + msg212453
2014-02-26 22:28:08yselivanovsetpriority: normal -> release blocker
2014-02-26 22:27:13yselivanovsetmessages: + msg212315
2014-02-26 22:20:48yselivanovsetnosy: + ncoghlan, larry, yselivanov
2014-02-26 22:14:32zzzeeksetmessages: + msg212314
2014-02-26 22:12:10zzzeeksettype: behavior
components: + Library (Lib)
2014-02-26 22:10:15zzzeekcreate