Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/_testing/__init__.py: 42%

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

210 statements  

1from __future__ import annotations 

2 

3from concurrent.futures import ThreadPoolExecutor 

4from decimal import Decimal 

5import operator 

6import os 

7from sys import byteorder 

8import threading 

9from typing import ( 

10 TYPE_CHECKING, 

11 ContextManager, 

12) 

13 

14import numpy as np 

15 

16from pandas._config import using_string_dtype 

17from pandas._config.localization import ( 

18 can_set_locale, 

19 get_locales, 

20 set_locale, 

21) 

22 

23from pandas.compat import HAS_PYARROW 

24 

25import pandas as pd 

26from pandas import ( 

27 ArrowDtype, 

28 DataFrame, 

29 Index, 

30 MultiIndex, 

31 RangeIndex, 

32 Series, 

33) 

34from pandas._testing._io import ( 

35 round_trip_pathlib, 

36 round_trip_pickle, 

37 write_to_compressed, 

38) 

39from pandas._testing._warnings import ( 

40 assert_produces_warning, 

41 maybe_produces_warning, 

42) 

43from pandas._testing.asserters import ( 

44 assert_almost_equal, 

45 assert_attr_equal, 

46 assert_categorical_equal, 

47 assert_class_equal, 

48 assert_contains_all, 

49 assert_copy, 

50 assert_datetime_array_equal, 

51 assert_dict_equal, 

52 assert_equal, 

53 assert_extension_array_equal, 

54 assert_frame_equal, 

55 assert_index_equal, 

56 assert_indexing_slices_equivalent, 

57 assert_interval_array_equal, 

58 assert_is_sorted, 

59 assert_metadata_equivalent, 

60 assert_numpy_array_equal, 

61 assert_period_array_equal, 

62 assert_series_equal, 

63 assert_sp_array_equal, 

64 assert_timedelta_array_equal, 

65 raise_assert_detail, 

66) 

67from pandas._testing.compat import ( 

68 get_dtype, 

69 get_obj, 

70) 

71from pandas._testing.contexts import ( 

72 decompress_file, 

73 raises_chained_assignment_error, 

74 set_timezone, 

75 with_csv_dialect, 

76) 

77from pandas.core.arrays import ( 

78 ArrowExtensionArray, 

79 BaseMaskedArray, 

80 NumpyExtensionArray, 

81) 

82from pandas.core.arrays._mixins import NDArrayBackedExtensionArray 

83from pandas.core.construction import extract_array 

84 

85if TYPE_CHECKING: 

86 from collections.abc import Callable 

87 

88 from pandas._typing import ( 

89 Dtype, 

90 NpDtype, 

91 ) 

92 

93 

94UNSIGNED_INT_NUMPY_DTYPES: list[NpDtype] = ["uint8", "uint16", "uint32", "uint64"] 

95UNSIGNED_INT_EA_DTYPES: list[Dtype] = ["UInt8", "UInt16", "UInt32", "UInt64"] 

96SIGNED_INT_NUMPY_DTYPES: list[NpDtype] = [int, "int8", "int16", "int32", "int64"] 

97SIGNED_INT_EA_DTYPES: list[Dtype] = ["Int8", "Int16", "Int32", "Int64"] 

98ALL_INT_NUMPY_DTYPES = UNSIGNED_INT_NUMPY_DTYPES + SIGNED_INT_NUMPY_DTYPES 

99ALL_INT_EA_DTYPES = UNSIGNED_INT_EA_DTYPES + SIGNED_INT_EA_DTYPES 

100ALL_INT_DTYPES: list[Dtype] = [*ALL_INT_NUMPY_DTYPES, *ALL_INT_EA_DTYPES] 

101 

102FLOAT_NUMPY_DTYPES: list[NpDtype] = [float, "float32", "float64"] 

103FLOAT_EA_DTYPES: list[Dtype] = ["Float32", "Float64"] 

104ALL_FLOAT_DTYPES: list[Dtype] = [*FLOAT_NUMPY_DTYPES, *FLOAT_EA_DTYPES] 

105 

