Skip to content

Commit 90c1b61

Browse files
bashtageKevin Sheppard
and
Kevin Sheppard
authored
MAINT: Fix for future change (#409)
* MAINT: Fix for future change * ENH: Add pytest warns context manager manager * Switch to pandas Version * ENH: Improve typing for Timedelta (#388) * ENH: Improve typing for Timedelta * ENH: Improve typing of timedelta * ENH/TST: Improve Timedelta and its tests * ENH: Final changes for timedelta * ENH: Further improvements to timestamp * ENH: Add more types * Final changes to timedelta * Final cleanup * CLN: Final clean * CLN: Final clean Co-authored-by: Kevin Sheppard <[email protected]> * ENH: Add typing for Version Co-authored-by: Kevin Sheppard <[email protected]>
1 parent 8e12c05 commit 90c1b61

File tree

4 files changed

+147
-7
lines changed

4 files changed

+147
-7
lines changed
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
def parse(version: str) -> LegacyVersion | Version: ...
2+
3+
class _BaseVersion:
4+
def __lt__(self, other: _BaseVersion) -> bool: ...
5+
def __le__(self, other: _BaseVersion) -> bool: ...
6+
def __eq__(self, other: object) -> bool: ...
7+
def __ge__(self, other: _BaseVersion) -> bool: ...
8+
def __gt__(self, other: _BaseVersion) -> bool: ...
9+
def __ne__(self, other: object) -> bool: ...
10+
11+
class LegacyVersion(_BaseVersion):
12+
def __init__(self, version: str) -> None: ...
13+
@property
14+
def public(self) -> str: ...
15+
@property
16+
def base_version(self) -> str: ...
17+
@property
18+
def epoch(self) -> int: ...
19+
@property
20+
def release(self) -> None: ...
21+
@property
22+
def pre(self) -> None: ...
23+
@property
24+
def post(self) -> None: ...
25+
@property
26+
def dev(self) -> None: ...
27+
@property
28+
def local(self) -> None: ...
29+
@property
30+
def is_prerelease(self) -> bool: ...
31+
@property
32+
def is_postrelease(self) -> bool: ...
33+
@property
34+
def is_devrelease(self) -> bool: ...
35+
36+
class Version(_BaseVersion):
37+
def __init__(self, version: str) -> None: ...
38+
@property
39+
def epoch(self) -> int: ...
40+
@property
41+
def release(self) -> tuple[int, ...]: ...
42+
@property
43+
def pre(self) -> tuple[str, int] | None: ...
44+
@property
45+
def post(self) -> int | None: ...
46+
@property
47+
def dev(self) -> int | None: ...
48+
@property
49+
def local(self) -> str | None: ...
50+
@property
51+
def public(self) -> str: ...
52+
@property
53+
def base_version(self) -> str: ...
54+
@property
55+
def is_prerelease(self) -> bool: ...
56+
@property
57+
def is_postrelease(self) -> bool: ...
58+
@property
59+
def is_devrelease(self) -> bool: ...
60+
@property
61+
def major(self) -> int: ...
62+
@property
63+
def minor(self) -> int: ...
64+
@property
65+
def micro(self) -> int: ...

tests/__init__.py

+65
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
from __future__ import annotations
22

3+
from contextlib import (
4+
AbstractContextManager,
5+
nullcontext,
6+
)
37
import os
48
import platform
59
from typing import (
610
TYPE_CHECKING,
711
Final,
812
)
913

14+
import pandas as pd
15+
from pandas.util.version import Version
16+
import pytest
17+
1018
from pandas._typing import T
1119

1220
TYPE_CHECKING_INVALID_USAGE: Final = TYPE_CHECKING
1321
WINDOWS = os.name == "nt" or "cygwin" in platform.system().lower()
22+
PD_LTE_15 = Version(pd.__version__) < Version("1.5.999")
1423

1524

1625
def check(actual: T, klass: type, dtype: type | None = None, attr: str = "left") -> T:
@@ -28,3 +37,59 @@ def check(actual: T, klass: type, dtype: type | None = None, attr: str = "left")
2837
if not isinstance(value, dtype):
2938
raise RuntimeError(f"Expected type '{dtype}' but got '{type(value)}'")
3039
return actual # type: ignore[return-value]
40+
41+
42+
def pytest_warns_bounded(
43+
warning: type[Warning],
44+
match: str,
45+
lower: str | None = None,
46+
upper: str | None = None,
47+
) -> AbstractContextManager:
48+
"""
49+
Version conditional pytest.warns context manager
50+
51+
Returns a context manager that will raise an error if
52+
the warning is not issued when pandas version is
53+
between the lower and upper version given.
54+
55+
Parameters
56+
----------
57+
warning : type[Warning]
58+
The warning class to check for.
59+
match : str
60+
The string to match in the warning message.
61+
lower : str, optional
62+
The lower bound of the version to check for the warning.
63+
upper : str, optional
64+
The upper bound of the version to check for the warning.
65+
66+
Notes
67+
-----
68+
The lower and upper bounds are exclusive so that a pytest.warns context
69+
manager is returned if lower < pd.__version__ < upper.
70+
71+
Examples
72+
--------
73+
with pytest_warns_bounded(UserWarning, match="foo", lower="1.2.99"):
74+
# Versions 1.3.0 and above will raise an error
75+
# if the warning is not issued
76+
pass
77+
78+
with pytest_warns_bounded(UserWarning, match="foo", upper="1.5.99"):
79+
# Versions 1.6.0 and below will raise an error
80+
# if the warning is not issued
81+
pass
82+
83+
with pytest_warns_bounded(
84+
UserWarning, match="foo", lower="1.2.99", upper="1.5.99"
85+
):
86+
# Versions between 1.3.x and 1.5.x will raise an error
87+
pass
88+
"""
89+
lb = Version("0.0.0") if lower is None else Version(lower)
90+
ub = Version("9999.0.0") if upper is None else Version(upper)
91+
current = Version(pd.__version__)
92+
if lb < current < ub:
93+
return pytest.warns(warning, match=match)
94+
else:
95+
return nullcontext()

tests/test_frame.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@
3636
from pandas._typing import Scalar
3737

3838
from tests import (
39+
PD_LTE_15,
3940
TYPE_CHECKING_INVALID_USAGE,
4041
check,
42+
pytest_warns_bounded,
4143
)
4244

4345
from pandas.io.formats.style import Styler
@@ -933,12 +935,16 @@ def test_types_describe() -> None:
933935
}
934936
)
935937
df.describe()
936-
with pytest.warns(FutureWarning, match="Treating datetime data as categorical"):
938+
with pytest_warns_bounded(
939+
FutureWarning, match="Treating datetime data as categorical", upper="1.5.999"
940+
):
937941
df.describe(percentiles=[0.5], include="all")
938-
with pytest.warns(FutureWarning, match="Treating datetime data as categorical"):
939942
df.describe(exclude=[np.number])
940-
# datetime_is_numeric param added in 1.1.0 https://pandas.pydata.org/docs/whatsnew/v1.1.0.html
941-
df.describe(datetime_is_numeric=True)
943+
if PD_LTE_15:
944+
# datetime_is_numeric param added in 1.1.0
945+
# https://pandas.pydata.org/docs/whatsnew/v1.1.0.html
946+
# Remove in 2.0.0
947+
df.describe(datetime_is_numeric=True)
942948

943949

944950
def test_types_to_string() -> None:

tests/test_series.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
)
3434

3535
from tests import (
36+
PD_LTE_15,
3637
TYPE_CHECKING_INVALID_USAGE,
3738
check,
3839
)
@@ -648,9 +649,12 @@ def test_types_describe() -> None:
648649
s.describe(percentiles=[0.5], include="all")
649650
with pytest.warns(DeprecationWarning, match="elementwise comparison failed"):
650651
s.describe(exclude=np.number)
651-
# datetime_is_numeric param added in 1.1.0 https://pandas.pydata.org/docs/whatsnew/v1.1.0.html
652-
with pytest.warns(DeprecationWarning, match="elementwise comparison failed"):
653-
s.describe(datetime_is_numeric=True)
652+
if PD_LTE_15:
653+
# datetime_is_numeric param added in 1.1.0
654+
# https://pandas.pydata.org/docs/whatsnew/v1.1.0.html
655+
# Remove in 2.0.0
656+
with pytest.warns(DeprecationWarning, match="elementwise comparison failed"):
657+
s.describe(datetime_is_numeric=True)
654658

655659

656660
def test_types_resample() -> None:

0 commit comments

Comments
 (0)