diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 0efdcd838b..90ae7feb15 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -15,6 +15,7 @@ from StringIO import StringIO import csv import operator +import sys import warnings from numpy import nan @@ -550,7 +551,6 @@ def to_string(self, buf=None, columns=None, colSpace=None, nanRep='NaN', formatters=None, float_format=None, sparsify=True): from pandas.core.common import _format, adjoin - import sys if buf is None: # pragma: no cover buf = sys.stdout @@ -629,7 +629,6 @@ def info(self, verbose=True, buf=None): If False, don't print column count summary buf : writable buffer, defaults to sys.stdout """ - import sys if buf is None: # pragma: no cover buf = sys.stdout @@ -3304,6 +3303,25 @@ def _homogenize(data, index, columns, dtype=None): def _put_str(s, space): return ('%s' % s)[:space].ljust(space) +def install_ipython_completers(): + """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 py3compat.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: + try: + install_ipython_completers() + except Exception: + pass + + if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], diff --git a/pandas/util/py3compat.py b/pandas/util/py3compat.py index e8bb212e21..afb48ef41c 100644 --- a/pandas/util/py3compat.py +++ b/pandas/util/py3compat.py @@ -1,3 +1,14 @@ import sys PY3 = (sys.version_info[0] >= 3) + +if PY3: + def isidentifier(s): + return s.isidentifier() + +else: + # Python 2 + import re + _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") + def isidentifier(s, dotted=False): + return bool(_name_re.match(s))