106COMPLEX_DTYPES: list[Dtype] = [complex, "complex64", "complex128"] 

107if using_string_dtype(): 

108 STRING_DTYPES: list[Dtype] = ["U"] 

109else: 

110 STRING_DTYPES: list[Dtype] = [str, "str", "U"] # type: ignore[no-redef] 

111COMPLEX_FLOAT_DTYPES: list[Dtype] = [*COMPLEX_DTYPES, *FLOAT_NUMPY_DTYPES] 

112 

113DATETIME64_DTYPES: list[Dtype] = ["datetime64[ns]", "M8[ns]"] 

114TIMEDELTA64_DTYPES: list[Dtype] = ["timedelta64[ns]", "m8[ns]"] 

115 

116BOOL_DTYPES: list[Dtype] = [bool, "bool"] 

117BYTES_DTYPES: list[Dtype] = [bytes, "bytes"] 

118OBJECT_DTYPES: list[Dtype] = [object, "object"] 

119 

120ALL_REAL_NUMPY_DTYPES = FLOAT_NUMPY_DTYPES + ALL_INT_NUMPY_DTYPES 

121ALL_REAL_EXTENSION_DTYPES = FLOAT_EA_DTYPES + ALL_INT_EA_DTYPES 

122ALL_REAL_DTYPES: list[Dtype] = [*ALL_REAL_NUMPY_DTYPES, *ALL_REAL_EXTENSION_DTYPES] 

123ALL_NUMERIC_DTYPES: list[Dtype] = [*ALL_REAL_DTYPES, *COMPLEX_DTYPES] 

124 

125ALL_NUMPY_DTYPES = ( 

126 ALL_REAL_NUMPY_DTYPES 

127 + COMPLEX_DTYPES 

128 + STRING_DTYPES 

129 + DATETIME64_DTYPES 

130 + TIMEDELTA64_DTYPES 

131 + BOOL_DTYPES 

132 + OBJECT_DTYPES 

133 + BYTES_DTYPES 

134) 

135 

136NARROW_NP_DTYPES = [ 

137 np.float16, 

138 np.float32, 

139 np.int8, 

140 np.int16, 

141 np.int32, 

142 np.uint8, 

143 np.uint16, 

144 np.uint32, 

145] 

146 

147PYTHON_DATA_TYPES = [ 

148 str, 

149 int, 

150 float, 

151 complex, 

152 list, 

153 tuple, 

154 range, 

155 dict, 

156 set, 

157 frozenset, 

158 bool, 

159 bytes, 

160 bytearray, 

161 memoryview, 

162] 

163 

164ENDIAN = {"little": "<", "big": ">"}[byteorder] 

165 

166NULL_OBJECTS = [None, np.nan, pd.NaT, float("nan"), pd.NA, Decimal("NaN")] 

167NP_NAT_OBJECTS = [ 

168 cls("NaT", unit) 

169 for cls in [np.datetime64, np.timedelta64] 

170 for unit in [ 

171 "Y", 

172 "M", 

173 "W", 

174 "D", 

175 "h", 

176 "m", 

177 "s", 

178 "ms", 

179 "us", 

180 "ns", 

181 "ps", 

182 "fs", 

183 "as", 

184 ] 

185] 

186 

187if HAS_PYARROW: 

188 import pyarrow as pa 

189 

190 UNSIGNED_INT_PYARROW_DTYPES = [pa.uint8(), pa.uint16(), pa.uint32(), pa.uint64()] 

191 SIGNED_INT_PYARROW_DTYPES = [pa.int8(), pa.int16(), pa.int32(), pa.int64()] 

192 ALL_INT_PYARROW_DTYPES = UNSIGNED_INT_PYARROW_DTYPES + SIGNED_INT_PYARROW_DTYPES 

193 ALL_INT_PYARROW_DTYPES_STR_REPR = [ 

194 str(ArrowDtype(typ)) for typ in ALL_INT_PYARROW_DTYPES 

195 ] 

196 

197 # pa.float16 doesn't seem supported 

198 # https://github.com/apache/arrow/blob/master/python/pyarrow/src/arrow/python/helpers.cc#L86 

