From c7f6560b4aebb3431e4f203d302a6a5231c7d364 Mon Sep 17 00:00:00 2001 From: jreback Date: Sun, 29 Sep 2013 21:57:51 -0400 Subject: [PATCH] API: provide __dir__ method (and local context) for tab completion / remove ipython completers code (GH4501) --- doc/source/release.rst | 2 ++ pandas/core/base.py | 10 ++++++++++ pandas/core/frame.py | 19 ------------------- pandas/core/generic.py | 13 +++++++++---- pandas/core/groupby.py | 27 --------------------------- pandas/core/panel.py | 18 ------------------ 6 files changed, 21 insertions(+), 68 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 801158a00b9ab..23b8252cd57e5 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -274,6 +274,8 @@ API Changes support ``pow`` or ``mod`` with non-scalars. (:issue:`3765`) - Provide numpy compatibility with 1.7 for a calling convention like ``np.prod(pandas_object)`` as numpy call with additional keyword args (:issue:`4435`) + - Provide __dir__ method (and local context) for tab completion / remove ipython completers code + (:issue:`4501`) Internal Refactoring diff --git a/pandas/core/base.py b/pandas/core/base.py index 14070d8825393..f390592a6f6c4 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -48,6 +48,16 @@ def __repr__(self): """ return str(self) + def _local_dir(self): + """ provide addtional __dir__ for this object """ + return [] + + def __dir__(self): + """ + Provide method name lookup and completion + Only provide 'public' methods + """ + return list(sorted(list(set(dir(type(self)) + self._local_dir())))) class PandasObject(StringMixin): """baseclass for various pandas objects""" diff --git a/pandas/core/frame.py b/pandas/core/frame.py index dbd67aa3c5c25..05514372de6fc 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4674,25 +4674,6 @@ def _put_str(s, space): return ('%s' % s)[:space].ljust(space) -def install_ipython_completers(): # pragma: no cover - """Register the DataFrame type with IPython's tab completion machinery, so - that it knows about accessing column names as attributes.""" - from IPython.utils.generics import complete_object - - @complete_object.when_type(DataFrame) - def complete_dataframe(obj, prev_completions): - return prev_completions + [c for c in obj.columns - if isinstance(c, compat.string_types) and compat.isidentifier(c)] - - -# Importing IPython brings in about 200 modules, so we want to avoid it unless -# we're in IPython (when those modules are loaded anyway). -if "IPython" in sys.modules: # pragma: no cover - try: - install_ipython_completers() - except Exception: - pass - #---------------------------------------------------------------------- # Add plotting methods to DataFrame diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 18a03eb313dd2..7d304209168b1 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -16,7 +16,7 @@ import pandas.core.common as com import pandas.core.datetools as datetools from pandas import compat, _np_version_under1p7 -from pandas.compat import map, zip, lrange +from pandas.compat import map, zip, lrange, string_types, isidentifier from pandas.core.common import (isnull, notnull, is_list_like, _values_from_object, _infer_dtype_from_scalar, _maybe_promote, @@ -109,6 +109,11 @@ def __unicode__(self): prepr = '[%s]' % ','.join(map(com.pprint_thing, self)) return '%s(%s)' % (self.__class__.__name__, prepr) + def _local_dir(self): + """ add the string-like attributes from the info_axis """ + return [c for c in self._info_axis + if isinstance(c, string_types) and isidentifier(c) ] + @property def _constructor_sliced(self): raise NotImplementedError @@ -252,7 +257,7 @@ def _get_axis_number(self, axis): def _get_axis_name(self, axis): axis = self._AXIS_ALIASES.get(axis, axis) - if isinstance(axis, compat.string_types): + if isinstance(axis, string_types): if axis in self._AXIS_NUMBERS: return axis else: @@ -1311,7 +1316,7 @@ def filter(self, items=None, like=None, regex=None, axis=None): if items is not None: return self.reindex(**{axis_name: [r for r in items if r in axis_values]}) elif like: - matchf = lambda x: (like in x if isinstance(x, compat.string_types) + matchf = lambda x: (like in x if isinstance(x, string_types) else like in str(x)) return self.select(matchf, axis=axis_name) elif regex: @@ -2601,7 +2606,7 @@ def tshift(self, periods=1, freq=None, axis=0, **kwds): offset = _resolve_offset(freq, kwds) - if isinstance(offset, compat.string_types): + if isinstance(offset, string_types): offset = datetools.to_offset(offset) block_axis = self._get_block_manager_axis(axis) diff --git a/pandas/core/groupby.py b/pandas/core/groupby.py index 2e07662bffbfe..e70c01ffcb12f 100644 --- a/pandas/core/groupby.py +++ b/pandas/core/groupby.py @@ -2704,30 +2704,3 @@ def numpy_groupby(data, labels, axis=0): group_sums = np.add.reduceat(ordered_data, groups_at, axis=axis) return group_sums - -#----------------------------------------------------------------------- -# Helper functions - - -from pandas import compat -import sys - - -def install_ipython_completers(): # pragma: no cover - """Register the DataFrame type with IPython's tab completion machinery, so - that it knows about accessing column names as attributes.""" - from IPython.utils.generics import complete_object - - @complete_object.when_type(DataFrameGroupBy) - def complete_dataframe(obj, prev_completions): - return prev_completions + [c for c in obj.obj.columns - if isinstance(c, compat.string_types) and compat.isidentifier(c)] - - -# Importing IPython brings in about 200 modules, so we want to avoid it unless -# we're in IPython (when those modules are loaded anyway). -if "IPython" in sys.modules: # pragma: no cover - try: - install_ipython_completers() - except Exception: - pass diff --git a/pandas/core/panel.py b/pandas/core/panel.py index f0bad6b796e7c..b6054c1a96781 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -1230,21 +1230,3 @@ def f(self, other, axis=0): LongPanel = DataFrame -def install_ipython_completers(): # pragma: no cover - """Register the Panel type with IPython's tab completion machinery, so - that it knows about accessing column names as attributes.""" - from IPython.utils.generics import complete_object - - @complete_object.when_type(Panel) - def complete_dataframe(obj, prev_completions): - return prev_completions + [c for c in obj.keys() - if isinstance(c, compat.string_types) - and compat.isidentifier(c)] - -# Importing IPython brings in about 200 modules, so we want to avoid it unless -# we're in IPython (when those modules are loaded anyway). -if "IPython" in sys.modules: # pragma: no cover - try: - install_ipython_completers() - except Exception: - pass