diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index 884201e28b80a4..fb33812633fad4 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -42,6 +42,10 @@ Bug Fixes - Bug in ``DataFrame.update()`` with ``overwrite=False`` and ``NaN values`` (:issue:`15593`) + +- Fixed a compatibility issue with IPython 6.0's tab completion showing deprecation warnings on Categoricals (:issue:`16409`) + + Conversion ^^^^^^^^^^ diff --git a/pandas/conftest.py b/pandas/conftest.py index 1149fae3fc0b0d..8a3ffe22242acb 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -45,3 +45,13 @@ def spmatrix(request): tm._skip_if_no_scipy() from scipy import sparse return getattr(sparse, request.param + '_matrix') + + +@pytest.fixture +def ip(): + """An instance of IPython.InteractiveShell. + Will raise a skip if IPython is not installed. + """ + pytest.importorskip('IPython', minversion="6.0.0") + from IPython.core.interactiveshell import InteractiveShell + return InteractiveShell() diff --git a/pandas/core/categorical.py b/pandas/core/categorical.py index 5b663f1d85ee76..f58eed74f760eb 100644 --- a/pandas/core/categorical.py +++ b/pandas/core/categorical.py @@ -342,6 +342,13 @@ def __init__(self, values, categories=None, ordered=False, fastpath=False): self._categories = categories self._codes = coerce_indexer_dtype(codes, categories) + def __dir__(self): + # Avoid IPython warnings for deprecated properties + # https://github.com/pandas-dev/pandas/issues/16409 + rv = set(dir(type(self))) + rv.discard("labels") + return sorted(rv) + @property def _constructor(self): return Categorical diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 631b91c3aad11e..2bb825541e23bf 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -184,6 +184,12 @@ def __getattr__(self, attr): matches_pattern = any(attr.startswith(x) for x in self._deprecated_valid_patterns) if not matches_pattern and attr not in self._deprecated_valids: + # avoid the warning, if it's just going to be an exception + # anyway. + if not hasattr(self.obj, attr): + raise AttributeError("'{}' has no attribute '{}'".format( + type(self.obj).__name__, attr + )) self = self._deprecated(attr) return object.__getattribute__(self, attr) diff --git a/pandas/tests/test_categorical.py b/pandas/tests/test_categorical.py index f48eea23220b82..1ffe956b3a6078 100644 --- a/pandas/tests/test_categorical.py +++ b/pandas/tests/test_categorical.py @@ -736,6 +736,17 @@ def test_unicode_print(self): assert _rep(c) == expected + def test_tab_complete_warning(self, ip): + # https://github.com/pandas-dev/pandas/issues/16409 + pytest.importorskip('IPython', minversion="6.0.0") + from IPython.core.completer import provisionalcompleter + + code = "import pandas as pd; c = pd.Categorical([])" + ip.run_code(code) + with tm.assert_produces_warning(None): + with provisionalcompleter('ignore'): + list(ip.Completer.completions('c.', 1)) + def test_periodindex(self): idx1 = PeriodIndex(['2014-01', '2014-01', '2014-02', '2014-02', '2014-03', '2014-03'], freq='M') diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py index 37e2fd0e9b188b..170cab4947a5a7 100644 --- a/pandas/tests/test_resample.py +++ b/pandas/tests/test_resample.py @@ -3,6 +3,7 @@ from warnings import catch_warnings from datetime import datetime, timedelta from functools import partial +from textwrap import dedent import pytz import pytest @@ -284,8 +285,7 @@ def test_attribute_access(self): tm.assert_series_equal(r.A.sum(), r['A'].sum()) # getting - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): - pytest.raises(AttributeError, lambda: r.F) + pytest.raises(AttributeError, lambda: r.F) # setting def f(): @@ -2816,6 +2816,19 @@ def test_back_compat_v180(self): expected = df.groupby('A').resample('4s').mean().ffill() assert_frame_equal(result, expected) + def test_tab_complete_ipython6_warning(self, ip): + from IPython.core.completer import provisionalcompleter + code = dedent("""\ + import pandas.util.testing as tm + s = tm.makeTimeSeries() + rs = s.resample("D") + """) + ip.run_code(code) + + with tm.assert_produces_warning(None): + with provisionalcompleter('ignore'): + list(ip.Completer.completions('rs.', 1)) + def test_deferred_with_groupby(self): # GH 12486