199 FLOAT_PYARROW_DTYPES = [pa.float32(), pa.float64()] 

200 FLOAT_PYARROW_DTYPES_STR_REPR = [ 

201 str(ArrowDtype(typ)) for typ in FLOAT_PYARROW_DTYPES 

202 ] 

203 DECIMAL_PYARROW_DTYPES = [pa.decimal128(7, 3)] 

204 STRING_PYARROW_DTYPES = [pa.string()] 

205 BINARY_PYARROW_DTYPES = [pa.binary()] 

206 

207 TIME_PYARROW_DTYPES = [ 

208 pa.time32("s"), 

209 pa.time32("ms"), 

210 pa.time64("us"), 

211 pa.time64("ns"), 

212 ] 

213 DATE_PYARROW_DTYPES = [pa.date32(), pa.date64()] 

214 DATETIME_PYARROW_DTYPES = [ 

215 pa.timestamp(unit=unit, tz=tz) 

216 for unit in ["s", "ms", "us", "ns"] 

217 for tz in [None, "UTC", "US/Pacific", "US/Eastern"] 

218 ] 

219 TIMEDELTA_PYARROW_DTYPES = [pa.duration(unit) for unit in ["s", "ms", "us", "ns"]] 

220 

221 BOOL_PYARROW_DTYPES = [pa.bool_()] 

222 

223 # TODO: Add container like pyarrow types: 

224 # https://arrow.apache.org/docs/python/api/datatypes.html#factory-functions 

225 ALL_PYARROW_DTYPES = ( 

226 ALL_INT_PYARROW_DTYPES 

227 + FLOAT_PYARROW_DTYPES 

228 + DECIMAL_PYARROW_DTYPES 

229 + STRING_PYARROW_DTYPES 

230 + BINARY_PYARROW_DTYPES 

231 + TIME_PYARROW_DTYPES 

232 + DATE_PYARROW_DTYPES 

233 + DATETIME_PYARROW_DTYPES 

234 + TIMEDELTA_PYARROW_DTYPES 

235 + BOOL_PYARROW_DTYPES 

236 ) 

237 ALL_REAL_PYARROW_DTYPES_STR_REPR = ( 

238 ALL_INT_PYARROW_DTYPES_STR_REPR + FLOAT_PYARROW_DTYPES_STR_REPR 

239 ) 

240else: 

241 FLOAT_PYARROW_DTYPES_STR_REPR = [] 

242 ALL_INT_PYARROW_DTYPES_STR_REPR = [] 

243 ALL_PYARROW_DTYPES = [] 

244 ALL_REAL_PYARROW_DTYPES_STR_REPR = [] 

245 

246ALL_REAL_NULLABLE_DTYPES = ( 

247 FLOAT_NUMPY_DTYPES + ALL_REAL_EXTENSION_DTYPES + ALL_REAL_PYARROW_DTYPES_STR_REPR 

248) 

249 

250arithmetic_dunder_methods = [ 

251 "__add__", 

252 "__radd__", 

253 "__sub__", 

254 "__rsub__", 

255 "__mul__", 

256 "__rmul__", 

257 "__floordiv__", 

258 "__rfloordiv__", 

259 "__truediv__", 

260 "__rtruediv__", 

261 "__pow__", 

262 "__rpow__", 

263 "__mod__", 

264 "__rmod__", 

265] 

266 

267comparison_dunder_methods = ["__eq__", "__ne__", "__le__", "__lt__", "__ge__", "__gt__"] 

268 

269 

270# ----------------------------------------------------------------------------- 

271# Comparators 

272 

273 

274def box_expected(expected, box_cls, transpose: bool = True): 

275 """ 

276 Helper function to wrap the expected output of a test in a given box_class. 

277 

278 Parameters 

279 ---------- 

280 expected : np.ndarray, Index, Series 

281 box_cls : {Index, Series, DataFrame} 

282 

283 Returns 

284 ------- 

285 subclass of box_cls 

286 """ 

287 if box_cls is pd.array: 

