Skip to content

Commit c0f221c

Browse files
jbrockmendelalanbato
authored andcommitted
Unify Index._dir_* with Series implementation (pandas-dev#17117)
1 parent ab0a796 commit c0f221c

File tree

6 files changed

+53
-55
lines changed

6 files changed

+53
-55
lines changed

pandas/core/accessor.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
4+
accessor.py contains base classes for implementing accessor properties
5+
that can be mixed into or pinned onto other pandas classes.
6+
7+
"""
8+
9+
10+
class DirNamesMixin(object):
11+
_accessors = frozenset([])
12+
13+
def _dir_deletions(self):
14+
""" delete unwanted __dir__ for this object """
15+
return self._accessors
16+
17+
def _dir_additions(self):
18+
""" add addtional __dir__ for this object """
19+
rv = set()
20+
for accessor in self._accessors:
21+
try:
22+
getattr(self, accessor)
23+
rv.add(accessor)
24+
except AttributeError:
25+
pass
26+
return rv
27+
28+
def __dir__(self):
29+
"""
30+
Provide method name lookup and completion
31+
Only provide 'public' methods
32+
"""
33+
rv = set(dir(type(self)))
34+
rv = (rv - self._dir_deletions()) | self._dir_additions()
35+
return sorted(rv)

pandas/core/base.py

+3-19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pandas.util._decorators import (Appender, cache_readonly,
2020
deprecate_kwarg, Substitution)
2121
from pandas.core.common import AbstractMethodError
22+
from pandas.core.accessor import DirNamesMixin
2223

2324
_shared_docs = dict()
2425
_indexops_doc_kwargs = dict(klass='IndexOpsMixin', inplace='',
@@ -73,7 +74,7 @@ def __repr__(self):
7374
return str(self)
7475

7576

76-
class PandasObject(StringMixin):
77+
class PandasObject(StringMixin, DirNamesMixin):
7778

7879
"""baseclass for various pandas objects"""
7980

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

95-
def _dir_additions(self):
96-
""" add addtional __dir__ for this object """
97-
return set()
98-
99-
def _dir_deletions(self):
100-
""" delete unwanted __dir__ for this object """
101-
return set()
102-
103-
def __dir__(self):
104-
"""
105-
Provide method name lookup and completion
106-
Only provide 'public' methods
107-
"""
108-
rv = set(dir(type(self)))
109-
rv = (rv - self._dir_deletions()) | self._dir_additions()
110-
return sorted(rv)
111-
11296
def _reset_cache(self, key=None):
11397
"""
11498
Reset cached properties. If ``key`` is passed, only clears that key.
@@ -141,7 +125,7 @@ class NoNewAttributesMixin(object):
141125
142126
Prevents additional attributes via xxx.attribute = "something" after a
143127
call to `self.__freeze()`. Mainly used to prevent the user from using
144-
wrong attrirbutes on a accessor (`Series.cat/.str/.dt`).
128+
wrong attributes on a accessor (`Series.cat/.str/.dt`).
145129
146130
If you really want to add a new attribute at a later time, you need to use
147131
`object.__setattr__(self, key, value)`.

pandas/core/generic.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ def __unicode__(self):
192192

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

198199
@property
199200
def _constructor_sliced(self):

pandas/core/indexes/base.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
import pandas.core.sorting as sorting
5757
from pandas.io.formats.printing import pprint_thing
5858
from pandas.core.ops import _comp_method_OBJECT_ARRAY
59-
from pandas.core.strings import StringAccessorMixin
59+
from pandas.core import strings
6060
from pandas.core.config import get_option
6161

6262

@@ -102,7 +102,7 @@ def _new_Index(cls, d):
102102
return cls.__new__(cls, **d)
103103

104104

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

156156
_engine_type = libindex.ObjectEngine
157157

158+
_accessors = frozenset(['str'])
159+
160+
# String Methods
161+
str = base.AccessorProperty(strings.StringMethods)
162+
158163
def __new__(cls, data=None, dtype=None, copy=False, name=None,
159164
fastpath=False, tupleize_cols=True, **kwargs):
160165

pandas/core/series.py

+3-14
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ def wrapper(self):
114114
# Series class
115115

116116

117-
class Series(base.IndexOpsMixin, strings.StringAccessorMixin,
118-
generic.NDFrame,):
117+
class Series(base.IndexOpsMixin, generic.NDFrame):
119118
"""
120119
One-dimensional ndarray with axis labels (including time series).
121120
@@ -2925,18 +2924,8 @@ def to_period(self, freq=None, copy=True):
29252924
# Categorical methods
29262925
cat = base.AccessorProperty(CategoricalAccessor)
29272926

2928-
def _dir_deletions(self):
2929-
return self._accessors
2930-
2931-
def _dir_additions(self):
2932-
rv = set()
2933-
for accessor in self._accessors:
2934-
try:
2935-
getattr(self, accessor)
2936-
rv.add(accessor)
2937-
except AttributeError:
2938-
pass
2939-
return rv
2927+
# String Methods
2928+
str = base.AccessorProperty(strings.StringMethods)
29402929

29412930
# ----------------------------------------------------------------------
29422931
# Add plotting methods to Series

pandas/core/strings.py

+2-18
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from pandas.core.algorithms import take_1d
1818
import pandas.compat as compat
19-
from pandas.core.base import AccessorProperty, NoNewAttributesMixin
19+
from pandas.core.base import NoNewAttributesMixin
2020
from pandas.util._decorators import Appender
2121
import re
2222
import pandas._libs.lib as lib
@@ -1920,20 +1920,4 @@ def _make_accessor(cls, data):
19201920
message = ("Can only use .str accessor with Index, not "
19211921
"MultiIndex")
19221922
raise AttributeError(message)
1923-
return StringMethods(data)
1924-
1925-
1926-
class StringAccessorMixin(object):
1927-
""" Mixin to add a `.str` acessor to the class."""
1928-
1929-
str = AccessorProperty(StringMethods)
1930-
1931-
def _dir_additions(self):
1932-
return set()
1933-
1934-
def _dir_deletions(self):
1935-
try:
1936-
getattr(self, 'str')
1937-
except AttributeError:
1938-
return set(['str'])
1939-
return set()
1923+
return cls(data)

0 commit comments

Comments
 (0)