Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/internals/api.py: 34%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

59 statements  

1""" 

2This is a pseudo-public API for downstream libraries. We ask that downstream 

3authors 

4 

51) Try to avoid using internals directly altogether, and failing that, 

62) Use only functions exposed here (or in core.internals) 

7 

8""" 

9 

10from __future__ import annotations 

11 

12from typing import TYPE_CHECKING 

13import warnings 

14 

15import numpy as np 

16 

17from pandas._libs.internals import BlockPlacement 

18from pandas.errors import Pandas4Warning 

19 

20from pandas.core.dtypes.common import pandas_dtype 

21from pandas.core.dtypes.dtypes import ( 

22 DatetimeTZDtype, 

23 ExtensionDtype, 

24 PeriodDtype, 

25) 

26 

27from pandas.core.arrays import ( 

28 DatetimeArray, 

29 TimedeltaArray, 

30) 

31from pandas.core.construction import extract_array 

32from pandas.core.internals.blocks import ( 

33 DatetimeLikeBlock, 

34 check_ndim, 

35 ensure_block_shape, 

36 extract_pandas_array, 

37 get_block_type, 

38 maybe_coerce_values, 

39) 

40 

41if TYPE_CHECKING: 

42 from pandas._typing import ( 

43 ArrayLike, 

44 Dtype, 

45 ) 

46 

47 from pandas.core.internals.blocks import Block 

48 

49 

50def _make_block(values: ArrayLike, placement: np.ndarray) -> Block: 

51 """ 

52 This is an analogue to blocks.new_block(_2d) that ensures: 

53 1) correct dimension for EAs that support 2D (`ensure_block_shape`), and 

54 2) correct EA class for datetime64/timedelta64 (`maybe_coerce_values`). 

55 

56 The input `values` is assumed to be either numpy array or ExtensionArray: 

57 - In case of a numpy array, it is assumed to already be in the expected 

58 shape for Blocks (2D, (cols, rows)). 

59 - In case of an ExtensionArray the input can be 1D, also for EAs that are 

60 internally stored as 2D. 

61 

62 For the rest no preprocessing or validation is done, except for those dtypes 

63 that are internally stored as EAs but have an exact numpy equivalent (and at 

64 the moment use that numpy dtype), i.e. datetime64/timedelta64. 

65 """ 

66 dtype = values.dtype 

67 klass = get_block_type(dtype) 

68 placement_obj = BlockPlacement(placement) 

69 

70 if (isinstance(dtype, ExtensionDtype) and dtype._supports_2d) or isinstance( 

71 values, (DatetimeArray, TimedeltaArray) 

72 ): 

73 values = ensure_block_shape(values, ndim=2) 

74 

75 values = maybe_coerce_values(values) 

76 return klass(values, ndim=2, placement=placement_obj) 

77 

78 

79class _DatetimeTZBlock(DatetimeLikeBlock): 

80 """implement a datetime64 block with a tz attribute""" 

81 

82 values: DatetimeArray 

83 

84 __slots__ = () 

85 

86 

87def make_block( 

88 values, placement, klass=None, ndim=None, dtype: Dtype | None = None 

89) -> Block: 

90 """ 

91 This is a pseudo-public analogue to blocks.new_block. 

92 

93 We ask that downstream libraries use this rather than any fully-internal 

94 APIs, including but not limited to: 

95 

96 - core.internals.blocks.make_block 

97 - Block.make_block 

98 - Block.make_block_same_class 

99 - Block.__init__ 

100 """ 

101 warnings.warn( 

102 # GH#56815 

103 "make_block is deprecated and will be removed in a future version. " 

104 "Use pd.api.internals.create_dataframe_from_blocks or " 

105 "(recommended) higher-level public APIs instead.", 

106 Pandas4Warning, 

107 stacklevel=2, 

108 ) 

109 

110 if dtype is not None: 

111 dtype = pandas_dtype(dtype) 

112 

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

114 

115 from pandas.core.internals.blocks import ExtensionBlock 

116 

117 if klass is ExtensionBlock and isinstance(values.dtype, PeriodDtype): 

118 # GH-44681 changed PeriodArray to be stored in the 2D 

119 # NDArrayBackedExtensionBlock instead of ExtensionBlock 

120 # -> still allow ExtensionBlock to be passed in this case for back compat 

121 klass = None 

122 

123 if klass is None: 

124 dtype = dtype or values.dtype 

125 klass = get_block_type(dtype) 

126 

127 elif klass is _DatetimeTZBlock and not isinstance(values.dtype, DatetimeTZDtype): 

128 # pyarrow calls get here (pyarrow<15) 

129 values = DatetimeArray._simple_new( 

130 # error: Argument "dtype" to "_simple_new" of "DatetimeArray" has 

131 # incompatible type "Union[ExtensionDtype, dtype[Any], None]"; 

132 # expected "Union[dtype[datetime64], DatetimeTZDtype]" 

133 values, 

134 dtype=dtype, # type: ignore[arg-type] 

135 ) 

136 

137 if not isinstance(placement, BlockPlacement): 

138 placement = BlockPlacement(placement) 

139 

140 ndim = _maybe_infer_ndim(values, placement, ndim) 

141 if isinstance(values.dtype, (PeriodDtype, DatetimeTZDtype)): 

142 # GH#41168 ensure we can pass 1D dt64tz values 

143 # More generally, any EA dtype that isn't is_1d_only_ea_dtype 

144 values = extract_array(values, extract_numpy=True) 

145 values = ensure_block_shape(values, ndim) 

146 

147 check_ndim(values, placement, ndim) 

148 values = maybe_coerce_values(values) 

149 return klass(values, ndim=ndim, placement=placement) 

150 

151 

152def _maybe_infer_ndim(values, placement: BlockPlacement, ndim: int | None) -> int: 

153 """ 

154 If `ndim` is not provided, infer it from placement and values. 

155 """ 

156 if ndim is None: 

157 # GH#38134 Block constructor now assumes ndim is not None 

158 if not isinstance(values.dtype, np.dtype): 

159 if len(placement) != 1: 

160 ndim = 1 

161 else: 

162 ndim = 2 

163 else: 

164 ndim = values.ndim 

165 return ndim 

166 

167 

168def maybe_infer_ndim(values, placement: BlockPlacement, ndim: int | None) -> int: 

169 """ 

170 If `ndim` is not provided, infer it from placement and values. 

171 """ 

172 warnings.warn( 

173 "maybe_infer_ndim is deprecated and will be removed in a future version.", 

174 Pandas4Warning, 

175 stacklevel=2, 

176 ) 

177 return _maybe_infer_ndim(values, placement, ndim)