288 if isinstance(expected, RangeIndex): 

289 # pd.array would return an IntegerArray 

290 expected = NumpyExtensionArray(np.asarray(expected._values)) 

291 else: 

292 expected = pd.array(expected, copy=False) 

293 elif box_cls is Index: 

294 expected = Index(expected, copy=False) 

295 elif box_cls is Series: 

296 expected = Series(expected) 

297 elif box_cls is DataFrame: 

298 expected = Series(expected).to_frame() 

299 if transpose: 

300 # for vector operations, we need a DataFrame to be a single-row, 

301 # not a single-column, in order to operate against non-DataFrame 

302 # vectors of the same length. But convert to two rows to avoid 

303 # single-row special cases in datetime arithmetic 

304 expected = expected.T 

305 expected = pd.concat([expected] * 2, ignore_index=True) 

306 elif box_cls is np.ndarray or box_cls is np.array: 

307 expected = np.array(expected) 

308 elif box_cls is to_array: 

309 expected = to_array(expected) 

310 else: 

311 raise NotImplementedError(box_cls) 

312 return expected 

313 

314 

315def to_array(obj): 

316 """ 

317 Similar to pd.array, but does not cast numpy dtypes to nullable dtypes. 

318 """ 

319 # temporary implementation until we get pd.array in place 

320 dtype = getattr(obj, "dtype", None) 

321 

322 if dtype is None: 

323 return np.asarray(obj) 

324 

325 return extract_array(obj, extract_numpy=True) 

326 

327 

328class SubclassedSeries(Series): 

329 _metadata = ["testattr", "name"] 

330 

331 @property 

332 def _constructor(self): 

333 # For testing, those properties return a generic callable, and not 

334 # the actual class. In this case that is equivalent, but it is to 

335 # ensure we don't rely on the property returning a class 

336 # See https://github.com/pandas-dev/pandas/pull/46018 and 

337 # https://github.com/pandas-dev/pandas/issues/32638 and linked issues 

338 return lambda *args, **kwargs: SubclassedSeries(*args, **kwargs) 

339 

340 @property 

341 def _constructor_expanddim(self): 

342 return lambda *args, **kwargs: SubclassedDataFrame(*args, **kwargs) 

343 

344 

345class SubclassedDataFrame(DataFrame): 

346 _metadata = ["testattr"] 

347 

348 @property 

349 def _constructor(self): 

350 return lambda *args, **kwargs: SubclassedDataFrame(*args, **kwargs) 

351 

352 # error: Cannot override writeable attribute with read-only property 

353 @property 

354 def _constructor_sliced(self): # type: ignore[override] 

355 return lambda *args, **kwargs: SubclassedSeries(*args, **kwargs) 

356 

357 

358def convert_rows_list_to_csv_str(rows_list: list[str]) -> str: 

359 """ 

360 Convert list of CSV rows to single CSV-formatted string for current OS. 

361 

362 This method is used for creating expected value of to_csv() method. 

363 

364 Parameters 

365 ---------- 

366 rows_list : List[str] 

367 Each element represents the row of csv. 

368 

369 Returns 

370 ------- 

371 str 

372 Expected output of to_csv() in current OS. 

373 """ 

374 sep = os.linesep 

375 return sep.join(rows_list) + sep 

376 

377 

378def external_error_raised(expected_exception: type[Exception]) -> ContextManager: 

379 """ 

380 Helper function to mark pytest.raises that have an external error message. 

381 

382 Parameters 

383 ---------- 

384 expected_exception : Exception 

385 Expected error to raise. 

386 

387 Returns 

388 ------- 

389 Callable 

390 Regular `pytest.raises` function with `match` equal to `None`. 

391 """ 

392 import pytest 

393 

394 return pytest.raises(expected_exception, match=None) 

395 

396 

397def get_cython_table_params(ndframe, func_names_and_expected): 

