Skip to content

groupby isinstance(f, types.MethodType) in py3 #17608

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

Closed
jbrockmendel opened this issue Sep 21, 2017 · 1 comment
Closed

groupby isinstance(f, types.MethodType) in py3 #17608

jbrockmendel opened this issue Sep 21, 2017 · 1 comment

Comments

@jbrockmendel
Copy link
Member

in core.groupby._whitelist_method_generator (https://github.com/pandas-dev/pandas/blob/master/pandas/core/groupby.py#L2801)

    method_wrapper_template = \
        """def %(name)s(%(sig)s) :
    \"""
    %(doc)s
    \"""
    f = %(self)s.__getattr__('%(name)s')
    return f(%(args)s)"""
    property_wrapper_template = \
        """@property
def %(name)s(self) :
    \"""
    %(doc)s
    \"""
    return self.__getattr__('%(name)s')"""
    for name in whitelist:
        # don't override anything that was explicitly defined
        # in the base class
        if hasattr(GroupBy, name):
            continue
        # ugly, but we need the name string itself in the method.
        f = getattr(klass, name)
        doc = f.__doc__
        doc = doc if type(doc) == str else ''
        if isinstance(f, types.MethodType):
            wrapper_template = method_wrapper_template
            decl, args = make_signature(f)
            # pass args by name to f because otherwise
            # GroupBy._make_wrapper won't know whether
            # we passed in an axis parameter.
            args_by_name = ['{0}={0}'.format(arg) for arg in args[1:]]
            params = {'name': name,
                      'doc': doc,
                      'sig': ','.join(decl),
                      'self': args[0],
                      'args': ','.join(args_by_name)}
        else:
            wrapper_template = property_wrapper_template
            params = {'name': name, 'doc': doc}
        yield wrapper_template % params

It looks like isinstance(f, types.MethodType) is never evaluating True in py3, so these are all coming out as properties.

PY2:

In [1]: import pandas as pd
In [2]: gb = pd.Series(range(10)).groupby(lambda x: x % 2)
In [3]: gb.mad
Out[3]: <bound method SeriesGroupBy.mad of <pandas.core.groupby.SeriesGroupBy object at 0x10f394f10>>
In [4]: gb.mad.__doc__
Out[4]: '\n    \n\nReturn the mean absolute deviation of the values for the requested axis\n\nParameters\n----------\naxis : {index (0)}\nskipna : boolean, default True\n    Exclude NA/null values. If an entire row/column is NA, the result\n    will be NA\nlevel : int or level name, default None\n    If the axis is a MultiIndex (hierarchical), count along a\n    particular level, collapsing into a scalar\nnumeric_only : boolean, default None\n    Include only float, int, boolean columns. If None, will attempt to use\n    everything, then use only numeric data. Not implemented for Series.\n\nReturns\n-------\nmad : scalar or Series (if level specified)\n\n    '

PY3:

In [1]: import pandas as pd
In [2]: gb = pd.Series(range(10)).groupby(lambda x: x % 2)
In [3]: gb.mad
Out[3]: <function pandas.core.groupby._GroupBy._make_wrapper.<locals>.wrapper>
In [4]: gb.mad.__doc__
In [5]:

If we change the condition from isinstance(f, types.MethodType) to not isinstance(f, property), a TypeError is raised (py3 only):

  File "[...]/pandas/core/groupby.py", line 2796, in _whitelist_method_generator
    decl, args = make_signature(f)
  File "[...]/pandas/util/_decorators.py", line 245, in make_signature
    defaults = ('',) * n_wo_defaults + spec.defaults
TypeError: can only concatenate tuple (not "list") to tuple

#17600 should make this problem irrelevant eventually, but someone might want to look at it more short-term.

@jbrockmendel
Copy link
Member Author

Closed by #17609

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

No branches or pull requests

2 participants