Skip to content

Commit

Permalink
DEPR: deprecate exposing blocks in core.internals (#55139)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored Nov 20, 2023
1 parent d5e97d0 commit 48899c3
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 26 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ Other Deprecations
- Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`)
- Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`)
- Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`)
- Deprecated ``core.internals`` members ``Block``, ``ExtensionBlock``, and ``DatetimeTZBlock``, use public APIs instead (:issue:`55139`)
- Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`)
- Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_clipboard`. (:issue:`54229`)
- Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_csv` except ``path_or_buf``. (:issue:`54229`)
Expand Down
44 changes: 30 additions & 14 deletions pandas/core/internals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pandas.core.internals.api import make_block
from pandas.core.internals.api import make_block # 2023-09-18 pyarrow uses this
from pandas.core.internals.array_manager import (
ArrayManager,
SingleArrayManager,
Expand All @@ -7,21 +7,16 @@
DataManager,
SingleDataManager,
)
from pandas.core.internals.blocks import ( # io.pytables, io.packers
Block,
DatetimeTZBlock,
ExtensionBlock,
)
from pandas.core.internals.concat import concatenate_managers
from pandas.core.internals.managers import (
BlockManager,
SingleBlockManager,
)

__all__ = [
"Block",
"DatetimeTZBlock",
"ExtensionBlock",
"Block", # pylint: disable=undefined-all-variable
"DatetimeTZBlock", # pylint: disable=undefined-all-variable
"ExtensionBlock", # pylint: disable=undefined-all-variable
"make_block",
"DataManager",
"ArrayManager",
Expand All @@ -34,33 +29,54 @@


def __getattr__(name: str):
# GH#55139
import warnings

from pandas.util._exceptions import find_stack_level

if name == "create_block_manager_from_blocks":
# GH#33892
warnings.warn(
f"{name} is deprecated and will be removed in a future version. "
"Use public APIs instead.",
DeprecationWarning,
stacklevel=find_stack_level(),
# https://github.com/pandas-dev/pandas/pull/55139#pullrequestreview-1720690758
# on hard-coding stacklevel
stacklevel=2,
)
from pandas.core.internals.managers import create_block_manager_from_blocks

return create_block_manager_from_blocks

if name in ["NumericBlock", "ObjectBlock"]:
if name in [
"NumericBlock",
"ObjectBlock",
"Block",
"ExtensionBlock",
"DatetimeTZBlock",
]:
warnings.warn(
f"{name} is deprecated and will be removed in a future version. "
"Use public APIs instead.",
DeprecationWarning,
stacklevel=find_stack_level(),
# https://github.com/pandas-dev/pandas/pull/55139#pullrequestreview-1720690758
# on hard-coding stacklevel
stacklevel=2,
)
if name == "NumericBlock":
from pandas.core.internals.blocks import NumericBlock

return NumericBlock
elif name == "DatetimeTZBlock":
from pandas.core.internals.blocks import DatetimeTZBlock

return DatetimeTZBlock
elif name == "ExtensionBlock":
from pandas.core.internals.blocks import ExtensionBlock

return ExtensionBlock
elif name == "Block":
from pandas.core.internals.blocks import Block

return Block
else:
from pandas.core.internals.blocks import ObjectBlock

Expand Down
45 changes: 36 additions & 9 deletions pandas/core/internals/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
from pandas.core.arrays import DatetimeArray
from pandas.core.construction import extract_array
from pandas.core.internals.blocks import (
Block,
DatetimeTZBlock,
ExtensionBlock,
check_ndim,
ensure_block_shape,
extract_pandas_array,
Expand All @@ -36,6 +33,8 @@
if TYPE_CHECKING:
from pandas._typing import Dtype

from pandas.core.internals.blocks import Block


def make_block(
values, placement, klass=None, ndim=None, dtype: Dtype | None = None
Expand All @@ -56,6 +55,11 @@ def make_block(

values, dtype = extract_pandas_array(values, dtype, ndim)

from pandas.core.internals.blocks import (
DatetimeTZBlock,
ExtensionBlock,
)

if klass is ExtensionBlock and isinstance(values.dtype, PeriodDtype):
# GH-44681 changed PeriodArray to be stored in the 2D
# NDArrayBackedExtensionBlock instead of ExtensionBlock
Expand Down Expand Up @@ -108,21 +112,44 @@ def maybe_infer_ndim(values, placement: BlockPlacement, ndim: int | None) -> int


def __getattr__(name: str):
# GH#55139
import warnings

from pandas.util._exceptions import find_stack_level

if name == "create_block_manager_from_blocks":
if name in [
"Block",
"ExtensionBlock",
"DatetimeTZBlock",
"create_block_manager_from_blocks",
]:
# GH#33892
warnings.warn(
f"{name} is deprecated and will be removed in a future version. "
"Use public APIs instead.",
DeprecationWarning,
stacklevel=find_stack_level(),
# https://github.com/pandas-dev/pandas/pull/55139#pullrequestreview-1720690758
# on hard-coding stacklevel
stacklevel=2,
)
from pandas.core.internals.managers import create_block_manager_from_blocks

return create_block_manager_from_blocks
if name == "create_block_manager_from_blocks":
from pandas.core.internals.managers import create_block_manager_from_blocks

return create_block_manager_from_blocks

elif name == "Block":
from pandas.core.internals.blocks import Block

return Block

elif name == "DatetimeTZBlock":
from pandas.core.internals.blocks import DatetimeTZBlock

return DatetimeTZBlock

elif name == "ExtensionBlock":
from pandas.core.internals.blocks import ExtensionBlock

return ExtensionBlock

raise AttributeError(
f"module 'pandas.core.internals.api' has no attribute '{name}'"
Expand Down
27 changes: 24 additions & 3 deletions pandas/tests/internals/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
in core.internals
"""

import pytest

import pandas as pd
import pandas._testing as tm
from pandas.core import internals
Expand All @@ -27,9 +29,6 @@ def test_namespace():
"ops",
]
expected = [
"Block",
"DatetimeTZBlock",
"ExtensionBlock",
"make_block",
"DataManager",
"ArrayManager",
Expand All @@ -44,6 +43,28 @@ def test_namespace():
assert set(result) == set(expected + modules)


@pytest.mark.parametrize(
"name",
[
"NumericBlock",
"ObjectBlock",
"Block",
"ExtensionBlock",
"DatetimeTZBlock",
],
)
def test_deprecations(name):
# GH#55139
msg = f"{name} is deprecated.* Use public APIs instead"
with tm.assert_produces_warning(DeprecationWarning, match=msg):
getattr(internals, name)

if name not in ["NumericBlock", "ObjectBlock"]:
# NumericBlock and ObjectBlock are not in the internals.api namespace
with tm.assert_produces_warning(DeprecationWarning, match=msg):
getattr(api, name)


def test_make_block_2d_with_dti():
# GH#41168
dti = pd.date_range("2012", periods=3, tz="UTC")
Expand Down

0 comments on commit 48899c3

Please sign in to comment.