398 """ 

399 Combine frame, functions from com._cython_table 

400 keys and expected result. 

401 

402 Parameters 

403 ---------- 

404 ndframe : DataFrame or Series 

405 func_names_and_expected : Sequence of two items 

406 The first item is a name of an NDFrame method ('sum', 'prod') etc. 

407 The second item is the expected return value. 

408 

409 Returns 

410 ------- 

411 list 

412 List of three items (DataFrame, function, expected result) 

413 """ 

414 results = [] 

415 for func_name, expected in func_names_and_expected: 

416 results.append((ndframe, func_name, expected)) 

417 return results 

418 

419 

420def get_op_from_name(op_name: str) -> Callable: 

421 """ 

422 The operator function for a given op name. 

423 

424 Parameters 

425 ---------- 

426 op_name : str 

427 The op name, in form of "add" or "__add__". 

428 

429 Returns 

430 ------- 

431 function 

432 A function performing the operation. 

433 """ 

434 short_opname = op_name.strip("_") 

435 try: 

436 op = getattr(operator, short_opname) 

437 except AttributeError: 

438 # Assume it is the reverse operator 

439 rop = getattr(operator, short_opname[1:]) 

440 op = lambda x, y: rop(y, x) 

441 

442 return op 

443 

444 

445# ----------------------------------------------------------------------------- 

446# Indexing test helpers 

447 

448 

449def getitem(x): 

450 return x 

451 

452 

453def setitem(x): 

454 return x 

455 

456 

457def loc(x): 

458 return x.loc 

459 

460 

461def iloc(x): 

462 return x.iloc 

463 

464 

465def at(x): 

466 return x.at 

467 

468 

469def iat(x): 

470 return x.iat 

471 

472 

473# ----------------------------------------------------------------------------- 

474 

475_UNITS = ["s", "ms", "us", "ns"] 

476 

477 

478def get_finest_unit(left: str, right: str) -> str: 

479 """ 

480 Find the higher of two datetime64 units. 

481 """ 

482 if _UNITS.index(left) >= _UNITS.index(right): 

483 return left 

484 return right 

485 

486 

487def shares_memory(left, right) -> bool: 

488 """ 

489 Pandas-compat for np.shares_memory. 

490 """ 

491 if isinstance(left, np.ndarray) and isinstance(right, np.ndarray): 

492 return np.shares_memory(left, right) 

493 elif isinstance(left, np.ndarray): 

494 # Call with reversed args to get to unpacking logic below. 

495 return shares_memory(right, left) 

496 

497 if isinstance(left, RangeIndex): 

498 return False 

499 if isinstance(left, MultiIndex): 

500 return shares_memory(left._codes, right) 

501 if isinstance(left, (Index, Series)): 

502 if isinstance(right, (Index, Series)): 

503 return shares_memory(left._values, right._values) 

504 return shares_memory(left._values, right) 

505 

506 if isinstance(left, NDArrayBackedExtensionArray): 

507 return shares_memory(left._ndarray, right) 

508 if isinstance(left, pd.core.arrays.SparseArray): 

509 return shares_memory(left.sp_values, right) 

510 if isinstance(left, pd.core.arrays.IntervalArray): 

511 return shares_memory(left._left, right) or shares_memory(left._right, right) 

512 

513 if isinstance(left, ArrowExtensionArray): 

514 if isinstance(right, ArrowExtensionArray): 

515 # https://github.com/pandas-dev/pandas/pull/43930#discussion_r736862669 

516 left_pa_data = left._pa_array 

517 right_pa_data = right._pa_array 

518 left_buf1 = left_pa_data.chunk(0).buffers()[1] 

519 right_buf1 = right_pa_data.chunk(0).buffers()[1] 

520 return left_buf1.address == right_buf1.address 

521 else: 

522 # if we have one one ArrowExtensionArray and one other array, assume 

523 # they can only share memory if they share the same numpy buffer 

524 return np.shares_memory(left, right) 

525 

526 if isinstance(left, BaseMaskedArray) and isinstance(right, BaseMaskedArray): 

527 # By convention, we'll say these share memory if they share *either* 

528 # the _data or the _mask 

529 return np.shares_memory(left._data, right._data) or np.shares_memory( 

530 left._mask, right._mask 

531 ) 

532 

