From 38f7e4eed3ee911bd35dd9577d11bed666cd9aa6 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 27 Mar 2020 20:32:49 -0700 Subject: [PATCH 1/3] TYP: enforce tighter inputs on SingleBlockManager --- pandas/core/internals/managers.py | 22 +++++++--------------- pandas/core/reshape/concat.py | 2 +- pandas/tests/internals/test_internals.py | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index dda932cafe73b..577b864e619b5 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -1515,25 +1515,14 @@ class SingleBlockManager(BlockManager): def __init__( self, block: Block, - axis: Union[Index, List[Index]], + axis: Index, do_integrity_check: bool = False, fastpath: bool = False, ): assert isinstance(block, Block), type(block) + assert isinstance(axis, Index), type(axis) - if isinstance(axis, list): - if len(axis) != 1: - raise ValueError( - "cannot create SingleBlockManager with more than 1 axis" - ) - axis = axis[0] - - # passed from constructor, single block, single axis - if fastpath: - self.axes = [axis] - else: - self.axes = [ensure_index(axis)] - + self.axes = [axis] self.blocks = tuple([block]) @classmethod @@ -1633,7 +1622,9 @@ def fast_xs(self, loc): """ raise NotImplementedError("Use series._values[loc] instead") - def concat(self, to_concat, new_axis: Index) -> "SingleBlockManager": + def concat( + self, to_concat: List["SingleBlockManager"], new_axis: Index + ) -> "SingleBlockManager": """ Concatenate a list of SingleBlockManagers into a single SingleBlockManager. @@ -1649,6 +1640,7 @@ def concat(self, to_concat, new_axis: Index) -> "SingleBlockManager": ------- SingleBlockManager """ + assert isinstance(new_axis, Index), new_axis non_empties = [x for x in to_concat if len(x) > 0] # check if all series are of the same block type: diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index b4497ce1780e6..efb72d1b61d1f 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -458,7 +458,7 @@ def get_result(self): name = com.consensus_name_attr(self.objs) mgr = self.objs[0]._data.concat( - [x._data for x in self.objs], self.new_axes + [x._data for x in self.objs], self.new_axes[0] ) cons = self.objs[0]._constructor return cons(mgr, name=name).__finalize__(self, method="concat") diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index bbf968aef4a5c..b0cc3a0e3458d 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -135,7 +135,7 @@ def create_single_mgr(typestr, num_rows=None): return SingleBlockManager( create_block(typestr, placement=slice(0, num_rows), item_shape=()), - np.arange(num_rows), + Index(np.arange(num_rows)), ) From b241365e677839b90a9ed67bfcaa744a1fdba5bc Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sat, 28 Mar 2020 09:49:44 -0700 Subject: [PATCH 2/3] update per comments --- pandas/core/internals/managers.py | 18 +++++------------- pandas/core/series.py | 4 +--- pandas/tests/extension/test_external_block.py | 2 +- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index 577b864e619b5..470b010f98546 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -540,9 +540,7 @@ def get_axe(block, qs, axes): values = values.take(indexer) return SingleBlockManager( - make_block(values, ndim=1, placement=np.arange(len(values))), - axes[0], - fastpath=True, + make_block(values, ndim=1, placement=np.arange(len(values))), axes[0], ) def isna(self, func) -> "BlockManager": @@ -1007,7 +1005,6 @@ def iget(self, i: int) -> "SingleBlockManager": values, placement=slice(0, len(values)), ndim=1 ), self.axes[1], - fastpath=True, ) def delete(self, item): @@ -1513,11 +1510,7 @@ class SingleBlockManager(BlockManager): __slots__ = () def __init__( - self, - block: Block, - axis: Index, - do_integrity_check: bool = False, - fastpath: bool = False, + self, block: Block, axis: Index, do_integrity_check: bool = False, ): assert isinstance(block, Block), type(block) assert isinstance(axis, Index), type(axis) @@ -1534,7 +1527,7 @@ def from_blocks( """ assert len(blocks) == 1 assert len(axes) == 1 - return cls(blocks[0], axes[0], do_integrity_check=False, fastpath=True) + return cls(blocks[0], axes[0], do_integrity_check=False) @classmethod def from_array(cls, array: ArrayLike, index: Index) -> "SingleBlockManager": @@ -1542,7 +1535,7 @@ def from_array(cls, array: ArrayLike, index: Index) -> "SingleBlockManager": Constructor for if we have an array that is not yet a Block. """ block = make_block(array, placement=slice(0, len(index)), ndim=1) - return cls(block, index, fastpath=True) + return cls(block, index) def _post_setstate(self): pass @@ -1568,7 +1561,7 @@ def get_slice(self, slobj: slice, axis: int = 0) -> "SingleBlockManager": blk = self._block array = blk._slice(slobj) block = blk.make_block_same_class(array, placement=range(len(array))) - return type(self)(block, self.index[slobj], fastpath=True) + return type(self)(block, self.index[slobj]) @property def index(self) -> Index: @@ -1640,7 +1633,6 @@ def concat( ------- SingleBlockManager """ - assert isinstance(new_axis, Index), new_axis non_empties = [x for x in to_concat if len(x) > 0] # check if all series are of the same block type: diff --git a/pandas/core/series.py b/pandas/core/series.py index 39e1178a3a5c3..92782581a67e8 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -978,9 +978,7 @@ def _get_values_tuple(self, key): def _get_values(self, indexer): try: - return self._constructor( - self._data.get_slice(indexer), fastpath=True - ).__finalize__(self) + return self._constructor(self._data.get_slice(indexer)).__finalize__(self) except ValueError: # mpl compat if we look up e.g. ser[:, np.newaxis]; # see tests.series.timeseries.test_mpl_compat_hack diff --git a/pandas/tests/extension/test_external_block.py b/pandas/tests/extension/test_external_block.py index 26606d7e799e8..0a60e3bc451e5 100644 --- a/pandas/tests/extension/test_external_block.py +++ b/pandas/tests/extension/test_external_block.py @@ -38,7 +38,7 @@ def test_concat_series(): values = np.arange(3, dtype="int64") block = CustomBlock(values, placement=slice(0, 3)) mgr = SingleBlockManager(block, pd.RangeIndex(3)) - s = pd.Series(mgr, pd.RangeIndex(3), fastpath=True) + s = pd.Series(mgr, pd.RangeIndex(3)) res = pd.concat([s, s]) assert isinstance(res._data.blocks[0], CustomBlock) From 6e89f106cb9c377c5f74d5f90ccb8410b3513abd Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 30 Mar 2020 08:40:16 -0700 Subject: [PATCH 3/3] Deprecated fastpath --- doc/source/whatsnew/v1.1.0.rst | 1 + pandas/core/internals/managers.py | 15 ++++++++++++++- pandas/tests/internals/test_internals.py | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 58ac2b4cba3b7..d03ef394e91c9 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -253,6 +253,7 @@ Deprecations - Setting values with ``.loc`` using a positional slice is deprecated and will raise in a future version. Use ``.loc`` with labels or ``.iloc`` with positions instead (:issue:`31840`) - :meth:`DataFrame.to_dict` has deprecated accepting short names for ``orient`` in future versions (:issue:`32515`) - :meth:`Categorical.to_dense` is deprecated and will be removed in a future version, use ``np.asarray(cat)`` instead (:issue:`32639`) +- The ``fastpath`` keyword in the ``SingleBlockManager`` constructor is deprecated and will be removed in a future version (:issue:`33092`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index f7aef156efb3e..eb6f1cba54824 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -4,6 +4,7 @@ import operator import re from typing import Dict, List, Optional, Sequence, Tuple, TypeVar, Union +import warnings import numpy as np @@ -1504,11 +1505,23 @@ class SingleBlockManager(BlockManager): __slots__ = () def __init__( - self, block: Block, axis: Index, do_integrity_check: bool = False, + self, + block: Block, + axis: Index, + do_integrity_check: bool = False, + fastpath=lib.no_default, ): assert isinstance(block, Block), type(block) assert isinstance(axis, Index), type(axis) + if fastpath is not lib.no_default: + warnings.warn( + "The `fastpath` keyword is deprecated and will be removed " + "in a future version.", + FutureWarning, + stacklevel=2, + ) + self.axes = [axis] self.blocks = tuple([block]) diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index b0cc3a0e3458d..91ec1c29873cf 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -1297,3 +1297,11 @@ def test_interleave_non_unique_cols(): assert df_unique.values.shape == df.values.shape tm.assert_numpy_array_equal(df_unique.values[0], df.values[0]) tm.assert_numpy_array_equal(df_unique.values[1], df.values[1]) + + +def test_single_block_manager_fastpath_deprecated(): + # GH#33092 + ser = pd.Series(range(3)) + blk = ser._data.blocks[0] + with tm.assert_produces_warning(FutureWarning): + SingleBlockManager(blk, ser.index, fastpath=True)