conftest.py 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065
  1. """
  2. This file is very long and growing, but it was decided to not split it yet, as
  3. it's still manageable (2020-03-17, ~1.1k LoC). See gh-31989
  4. Instead of splitting it was decided to define sections here:
  5. - Configuration / Settings
  6. - Autouse fixtures
  7. - Common arguments
  8. - Missing values & co.
  9. - Classes
  10. - Indices
  11. - Series'
  12. - DataFrames
  13. - Operators & Operations
  14. - Data sets/files
  15. - Time zones
  16. - Dtypes
  17. - Misc
  18. """
  19. from __future__ import annotations
  20. from collections import abc
  21. from datetime import (
  22. date,
  23. datetime,
  24. time,
  25. timedelta,
  26. timezone,
  27. )
  28. from decimal import Decimal
  29. import operator
  30. import os
  31. from typing import (
  32. TYPE_CHECKING,
  33. Callable,
  34. )
  35. from dateutil.tz import (
  36. tzlocal,
  37. tzutc,
  38. )
  39. import hypothesis
  40. from hypothesis import strategies as st
  41. import numpy as np
  42. import pytest
  43. from pytz import (
  44. FixedOffset,
  45. utc,
  46. )
  47. from pandas._config.config import _get_option
  48. import pandas.util._test_decorators as td
  49. from pandas.core.dtypes.dtypes import (
  50. DatetimeTZDtype,
  51. IntervalDtype,
  52. )
  53. import pandas as pd
  54. from pandas import (
  55. CategoricalIndex,
  56. DataFrame,
  57. Interval,
  58. IntervalIndex,
  59. Period,
  60. RangeIndex,
  61. Series,
  62. Timedelta,
  63. Timestamp,
  64. date_range,
  65. period_range,
  66. timedelta_range,
  67. )
  68. import pandas._testing as tm
  69. from pandas.core import ops
  70. from pandas.core.indexes.api import (
  71. Index,
  72. MultiIndex,
  73. )
  74. from pandas.util.version import Version
  75. if TYPE_CHECKING:
  76. from collections.abc import (
  77. Hashable,
  78. Iterator,
  79. )
  80. try:
  81. import pyarrow as pa
  82. except ImportError:
  83. has_pyarrow = False
  84. else:
  85. del pa
  86. has_pyarrow = True
  87. import zoneinfo
  88. try:
  89. zoneinfo.ZoneInfo("UTC")
  90. except zoneinfo.ZoneInfoNotFoundError:
  91. zoneinfo = None # type: ignore[assignment]
  92. # ----------------------------------------------------------------
  93. # Configuration / Settings
  94. # ----------------------------------------------------------------
  95. # pytest
  96. def pytest_addoption(parser) -> None:
  97. parser.addoption(
  98. "--no-strict-data-files",
  99. action="store_false",
  100. help="Don't fail if a test is skipped for missing data file.",
  101. )
  102. def ignore_doctest_warning(item: pytest.Item, path: str, message: str) -> None:
  103. """Ignore doctest warning.
  104. Parameters
  105. ----------
  106. item : pytest.Item
  107. pytest test item.
  108. path : str
  109. Module path to Python object, e.g. "pandas.core.frame.DataFrame.append". A
  110. warning will be filtered when item.name ends with in given path. So it is
  111. sufficient to specify e.g. "DataFrame.append".
  112. message : str
  113. Message to be filtered.
  114. """
  115. if item.name.endswith(path):
  116. item.add_marker(pytest.mark.filterwarnings(f"ignore:{message}"))
  117. def pytest_collection_modifyitems(items, config) -> None:
  118. is_doctest = config.getoption("--doctest-modules") or config.getoption(
  119. "--doctest-cython", default=False
  120. )
  121. # Warnings from doctests that can be ignored; place reason in comment above.
  122. # Each entry specifies (path, message) - see the ignore_doctest_warning function
  123. ignored_doctest_warnings = [
  124. ("is_int64_dtype", "is_int64_dtype is deprecated"),
  125. ("is_interval_dtype", "is_interval_dtype is deprecated"),
  126. ("is_period_dtype", "is_period_dtype is deprecated"),
  127. ("is_datetime64tz_dtype", "is_datetime64tz_dtype is deprecated"),
  128. ("is_categorical_dtype", "is_categorical_dtype is deprecated"),
  129. ("is_sparse", "is_sparse is deprecated"),
  130. ("DataFrameGroupBy.fillna", "DataFrameGroupBy.fillna is deprecated"),
  131. ("NDFrame.replace", "The 'method' keyword"),
  132. ("NDFrame.replace", "Series.replace without 'value'"),
  133. ("NDFrame.clip", "Downcasting behavior in Series and DataFrame methods"),
  134. ("Series.idxmin", "The behavior of Series.idxmin"),
  135. ("Series.idxmax", "The behavior of Series.idxmax"),
  136. ("SeriesGroupBy.fillna", "SeriesGroupBy.fillna is deprecated"),
  137. ("SeriesGroupBy.idxmin", "The behavior of Series.idxmin"),
  138. ("SeriesGroupBy.idxmax", "The behavior of Series.idxmax"),
  139. # Docstring divides by zero to show behavior difference
  140. ("missing.mask_zero_div_zero", "divide by zero encountered"),
  141. (
  142. "to_pydatetime",
  143. "The behavior of DatetimeProperties.to_pydatetime is deprecated",
  144. ),
  145. (
  146. "pandas.core.generic.NDFrame.bool",
  147. "(Series|DataFrame).bool is now deprecated and will be removed "
  148. "in future version of pandas",
  149. ),
  150. (
  151. "pandas.core.generic.NDFrame.first",
  152. "first is deprecated and will be removed in a future version. "
  153. "Please create a mask and filter using `.loc` instead",
  154. ),
  155. (
  156. "Resampler.fillna",
  157. "DatetimeIndexResampler.fillna is deprecated",
  158. ),
  159. (
  160. "DataFrameGroupBy.fillna",
  161. "DataFrameGroupBy.fillna with 'method' is deprecated",
  162. ),
  163. (
  164. "DataFrameGroupBy.fillna",
  165. "DataFrame.fillna with 'method' is deprecated",
  166. ),
  167. ("read_parquet", "Passing a BlockManager to DataFrame is deprecated"),
  168. ]
  169. if is_doctest:
  170. for item in items:
  171. for path, message in ignored_doctest_warnings:
  172. ignore_doctest_warning(item, path, message)
  173. hypothesis_health_checks = [hypothesis.HealthCheck.too_slow]
  174. if Version(hypothesis.__version__) >= Version("6.83.2"):
  175. hypothesis_health_checks.append(hypothesis.HealthCheck.differing_executors)
  176. # Hypothesis
  177. hypothesis.settings.register_profile(
  178. "ci",
  179. # Hypothesis timing checks are tuned for scalars by default, so we bump
  180. # them from 200ms to 500ms per test case as the global default. If this
  181. # is too short for a specific test, (a) try to make it faster, and (b)
  182. # if it really is slow add `@settings(deadline=...)` with a working value,
  183. # or `deadline=None` to entirely disable timeouts for that test.
  184. # 2022-02-09: Changed deadline from 500 -> None. Deadline leads to
  185. # non-actionable, flaky CI failures (# GH 24641, 44969, 45118, 44969)
  186. deadline=None,
  187. suppress_health_check=tuple(hypothesis_health_checks),
  188. )
  189. hypothesis.settings.load_profile("ci")
  190. # Registering these strategies makes them globally available via st.from_type,
  191. # which is use for offsets in tests/tseries/offsets/test_offsets_properties.py
  192. for name in "MonthBegin MonthEnd BMonthBegin BMonthEnd".split():
  193. cls = getattr(pd.tseries.offsets, name)
  194. st.register_type_strategy(
  195. cls, st.builds(cls, n=st.integers(-99, 99), normalize=st.booleans())
  196. )
  197. for name in "YearBegin YearEnd BYearBegin BYearEnd".split():
  198. cls = getattr(pd.tseries.offsets, name)
  199. st.register_type_strategy(
  200. cls,
  201. st.builds(
  202. cls,
  203. n=st.integers(-5, 5),
  204. normalize=st.booleans(),
  205. month=st.integers(min_value=1, max_value=12),
  206. ),
  207. )
  208. for name in "QuarterBegin QuarterEnd BQuarterBegin BQuarterEnd".split():
  209. cls = getattr(pd.tseries.offsets, name)
  210. st.register_type_strategy(
  211. cls,
  212. st.builds(
  213. cls,
  214. n=st.integers(-24, 24),
  215. normalize=st.booleans(),
  216. startingMonth=st.integers(min_value=1, max_value=12),
  217. ),
  218. )
  219. # ----------------------------------------------------------------
  220. # Autouse fixtures
  221. # ----------------------------------------------------------------
  222. # https://github.com/pytest-dev/pytest/issues/11873
  223. # Would like to avoid autouse=True, but cannot as of pytest 8.0.0
  224. @pytest.fixture(autouse=True)
  225. def add_doctest_imports(doctest_namespace) -> None:
  226. """
  227. Make `np` and `pd` names available for doctests.
  228. """
  229. doctest_namespace["np"] = np
  230. doctest_namespace["pd"] = pd
  231. @pytest.fixture(autouse=True)
  232. def configure_tests() -> None:
  233. """
  234. Configure settings for all tests and test modules.
  235. """
  236. pd.set_option("chained_assignment", "raise")
  237. # ----------------------------------------------------------------
  238. # Common arguments
  239. # ----------------------------------------------------------------
  240. @pytest.fixture(params=[0, 1, "index", "columns"], ids=lambda x: f"axis={repr(x)}")
  241. def axis(request):
  242. """
  243. Fixture for returning the axis numbers of a DataFrame.
  244. """
  245. return request.param
  246. axis_frame = axis
  247. @pytest.fixture(params=[1, "columns"], ids=lambda x: f"axis={repr(x)}")
  248. def axis_1(request):
  249. """
  250. Fixture for returning aliases of axis 1 of a DataFrame.
  251. """
  252. return request.param
  253. @pytest.fixture(params=[True, False, None])
  254. def observed(request):
  255. """
  256. Pass in the observed keyword to groupby for [True, False]
  257. This indicates whether categoricals should return values for
  258. values which are not in the grouper [False / None], or only values which
  259. appear in the grouper [True]. [None] is supported for future compatibility
  260. if we decide to change the default (and would need to warn if this
  261. parameter is not passed).
  262. """
  263. return request.param
  264. @pytest.fixture(params=[True, False, None])
  265. def ordered(request):
  266. """
  267. Boolean 'ordered' parameter for Categorical.
  268. """
  269. return request.param
  270. @pytest.fixture(params=[True, False])
  271. def skipna(request):
  272. """
  273. Boolean 'skipna' parameter.
  274. """
  275. return request.param
  276. @pytest.fixture(params=["first", "last", False])
  277. def keep(request):
  278. """
  279. Valid values for the 'keep' parameter used in
  280. .duplicated or .drop_duplicates
  281. """
  282. return request.param
  283. @pytest.fixture(params=["both", "neither", "left", "right"])
  284. def inclusive_endpoints_fixture(request):
  285. """
  286. Fixture for trying all interval 'inclusive' parameters.
  287. """
  288. return request.param
  289. @pytest.fixture(params=["left", "right", "both", "neither"])
  290. def closed(request):
  291. """
  292. Fixture for trying all interval closed parameters.
  293. """
  294. return request.param
  295. @pytest.fixture(params=["left", "right", "both", "neither"])
  296. def other_closed(request):
  297. """
  298. Secondary closed fixture to allow parametrizing over all pairs of closed.
  299. """
  300. return request.param
  301. @pytest.fixture(
  302. params=[
  303. None,
  304. "gzip",
  305. "bz2",
  306. "zip",
  307. "xz",
  308. "tar",
  309. pytest.param("zstd", marks=td.skip_if_no("zstandard")),
  310. ]
  311. )
  312. def compression(request):
  313. """
  314. Fixture for trying common compression types in compression tests.
  315. """
  316. return request.param
  317. @pytest.fixture(
  318. params=[
  319. "gzip",
  320. "bz2",
  321. "zip",
  322. "xz",
  323. "tar",
  324. pytest.param("zstd", marks=td.skip_if_no("zstandard")),
  325. ]
  326. )
  327. def compression_only(request):
  328. """
  329. Fixture for trying common compression types in compression tests excluding
  330. uncompressed case.
  331. """
  332. return request.param
  333. @pytest.fixture(params=[True, False])
  334. def writable(request):
  335. """
  336. Fixture that an array is writable.
  337. """
  338. return request.param
  339. @pytest.fixture(params=["inner", "outer", "left", "right"])
  340. def join_type(request):
  341. """
  342. Fixture for trying all types of join operations.
  343. """
  344. return request.param
  345. @pytest.fixture(params=["nlargest", "nsmallest"])
  346. def nselect_method(request):
  347. """
  348. Fixture for trying all nselect methods.
  349. """
  350. return request.param
  351. # ----------------------------------------------------------------
  352. # Missing values & co.
  353. # ----------------------------------------------------------------
  354. @pytest.fixture(params=tm.NULL_OBJECTS, ids=lambda x: type(x).__name__)
  355. def nulls_fixture(request):
  356. """
  357. Fixture for each null type in pandas.
  358. """
  359. return request.param
  360. nulls_fixture2 = nulls_fixture # Generate cartesian product of nulls_fixture
  361. @pytest.fixture(params=[None, np.nan, pd.NaT])
  362. def unique_nulls_fixture(request):
  363. """
  364. Fixture for each null type in pandas, each null type exactly once.
  365. """
  366. return request.param
  367. # Generate cartesian product of unique_nulls_fixture:
  368. unique_nulls_fixture2 = unique_nulls_fixture
  369. @pytest.fixture(params=tm.NP_NAT_OBJECTS, ids=lambda x: type(x).__name__)
  370. def np_nat_fixture(request):
  371. """
  372. Fixture for each NaT type in numpy.
  373. """
  374. return request.param
  375. # Generate cartesian product of np_nat_fixture:
  376. np_nat_fixture2 = np_nat_fixture
  377. # ----------------------------------------------------------------
  378. # Classes
  379. # ----------------------------------------------------------------
  380. @pytest.fixture(params=[DataFrame, Series])
  381. def frame_or_series(request):
  382. """
  383. Fixture to parametrize over DataFrame and Series.
  384. """
  385. return request.param
  386. @pytest.fixture(params=[Index, Series], ids=["index", "series"])
  387. def index_or_series(request):
  388. """
  389. Fixture to parametrize over Index and Series, made necessary by a mypy
  390. bug, giving an error:
  391. List item 0 has incompatible type "Type[Series]"; expected "Type[PandasObject]"
  392. See GH#29725
  393. """
  394. return request.param
  395. # Generate cartesian product of index_or_series fixture:
  396. index_or_series2 = index_or_series
  397. @pytest.fixture(params=[Index, Series, pd.array], ids=["index", "series", "array"])
  398. def index_or_series_or_array(request):
  399. """
  400. Fixture to parametrize over Index, Series, and ExtensionArray
  401. """
  402. return request.param
  403. @pytest.fixture(params=[Index, Series, DataFrame, pd.array], ids=lambda x: x.__name__)
  404. def box_with_array(request):
  405. """
  406. Fixture to test behavior for Index, Series, DataFrame, and pandas Array
  407. classes
  408. """
  409. return request.param
  410. box_with_array2 = box_with_array
  411. @pytest.fixture
  412. def dict_subclass() -> type[dict]:
  413. """
  414. Fixture for a dictionary subclass.
  415. """
  416. class TestSubDict(dict):
  417. def __init__(self, *args, **kwargs) -> None:
  418. dict.__init__(self, *args, **kwargs)
  419. return TestSubDict
  420. @pytest.fixture
  421. def non_dict_mapping_subclass() -> type[abc.Mapping]:
  422. """
  423. Fixture for a non-mapping dictionary subclass.
  424. """
  425. class TestNonDictMapping(abc.Mapping):
  426. def __init__(self, underlying_dict) -> None:
  427. self._data = underlying_dict
  428. def __getitem__(self, key):
  429. return self._data.__getitem__(key)
  430. def __iter__(self) -> Iterator:
  431. return self._data.__iter__()
  432. def __len__(self) -> int:
  433. return self._data.__len__()
  434. return TestNonDictMapping
  435. # ----------------------------------------------------------------
  436. # Indices
  437. # ----------------------------------------------------------------
  438. @pytest.fixture
  439. def multiindex_year_month_day_dataframe_random_data():
  440. """
  441. DataFrame with 3 level MultiIndex (year, month, day) covering
  442. first 100 business days from 2000-01-01 with random data
  443. """
  444. tdf = DataFrame(
  445. np.random.default_rng(2).standard_normal((100, 4)),
  446. columns=Index(list("ABCD")),
  447. index=date_range("2000-01-01", periods=100, freq="B"),
  448. )
  449. ymd = tdf.groupby([lambda x: x.year, lambda x: x.month, lambda x: x.day]).sum()
  450. # use int64 Index, to make sure things work
  451. ymd.index = ymd.index.set_levels([lev.astype("i8") for lev in ymd.index.levels])
  452. ymd.index.set_names(["year", "month", "day"], inplace=True)
  453. return ymd
  454. @pytest.fixture
  455. def lexsorted_two_level_string_multiindex() -> MultiIndex:
  456. """
  457. 2-level MultiIndex, lexsorted, with string names.
  458. """
  459. return MultiIndex(
  460. levels=[["foo", "bar", "baz", "qux"], ["one", "two", "three"]],
  461. codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3], [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
  462. names=["first", "second"],
  463. )
  464. @pytest.fixture
  465. def multiindex_dataframe_random_data(
  466. lexsorted_two_level_string_multiindex,
  467. ) -> DataFrame:
  468. """DataFrame with 2 level MultiIndex with random data"""
  469. index = lexsorted_two_level_string_multiindex
  470. return DataFrame(
  471. np.random.default_rng(2).standard_normal((10, 3)),
  472. index=index,
  473. columns=Index(["A", "B", "C"], name="exp"),
  474. )
  475. def _create_multiindex():
  476. """
  477. MultiIndex used to test the general functionality of this object
  478. """
  479. # See Also: tests.multi.conftest.idx
  480. major_axis = Index(["foo", "bar", "baz", "qux"])
  481. minor_axis = Index(["one", "two"])
  482. major_codes = np.array([0, 0, 1, 2, 3, 3])
  483. minor_codes = np.array([0, 1, 0, 1, 0, 1])
  484. index_names = ["first", "second"]
  485. return MultiIndex(
  486. levels=[major_axis, minor_axis],
  487. codes=[major_codes, minor_codes],
  488. names=index_names,
  489. verify_integrity=False,
  490. )
  491. def _create_mi_with_dt64tz_level():
  492. """
  493. MultiIndex with a level that is a tzaware DatetimeIndex.
  494. """
  495. # GH#8367 round trip with pickle
  496. return MultiIndex.from_product(
  497. [[1, 2], ["a", "b"], date_range("20130101", periods=3, tz="US/Eastern")],
  498. names=["one", "two", "three"],
  499. )
  500. indices_dict = {
  501. "object": Index([f"pandas_{i}" for i in range(100)], dtype=object),
  502. "string": Index([f"pandas_{i}" for i in range(100)], dtype="str"),
  503. "datetime": date_range("2020-01-01", periods=100),
  504. "datetime-tz": date_range("2020-01-01", periods=100, tz="US/Pacific"),
  505. "period": period_range("2020-01-01", periods=100, freq="D"),
  506. "timedelta": timedelta_range(start="1 day", periods=100, freq="D"),
  507. "range": RangeIndex(100),
  508. "int8": Index(np.arange(100), dtype="int8"),
  509. "int16": Index(np.arange(100), dtype="int16"),
  510. "int32": Index(np.arange(100), dtype="int32"),
  511. "int64": Index(np.arange(100), dtype="int64"),
  512. "uint8": Index(np.arange(100), dtype="uint8"),
  513. "uint16": Index(np.arange(100), dtype="uint16"),
  514. "uint32": Index(np.arange(100), dtype="uint32"),
  515. "uint64": Index(np.arange(100), dtype="uint64"),
  516. "float32": Index(np.arange(100), dtype="float32"),
  517. "float64": Index(np.arange(100), dtype="float64"),
  518. "bool-object": Index([True, False] * 5, dtype=object),
  519. "bool-dtype": Index([True, False] * 5, dtype=bool),
  520. "complex64": Index(
  521. np.arange(100, dtype="complex64") + 1.0j * np.arange(100, dtype="complex64")
  522. ),
  523. "complex128": Index(
  524. np.arange(100, dtype="complex128") + 1.0j * np.arange(100, dtype="complex128")
  525. ),
  526. "categorical": CategoricalIndex(list("abcd") * 25),
  527. "interval": IntervalIndex.from_breaks(np.linspace(0, 100, num=101)),
  528. "empty": Index([]),
  529. "tuples": MultiIndex.from_tuples(zip(["foo", "bar", "baz"], [1, 2, 3])),
  530. "mi-with-dt64tz-level": _create_mi_with_dt64tz_level(),
  531. "multi": _create_multiindex(),
  532. "repeats": Index([0, 0, 1, 1, 2, 2]),
  533. "nullable_int": Index(np.arange(100), dtype="Int64"),
  534. "nullable_uint": Index(np.arange(100), dtype="UInt16"),
  535. "nullable_float": Index(np.arange(100), dtype="Float32"),
  536. "nullable_bool": Index(np.arange(100).astype(bool), dtype="boolean"),
  537. "string-python": Index(
  538. pd.array([f"pandas_{i}" for i in range(100)], dtype="string[python]")
  539. ),
  540. }
  541. if has_pyarrow:
  542. idx = Index(pd.array([f"pandas_{i}" for i in range(100)], dtype="string[pyarrow]"))
  543. indices_dict["string-pyarrow"] = idx
  544. @pytest.fixture(params=indices_dict.keys())
  545. def index(request):
  546. """
  547. Fixture for many "simple" kinds of indices.
  548. These indices are unlikely to cover corner cases, e.g.
  549. - no names
  550. - no NaTs/NaNs
  551. - no values near implementation bounds
  552. - ...
  553. """
  554. # copy to avoid mutation, e.g. setting .name
  555. return indices_dict[request.param].copy()
  556. # Needed to generate cartesian product of indices
  557. index_fixture2 = index
  558. @pytest.fixture(
  559. params=[
  560. key for key, value in indices_dict.items() if not isinstance(value, MultiIndex)
  561. ]
  562. )
  563. def index_flat(request):
  564. """
  565. index fixture, but excluding MultiIndex cases.
  566. """
  567. key = request.param
  568. return indices_dict[key].copy()
  569. # Alias so we can test with cartesian product of index_flat
  570. index_flat2 = index_flat
  571. @pytest.fixture(
  572. params=[
  573. key
  574. for key, value in indices_dict.items()
  575. if not (
  576. key.startswith(("int", "uint", "float"))
  577. or key in ["range", "empty", "repeats", "bool-dtype"]
  578. )
  579. and not isinstance(value, MultiIndex)
  580. ]
  581. )
  582. def index_with_missing(request):
  583. """
  584. Fixture for indices with missing values.
  585. Integer-dtype and empty cases are excluded because they cannot hold missing
  586. values.
  587. MultiIndex is excluded because isna() is not defined for MultiIndex.
  588. """
  589. # GH 35538. Use deep copy to avoid illusive bug on np-dev
  590. # GHA pipeline that writes into indices_dict despite copy
  591. ind = indices_dict[request.param].copy(deep=True)
  592. vals = ind.values.copy()
  593. if request.param in ["tuples", "mi-with-dt64tz-level", "multi"]:
  594. # For setting missing values in the top level of MultiIndex
  595. vals = ind.tolist()
  596. vals[0] = (None,) + vals[0][1:]
  597. vals[-1] = (None,) + vals[-1][1:]
  598. return MultiIndex.from_tuples(vals)
  599. else:
  600. vals[0] = None
  601. vals[-1] = None
  602. return type(ind)(vals)
  603. # ----------------------------------------------------------------
  604. # Series'
  605. # ----------------------------------------------------------------
  606. @pytest.fixture
  607. def string_series() -> Series:
  608. """
  609. Fixture for Series of floats with Index of unique strings
  610. """
  611. return Series(
  612. np.arange(30, dtype=np.float64) * 1.1,
  613. index=Index([f"i_{i}" for i in range(30)]),
  614. name="series",
  615. )
  616. @pytest.fixture
  617. def object_series() -> Series:
  618. """
  619. Fixture for Series of dtype object with Index of unique strings
  620. """
  621. data = [f"foo_{i}" for i in range(30)]
  622. index = Index([f"bar_{i}" for i in range(30)])
  623. return Series(data, index=index, name="objects", dtype=object)
  624. @pytest.fixture
  625. def datetime_series() -> Series:
  626. """
  627. Fixture for Series of floats with DatetimeIndex
  628. """
  629. return Series(
  630. np.random.default_rng(2).standard_normal(30),
  631. index=date_range("2000-01-01", periods=30, freq="B"),
  632. name="ts",
  633. )
  634. def _create_series(index):
  635. """Helper for the _series dict"""
  636. size = len(index)
  637. data = np.random.default_rng(2).standard_normal(size)
  638. return Series(data, index=index, name="a", copy=False)
  639. _series = {
  640. f"series-with-{index_id}-index": _create_series(index)
  641. for index_id, index in indices_dict.items()
  642. }
  643. @pytest.fixture
  644. def series_with_simple_index(index) -> Series:
  645. """
  646. Fixture for tests on series with changing types of indices.
  647. """
  648. return _create_series(index)
  649. _narrow_series = {
  650. f"{dtype.__name__}-series": Series(
  651. range(30), index=[f"i-{i}" for i in range(30)], name="a", dtype=dtype
  652. )
  653. for dtype in tm.NARROW_NP_DTYPES
  654. }
  655. _index_or_series_objs = {**indices_dict, **_series, **_narrow_series}
  656. @pytest.fixture(params=_index_or_series_objs.keys())
  657. def index_or_series_obj(request):
  658. """
  659. Fixture for tests on indexes, series and series with a narrow dtype
  660. copy to avoid mutation, e.g. setting .name
  661. """
  662. return _index_or_series_objs[request.param].copy(deep=True)
  663. _typ_objects_series = {
  664. f"{dtype.__name__}-series": Series(dtype) for dtype in tm.PYTHON_DATA_TYPES
  665. }
  666. _index_or_series_memory_objs = {
  667. **indices_dict,
  668. **_series,
  669. **_narrow_series,
  670. **_typ_objects_series,
  671. }
  672. @pytest.fixture(params=_index_or_series_memory_objs.keys())
  673. def index_or_series_memory_obj(request):
  674. """
  675. Fixture for tests on indexes, series, series with a narrow dtype and
  676. series with empty objects type
  677. copy to avoid mutation, e.g. setting .name
  678. """
  679. return _index_or_series_memory_objs[request.param].copy(deep=True)
  680. # ----------------------------------------------------------------
  681. # DataFrames
  682. # ----------------------------------------------------------------
  683. @pytest.fixture
  684. def int_frame() -> DataFrame:
  685. """
  686. Fixture for DataFrame of ints with index of unique strings
  687. Columns are ['A', 'B', 'C', 'D']
  688. """
  689. return DataFrame(
  690. np.ones((30, 4), dtype=np.int64),
  691. index=Index([f"foo_{i}" for i in range(30)]),
  692. columns=Index(list("ABCD")),
  693. )
  694. @pytest.fixture
  695. def float_frame() -> DataFrame:
  696. """
  697. Fixture for DataFrame of floats with index of unique strings
  698. Columns are ['A', 'B', 'C', 'D'].
  699. """
  700. return DataFrame(
  701. np.random.default_rng(2).standard_normal((30, 4)),
  702. index=Index([f"foo_{i}" for i in range(30)]),
  703. columns=Index(list("ABCD")),
  704. )
  705. @pytest.fixture
  706. def rand_series_with_duplicate_datetimeindex() -> Series:
  707. """
  708. Fixture for Series with a DatetimeIndex that has duplicates.
  709. """
  710. dates = [
  711. datetime(2000, 1, 2),
  712. datetime(2000, 1, 2),
  713. datetime(2000, 1, 2),
  714. datetime(2000, 1, 3),
  715. datetime(2000, 1, 3),
  716. datetime(2000, 1, 3),
  717. datetime(2000, 1, 4),
  718. datetime(2000, 1, 4),
  719. datetime(2000, 1, 4),
  720. datetime(2000, 1, 5),
  721. ]
  722. return Series(np.random.default_rng(2).standard_normal(len(dates)), index=dates)
  723. # ----------------------------------------------------------------
  724. # Scalars
  725. # ----------------------------------------------------------------
  726. @pytest.fixture(
  727. params=[
  728. (Interval(left=0, right=5), IntervalDtype("int64", "right")),
  729. (Interval(left=0.1, right=0.5), IntervalDtype("float64", "right")),
  730. (Period("2012-01", freq="M"), "period[M]"),
  731. (Period("2012-02-01", freq="D"), "period[D]"),
  732. (
  733. Timestamp("2011-01-01", tz="US/Eastern"),
  734. DatetimeTZDtype(unit="s", tz="US/Eastern"),
  735. ),
  736. (Timedelta(seconds=500), "timedelta64[ns]"),
  737. ]
  738. )
  739. def ea_scalar_and_dtype(request):
  740. return request.param
  741. # ----------------------------------------------------------------
  742. # Operators & Operations
  743. # ----------------------------------------------------------------
  744. @pytest.fixture(params=tm.arithmetic_dunder_methods)
  745. def all_arithmetic_operators(request):
  746. """
  747. Fixture for dunder names for common arithmetic operations.
  748. """
  749. return request.param
  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. )
  780. def all_binary_operators(request):
  781. """
  782. Fixture for operator and roperator arithmetic, comparison, and logical ops.
  783. """
  784. return request.param
  785. @pytest.fixture(
  786. params=[
  787. operator.add,
  788. ops.radd,
  789. operator.sub,
  790. ops.rsub,
  791. operator.mul,
  792. ops.rmul,
  793. operator.truediv,
  794. ops.rtruediv,
  795. operator.floordiv,
  796. ops.rfloordiv,
  797. operator.mod,
  798. ops.rmod,
  799. operator.pow,
  800. ops.rpow,
  801. ]
  802. )
  803. def all_arithmetic_functions(request):
  804. """
  805. Fixture for operator and roperator arithmetic functions.
  806. Notes
  807. -----
  808. This includes divmod and rdivmod, whereas all_arithmetic_operators
  809. does not.
  810. """
  811. return request.param
  812. _all_numeric_reductions = [
  813. "count",
  814. "sum",
  815. "max",
  816. "min",
  817. "mean",
  818. "prod",
  819. "std",
  820. "var",
  821. "median",
  822. "kurt",
  823. "skew",
  824. "sem",
  825. ]
  826. @pytest.fixture(params=_all_numeric_reductions)
  827. def all_numeric_reductions(request):
  828. """
  829. Fixture for numeric reduction names.
  830. """
  831. return request.param
  832. _all_boolean_reductions = ["all", "any"]
  833. @pytest.fixture(params=_all_boolean_reductions)
  834. def all_boolean_reductions(request):
  835. """
  836. Fixture for boolean reduction names.
  837. """
  838. return request.param
  839. _all_reductions = _all_numeric_reductions + _all_boolean_reductions
  840. @pytest.fixture(params=_all_reductions)
  841. def all_reductions(request):
  842. """
  843. Fixture for all (boolean + numeric) reduction names.
  844. """
  845. return request.param
  846. @pytest.fixture(
  847. params=[
  848. operator.eq,
  849. operator.ne,
  850. operator.gt,
  851. operator.ge,
  852. operator.lt,
  853. operator.le,
  854. ]
  855. )
  856. def comparison_op(request):
  857. """
  858. Fixture for operator module comparison functions.
  859. """
  860. return request.param
  861. @pytest.fixture(params=["__le__", "__lt__", "__ge__", "__gt__"])
  862. def compare_operators_no_eq_ne(request):
  863. """
  864. Fixture for dunder names for compare operations except == and !=
  865. * >=
  866. * >
  867. * <
  868. * <=
  869. """
  870. return request.param
  871. @pytest.fixture(
  872. params=["__and__", "__rand__", "__or__", "__ror__", "__xor__", "__rxor__"]
  873. )
  874. def all_logical_operators(request):
  875. """
  876. Fixture for dunder names for common logical operations
  877. * |
  878. * &
  879. * ^
  880. """
  881. return request.param
  882. _all_numeric_accumulations = ["cumsum", "cumprod", "cummin", "cummax"]
  883. @pytest.fixture(params=_all_numeric_accumulations)
  884. def all_numeric_accumulations(request):
  885. """
  886. Fixture for numeric accumulation names
  887. """
  888. return request.param
  889. # ----------------------------------------------------------------
  890. # Data sets/files
  891. # ----------------------------------------------------------------
  892. @pytest.fixture
  893. def strict_data_files(pytestconfig):
  894. """
  895. Returns the configuration for the test setting `--no-strict-data-files`.
  896. """
  897. return pytestconfig.getoption("--no-strict-data-files")
  898. @pytest.fixture
  899. def datapath(strict_data_files: str) -> Callable[..., str]:
  900. """
  901. Get the path to a data file.
  902. Parameters
  903. ----------
  904. path : str
  905. Path to the file, relative to ``pandas/tests/``
  906. Returns
  907. -------
  908. path including ``pandas/tests``.
  909. Raises
  910. ------
  911. ValueError
  912. If the path doesn't exist and the --no-strict-data-files option is not set.
  913. """
  914. BASE_PATH = os.path.join(os.path.dirname(__file__), "tests")
  915. def deco(*args):
  916. path = os.path.join(BASE_PATH, *args)
  917. if not os.path.exists(path):
  918. if strict_data_files:
  919. raise ValueError(
  920. f"Could not find file {path} and --no-strict-data-files is not set."
  921. )
  922. pytest.skip(f"Could not find {path}.")
  923. return path
  924. return deco
  925. # ----------------------------------------------------------------
  926. # Time zones
  927. # ----------------------------------------------------------------
  928. TIMEZONES = [
  929. None,
  930. "UTC",
  931. "US/Eastern",
  932. "Asia/Tokyo",
  933. "dateutil/US/Pacific",
  934. "dateutil/Asia/Singapore",
  935. "+01:15",
  936. "-02:15",
  937. "UTC+01:15",
  938. "UTC-02:15",
  939. tzutc(),
  940. tzlocal(),
  941. FixedOffset(300),
  942. FixedOffset(0),
  943. FixedOffset(-300),
  944. timezone.utc,
  945. timezone(timedelta(hours=1)),
  946. timezone(timedelta(hours=-1), name="foo"),
  947. ]
  948. if zoneinfo is not None:
  949. TIMEZONES.extend(
  950. [
  951. zoneinfo.ZoneInfo("US/Pacific"), # type: ignore[list-item]
  952. zoneinfo.ZoneInfo("UTC"), # type: ignore[list-item]
  953. ]
  954. )
  955. TIMEZONE_IDS = [repr(i) for i in TIMEZONES]
  956. @td.parametrize_fixture_doc(str(TIMEZONE_IDS))
  957. @pytest.fixture(params=TIMEZONES, ids=TIMEZONE_IDS)
  958. def tz_naive_fixture(request):
  959. """
  960. Fixture for trying timezones including default (None): {0}
  961. """
  962. return request.param
  963. @td.parametrize_fixture_doc(str(TIMEZONE_IDS[1:]))
  964. @pytest.fixture(params=TIMEZONES[1:], ids=TIMEZONE_IDS[1:])
  965. def tz_aware_fixture(request):
  966. """
  967. Fixture for trying explicit timezones: {0}
  968. """
  969. return request.param
  970. # Generate cartesian product of tz_aware_fixture:
  971. tz_aware_fixture2 = tz_aware_fixture
  972. _UTCS = ["utc", "dateutil/UTC", utc, tzutc(), timezone.utc]
  973. if zoneinfo is not None:
  974. _UTCS.append(zoneinfo.ZoneInfo("UTC"))
  975. @pytest.fixture(params=_UTCS)
  976. def utc_fixture(request):
  977. """
  978. Fixture to provide variants of UTC timezone strings and tzinfo objects.
  979. """
  980. return request.param
  981. utc_fixture2 = utc_fixture
  982. @pytest.fixture(params=["s", "ms", "us", "ns"])
  983. def unit(request):
  984. """
  985. datetime64 units we support.
  986. """
  987. return request.param
  988. unit2 = unit
  989. # ----------------------------------------------------------------
  990. # Dtypes
  991. # ----------------------------------------------------------------
  992. @pytest.fixture(params=tm.STRING_DTYPES)
  993. def string_dtype(request):
  994. """
  995. Parametrized fixture for string dtypes.
  996. * str
  997. * 'str'
  998. * 'U'
  999. """
  1000. return request.param
  1001. @pytest.fixture(
  1002. params=[
  1003. ("python", pd.NA),
  1004. pytest.param(("pyarrow", pd.NA), marks=td.skip_if_no("pyarrow")),
  1005. pytest.param(("pyarrow", np.nan), marks=td.skip_if_no("pyarrow")),
  1006. ("python", np.nan),
  1007. ],
  1008. ids=[
  1009. "string=string[python]",
  1010. "string=string[pyarrow]",
  1011. "string=str[pyarrow]",
  1012. "string=str[python]",
  1013. ],
  1014. )
  1015. def string_dtype_no_object(request):
  1016. """
  1017. Parametrized fixture for string dtypes.
  1018. * 'string[python]' (NA variant)
  1019. * 'string[pyarrow]' (NA variant)
  1020. * 'str' (NaN variant, with pyarrow)
  1021. * 'str' (NaN variant, without pyarrow)
  1022. """
  1023. # need to instantiate the StringDtype here instead of in the params
  1024. # to avoid importing pyarrow during test collection
  1025. storage, na_value = request.param
  1026. return pd.StringDtype(storage, na_value)
  1027. @pytest.fixture(
  1028. params=[
  1029. "string[python]",
  1030. pytest.param("string[pyarrow]", marks=td.skip_if_no("pyarrow")),
  1031. ]
  1032. )
  1033. def nullable_string_dtype(request):
  1034. """
  1035. Parametrized fixture for string dtypes.
  1036. * 'string[python]'
  1037. * 'string[pyarrow]'
  1038. """
  1039. return request.param
  1040. @pytest.fixture(
  1041. params=[
  1042. pytest.param(("pyarrow", np.nan), marks=td.skip_if_no("pyarrow")),
  1043. pytest.param(("pyarrow", pd.NA), marks=td.skip_if_no("pyarrow")),
  1044. ]
  1045. )
  1046. def pyarrow_string_dtype(request):
  1047. """
  1048. Parametrized fixture for string dtypes backed by Pyarrow.
  1049. * 'str[pyarrow]'
  1050. * 'string[pyarrow]'
  1051. """
  1052. return pd.StringDtype(*request.param)
  1053. @pytest.fixture(
  1054. params=[
  1055. "python",
  1056. pytest.param("pyarrow", marks=td.skip_if_no("pyarrow")),
  1057. ]
  1058. )
  1059. def string_storage(request):
  1060. """
  1061. Parametrized fixture for pd.options.mode.string_storage.
  1062. * 'python'
  1063. * 'pyarrow'
  1064. """
  1065. return request.param
  1066. @pytest.fixture(
  1067. params=[
  1068. ("python", pd.NA),
  1069. pytest.param(("pyarrow", pd.NA), marks=td.skip_if_no("pyarrow")),
  1070. pytest.param(("pyarrow", np.nan), marks=td.skip_if_no("pyarrow")),
  1071. ("python", np.nan),
  1072. ],
  1073. ids=[
  1074. "string=string[python]",
  1075. "string=string[pyarrow]",
  1076. "string=str[pyarrow]",
  1077. "string=str[python]",
  1078. ],
  1079. )
  1080. def string_dtype_arguments(request):
  1081. """
  1082. Parametrized fixture for StringDtype storage and na_value.
  1083. * 'python' + pd.NA
  1084. * 'pyarrow' + pd.NA
  1085. * 'pyarrow' + np.nan
  1086. """
  1087. return request.param
  1088. @pytest.fixture(
  1089. params=[
  1090. "numpy_nullable",
  1091. pytest.param("pyarrow", marks=td.skip_if_no("pyarrow")),
  1092. ]
  1093. )
  1094. def dtype_backend(request):
  1095. """
  1096. Parametrized fixture for pd.options.mode.string_storage.
  1097. * 'python'
  1098. * 'pyarrow'
  1099. """
  1100. return request.param
  1101. # Alias so we can test with cartesian product of string_storage
  1102. string_storage2 = string_storage
  1103. string_dtype_arguments2 = string_dtype_arguments
  1104. @pytest.fixture(params=tm.BYTES_DTYPES)
  1105. def bytes_dtype(request):
  1106. """
  1107. Parametrized fixture for bytes dtypes.
  1108. * bytes
  1109. * 'bytes'
  1110. """
  1111. return request.param
  1112. @pytest.fixture(params=tm.OBJECT_DTYPES)
  1113. def object_dtype(request):
  1114. """
  1115. Parametrized fixture for object dtypes.
  1116. * object
  1117. * 'object'
  1118. """
  1119. return request.param
  1120. @pytest.fixture(
  1121. params=[
  1122. np.dtype("object"),
  1123. ("python", pd.NA),
  1124. pytest.param(("pyarrow", pd.NA), marks=td.skip_if_no("pyarrow")),
  1125. pytest.param(("pyarrow", np.nan), marks=td.skip_if_no("pyarrow")),
  1126. ("python", np.nan),
  1127. ],
  1128. ids=[
  1129. "string=object",
  1130. "string=string[python]",
  1131. "string=string[pyarrow]",
  1132. "string=str[pyarrow]",
  1133. "string=str[python]",
  1134. ],
  1135. )
  1136. def any_string_dtype(request):
  1137. """
  1138. Parametrized fixture for string dtypes.
  1139. * 'object'
  1140. * 'string[python]' (NA variant)
  1141. * 'string[pyarrow]' (NA variant)
  1142. * 'str' (NaN variant, with pyarrow)
  1143. * 'str' (NaN variant, without pyarrow)
  1144. """
  1145. if isinstance(request.param, np.dtype):
  1146. return request.param
  1147. else:
  1148. # need to instantiate the StringDtype here instead of in the params
  1149. # to avoid importing pyarrow during test collection
  1150. storage, na_value = request.param
  1151. return pd.StringDtype(storage, na_value)
  1152. @pytest.fixture(params=tm.DATETIME64_DTYPES)
  1153. def datetime64_dtype(request):
  1154. """
  1155. Parametrized fixture for datetime64 dtypes.
  1156. * 'datetime64[ns]'
  1157. * 'M8[ns]'
  1158. """
  1159. return request.param
  1160. @pytest.fixture(params=tm.TIMEDELTA64_DTYPES)
  1161. def timedelta64_dtype(request):
  1162. """
  1163. Parametrized fixture for timedelta64 dtypes.
  1164. * 'timedelta64[ns]'
  1165. * 'm8[ns]'
  1166. """
  1167. return request.param
  1168. @pytest.fixture
  1169. def fixed_now_ts() -> Timestamp:
  1170. """
  1171. Fixture emits fixed Timestamp.now()
  1172. """
  1173. return Timestamp( # pyright: ignore[reportGeneralTypeIssues]
  1174. year=2021, month=1, day=1, hour=12, minute=4, second=13, microsecond=22
  1175. )
  1176. @pytest.fixture(params=tm.FLOAT_NUMPY_DTYPES)
  1177. def float_numpy_dtype(request):
  1178. """
  1179. Parameterized fixture for float dtypes.
  1180. * float
  1181. * 'float32'
  1182. * 'float64'
  1183. """
  1184. return request.param
  1185. @pytest.fixture(params=tm.FLOAT_EA_DTYPES)
  1186. def float_ea_dtype(request):
  1187. """
  1188. Parameterized fixture for float dtypes.
  1189. * 'Float32'
  1190. * 'Float64'
  1191. """
  1192. return request.param
  1193. @pytest.fixture(params=tm.ALL_FLOAT_DTYPES)
  1194. def any_float_dtype(request):
  1195. """
  1196. Parameterized fixture for float dtypes.
  1197. * float
  1198. * 'float32'
  1199. * 'float64'
  1200. * 'Float32'
  1201. * 'Float64'
  1202. """
  1203. return request.param
  1204. @pytest.fixture(params=tm.COMPLEX_DTYPES)
  1205. def complex_dtype(request):
  1206. """
  1207. Parameterized fixture for complex dtypes.
  1208. * complex
  1209. * 'complex64'
  1210. * 'complex128'
  1211. """
  1212. return request.param
  1213. @pytest.fixture(params=tm.COMPLEX_FLOAT_DTYPES)
  1214. def complex_or_float_dtype(request):
  1215. """
  1216. Parameterized fixture for complex and numpy float dtypes.
  1217. * complex
  1218. * 'complex64'
  1219. * 'complex128'
  1220. * float
  1221. * 'float32'
  1222. * 'float64'
  1223. """
  1224. return request.param
  1225. @pytest.fixture(params=tm.SIGNED_INT_NUMPY_DTYPES)
  1226. def any_signed_int_numpy_dtype(request):
  1227. """
  1228. Parameterized fixture for signed integer dtypes.
  1229. * int
  1230. * 'int8'
  1231. * 'int16'
  1232. * 'int32'
  1233. * 'int64'
  1234. """
  1235. return request.param
  1236. @pytest.fixture(params=tm.UNSIGNED_INT_NUMPY_DTYPES)
  1237. def any_unsigned_int_numpy_dtype(request):
  1238. """
  1239. Parameterized fixture for unsigned integer dtypes.
  1240. * 'uint8'
  1241. * 'uint16'
  1242. * 'uint32'
  1243. * 'uint64'
  1244. """
  1245. return request.param
  1246. @pytest.fixture(params=tm.ALL_INT_NUMPY_DTYPES)
  1247. def any_int_numpy_dtype(request):
  1248. """
  1249. Parameterized fixture for any integer dtype.
  1250. * int
  1251. * 'int8'
  1252. * 'uint8'
  1253. * 'int16'
  1254. * 'uint16'
  1255. * 'int32'
  1256. * 'uint32'
  1257. * 'int64'
  1258. * 'uint64'
  1259. """
  1260. return request.param
  1261. @pytest.fixture(params=tm.ALL_INT_EA_DTYPES)
  1262. def any_int_ea_dtype(request):
  1263. """
  1264. Parameterized fixture for any nullable integer dtype.
  1265. * 'UInt8'
  1266. * 'Int8'
  1267. * 'UInt16'
  1268. * 'Int16'
  1269. * 'UInt32'
  1270. * 'Int32'
  1271. * 'UInt64'
  1272. * 'Int64'
  1273. """
  1274. return request.param
  1275. @pytest.fixture(params=tm.ALL_INT_DTYPES)
  1276. def any_int_dtype(request):
  1277. """
  1278. Parameterized fixture for any nullable integer dtype.
  1279. * int
  1280. * 'int8'
  1281. * 'uint8'
  1282. * 'int16'
  1283. * 'uint16'
  1284. * 'int32'
  1285. * 'uint32'
  1286. * 'int64'
  1287. * 'uint64'
  1288. * 'UInt8'
  1289. * 'Int8'
  1290. * 'UInt16'
  1291. * 'Int16'
  1292. * 'UInt32'
  1293. * 'Int32'
  1294. * 'UInt64'
  1295. * 'Int64'
  1296. """
  1297. return request.param
  1298. @pytest.fixture(params=tm.ALL_INT_EA_DTYPES + tm.FLOAT_EA_DTYPES)
  1299. def any_numeric_ea_dtype(request):
  1300. """
  1301. Parameterized fixture for any nullable integer dtype and
  1302. any float ea dtypes.
  1303. * 'UInt8'
  1304. * 'Int8'
  1305. * 'UInt16'
  1306. * 'Int16'
  1307. * 'UInt32'
  1308. * 'Int32'
  1309. * 'UInt64'
  1310. * 'Int64'
  1311. * 'Float32'
  1312. * 'Float64'
  1313. """
  1314. return request.param
  1315. # Unsupported operand types for + ("List[Union[str, ExtensionDtype, dtype[Any],
  1316. # Type[object]]]" and "List[str]")
  1317. @pytest.fixture(
  1318. params=tm.ALL_INT_EA_DTYPES
  1319. + tm.FLOAT_EA_DTYPES
  1320. + tm.ALL_INT_PYARROW_DTYPES_STR_REPR
  1321. + tm.FLOAT_PYARROW_DTYPES_STR_REPR # type: ignore[operator]
  1322. )
  1323. def any_numeric_ea_and_arrow_dtype(request):
  1324. """
  1325. Parameterized fixture for any nullable integer dtype and
  1326. any float ea dtypes.
  1327. * 'UInt8'
  1328. * 'Int8'
  1329. * 'UInt16'
  1330. * 'Int16'
  1331. * 'UInt32'
  1332. * 'Int32'
  1333. * 'UInt64'
  1334. * 'Int64'
  1335. * 'Float32'
  1336. * 'Float64'
  1337. * 'uint8[pyarrow]'
  1338. * 'int8[pyarrow]'
  1339. * 'uint16[pyarrow]'
  1340. * 'int16[pyarrow]'
  1341. * 'uint32[pyarrow]'
  1342. * 'int32[pyarrow]'
  1343. * 'uint64[pyarrow]'
  1344. * 'int64[pyarrow]'
  1345. * 'float32[pyarrow]'
  1346. * 'float64[pyarrow]'
  1347. """
  1348. return request.param
  1349. @pytest.fixture(params=tm.SIGNED_INT_EA_DTYPES)
  1350. def any_signed_int_ea_dtype(request):
  1351. """
  1352. Parameterized fixture for any signed nullable integer dtype.
  1353. * 'Int8'
  1354. * 'Int16'
  1355. * 'Int32'
  1356. * 'Int64'
  1357. """
  1358. return request.param
  1359. @pytest.fixture(params=tm.ALL_REAL_NUMPY_DTYPES)
  1360. def any_real_numpy_dtype(request):
  1361. """
  1362. Parameterized fixture for any (purely) real numeric dtype.
  1363. * int
  1364. * 'int8'
  1365. * 'uint8'
  1366. * 'int16'
  1367. * 'uint16'
  1368. * 'int32'
  1369. * 'uint32'
  1370. * 'int64'
  1371. * 'uint64'
  1372. * float
  1373. * 'float32'
  1374. * 'float64'
  1375. """
  1376. return request.param
  1377. @pytest.fixture(params=tm.ALL_REAL_DTYPES)
  1378. def any_real_numeric_dtype(request):
  1379. """
  1380. Parameterized fixture for any (purely) real numeric dtype.
  1381. * int
  1382. * 'int8'
  1383. * 'uint8'
  1384. * 'int16'
  1385. * 'uint16'
  1386. * 'int32'
  1387. * 'uint32'
  1388. * 'int64'
  1389. * 'uint64'
  1390. * float
  1391. * 'float32'
  1392. * 'float64'
  1393. and associated ea dtypes.
  1394. """
  1395. return request.param
  1396. @pytest.fixture(params=tm.ALL_NUMPY_DTYPES)
  1397. def any_numpy_dtype(request):
  1398. """
  1399. Parameterized fixture for all numpy dtypes.
  1400. * bool
  1401. * 'bool'
  1402. * int
  1403. * 'int8'
  1404. * 'uint8'
  1405. * 'int16'
  1406. * 'uint16'
  1407. * 'int32'
  1408. * 'uint32'
  1409. * 'int64'
  1410. * 'uint64'
  1411. * float
  1412. * 'float32'
  1413. * 'float64'
  1414. * complex
  1415. * 'complex64'
  1416. * 'complex128'
  1417. * str
  1418. * 'str'
  1419. * 'U'
  1420. * bytes
  1421. * 'bytes'
  1422. * 'datetime64[ns]'
  1423. * 'M8[ns]'
  1424. * 'timedelta64[ns]'
  1425. * 'm8[ns]'
  1426. * object
  1427. * 'object'
  1428. """
  1429. return request.param
  1430. @pytest.fixture(params=tm.ALL_REAL_NULLABLE_DTYPES)
  1431. def any_real_nullable_dtype(request):
  1432. """
  1433. Parameterized fixture for all real dtypes that can hold NA.
  1434. * float
  1435. * 'float32'
  1436. * 'float64'
  1437. * 'Float32'
  1438. * 'Float64'
  1439. * 'UInt8'
  1440. * 'UInt16'
  1441. * 'UInt32'
  1442. * 'UInt64'
  1443. * 'Int8'
  1444. * 'Int16'
  1445. * 'Int32'
  1446. * 'Int64'
  1447. * 'uint8[pyarrow]'
  1448. * 'uint16[pyarrow]'
  1449. * 'uint32[pyarrow]'
  1450. * 'uint64[pyarrow]'
  1451. * 'int8[pyarrow]'
  1452. * 'int16[pyarrow]'
  1453. * 'int32[pyarrow]'
  1454. * 'int64[pyarrow]'
  1455. * 'float[pyarrow]'
  1456. * 'double[pyarrow]'
  1457. """
  1458. return request.param
  1459. @pytest.fixture(params=tm.ALL_NUMERIC_DTYPES)
  1460. def any_numeric_dtype(request):
  1461. """
  1462. Parameterized fixture for all numeric dtypes.
  1463. * int
  1464. * 'int8'
  1465. * 'uint8'
  1466. * 'int16'
  1467. * 'uint16'
  1468. * 'int32'
  1469. * 'uint32'
  1470. * 'int64'
  1471. * 'uint64'
  1472. * float
  1473. * 'float32'
  1474. * 'float64'
  1475. * complex
  1476. * 'complex64'
  1477. * 'complex128'
  1478. * 'UInt8'
  1479. * 'Int8'
  1480. * 'UInt16'
  1481. * 'Int16'
  1482. * 'UInt32'
  1483. * 'Int32'
  1484. * 'UInt64'
  1485. * 'Int64'
  1486. * 'Float32'
  1487. * 'Float64'
  1488. """
  1489. return request.param
  1490. # categoricals are handled separately
  1491. _any_skipna_inferred_dtype = [
  1492. ("string", ["a", np.nan, "c"]),
  1493. ("string", ["a", pd.NA, "c"]),
  1494. ("mixed", ["a", pd.NaT, "c"]), # pd.NaT not considered valid by is_string_array
  1495. ("bytes", [b"a", np.nan, b"c"]),
  1496. ("empty", [np.nan, np.nan, np.nan]),
  1497. ("empty", []),
  1498. ("mixed-integer", ["a", np.nan, 2]),
  1499. ("mixed", ["a", np.nan, 2.0]),
  1500. ("floating", [1.0, np.nan, 2.0]),
  1501. ("integer", [1, np.nan, 2]),
  1502. ("mixed-integer-float", [1, np.nan, 2.0]),
  1503. ("decimal", [Decimal(1), np.nan, Decimal(2)]),
  1504. ("boolean", [True, np.nan, False]),
  1505. ("boolean", [True, pd.NA, False]),
  1506. ("datetime64", [np.datetime64("2013-01-01"), np.nan, np.datetime64("2018-01-01")]),
  1507. ("datetime", [Timestamp("20130101"), np.nan, Timestamp("20180101")]),
  1508. ("date", [date(2013, 1, 1), np.nan, date(2018, 1, 1)]),
  1509. ("complex", [1 + 1j, np.nan, 2 + 2j]),
  1510. # The following dtype is commented out due to GH 23554
  1511. # ('timedelta64', [np.timedelta64(1, 'D'),
  1512. # np.nan, np.timedelta64(2, 'D')]),
  1513. ("timedelta", [timedelta(1), np.nan, timedelta(2)]),
  1514. ("time", [time(1), np.nan, time(2)]),
  1515. ("period", [Period(2013), pd.NaT, Period(2018)]),
  1516. ("interval", [Interval(0, 1), np.nan, Interval(0, 2)]),
  1517. ]
  1518. ids, _ = zip(*_any_skipna_inferred_dtype) # use inferred type as fixture-id
  1519. @pytest.fixture(params=_any_skipna_inferred_dtype, ids=ids)
  1520. def any_skipna_inferred_dtype(request):
  1521. """
  1522. Fixture for all inferred dtypes from _libs.lib.infer_dtype
  1523. The covered (inferred) types are:
  1524. * 'string'
  1525. * 'empty'
  1526. * 'bytes'
  1527. * 'mixed'
  1528. * 'mixed-integer'
  1529. * 'mixed-integer-float'
  1530. * 'floating'
  1531. * 'integer'
  1532. * 'decimal'
  1533. * 'boolean'
  1534. * 'datetime64'
  1535. * 'datetime'
  1536. * 'date'
  1537. * 'timedelta'
  1538. * 'time'
  1539. * 'period'
  1540. * 'interval'
  1541. Returns
  1542. -------
  1543. inferred_dtype : str
  1544. The string for the inferred dtype from _libs.lib.infer_dtype
  1545. values : np.ndarray
  1546. An array of object dtype that will be inferred to have
  1547. `inferred_dtype`
  1548. Examples
  1549. --------
  1550. >>> from pandas._libs import lib
  1551. >>>
  1552. >>> def test_something(any_skipna_inferred_dtype):
  1553. ... inferred_dtype, values = any_skipna_inferred_dtype
  1554. ... # will pass
  1555. ... assert lib.infer_dtype(values, skipna=True) == inferred_dtype
  1556. """
  1557. inferred_dtype, values = request.param
  1558. values = np.array(values, dtype=object) # object dtype to avoid casting
  1559. # correctness of inference tested in tests/dtypes/test_inference.py
  1560. return inferred_dtype, values
  1561. # ----------------------------------------------------------------
  1562. # Misc
  1563. # ----------------------------------------------------------------
  1564. @pytest.fixture
  1565. def ip():
  1566. """
  1567. Get an instance of IPython.InteractiveShell.
  1568. Will raise a skip if IPython is not installed.
  1569. """
  1570. pytest.importorskip("IPython", minversion="6.0.0")
  1571. from IPython.core.interactiveshell import InteractiveShell
  1572. # GH#35711 make sure sqlite history file handle is not leaked
  1573. from traitlets.config import Config # isort:skip
  1574. c = Config()
  1575. c.HistoryManager.hist_file = ":memory:"
  1576. return InteractiveShell(config=c)
  1577. @pytest.fixture(params=["bsr", "coo", "csc", "csr", "dia", "dok", "lil"])
  1578. def spmatrix(request):
  1579. """
  1580. Yields scipy sparse matrix classes.
  1581. """
  1582. sparse = pytest.importorskip("scipy.sparse")
  1583. return getattr(sparse, request.param + "_matrix")
  1584. @pytest.fixture(
  1585. params=[
  1586. getattr(pd.offsets, o)
  1587. for o in pd.offsets.__all__
  1588. if issubclass(getattr(pd.offsets, o), pd.offsets.Tick) and o != "Tick"
  1589. ]
  1590. )
  1591. def tick_classes(request):
  1592. """
  1593. Fixture for Tick based datetime offsets available for a time series.
  1594. """
  1595. return request.param
  1596. @pytest.fixture(params=[None, lambda x: x])
  1597. def sort_by_key(request):
  1598. """
  1599. Simple fixture for testing keys in sorting methods.
  1600. Tests None (no key) and the identity key.
  1601. """
  1602. return request.param
  1603. @pytest.fixture(
  1604. params=[
  1605. ("foo", None, None),
  1606. ("Egon", "Venkman", None),
  1607. ("NCC1701D", "NCC1701D", "NCC1701D"),
  1608. # possibly-matching NAs
  1609. (np.nan, np.nan, np.nan),
  1610. (np.nan, pd.NaT, None),
  1611. (np.nan, pd.NA, None),
  1612. (pd.NA, pd.NA, pd.NA),
  1613. ]
  1614. )
  1615. def names(request) -> tuple[Hashable, Hashable, Hashable]:
  1616. """
  1617. A 3-tuple of names, the first two for operands, the last for a result.
  1618. """
  1619. return request.param
  1620. @pytest.fixture(params=[tm.setitem, tm.loc, tm.iloc])
  1621. def indexer_sli(request):
  1622. """
  1623. Parametrize over __setitem__, loc.__setitem__, iloc.__setitem__
  1624. """
  1625. return request.param
  1626. @pytest.fixture(params=[tm.loc, tm.iloc])
  1627. def indexer_li(request):
  1628. """
  1629. Parametrize over loc.__getitem__, iloc.__getitem__
  1630. """
  1631. return request.param
  1632. @pytest.fixture(params=[tm.setitem, tm.iloc])
  1633. def indexer_si(request):
  1634. """
  1635. Parametrize over __setitem__, iloc.__setitem__
  1636. """
  1637. return request.param
  1638. @pytest.fixture(params=[tm.setitem, tm.loc])
  1639. def indexer_sl(request):
  1640. """
  1641. Parametrize over __setitem__, loc.__setitem__
  1642. """
  1643. return request.param
  1644. @pytest.fixture(params=[tm.at, tm.loc])
  1645. def indexer_al(request):
  1646. """
  1647. Parametrize over at.__setitem__, loc.__setitem__
  1648. """
  1649. return request.param
  1650. @pytest.fixture(params=[tm.iat, tm.iloc])
  1651. def indexer_ial(request):
  1652. """
  1653. Parametrize over iat.__setitem__, iloc.__setitem__
  1654. """
  1655. return request.param
  1656. @pytest.fixture
  1657. def using_array_manager() -> bool:
  1658. """
  1659. Fixture to check if the array manager is being used.
  1660. """
  1661. return _get_option("mode.data_manager", silent=True) == "array"
  1662. @pytest.fixture
  1663. def using_copy_on_write() -> bool:
  1664. """
  1665. Fixture to check if Copy-on-Write is enabled.
  1666. """
  1667. return (
  1668. pd.options.mode.copy_on_write is True
  1669. and _get_option("mode.data_manager", silent=True) == "block"
  1670. )
  1671. @pytest.fixture
  1672. def warn_copy_on_write() -> bool:
  1673. """
  1674. Fixture to check if Copy-on-Write is in warning mode.
  1675. """
  1676. return (
  1677. pd.options.mode.copy_on_write == "warn"
  1678. and _get_option("mode.data_manager", silent=True) == "block"
  1679. )
  1680. @pytest.fixture
  1681. def using_infer_string() -> bool:
  1682. """
  1683. Fixture to check if infer string option is enabled.
  1684. """
  1685. return pd.options.future.infer_string is True
  1686. warsaws = ["Europe/Warsaw", "dateutil/Europe/Warsaw"]
  1687. if zoneinfo is not None:
  1688. warsaws.append(zoneinfo.ZoneInfo("Europe/Warsaw")) # type: ignore[arg-type]
  1689. @pytest.fixture(params=warsaws)
  1690. def warsaw(request) -> str:
  1691. """
  1692. tzinfo for Europe/Warsaw using pytz, dateutil, or zoneinfo.
  1693. """
  1694. return request.param
  1695. @pytest.fixture()
  1696. def arrow_string_storage():
  1697. return ("pyarrow", "pyarrow_numpy")