Skip to content

Commit

Permalink
Unify Index._dir_* with Series implementation (pandas-dev#17117)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Aug 29, 2017
1 parent 9a1dfca commit e8a1765
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 55 deletions.
35 changes: 35 additions & 0 deletions pandas/core/accessor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""
accessor.py contains base classes for implementing accessor properties
that can be mixed into or pinned onto other pandas classes.
"""


class DirNamesMixin(object):
_accessors = frozenset([])

def _dir_deletions(self):
""" delete unwanted __dir__ for this object """
return self._accessors

def _dir_additions(self):
""" add addtional __dir__ for this object """
rv = set()
for accessor in self._accessors:
try:
getattr(self, accessor)
rv.add(accessor)
except AttributeError:
pass
return rv

def __dir__(self):
"""
Provide method name lookup and completion
Only provide 'public' methods
"""
rv = set(dir(type(self)))
rv = (rv - self._dir_deletions()) | self._dir_additions()
return sorted(rv)
22 changes: 3 additions & 19 deletions pandas/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from pandas.util._decorators import (Appender, cache_readonly,
deprecate_kwarg, Substitution)
from pandas.core.common import AbstractMethodError
from pandas.core.accessor import DirNamesMixin

_shared_docs = dict()
_indexops_doc_kwargs = dict(klass='IndexOpsMixin', inplace='',
Expand Down Expand Up @@ -73,7 +74,7 @@ def __repr__(self):
return str(self)


class PandasObject(StringMixin):
class PandasObject(StringMixin, DirNamesMixin):

"""baseclass for various pandas objects"""

Expand All @@ -92,23 +93,6 @@ def __unicode__(self):
# Should be overwritten by base classes
return object.__repr__(self)

def _dir_additions(self):
""" add addtional __dir__ for this object """
return set()

def _dir_deletions(self):
""" delete unwanted __dir__ for this object """
return set()

def __dir__(self):
"""
Provide method name lookup and completion
Only provide 'public' methods
"""
rv = set(dir(type(self)))
rv = (rv - self._dir_deletions()) | self._dir_additions()
return sorted(rv)

def _reset_cache(self, key=None):
"""
Reset cached properties. If ``key`` is passed, only clears that key.
Expand Down Expand Up @@ -141,7 +125,7 @@ class NoNewAttributesMixin(object):
Prevents additional attributes via xxx.attribute = "something" after a
call to `self.__freeze()`. Mainly used to prevent the user from using
wrong attrirbutes on a accessor (`Series.cat/.str/.dt`).
wrong attributes on a accessor (`Series.cat/.str/.dt`).
If you really want to add a new attribute at a later time, you need to use
`object.__setattr__(self, key, value)`.
Expand Down
5 changes: 3 additions & 2 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ def __unicode__(self):

def _dir_additions(self):
""" add the string-like attributes from the info_axis """
return set([c for c in self._info_axis
if isinstance(c, string_types) and isidentifier(c)])
additions = set([c for c in self._info_axis
if isinstance(c, string_types) and isidentifier(c)])
return super(NDFrame, self)._dir_additions().union(additions)

@property
def _constructor_sliced(self):
Expand Down
9 changes: 7 additions & 2 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
import pandas.core.sorting as sorting
from pandas.io.formats.printing import pprint_thing
from pandas.core.ops import _comp_method_OBJECT_ARRAY
from pandas.core.strings import StringAccessorMixin
from pandas.core import strings
from pandas.core.config import get_option


Expand Down Expand Up @@ -102,7 +102,7 @@ def _new_Index(cls, d):
return cls.__new__(cls, **d)


class Index(IndexOpsMixin, StringAccessorMixin, PandasObject):
class Index(IndexOpsMixin, PandasObject):
"""
Immutable ndarray implementing an ordered, sliceable set. The basic object
storing axis labels for all pandas objects
Expand Down Expand Up @@ -155,6 +155,11 @@ class Index(IndexOpsMixin, StringAccessorMixin, PandasObject):

_engine_type = libindex.ObjectEngine

_accessors = frozenset(['str'])

# String Methods
str = base.AccessorProperty(strings.StringMethods)

def __new__(cls, data=None, dtype=None, copy=False, name=None,
fastpath=False, tupleize_cols=True, **kwargs):

Expand Down
17 changes: 3 additions & 14 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ def wrapper(self):
# Series class


class Series(base.IndexOpsMixin, strings.StringAccessorMixin,
generic.NDFrame,):
class Series(base.IndexOpsMixin, generic.NDFrame):
"""
One-dimensional ndarray with axis labels (including time series).
Expand Down Expand Up @@ -2923,18 +2922,8 @@ def to_period(self, freq=None, copy=True):
# Categorical methods
cat = base.AccessorProperty(CategoricalAccessor)

def _dir_deletions(self):
return self._accessors

def _dir_additions(self):
rv = set()
for accessor in self._accessors:
try:
getattr(self, accessor)
rv.add(accessor)
except AttributeError:
pass
return rv
# String Methods
str = base.AccessorProperty(strings.StringMethods)

# ----------------------------------------------------------------------
# Add plotting methods to Series
Expand Down
20 changes: 2 additions & 18 deletions pandas/core/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from pandas.core.algorithms import take_1d
import pandas.compat as compat
from pandas.core.base import AccessorProperty, NoNewAttributesMixin
from pandas.core.base import NoNewAttributesMixin
from pandas.util._decorators import Appender
import re
import pandas._libs.lib as lib
Expand Down Expand Up @@ -1920,20 +1920,4 @@ def _make_accessor(cls, data):
message = ("Can only use .str accessor with Index, not "
"MultiIndex")
raise AttributeError(message)
return StringMethods(data)


class StringAccessorMixin(object):
""" Mixin to add a `.str` acessor to the class."""

str = AccessorProperty(StringMethods)

def _dir_additions(self):
return set()

def _dir_deletions(self):
try:
getattr(self, 'str')
except AttributeError:
return set(['str'])
return set()
return cls(data)

0 comments on commit e8a1765

Please sign in to comment.