forked from pandas-dev/pandas
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathapi.py
165 lines (129 loc) · 4.85 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
This is a pseudo-public API for downstream libraries. We ask that downstream
authors
1) Try to avoid using internals directly altogether, and failing that,
2) Use only functions exposed here (or in core.internals)
"""
from __future__ import annotations
from typing import TYPE_CHECKING
import warnings
import numpy as np
from pandas._libs.internals import BlockPlacement
from pandas.util._exceptions import find_stack_level
from pandas.core.dtypes.common import pandas_dtype
from pandas.core.dtypes.dtypes import (
DatetimeTZDtype,
PeriodDtype,
)
from pandas.core.arrays import DatetimeArray
from pandas.core.construction import extract_array
from pandas.core.internals.blocks import (
check_ndim,
ensure_block_shape,
extract_pandas_array,
get_block_type,
maybe_coerce_values,
)
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
) -> Block:
"""
This is a pseudo-public analogue to blocks.new_block.
We ask that downstream libraries use this rather than any fully-internal
APIs, including but not limited to:
- core.internals.blocks.make_block
- Block.make_block
- Block.make_block_same_class
- Block.__init__
"""
warnings.warn(
# GH#40226
"make_block is deprecated and will be removed in a future version. "
"Use public APIs instead.",
DeprecationWarning,
stacklevel=find_stack_level(),
)
if dtype is not None:
dtype = pandas_dtype(dtype)
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
# -> still allow ExtensionBlock to be passed in this case for back compat
klass = None
if klass is None:
dtype = dtype or values.dtype
klass = get_block_type(dtype)
elif klass is DatetimeTZBlock and not isinstance(values.dtype, DatetimeTZDtype):
# pyarrow calls get here
values = DatetimeArray._simple_new(
# error: Argument "dtype" to "_simple_new" of "DatetimeArray" has
# incompatible type "Union[ExtensionDtype, dtype[Any], None]";
# expected "Union[dtype[datetime64], DatetimeTZDtype]"
values,
dtype=dtype, # type: ignore[arg-type]
)
if not isinstance(placement, BlockPlacement):
placement = BlockPlacement(placement)
ndim = maybe_infer_ndim(values, placement, ndim)
if isinstance(values.dtype, (PeriodDtype, DatetimeTZDtype)):
# GH#41168 ensure we can pass 1D dt64tz values
# More generally, any EA dtype that isn't is_1d_only_ea_dtype
values = extract_array(values, extract_numpy=True)
values = ensure_block_shape(values, ndim)
check_ndim(values, placement, ndim)
values = maybe_coerce_values(values)
return klass(values, ndim=ndim, placement=placement)
def maybe_infer_ndim(values, placement: BlockPlacement, ndim: int | None) -> int:
"""
If `ndim` is not provided, infer it from placement and values.
"""
if ndim is None:
# GH#38134 Block constructor now assumes ndim is not None
if not isinstance(values.dtype, np.dtype):
if len(placement) != 1:
ndim = 1
else:
ndim = 2
else:
ndim = values.ndim
return ndim
def __getattr__(name: str):
# GH#55139
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,
# https://github.com/pandas-dev/pandas/pull/55139#pullrequestreview-1720690758
# on hard-coding stacklevel
stacklevel=2,
)
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}'"
)