533 if isinstance(left, DataFrame) and len(left._mgr.blocks) == 1: 

534 arr = left._mgr.blocks[0].values 

535 return shares_memory(arr, right) 

536 

537 raise NotImplementedError(type(left), type(right)) 

538 

539 

540def run_multithreaded(closure, max_workers, arguments=None, pass_barrier=False): 

541 with ThreadPoolExecutor(max_workers=max_workers) as tpe: 

542 if arguments is None: 

543 arguments = [] 

544 else: 

545 arguments = list(arguments) 

546 

547 if pass_barrier: 

548 barrier = threading.Barrier(max_workers) 

549 arguments.append(barrier) 

550 

551 try: 

552 futures = [] 

553 for _ in range(max_workers): 

554 futures.append(tpe.submit(closure, *arguments)) # noqa: PERF401 

555 except RuntimeError as e: 

556 import pytest 

557 

558 pytest.skip( 

559 f"Spawning {max_workers} threads failed with " 

560 f"error {e!r} (likely due to resource limits on the " 

561 "system running the tests)" 

562 ) 

563 finally: 

564 if len(futures) < max_workers and pass_barrier: 

565 barrier.abort() 

566 for f in futures: 

567 f.result() 

568 

569 

570__all__ = [ 

571 "ALL_INT_EA_DTYPES", 

572 "ALL_INT_NUMPY_DTYPES", 

573 "ALL_NUMPY_DTYPES", 

574 "ALL_REAL_NUMPY_DTYPES", 

575 "BOOL_DTYPES", 

576 "BYTES_DTYPES", 

577 "COMPLEX_DTYPES", 

578 "DATETIME64_DTYPES", 

579 "ENDIAN", 

580 "FLOAT_EA_DTYPES", 

581 "FLOAT_NUMPY_DTYPES", 

582 "NARROW_NP_DTYPES", 

583 "NP_NAT_OBJECTS", 

584 "NULL_OBJECTS", 

585 "OBJECT_DTYPES", 

586 "SIGNED_INT_EA_DTYPES", 

587 "SIGNED_INT_NUMPY_DTYPES", 

588 "STRING_DTYPES", 

589 "TIMEDELTA64_DTYPES", 

590 "UNSIGNED_INT_EA_DTYPES", 

591 "UNSIGNED_INT_NUMPY_DTYPES", 

592 "SubclassedDataFrame", 

593 "SubclassedSeries", 

594 "assert_almost_equal", 

595 "assert_attr_equal", 

596 "assert_categorical_equal", 

597 "assert_class_equal", 

598 "assert_contains_all", 

599 "assert_copy", 

600 "assert_datetime_array_equal", 

601 "assert_dict_equal", 

602 "assert_equal", 

603 "assert_extension_array_equal", 

604 "assert_frame_equal", 

605 "assert_index_equal", 

606 "assert_indexing_slices_equivalent", 

607 "assert_interval_array_equal", 

608 "assert_is_sorted", 

609 "assert_metadata_equivalent", 

610 "assert_numpy_array_equal", 

611 "assert_period_array_equal", 

612 "assert_produces_warning", 

613 "assert_series_equal", 

614 "assert_sp_array_equal", 

615 "assert_timedelta_array_equal", 

616 "at", 

617 "box_expected", 

618 "can_set_locale", 

619 "convert_rows_list_to_csv_str", 

620 "decompress_file", 

621 "external_error_raised", 

622 "get_cython_table_params", 

623 "get_dtype", 

624 "get_finest_unit", 

625 "get_locales", 

626 "get_obj", 

627 "get_op_from_name", 

628 "getitem", 

629 "iat", 

630 "iloc", 

631 "loc", 

632 "maybe_produces_warning", 

633 "raise_assert_detail", 

634 "raises_chained_assignment_error", 

635 "round_trip_pathlib", 

636 "round_trip_pickle", 

637 "run_multithreaded", 

638 "set_locale", 

639 "set_timezone", 

640 "setitem", 

641 "shares_memory", 

642 "to_array", 

643 "with_csv_dialect", 

644 "write_to_compressed", 

645]