Skip to content

Use isdatadescriptor instead of isgetsetdescriptor #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 30, 2018

Conversation

jorisvandenbossche
Copy link
Contributor

This is a small change I did to our vendored version in pandas. Opening directly an PR instead of an issue as it is easier to show with the code. The reason for this is is because we have some properties in pandas defined on a DataFrame et al that are properties defined in cython. For those isinstance(param_obj, property) does not work (as expected), and inspect.isgetsetdescriptor(param_obj)) also not, but apparently inspect.isdatadescriptor(param_obj)) does recognize them.

So although this is a useful change for pandas, I am not really sure about the possible implications. I don't really know the difference between "datadescriptor" and "getsetdescriptor", but from the docs it seems datadescriptor is a bit more general and also contains getsetdescriptor: https://docs.python.org/3.6/library/inspect.html#inspect.isdatadescriptor

(the safer option would actually be to add the check, instead of replacing)

@jnothman
Copy link
Member

Seems a reasonable change. Can it be tested easily without c extensions

@jorisvandenbossche
Copy link
Contributor Author

Yes, it does not need to be from cython. Quick test that illustrates it:

In [22]: class Property(object):
    ...: 
    ...:     def __init__(self, axis=0, doc=""):
    ...:         self.axis = axis
    ...:         self.__doc__ = doc
    ...: 
    ...:     def __get__(self, obj, type):
    ...: 
    ...:         if obj is None:
    ...:             # Only instances have _data, not classes
    ...:             return self
    ...:         else:
    ...:             axes = obj._data.axes
    ...:         return axes[self.axis]
    ...: 
    ...:     def __set__(self, obj, value):
    ...:         obj._set_axis(self.axis, value)
    ...:         

In [23]: class A():
    ...:     
    ...:     attr = Property(doc="test attribute")
    ...: 

In [24]: A.attr
Out[24]: <__main__.Property at 0x7f97100de0f0>

In [25]: isinstance(A.attr, property)
Out[25]: False

In [26]: import inspect

In [27]: inspect.isgetsetdescriptor(A.attr)
Out[27]: False

In [28]: inspect.isdatadescriptor(A.attr)
Out[28]: True

In [29]: A.attr.__doc__
Out[29]: 'test attribute'

@jorisvandenbossche
Copy link
Contributor Author

Is this the best way to test it?

On branch:

In [3]: from numpydoc.docscrape_sphinx import get_doc_object

In [5]: print(get_doc_object(A))

Test docstring




:Attributes:

    attr
        test attribute

(and then test the appropriate substring is in there)

while on master:

In [3]: from numpydoc.docscrape_sphinx import get_doc_object

In [4]: print(get_doc_object(A))

Test docstring






@rgommers rgommers mentioned this pull request Mar 30, 2018
# Only instances have actual _data, not classes
return self
else:
return obj._data.axes[self.axis]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test case.
The line above is from our original example in pandas, and actually does not matter (it's the if obj is None: return self that matters, so I can also remove this

@rgommers rgommers added this to the v0.8.0 milestone Mar 30, 2018
@rgommers
Copy link
Member

LGTM, merging. Thanks @jorisvandenbossche

@rgommers rgommers merged commit 9ce2e69 into numpy:master Mar 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants