1""" 2This file is very long and growing, but it was decided to not split it yet, as 3it's still manageable (2020-03-17, ~1.1k LoC). See gh-31989 4 5Instead of splitting it was decided to define sections here: 6- Configuration / Settings 7- Autouse fixtures 8- Common arguments 9- Missing values & co. 10- Classes 11- Indices 12- Series' 13- DataFrames 14- Operators & Operations 15- Data sets/files 16- Time zones 17- Dtypes 18- Misc 19""" 20 21from collections import abc 22from datetime import date, time, timedelta, timezone 23from decimal import Decimal 24import operator 25import os 26 27from dateutil.tz import tzlocal, tzutc 28import hypothesis 29from hypothesis import strategies as st 30import numpy as np 31import pytest 32from pytz import FixedOffset, utc 33 34import pandas.util._test_decorators as td 35 36from pandas.core.dtypes.dtypes import DatetimeTZDtype, IntervalDtype 37 38import pandas as pd 39from pandas import DataFrame, Interval, Period, Series, Timedelta, Timestamp 40import pandas._testing as tm 41from pandas.core import ops 42from pandas.core.indexes.api import Index, MultiIndex 43 44 45# ---------------------------------------------------------------- 46# Configuration / Settings 47# ---------------------------------------------------------------- 48# pytest 49def pytest_configure(config): 50 # Register marks to avoid warnings in pandas.test() 51 # sync with setup.cfg 52 config.addinivalue_line("markers", "single: mark a test as single cpu only") 53 config.addinivalue_line("markers", "slow: mark a test as slow") 54 config.addinivalue_line("markers", "network: mark a test as network") 55 config.addinivalue_line( 56 "markers", "db: tests requiring a database (mysql or postgres)" 57 ) 58 config.addinivalue_line("markers", "high_memory: mark a test as a high-memory only") 59 config.addinivalue_line("markers", "clipboard: mark a pd.read_clipboard test") 60 config.addinivalue_line( 61 "markers", "arm_slow: mark a test as slow for arm64 architecture" 62 ) 63 64 65def pytest_addoption(parser): 66 parser.addoption("--skip-slow", action="store_true", help="skip slow tests") 67 parser.addoption("--skip-network", action="store_true", help="skip network tests") 68 parser.addoption("--skip-db", action="store_true", help="skip db tests") 69 parser.addoption( 70 "--run-high-memory", action="store_true", help="run high memory tests" 71 ) 72 parser.addoption("--only-slow", action="store_true", help="run only slow tests") 73 parser.addoption( 74 "--strict-data-files", 75 action="store_true", 76 help="Fail if a test is skipped for missing data file.", 77 ) 78 79 80def pytest_runtest_setup(item): 81 if "slow" in item.keywords and item.config.getoption("--skip-slow"): 82 pytest.skip("skipping due to --skip-slow") 83 84 if "slow" not in item.keywords and item.config.getoption("--only-slow"): 85 pytest.skip("skipping due to --only-slow") 86 87 if "network" in item.keywords and item.config.getoption("--skip-network"): 88 pytest.skip("skipping due to --skip-network") 89 90 if "db" in item.keywords and item.config.getoption("--skip-db"): 91 pytest.skip("skipping due to --skip-db") 92 93 if "high_memory" in item.keywords and not item.config.getoption( 94 "--run-high-memory" 95 ): 96 pytest.skip("skipping high memory test since --run-high-memory was not set") 97 98 99# Hypothesis 100hypothesis.settings.register_profile( 101 "ci", 102 # Hypothesis timing checks are tuned for scalars by default, so we bump 103 # them from 200ms to 500ms per test case as the global default. If this 104 # is too short for a specific test, (a) try to make it faster, and (b) 105 # if it really is slow add `@settings(deadline=...)` with a working value, 106 # or `deadline=None` to entirely disable timeouts for that test. 107 deadline=500, 108 suppress_health_check=(hypothesis.HealthCheck.too_slow,), 109) 110hypothesis.settings.load_profile("ci") 111 112# Registering these strategies makes them globally available via st.from_type, 113# which is use for offsets in tests/tseries/offsets/test_offsets_properties.py 114for name in "MonthBegin MonthEnd BMonthBegin BMonthEnd".split(): 115 cls = getattr(pd.tseries.offsets, name) 116 st.register_type_strategy( 117 cls, st.builds(cls, n=st.integers(-99, 99), normalize=st.booleans()) 118 ) 119 120for name in "YearBegin YearEnd BYearBegin BYearEnd".split(): 121 cls = getattr(pd.tseries.offsets, name) 122 st.register_type_strategy( 123 cls, 124 st.builds( 125 cls, 126 n=st.integers(-5, 5), 127 normalize=st.booleans(), 128 month=st.integers(min_value=1, max_value=12), 129 ), 130 ) 131 132for name in "QuarterBegin QuarterEnd BQuarterBegin BQuarterEnd".split(): 133 cls = getattr(pd.tseries.offsets, name) 134 st.register_type_strategy( 135 cls, 136 st.builds( 137 cls, 138 n=st.integers(-24, 24), 139 normalize=st.booleans(), 140 startingMonth=st.integers(min_value=1, max_value=12), 141 ), 142 ) 143 144 145# ---------------------------------------------------------------- 146# Autouse fixtures 147# ---------------------------------------------------------------- 148@pytest.fixture(autouse=True) 149def configure_tests(): 150 """ 151 Configure settings for all tests and test modules. 152 """ 153 pd.set_option("chained_assignment", "raise") 154 155 156@pytest.fixture(autouse=True) 157def add_imports(doctest_namespace): 158 """ 159 Make `np` and `pd` names available for doctests. 160 """ 161 doctest_namespace["np"] = np 162 doctest_namespace["pd"] = pd 163 164 165# ---------------------------------------------------------------- 166# Common arguments 167# ---------------------------------------------------------------- 168@pytest.fixture(params=[0, 1, "index", "columns"], ids=lambda x: f"axis {repr(x)}") 169def axis(request): 170 """ 171 Fixture for returning the axis numbers of a DataFrame. 172 """ 173 return request.param 174 175 176axis_frame = axis 177 178 179@pytest.fixture(params=[True, False, None]) 180def observed(request): 181 """ 182 Pass in the observed keyword to groupby for [True, False] 183 This indicates whether categoricals should return values for 184 values which are not in the grouper [False / None], or only values which 185 appear in the grouper [True]. [None] is supported for future compatibility 186 if we decide to change the default (and would need to warn if this 187 parameter is not passed). 188 """ 189 return request.param 190 191 192@pytest.fixture(params=[True, False, None]) 193def ordered(request): 194 """ 195 Boolean 'ordered' parameter for Categorical. 196 """ 197 return request.param 198 199 200@pytest.fixture(params=["first", "last", False]) 201def keep(request): 202 """ 203 Valid values for the 'keep' parameter used in 204 .duplicated or .drop_duplicates 205 """ 206 return request.param 207 208 209@pytest.fixture(params=["left", "right", "both", "neither"]) 210def closed(request): 211 """ 212 Fixture for trying all interval closed parameters. 213 """ 214 return request.param 215 216 217@pytest.fixture(params=["left", "right", "both", "neither"]) 218def other_closed(request): 219 """ 220 Secondary closed fixture to allow parametrizing over all pairs of closed. 221 """ 222 return request.param 223 224 225@pytest.fixture(params=[None, "gzip", "bz2", "zip", "xz"]) 226def compression(request): 227 """ 228 Fixture for trying common compression types in compression tests. 229 """ 230 return request.param 231 232 233@pytest.fixture(params=["gzip", "bz2", "zip", "xz"]) 234def compression_only(request): 235 """ 236 Fixture for trying common compression types in compression tests excluding 237 uncompressed case. 238 """ 239 return request.param 240 241 242@pytest.fixture(params=[True, False]) 243def writable(request): 244 """ 245 Fixture that an array is writable. 246 """ 247 return request.param 248 249 250@pytest.fixture(params=["inner", "outer", "left", "right"]) 251def join_type(request): 252 """ 253 Fixture for trying all types of join operations. 254 """ 255 return request.param 256 257 258@pytest.fixture(params=["nlargest", "nsmallest"]) 259def nselect_method(request): 260 """ 261 Fixture for trying all nselect methods. 262 """ 263 return request.param 264 265 266# ---------------------------------------------------------------- 267# Missing values & co. 268# ---------------------------------------------------------------- 269@pytest.fixture(params=tm.NULL_OBJECTS, ids=str) 270def nulls_fixture(request): 271 """ 272 Fixture for each null type in pandas. 273 """ 274 return request.param 275 276 277nulls_fixture2 = nulls_fixture # Generate cartesian product of nulls_fixture 278 279 280@pytest.fixture(params=[None, np.nan, pd.NaT]) 281def unique_nulls_fixture(request): 282 """ 283 Fixture for each null type in pandas, each null type exactly once. 284 """ 285 return request.param 286 287 288# Generate cartesian product of unique_nulls_fixture: 289unique_nulls_fixture2 = unique_nulls_fixture 290 291# ---------------------------------------------------------------- 292# Classes 293# ---------------------------------------------------------------- 294 295 296@pytest.fixture(params=[pd.DataFrame, pd.Series]) 297def frame_or_series(request): 298 """ 299 Fixture to parametrize over DataFrame and Series. 300 """ 301 return request.param 302 303 304@pytest.fixture( 305 params=[pd.Index, pd.Series], ids=["index", "series"] # type: ignore[list-item] 306) 307def index_or_series(request): 308 """ 309 Fixture to parametrize over Index and Series, made necessary by a mypy 310 bug, giving an error: 311 312 List item 0 has incompatible type "Type[Series]"; expected "Type[PandasObject]" 313 314 See GH#29725 315 """ 316 return request.param 317 318 319# Generate cartesian product of index_or_series fixture: 320index_or_series2 = index_or_series 321 322 323@pytest.fixture( 324 params=[pd.Index, pd.Series, pd.array], ids=["index", "series", "array"] 325) 326def index_or_series_or_array(request): 327 """ 328 Fixture to parametrize over Index, Series, and ExtensionArray 329 """ 330 return request.param 331 332 333@pytest.fixture 334def dict_subclass(): 335 """ 336 Fixture for a dictionary subclass. 337 """ 338 339 class TestSubDict(dict): 340 def __init__(self, *args, **kwargs): 341 dict.__init__(self, *args, **kwargs) 342 343 return TestSubDict 344 345 346@pytest.fixture 347def non_dict_mapping_subclass(): 348 """ 349 Fixture for a non-mapping dictionary subclass. 350 """ 351 352 class TestNonDictMapping(abc.Mapping): 353 def __init__(self, underlying_dict): 354 self._data = underlying_dict 355 356 def __getitem__(self, key): 357 return self._data.__getitem__(key) 358 359 def __iter__(self): 360 return self._data.__iter__() 361 362 def __len__(self): 363 return self._data.__len__() 364 365 return TestNonDictMapping 366 367 368# ---------------------------------------------------------------- 369# Indices 370# ---------------------------------------------------------------- 371@pytest.fixture 372def multiindex_year_month_day_dataframe_random_data(): 373 """ 374 DataFrame with 3 level MultiIndex (year, month, day) covering 375 first 100 business days from 2000-01-01 with random data 376 """ 377 tdf = tm.makeTimeDataFrame(100) 378 ymd = tdf.groupby([lambda x: x.year, lambda x: x.month, lambda x: x.day]).sum() 379 # use Int64Index, to make sure things work 380 ymd.index = ymd.index.set_levels([lev.astype("i8") for lev in ymd.index.levels]) 381 ymd.index.set_names(["year", "month", "day"], inplace=True) 382 return ymd 383 384 385@pytest.fixture 386def multiindex_dataframe_random_data(): 387 """DataFrame with 2 level MultiIndex with random data""" 388 index = MultiIndex( 389 levels=[["foo", "bar", "baz", "qux"], ["one", "two", "three"]], 390 codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]], 391 names=["first", "second"], 392 ) 393 return DataFrame( 394 np.random.randn(10, 3), index=index, columns=Index(["A", "B", "C"], name="exp") 395 ) 396 397 398def _create_multiindex(): 399 """ 400 MultiIndex used to test the general functionality of this object 401 """ 402 403 # See Also: tests.multi.conftest.idx 404 major_axis = Index(["foo", "bar", "baz", "qux"]) 405 minor_axis = Index(["one", "two"]) 406 407 major_codes = np.array([0, 0, 1, 2, 3, 3]) 408 minor_codes = np.array([0, 1, 0, 1, 0, 1]) 409 index_names = ["first", "second"] 410 return MultiIndex( 411 levels=[major_axis, minor_axis], 412 codes=[major_codes, minor_codes], 413 names=index_names, 414 verify_integrity=False, 415 ) 416 417 418def _create_mi_with_dt64tz_level(): 419 """ 420 MultiIndex with a level that is a tzaware DatetimeIndex. 421 """ 422 # GH#8367 round trip with pickle 423 return MultiIndex.from_product( 424 [[1, 2], ["a", "b"], pd.date_range("20130101", periods=3, tz="US/Eastern")], 425 names=["one", "two", "three"], 426 ) 427 428 429indices_dict = { 430 "unicode": tm.makeUnicodeIndex(100), 431 "string": tm.makeStringIndex(100), 432 "datetime": tm.makeDateIndex(100), 433 "datetime-tz": tm.makeDateIndex(100, tz="US/Pacific"), 434 "period": tm.makePeriodIndex(100), 435 "timedelta": tm.makeTimedeltaIndex(100), 436 "int": tm.makeIntIndex(100), 437 "uint": tm.makeUIntIndex(100), 438 "range": tm.makeRangeIndex(100), 439 "float": tm.makeFloatIndex(100), 440 "bool": tm.makeBoolIndex(10), 441 "categorical": tm.makeCategoricalIndex(100), 442 "interval": tm.makeIntervalIndex(100), 443 "empty": Index([]), 444 "tuples": MultiIndex.from_tuples(zip(["foo", "bar", "baz"], [1, 2, 3])), 445 "mi-with-dt64tz-level": _create_mi_with_dt64tz_level(), 446 "multi": _create_multiindex(), 447 "repeats": Index([0, 0, 1, 1, 2, 2]), 448} 449 450 451@pytest.fixture(params=indices_dict.keys()) 452def index(request): 453 """ 454 Fixture for many "simple" kinds of indices. 455 456 These indices are unlikely to cover corner cases, e.g. 457 - no names 458 - no NaTs/NaNs 459 - no values near implementation bounds 460 - ... 461 """ 462 # copy to avoid mutation, e.g. setting .name 463 return indices_dict[request.param].copy() 464 465 466# Needed to generate cartesian product of indices 467index_fixture2 = index 468 469 470@pytest.fixture(params=indices_dict.keys()) 471def index_with_missing(request): 472 """ 473 Fixture for indices with missing values 474 """ 475 if request.param in ["int", "uint", "range", "empty", "repeats"]: 476 pytest.xfail("missing values not supported") 477 # GH 35538. Use deep copy to avoid illusive bug on np-dev 478 # Azure pipeline that writes into indices_dict despite copy 479 ind = indices_dict[request.param].copy(deep=True) 480 vals = ind.values 481 if request.param in ["tuples", "mi-with-dt64tz-level", "multi"]: 482 # For setting missing values in the top level of MultiIndex 483 vals = ind.tolist() 484 vals[0] = (None,) + vals[0][1:] 485 vals[-1] = (None,) + vals[-1][1:] 486 return MultiIndex.from_tuples(vals) 487 else: 488 vals[0] = None 489 vals[-1] = None 490 return type(ind)(vals) 491 492 493# ---------------------------------------------------------------- 494# Series' 495# ---------------------------------------------------------------- 496@pytest.fixture 497def empty_series(): 498 return pd.Series([], index=[], dtype=np.float64) 499 500 501@pytest.fixture 502def string_series(): 503 """ 504 Fixture for Series of floats with Index of unique strings 505 """ 506 s = tm.makeStringSeries() 507 s.name = "series" 508 return s 509 510 511@pytest.fixture 512def object_series(): 513 """ 514 Fixture for Series of dtype object with Index of unique strings 515 """ 516 s = tm.makeObjectSeries() 517 s.name = "objects" 518 return s 519 520 521@pytest.fixture 522def datetime_series(): 523 """ 524 Fixture for Series of floats with DatetimeIndex 525 """ 526 s = tm.makeTimeSeries() 527 s.name = "ts" 528 return s 529 530 531def _create_series(index): 532 """ Helper for the _series dict """ 533 size = len(index) 534 data = np.random.randn(size) 535 return pd.Series(data, index=index, name="a") 536 537 538_series = { 539 f"series-with-{index_id}-index": _create_series(index) 540 for index_id, index in indices_dict.items() 541} 542 543 544@pytest.fixture 545def series_with_simple_index(index): 546 """ 547 Fixture for tests on series with changing types of indices. 548 """ 549 return _create_series(index) 550 551 552@pytest.fixture 553def series_with_multilevel_index(): 554 """ 555 Fixture with a Series with a 2-level MultiIndex. 556 """ 557 arrays = [ 558 ["bar", "bar", "baz", "baz", "qux", "qux", "foo", "foo"], 559 ["one", "two", "one", "two", "one", "two", "one", "two"], 560 ] 561 tuples = zip(*arrays) 562 index = MultiIndex.from_tuples(tuples) 563 data = np.random.randn(8) 564 ser = Series(data, index=index) 565 ser[3] = np.NaN 566 return ser 567 568 569_narrow_dtypes = [ 570 np.float16, 571 np.float32, 572 np.int8, 573 np.int16, 574 np.int32, 575 np.uint8, 576 np.uint16, 577 np.uint32, 578] 579_narrow_series = { 580 f"{dtype.__name__}-series": tm.makeFloatSeries(name="a").astype(dtype) 581 for dtype in _narrow_dtypes 582} 583 584 585@pytest.fixture(params=_narrow_series.keys()) 586def narrow_series(request): 587 """ 588 Fixture for Series with low precision data types 589 """ 590 # copy to avoid mutation, e.g. setting .name 591 return _narrow_series[request.param].copy() 592 593 594_index_or_series_objs = {**indices_dict, **_series, **_narrow_series} 595 596 597@pytest.fixture(params=_index_or_series_objs.keys()) 598def index_or_series_obj(request): 599 """ 600 Fixture for tests on indexes, series and series with a narrow dtype 601 copy to avoid mutation, e.g. setting .name 602 """ 603 return _index_or_series_objs[request.param].copy(deep=True) 604 605 606# ---------------------------------------------------------------- 607# DataFrames 608# ---------------------------------------------------------------- 609@pytest.fixture 610def empty_frame(): 611 return DataFrame() 612 613 614@pytest.fixture 615def int_frame(): 616 """ 617 Fixture for DataFrame of ints with index of unique strings 618 619 Columns are ['A', 'B', 'C', 'D'] 620 621 A B C D 622 vpBeWjM651 1 0 1 0 623 5JyxmrP1En -1 0 0 0 624 qEDaoD49U2 -1 1 0 0 625 m66TkTfsFe 0 0 0 0 626 EHPaNzEUFm -1 0 -1 0 627 fpRJCevQhi 2 0 0 0 628 OlQvnmfi3Q 0 0 -2 0 629 ... .. .. .. .. 630 uB1FPlz4uP 0 0 0 1 631 EcSe6yNzCU 0 0 -1 0 632 L50VudaiI8 -1 1 -2 0 633 y3bpw4nwIp 0 -1 0 0 634 H0RdLLwrCT 1 1 0 0 635 rY82K0vMwm 0 0 0 0 636 1OPIUjnkjk 2 0 0 0 637 638 [30 rows x 4 columns] 639 """ 640 return DataFrame(tm.getSeriesData()).astype("int64") 641 642 643@pytest.fixture 644def datetime_frame(): 645 """ 646 Fixture for DataFrame of floats with DatetimeIndex 647 648 Columns are ['A', 'B', 'C', 'D'] 649 650 A B C D 651 2000-01-03 -1.122153 0.468535 0.122226 1.693711 652 2000-01-04 0.189378 0.486100 0.007864 -1.216052 653 2000-01-05 0.041401 -0.835752 -0.035279 -0.414357 654 2000-01-06 0.430050 0.894352 0.090719 0.036939 655 2000-01-07 -0.620982 -0.668211 -0.706153 1.466335 656 2000-01-10 -0.752633 0.328434 -0.815325 0.699674 657 2000-01-11 -2.236969 0.615737 -0.829076 -1.196106 658 ... ... ... ... ... 659 2000-02-03 1.642618 -0.579288 0.046005 1.385249 660 2000-02-04 -0.544873 -1.160962 -0.284071 -1.418351 661 2000-02-07 -2.656149 -0.601387 1.410148 0.444150 662 2000-02-08 -1.201881 -1.289040 0.772992 -1.445300 663 2000-02-09 1.377373 0.398619 1.008453 -0.928207 664 2000-02-10 0.473194 -0.636677 0.984058 0.511519 665 2000-02-11 -0.965556 0.408313 -1.312844 -0.381948 666 667 [30 rows x 4 columns] 668 """ 669 return DataFrame(tm.getTimeSeriesData()) 670 671 672@pytest.fixture 673def float_frame(): 674 """ 675 Fixture for DataFrame of floats with index of unique strings 676 677 Columns are ['A', 'B', 'C', 'D']. 678 679 A B C D 680 P7GACiRnxd -0.465578 -0.361863 0.886172 -0.053465 681 qZKh6afn8n -0.466693 -0.373773 0.266873 1.673901 682 tkp0r6Qble 0.148691 -0.059051 0.174817 1.598433 683 wP70WOCtv8 0.133045 -0.581994 -0.992240 0.261651 684 M2AeYQMnCz -1.207959 -0.185775 0.588206 0.563938 685 QEPzyGDYDo -0.381843 -0.758281 0.502575 -0.565053 686 r78Jwns6dn -0.653707 0.883127 0.682199 0.206159 687 ... ... ... ... ... 688 IHEGx9NO0T -0.277360 0.113021 -1.018314 0.196316 689 lPMj8K27FA -1.313667 -0.604776 -1.305618 -0.863999 690 qa66YMWQa5 1.110525 0.475310 -0.747865 0.032121 691 yOa0ATsmcE -0.431457 0.067094 0.096567 -0.264962 692 65znX3uRNG 1.528446 0.160416 -0.109635 -0.032987 693 eCOBvKqf3e 0.235281 1.622222 0.781255 0.392871 694 xSucinXxuV -1.263557 0.252799 -0.552247 0.400426 695 696 [30 rows x 4 columns] 697 """ 698 return DataFrame(tm.getSeriesData()) 699 700 701# ---------------------------------------------------------------- 702# Scalars 703# ---------------------------------------------------------------- 704@pytest.fixture( 705 params=[ 706 (Interval(left=0, right=5), IntervalDtype("int64")), 707 (Interval(left=0.1, right=0.5), IntervalDtype("float64")), 708 (Period("2012-01", freq="M"), "period[M]"), 709 (Period("2012-02-01", freq="D"), "period[D]"), 710 ( 711 Timestamp("2011-01-01", tz="US/Eastern"), 712 DatetimeTZDtype(tz="US/Eastern"), 713 ), 714 (Timedelta(seconds=500), "timedelta64[ns]"), 715 ] 716) 717def ea_scalar_and_dtype(request): 718 return request.param 719 720 721# ---------------------------------------------------------------- 722# Operators & Operations 723# ---------------------------------------------------------------- 724_all_arithmetic_operators = [ 725 "__add__", 726 "__radd__", 727 "__sub__", 728 "__rsub__", 729 "__mul__", 730 "__rmul__", 731 "__floordiv__", 732 "__rfloordiv__", 733 "__truediv__", 734 "__rtruediv__", 735 "__pow__", 736 "__rpow__", 737 "__mod__", 738 "__rmod__", 739] 740 741 742@pytest.fixture(params=_all_arithmetic_operators) 743def all_arithmetic_operators(request): 744 """ 745 Fixture for dunder names for common arithmetic operations. 746 """ 747 return request.param 748 749 750@pytest.fixture( 751 params=[ 752 operator.add, 753 ops.radd, 754 operator.sub, 755 ops.rsub, 756 operator.mul, 757 ops.rmul, 758 operator.truediv, 759 ops.rtruediv, 760 operator.floordiv, 761 ops.rfloordiv, 762 operator.mod, 763 ops.rmod, 764 operator.pow, 765 ops.rpow, 766 operator.eq, 767 operator.ne, 768 operator.lt, 769 operator.le, 770 operator.gt, 771 operator.ge, 772 operator.and_, 773 ops.rand_, 774 operator.xor, 775 ops.rxor, 776 operator.or_, 777 ops.ror_, 778 ] 779) 780def all_binary_operators(request): 781 """ 782 Fixture for operator and roperator arithmetic, comparison, and logical ops. 783 """ 784 return request.param 785 786 787@pytest.fixture( 788 params=[ 789 operator.add, 790 ops.radd, 791 operator.sub, 792 ops.rsub, 793 operator.mul, 794 ops.rmul, 795 operator.truediv, 796 ops.rtruediv, 797 operator.floordiv, 798 ops.rfloordiv, 799 operator.mod, 800 ops.rmod, 801 operator.pow, 802 ops.rpow, 803 ] 804) 805def all_arithmetic_functions(request): 806 """ 807 Fixture for operator and roperator arithmetic functions. 808 809 Notes 810 ----- 811 This includes divmod and rdivmod, whereas all_arithmetic_operators 812 does not. 813 """ 814 return request.param 815 816 817_all_numeric_reductions = [ 818 "sum", 819 "max", 820 "min", 821 "mean", 822 "prod", 823 "std", 824 "var", 825 "median", 826 "kurt", 827 "skew", 828] 829 830 831@pytest.fixture(params=_all_numeric_reductions) 832def all_numeric_reductions(request): 833 """ 834 Fixture for numeric reduction names. 835 """ 836 return request.param 837 838 839_all_boolean_reductions = ["all", "any"] 840 841 842@pytest.fixture(params=_all_boolean_reductions) 843def all_boolean_reductions(request): 844 """ 845 Fixture for boolean reduction names. 846 """ 847 return request.param 848 849 850_all_reductions = _all_numeric_reductions + _all_boolean_reductions 851 852 853@pytest.fixture(params=_all_reductions) 854def all_reductions(request): 855 """ 856 Fixture for all (boolean + numeric) reduction names. 857 """ 858 return request.param 859 860 861@pytest.fixture(params=["__eq__", "__ne__", "__le__", "__lt__", "__ge__", "__gt__"]) 862def all_compare_operators(request): 863 """ 864 Fixture for dunder names for common compare operations 865 866 * >= 867 * > 868 * == 869 * != 870 * < 871 * <= 872 """ 873 return request.param 874 875 876@pytest.fixture(params=["__le__", "__lt__", "__ge__", "__gt__"]) 877def compare_operators_no_eq_ne(request): 878 """ 879 Fixture for dunder names for compare operations except == and != 880 881 * >= 882 * > 883 * < 884 * <= 885 """ 886 return request.param 887 888 889@pytest.fixture( 890 params=["__and__", "__rand__", "__or__", "__ror__", "__xor__", "__rxor__"] 891) 892def all_logical_operators(request): 893 """ 894 Fixture for dunder names for common logical operations 895 896 * | 897 * & 898 * ^ 899 """ 900 return request.param 901 902 903# ---------------------------------------------------------------- 904# Data sets/files 905# ---------------------------------------------------------------- 906@pytest.fixture 907def strict_data_files(pytestconfig): 908 """ 909 Returns the configuration for the test setting `--strict-data-files`. 910 """ 911 return pytestconfig.getoption("--strict-data-files") 912 913 914@pytest.fixture 915def datapath(strict_data_files): 916 """ 917 Get the path to a data file. 918 919 Parameters 920 ---------- 921 path : str 922 Path to the file, relative to ``pandas/tests/`` 923 924 Returns 925 ------- 926 path including ``pandas/tests``. 927 928 Raises 929 ------ 930 ValueError 931 If the path doesn't exist and the --strict-data-files option is set. 932 """ 933 BASE_PATH = os.path.join(os.path.dirname(__file__), "tests") 934 935 def deco(*args): 936 path = os.path.join(BASE_PATH, *args) 937 if not os.path.exists(path): 938 if strict_data_files: 939 raise ValueError( 940 f"Could not find file {path} and --strict-data-files is set." 941 ) 942 else: 943 pytest.skip(f"Could not find {path}.") 944 return path 945 946 return deco 947 948 949@pytest.fixture 950def iris(datapath): 951 """ 952 The iris dataset as a DataFrame. 953 """ 954 return pd.read_csv(datapath("io", "data", "csv", "iris.csv")) 955 956 957# ---------------------------------------------------------------- 958# Time zones 959# ---------------------------------------------------------------- 960TIMEZONES = [ 961 None, 962 "UTC", 963 "US/Eastern", 964 "Asia/Tokyo", 965 "dateutil/US/Pacific", 966 "dateutil/Asia/Singapore", 967 "+01:15", 968 "-02:15", 969 "UTC+01:15", 970 "UTC-02:15", 971 tzutc(), 972 tzlocal(), 973 FixedOffset(300), 974 FixedOffset(0), 975 FixedOffset(-300), 976 timezone.utc, 977 timezone(timedelta(hours=1)), 978 timezone(timedelta(hours=-1), name="foo"), 979] 980TIMEZONE_IDS = [repr(i) for i in TIMEZONES] 981 982 983@td.parametrize_fixture_doc(str(TIMEZONE_IDS)) 984@pytest.fixture(params=TIMEZONES, ids=TIMEZONE_IDS) 985def tz_naive_fixture(request): 986 """ 987 Fixture for trying timezones including default (None): {0} 988 """ 989 return request.param 990 991 992@td.parametrize_fixture_doc(str(TIMEZONE_IDS[1:])) 993@pytest.fixture(params=TIMEZONES[1:], ids=TIMEZONE_IDS[1:]) 994def tz_aware_fixture(request): 995 """ 996 Fixture for trying explicit timezones: {0} 997 """ 998 return request.param 999 1000 1001# Generate cartesian product of tz_aware_fixture: 1002tz_aware_fixture2 = tz_aware_fixture 1003 1004 1005@pytest.fixture(scope="module") 1006def datetime_tz_utc(): 1007 """ 1008 Yields the UTC timezone object from the datetime module. 1009 """ 1010 return timezone.utc 1011 1012 1013@pytest.fixture(params=["utc", "dateutil/UTC", utc, tzutc(), timezone.utc]) 1014def utc_fixture(request): 1015 """ 1016 Fixture to provide variants of UTC timezone strings and tzinfo objects. 1017 """ 1018 return request.param 1019 1020 1021# ---------------------------------------------------------------- 1022# Dtypes 1023# ---------------------------------------------------------------- 1024@pytest.fixture(params=tm.STRING_DTYPES) 1025def string_dtype(request): 1026 """ 1027 Parametrized fixture for string dtypes. 1028 1029 * str 1030 * 'str' 1031 * 'U' 1032 """ 1033 return request.param 1034 1035 1036@pytest.fixture(params=tm.BYTES_DTYPES) 1037def bytes_dtype(request): 1038 """ 1039 Parametrized fixture for bytes dtypes. 1040 1041 * bytes 1042 * 'bytes' 1043 """ 1044 return request.param 1045 1046 1047@pytest.fixture(params=tm.OBJECT_DTYPES) 1048def object_dtype(request): 1049 """ 1050 Parametrized fixture for object dtypes. 1051 1052 * object 1053 * 'object' 1054 """ 1055 return request.param 1056 1057 1058@pytest.fixture(params=tm.DATETIME64_DTYPES) 1059def datetime64_dtype(request): 1060 """ 1061 Parametrized fixture for datetime64 dtypes. 1062 1063 * 'datetime64[ns]' 1064 * 'M8[ns]' 1065 """ 1066 return request.param 1067 1068 1069@pytest.fixture(params=tm.TIMEDELTA64_DTYPES) 1070def timedelta64_dtype(request): 1071 """ 1072 Parametrized fixture for timedelta64 dtypes. 1073 1074 * 'timedelta64[ns]' 1075 * 'm8[ns]' 1076 """ 1077 return request.param 1078 1079 1080@pytest.fixture(params=tm.FLOAT_DTYPES) 1081def float_dtype(request): 1082 """ 1083 Parameterized fixture for float dtypes. 1084 1085 * float 1086 * 'float32' 1087 * 'float64' 1088 """ 1089 return request.param 1090 1091 1092@pytest.fixture(params=tm.FLOAT_EA_DTYPES) 1093def float_ea_dtype(request): 1094 """ 1095 Parameterized fixture for float dtypes. 1096 1097 * 'Float32' 1098 * 'Float64' 1099 """ 1100 return request.param 1101 1102 1103@pytest.fixture(params=tm.FLOAT_DTYPES + tm.FLOAT_EA_DTYPES) 1104def any_float_allowed_nullable_dtype(request): 1105 """ 1106 Parameterized fixture for float dtypes. 1107 1108 * float 1109 * 'float32' 1110 * 'float64' 1111 * 'Float32' 1112 * 'Float64' 1113 """ 1114 return request.param 1115 1116 1117@pytest.fixture(params=tm.COMPLEX_DTYPES) 1118def complex_dtype(request): 1119 """ 1120 Parameterized fixture for complex dtypes. 1121 1122 * complex 1123 * 'complex64' 1124 * 'complex128' 1125 """ 1126 return request.param 1127 1128 1129@pytest.fixture(params=tm.SIGNED_INT_DTYPES) 1130def sint_dtype(request): 1131 """ 1132 Parameterized fixture for signed integer dtypes. 1133 1134 * int 1135 * 'int8' 1136 * 'int16' 1137 * 'int32' 1138 * 'int64' 1139 """ 1140 return request.param 1141 1142 1143@pytest.fixture(params=tm.UNSIGNED_INT_DTYPES) 1144def uint_dtype(request): 1145 """ 1146 Parameterized fixture for unsigned integer dtypes. 1147 1148 * 'uint8' 1149 * 'uint16' 1150 * 'uint32' 1151 * 'uint64' 1152 """ 1153 return request.param 1154 1155 1156@pytest.fixture(params=tm.ALL_INT_DTYPES) 1157def any_int_dtype(request): 1158 """ 1159 Parameterized fixture for any integer dtype. 1160 1161 * int 1162 * 'int8' 1163 * 'uint8' 1164 * 'int16' 1165 * 'uint16' 1166 * 'int32' 1167 * 'uint32' 1168 * 'int64' 1169 * 'uint64' 1170 """ 1171 return request.param 1172 1173 1174@pytest.fixture(params=tm.ALL_EA_INT_DTYPES) 1175def any_nullable_int_dtype(request): 1176 """ 1177 Parameterized fixture for any nullable integer dtype. 1178 1179 * 'UInt8' 1180 * 'Int8' 1181 * 'UInt16' 1182 * 'Int16' 1183 * 'UInt32' 1184 * 'Int32' 1185 * 'UInt64' 1186 * 'Int64' 1187 """ 1188 return request.param 1189 1190 1191@pytest.fixture(params=tm.ALL_INT_DTYPES + tm.ALL_EA_INT_DTYPES) 1192def any_int_or_nullable_int_dtype(request): 1193 """ 1194 Parameterized fixture for any nullable integer dtype. 1195 1196 * int 1197 * 'int8' 1198 * 'uint8' 1199 * 'int16' 1200 * 'uint16' 1201 * 'int32' 1202 * 'uint32' 1203 * 'int64' 1204 * 'uint64' 1205 * 'UInt8' 1206 * 'Int8' 1207 * 'UInt16' 1208 * 'Int16' 1209 * 'UInt32' 1210 * 'Int32' 1211 * 'UInt64' 1212 * 'Int64' 1213 """ 1214 return request.param 1215 1216 1217@pytest.fixture(params=tm.ALL_EA_INT_DTYPES + tm.FLOAT_EA_DTYPES) 1218def any_numeric_dtype(request): 1219 """ 1220 Parameterized fixture for any nullable integer dtype and 1221 any float ea dtypes. 1222 1223 * 'UInt8' 1224 * 'Int8' 1225 * 'UInt16' 1226 * 'Int16' 1227 * 'UInt32' 1228 * 'Int32' 1229 * 'UInt64' 1230 * 'Int64' 1231 * 'Float32' 1232 * 'Float64' 1233 """ 1234 return request.param 1235 1236 1237@pytest.fixture(params=tm.SIGNED_EA_INT_DTYPES) 1238def any_signed_nullable_int_dtype(request): 1239 """ 1240 Parameterized fixture for any signed nullable integer dtype. 1241 1242 * 'Int8' 1243 * 'Int16' 1244 * 'Int32' 1245 * 'Int64' 1246 """ 1247 return request.param 1248 1249 1250@pytest.fixture(params=tm.ALL_REAL_DTYPES) 1251def any_real_dtype(request): 1252 """ 1253 Parameterized fixture for any (purely) real numeric dtype. 1254 1255 * int 1256 * 'int8' 1257 * 'uint8' 1258 * 'int16' 1259 * 'uint16' 1260 * 'int32' 1261 * 'uint32' 1262 * 'int64' 1263 * 'uint64' 1264 * float 1265 * 'float32' 1266 * 'float64' 1267 """ 1268 return request.param 1269 1270 1271@pytest.fixture(params=tm.ALL_NUMPY_DTYPES) 1272def any_numpy_dtype(request): 1273 """ 1274 Parameterized fixture for all numpy dtypes. 1275 1276 * bool 1277 * 'bool' 1278 * int 1279 * 'int8' 1280 * 'uint8' 1281 * 'int16' 1282 * 'uint16' 1283 * 'int32' 1284 * 'uint32' 1285 * 'int64' 1286 * 'uint64' 1287 * float 1288 * 'float32' 1289 * 'float64' 1290 * complex 1291 * 'complex64' 1292 * 'complex128' 1293 * str 1294 * 'str' 1295 * 'U' 1296 * bytes 1297 * 'bytes' 1298 * 'datetime64[ns]' 1299 * 'M8[ns]' 1300 * 'timedelta64[ns]' 1301 * 'm8[ns]' 1302 * object 1303 * 'object' 1304 """ 1305 return request.param 1306 1307 1308# categoricals are handled separately 1309_any_skipna_inferred_dtype = [ 1310 ("string", ["a", np.nan, "c"]), 1311 ("string", ["a", pd.NA, "c"]), 1312 ("bytes", [b"a", np.nan, b"c"]), 1313 ("empty", [np.nan, np.nan, np.nan]), 1314 ("empty", []), 1315 ("mixed-integer", ["a", np.nan, 2]), 1316 ("mixed", ["a", np.nan, 2.0]), 1317 ("floating", [1.0, np.nan, 2.0]), 1318 ("integer", [1, np.nan, 2]), 1319 ("mixed-integer-float", [1, np.nan, 2.0]), 1320 ("decimal", [Decimal(1), np.nan, Decimal(2)]), 1321 ("boolean", [True, np.nan, False]), 1322 ("boolean", [True, pd.NA, False]), 1323 ("datetime64", [np.datetime64("2013-01-01"), np.nan, np.datetime64("2018-01-01")]), 1324 ("datetime", [pd.Timestamp("20130101"), np.nan, pd.Timestamp("20180101")]), 1325 ("date", [date(2013, 1, 1), np.nan, date(2018, 1, 1)]), 1326 # The following two dtypes are commented out due to GH 23554 1327 # ('complex', [1 + 1j, np.nan, 2 + 2j]), 1328 # ('timedelta64', [np.timedelta64(1, 'D'), 1329 # np.nan, np.timedelta64(2, 'D')]), 1330 ("timedelta", [timedelta(1), np.nan, timedelta(2)]), 1331 ("time", [time(1), np.nan, time(2)]), 1332 ("period", [pd.Period(2013), pd.NaT, pd.Period(2018)]), 1333 ("interval", [pd.Interval(0, 1), np.nan, pd.Interval(0, 2)]), 1334] 1335ids, _ = zip(*_any_skipna_inferred_dtype) # use inferred type as fixture-id 1336 1337 1338@pytest.fixture(params=_any_skipna_inferred_dtype, ids=ids) 1339def any_skipna_inferred_dtype(request): 1340 """ 1341 Fixture for all inferred dtypes from _libs.lib.infer_dtype 1342 1343 The covered (inferred) types are: 1344 * 'string' 1345 * 'empty' 1346 * 'bytes' 1347 * 'mixed' 1348 * 'mixed-integer' 1349 * 'mixed-integer-float' 1350 * 'floating' 1351 * 'integer' 1352 * 'decimal' 1353 * 'boolean' 1354 * 'datetime64' 1355 * 'datetime' 1356 * 'date' 1357 * 'timedelta' 1358 * 'time' 1359 * 'period' 1360 * 'interval' 1361 1362 Returns 1363 ------- 1364 inferred_dtype : str 1365 The string for the inferred dtype from _libs.lib.infer_dtype 1366 values : np.ndarray 1367 An array of object dtype that will be inferred to have 1368 `inferred_dtype` 1369 1370 Examples 1371 -------- 1372 >>> import pandas._libs.lib as lib 1373 >>> 1374 >>> def test_something(any_skipna_inferred_dtype): 1375 ... inferred_dtype, values = any_skipna_inferred_dtype 1376 ... # will pass 1377 ... assert lib.infer_dtype(values, skipna=True) == inferred_dtype 1378 """ 1379 inferred_dtype, values = request.param 1380 values = np.array(values, dtype=object) # object dtype to avoid casting 1381 1382 # correctness of inference tested in tests/dtypes/test_inference.py 1383 return inferred_dtype, values 1384 1385 1386# ---------------------------------------------------------------- 1387# Misc 1388# ---------------------------------------------------------------- 1389@pytest.fixture 1390def ip(): 1391 """ 1392 Get an instance of IPython.InteractiveShell. 1393 1394 Will raise a skip if IPython is not installed. 1395 """ 1396 pytest.importorskip("IPython", minversion="6.0.0") 1397 from IPython.core.interactiveshell import InteractiveShell 1398 1399 # GH#35711 make sure sqlite history file handle is not leaked 1400 from traitlets.config import Config # isort:skip 1401 1402 c = Config() 1403 c.HistoryManager.hist_file = ":memory:" 1404 1405 return InteractiveShell(config=c) 1406 1407 1408@pytest.fixture(params=["bsr", "coo", "csc", "csr", "dia", "dok", "lil"]) 1409def spmatrix(request): 1410 """ 1411 Yields scipy sparse matrix classes. 1412 """ 1413 from scipy import sparse 1414 1415 return getattr(sparse, request.param + "_matrix") 1416 1417 1418@pytest.fixture( 1419 params=[ 1420 getattr(pd.offsets, o) 1421 for o in pd.offsets.__all__ 1422 if issubclass(getattr(pd.offsets, o), pd.offsets.Tick) 1423 ] 1424) 1425def tick_classes(request): 1426 """ 1427 Fixture for Tick based datetime offsets available for a time series. 1428 """ 1429 return request.param 1430 1431 1432@pytest.fixture(params=[None, lambda x: x]) 1433def sort_by_key(request): 1434 """ 1435 Simple fixture for testing keys in sorting methods. 1436 Tests None (no key) and the identity key. 1437 """ 1438 return request.param 1439 1440 1441@pytest.fixture() 1442def fsspectest(): 1443 pytest.importorskip("fsspec") 1444 from fsspec import register_implementation 1445 from fsspec.implementations.memory import MemoryFileSystem 1446 from fsspec.registry import _registry as registry 1447 1448 class TestMemoryFS(MemoryFileSystem): 1449 protocol = "testmem" 1450 test = [None] 1451 1452 def __init__(self, **kwargs): 1453 self.test[0] = kwargs.pop("test", None) 1454 super().__init__(**kwargs) 1455 1456 register_implementation("testmem", TestMemoryFS, clobber=True) 1457 yield TestMemoryFS() 1458 registry.pop("testmem", None) 1459 TestMemoryFS.test[0] = None 1460 TestMemoryFS.store.clear() 1461 1462 1463@pytest.fixture( 1464 params=[ 1465 ("foo", None, None), 1466 ("Egon", "Venkman", None), 1467 ("NCC1701D", "NCC1701D", "NCC1701D"), 1468 ] 1469) 1470def names(request): 1471 """ 1472 A 3-tuple of names, the first two for operands, the last for a result. 1473 """ 1474 return request.param 1475