diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 2c142bdd7185b..d5af3e51d2f7c 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -733,6 +733,7 @@ Deprecations many ``Series``, ``Index`` or 1-dimensional ``np.ndarray``, or alternatively, only scalar values. (:issue:`21950`) - :meth:`FrozenNDArray.searchsorted` has deprecated the ``v`` parameter in favor of ``value`` (:issue:`14645`) - :func:`DatetimeIndex.shift` and :func:`PeriodIndex.shift` now accept ``periods`` argument instead of ``n`` for consistency with :func:`Index.shift` and :func:`Series.shift`. Using ``n`` throws a deprecation warning (:issue:`22458`, :issue:`22912`) +- The ``fastpath`` keyword of the different Index constructors is deprecated (:issue:`23110`). .. _whatsnew_0240.prior_deprecations: diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 55b4201f41b2a..e5760f0141efb 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -262,13 +262,17 @@ def _outer_indexer(self, left, right): str = CachedAccessor("str", StringMethods) def __new__(cls, data=None, dtype=None, copy=False, name=None, - fastpath=False, tupleize_cols=True, **kwargs): + fastpath=None, tupleize_cols=True, **kwargs): if name is None and hasattr(data, 'name'): name = data.name - if fastpath: - return cls._simple_new(data, name) + if fastpath is not None: + warnings.warn("The 'fastpath' keyword is deprecated, and will be " + "removed in a future version.", + FutureWarning, stacklevel=2) + if fastpath: + return cls._simple_new(data, name) from .range import RangeIndex diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 7eab123497282..e4250ae790553 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -1,4 +1,5 @@ import operator +import warnings import numpy as np from pandas._libs import index as libindex @@ -87,10 +88,14 @@ class CategoricalIndex(Index, accessor.PandasDelegate): _attributes = ['name'] def __new__(cls, data=None, categories=None, ordered=None, dtype=None, - copy=False, name=None, fastpath=False): - - if fastpath: - return cls._simple_new(data, name=name, dtype=dtype) + copy=False, name=None, fastpath=None): + + if fastpath is not None: + warnings.warn("The 'fastpath' keyword is deprecated, and will be " + "removed in a future version.", + FutureWarning, stacklevel=2) + if fastpath: + return cls._simple_new(data, name=name, dtype=dtype) if name is None and hasattr(data, 'name'): name = data.name diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index eabbb43d155f6..420b862ae16a4 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -1,3 +1,5 @@ +import warnings + import numpy as np from pandas._libs import index as libindex from pandas.core.dtypes.common import ( @@ -34,10 +36,14 @@ class NumericIndex(Index): _is_numeric_dtype = True def __new__(cls, data=None, dtype=None, copy=False, name=None, - fastpath=False): - - if fastpath: - return cls._simple_new(data, name=name) + fastpath=None): + + if fastpath is not None: + warnings.warn("The 'fastpath' keyword is deprecated, and will be " + "removed in a future version.", + FutureWarning, stacklevel=2) + if fastpath: + return cls._simple_new(data, name=name) # is_scalar, generators handled in coerce_to_ndarray data = cls._coerce_to_ndarray(data) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index f452a57e82725..cbcd39317e17e 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -268,7 +268,7 @@ def __contains__(self, key): @cache_readonly def _int64index(self): - return Int64Index(self.asi8, name=self.name, fastpath=True) + return Int64Index._simple_new(self.asi8, name=self.name) @property def values(self): diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index ef19e9c88b072..30a803c5636c4 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -1,6 +1,7 @@ import operator from datetime import timedelta from sys import getsizeof +import warnings import numpy as np @@ -62,10 +63,14 @@ class RangeIndex(Int64Index): _engine_type = libindex.Int64Engine def __new__(cls, start=None, stop=None, step=None, - dtype=None, copy=False, name=None, fastpath=False): + dtype=None, copy=False, name=None, fastpath=None): - if fastpath: - return cls._simple_new(start, stop, step, name=name) + if fastpath is not None: + warnings.warn("The 'fastpath' keyword is deprecated, and will be " + "removed in a future version.", + FutureWarning, stacklevel=2) + if fastpath: + return cls._simple_new(start, stop, step, name=name) cls._validate_dtype(dtype) @@ -168,7 +173,7 @@ def _data(self): @cache_readonly def _int64index(self): - return Int64Index(self._data, name=self.name, fastpath=True) + return Int64Index._simple_new(self._data, name=self.name) def _get_data_as_items(self): """ return a list of tuples of start, stop, step """ @@ -256,8 +261,8 @@ def tolist(self): @Appender(_index_shared_docs['_shallow_copy']) def _shallow_copy(self, values=None, **kwargs): if values is None: - return RangeIndex(name=self.name, fastpath=True, - **dict(self._get_data_as_items())) + return RangeIndex._simple_new( + name=self.name, **dict(self._get_data_as_items())) else: kwargs.setdefault('name', self.name) return self._int64index._shallow_copy(values, **kwargs) @@ -267,8 +272,8 @@ def copy(self, name=None, deep=False, dtype=None, **kwargs): self._validate_dtype(dtype) if name is None: name = self.name - return RangeIndex(name=name, fastpath=True, - **dict(self._get_data_as_items())) + return RangeIndex._simple_new( + name=name, **dict(self._get_data_as_items())) def _minmax(self, meth): no_steps = len(self) - 1 @@ -368,7 +373,7 @@ def intersection(self, other): tmp_start = first._start + (second._start - first._start) * \ first._step // gcd * s new_step = first._step * second._step // gcd - new_index = RangeIndex(tmp_start, int_high, new_step, fastpath=True) + new_index = RangeIndex._simple_new(tmp_start, int_high, new_step) # adjust index to limiting interval new_index._start = new_index._min_fitting_element(int_low) @@ -546,7 +551,7 @@ def __getitem__(self, key): stop = self._start + self._step * stop step = self._step * step - return RangeIndex(start, stop, step, name=self.name, fastpath=True) + return RangeIndex._simple_new(start, stop, step, name=self.name) # fall back to Int64Index return super_getitem(key) @@ -559,12 +564,12 @@ def __floordiv__(self, other): start = self._start // other step = self._step // other stop = start + len(self) * step - return RangeIndex(start, stop, step, name=self.name, - fastpath=True) + return RangeIndex._simple_new( + start, stop, step, name=self.name) if len(self) == 1: start = self._start // other - return RangeIndex(start, start + 1, 1, name=self.name, - fastpath=True) + return RangeIndex._simple_new( + start, start + 1, 1, name=self.name) return self._int64index // other @classmethod diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index a753e925b0ed8..2eaa43e049f62 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -2530,3 +2530,32 @@ def test_index_subclass_constructor_wrong_kwargs(index_maker): # GH #19348 with tm.assert_raises_regex(TypeError, 'unexpected keyword argument'): index_maker(foo='bar') + + +def test_deprecated_fastpath(): + + with tm.assert_produces_warning(FutureWarning): + idx = pd.Index( + np.array(['a', 'b'], dtype=object), name='test', fastpath=True) + + expected = pd.Index(['a', 'b'], name='test') + tm.assert_index_equal(idx, expected) + + with tm.assert_produces_warning(FutureWarning): + idx = pd.Int64Index( + np.array([1, 2, 3], dtype='int64'), name='test', fastpath=True) + + expected = pd.Index([1, 2, 3], name='test', dtype='int64') + tm.assert_index_equal(idx, expected) + + with tm.assert_produces_warning(FutureWarning): + idx = pd.RangeIndex(0, 5, 2, name='test', fastpath=True) + + expected = pd.RangeIndex(0, 5, 2, name='test') + tm.assert_index_equal(idx, expected) + + with tm.assert_produces_warning(FutureWarning): + idx = pd.CategoricalIndex(['a', 'b', 'c'], name='test', fastpath=True) + + expected = pd.CategoricalIndex(['a', 'b', 'c'], name='test') + tm.assert_index_equal(idx, expected)