diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index 06c4068f86bfe..c638b9e4ea117 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -148,6 +148,7 @@ def decorator(accessor): UserWarning, stacklevel=2) setattr(cls, name, CachedAccessor(name, accessor)) + cls._accessors.add(name) return accessor return decorator diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 41d67c15c55b5..b67ed9cfd2241 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -326,6 +326,7 @@ def _constructor(self): _constructor_sliced = Series _deprecations = NDFrame._deprecations | frozenset( ['sortlevel', 'get_value', 'set_value', 'from_csv', 'from_items']) + _accessors = set() @property def _constructor_expanddim(self): diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 12bb09e8f8a8a..27668f925ce23 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -242,7 +242,8 @@ class Index(IndexOpsMixin, PandasObject): _engine_type = libindex.ObjectEngine - _accessors = frozenset(['str']) + _accessors = set(['str']) + str = CachedAccessor("str", StringMethods) def __new__(cls, data=None, dtype=None, copy=False, name=None, diff --git a/pandas/core/series.py b/pandas/core/series.py index 2ed4c99b7a998..13e94f971d003 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -153,7 +153,7 @@ class Series(base.IndexOpsMixin, generic.NDFrame): Copy input data """ _metadata = ['name'] - _accessors = frozenset(['dt', 'cat', 'str']) + _accessors = set(['dt', 'cat', 'str']) _deprecations = generic.NDFrame._deprecations | frozenset( ['asobject', 'sortlevel', 'reshape', 'get_value', 'set_value', 'from_csv', 'valid']) diff --git a/pandas/tests/test_register_accessor.py b/pandas/tests/test_register_accessor.py index fe0cf4c9b38af..33b9798b7606a 100644 --- a/pandas/tests/test_register_accessor.py +++ b/pandas/tests/test_register_accessor.py @@ -17,6 +17,7 @@ def ensure_removed(obj, attr): delattr(obj, attr) except AttributeError: pass + obj._accessors.discard(attr) class MyAccessor(object): @@ -38,13 +39,14 @@ def method(self): (pd.DataFrame, pd.api.extensions.register_dataframe_accessor), (pd.Index, pd.api.extensions.register_index_accessor) ]) -def test_series_register(obj, registrar): +def test_register(obj, registrar): with ensure_removed(obj, 'mine'): before = set(dir(obj)) registrar('mine')(MyAccessor) assert obj([]).mine.prop == 'item' after = set(dir(obj)) assert (before ^ after) == {'mine'} + assert 'mine' in obj._accessors def test_accessor_works(): diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 3863451757709..aed3eb2f1226d 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -182,7 +182,8 @@ def doc_parameters(self): @property def signature_parameters(self): if (inspect.isclass(self.method_obj) - and self.method_name.split('.')[-1] in {'dt', 'str', 'cat'}): + and self.method_name.split('.')[-1] in + self.method_obj._accessors): # accessor classes have a signature, but don't want to show this return tuple() try: