Skip to content

Commit fc51e5f

Browse files
committed
MNT: handle changes in error messages in Python 3.14
1 parent b475e7e commit fc51e5f

File tree

6 files changed

+64
-18
lines changed

6 files changed

+64
-18
lines changed

pandas/tests/indexes/test_indexing.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import numpy as np
1919
import pytest
2020

21+
from pandas.compat import PY314
2122
from pandas.errors import InvalidIndexError
2223

2324
from pandas.core.dtypes.common import (
@@ -160,13 +161,19 @@ def test_contains_requires_hashable_raises(self, index):
160161
with pytest.raises(TypeError, match=msg):
161162
[] in index
162163

164+
if PY314:
165+
container_or_iterable = "a container or iterable"
166+
else:
167+
container_or_iterable = "iterable"
168+
163169
msg = "|".join(
164170
[
165171
r"unhashable type: 'dict'",
166172
r"must be real number, not dict",
167173
r"an integer is required",
168174
r"\{\}",
169-
r"pandas\._libs\.interval\.IntervalTree' is not iterable",
175+
r"pandas\._libs\.interval\.IntervalTree' is not "
176+
f"{container_or_iterable}",
170177
]
171178
)
172179
with pytest.raises(TypeError, match=msg):

pandas/tests/io/parser/test_quoting.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010

11-
from pandas.compat import PY311
11+
from pandas.compat import PY311, PY314
1212
from pandas.errors import ParserError
1313

1414
from pandas import DataFrame
@@ -21,15 +21,23 @@
2121
skip_pyarrow = pytest.mark.usefixtures("pyarrow_skip")
2222

2323

24+
if PY314:
25+
# TODO: write a regex that works with all new possitibilities here
26+
MSG1 = ""
27+
MSG2 = "[\s\S]*"
28+
else:
29+
MSG1 = "a(n)? 1-character string"
30+
MSG2 = "string( or None)?"
31+
2432
@pytest.mark.parametrize(
2533
"kwargs,msg",
2634
[
27-
({"quotechar": "foo"}, '"quotechar" must be a(n)? 1-character string'),
35+
({"quotechar": "foo"}, f'"quotechar" must be {MSG1}'),
2836
(
2937
{"quotechar": None, "quoting": csv.QUOTE_MINIMAL},
3038
"quotechar must be set if quoting enabled",
3139
),
32-
({"quotechar": 2}, '"quotechar" must be string( or None)?, not int'),
40+
({"quotechar": 2}, f'"quotechar" must be {MSG2}, not int'),
3341
],
3442
)
3543
@skip_pyarrow # ParserError: CSV parse error: Empty CSV file or block
@@ -88,8 +96,12 @@ def test_null_quote_char(all_parsers, quoting, quote_char):
8896

8997
if quoting != csv.QUOTE_NONE:
9098
# Sanity checking.
99+
if not PY314:
100+
msg = "1-character string"
101+
else:
102+
msg = "unicode character or None"
91103
msg = (
92-
'"quotechar" must be a 1-character string'
104+
f'"quotechar" must be a {msg}'
93105
if PY311 and all_parsers.engine == "python" and quote_char == ""
94106
else "quotechar must be set if quoting enabled"
95107
)

pandas/tests/reshape/merge/test_merge.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import numpy as np
99
import pytest
1010

11+
from pandas.compat import PY314
1112
from pandas.core.dtypes.common import (
1213
is_object_dtype,
1314
is_string_dtype,
@@ -2420,10 +2421,12 @@ def test_merge_suffix_raises(suffixes):
24202421
merge(a, b, left_index=True, right_index=True, suffixes=suffixes)
24212422

24222423

2424+
TWO_GOT_THREE = "2, got 3" if PY314 else "2"
2425+
24232426
@pytest.mark.parametrize(
24242427
"col1, col2, suffixes, msg",
24252428
[
2426-
("a", "a", ("a", "b", "c"), r"too many values to unpack \(expected 2\)"),
2429+
("a", "a", ("a", "b", "c"), fr"too many values to unpack \(expected {TWO_GOT_THREE}\)"),
24272430
("a", "a", tuple("a"), r"not enough values to unpack \(expected 2, got 1\)"),
24282431
],
24292432
)

pandas/tests/scalar/period/test_period.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import numpy as np
99
import pytest
1010

11+
from pandas.compat import PY314
1112
from pandas._libs.tslibs import iNaT
1213
from pandas._libs.tslibs.ccalendar import (
1314
DAYS,
@@ -344,7 +345,10 @@ def test_invalid_arguments(self):
344345
msg = '^Given date string "-2000" not likely a datetime$'
345346
with pytest.raises(ValueError, match=msg):
346347
Period("-2000", "Y")
347-
msg = "day is out of range for month"
348+
if PY314:
349+
msg = 'day 0 must be in range 1..31 for month 1 in year 1: 0'
350+
else:
351+
msg = "day is out of range for month"
348352
with pytest.raises(DateParseError, match=msg):
349353
Period("0", "Y")
350354
msg = "Unknown datetime string format, unable to parse"

pandas/tests/scalar/timestamp/test_constructors.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import numpy as np
1717
import pytest
1818

19+
from pandas.compat import PY314
1920
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
2021
from pandas.errors import OutOfBoundsDatetime
2122

@@ -212,13 +213,19 @@ def test_constructor_positional(self):
212213
with pytest.raises(TypeError, match=msg):
213214
Timestamp(2000, 1)
214215

215-
msg = "month must be in 1..12"
216+
if PY314:
217+
msg = 'month must be in 1..12, not'
218+
else:
219+
msg = "day is out of range for month"
216220
with pytest.raises(ValueError, match=msg):
217221
Timestamp(2000, 0, 1)
218222
with pytest.raises(ValueError, match=msg):
219223
Timestamp(2000, 13, 1)
220224

221-
msg = "day is out of range for month"
225+
if PY314:
226+
msg = "must be in range 1..31 for month 1 in year 2000"
227+
else:
228+
msg = "day is out of range for month"
222229
with pytest.raises(ValueError, match=msg):
223230
Timestamp(2000, 1, 0)
224231
with pytest.raises(ValueError, match=msg):
@@ -242,7 +249,10 @@ def test_constructor_keyword(self):
242249
with pytest.raises(ValueError, match=msg):
243250
Timestamp(year=2000, month=13, day=1)
244251

245-
msg = "day is out of range for month"
252+
if PY314:
253+
msg = "must be in range 1..31 for month 1 in year 2000"
254+
else:
255+
msg = "day is out of range for month"
246256
with pytest.raises(ValueError, match=msg):
247257
Timestamp(year=2000, month=1, day=0)
248258
with pytest.raises(ValueError, match=msg):

pandas/tests/tools/test_to_datetime.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
iNaT,
2222
parsing,
2323
)
24-
from pandas.compat import WASM
24+
from pandas.compat import WASM, PY314
2525
from pandas.errors import (
2626
OutOfBoundsDatetime,
2727
OutOfBoundsTimedelta,
@@ -57,6 +57,13 @@
5757
r"alongside this."
5858
)
5959

60+
if PY314:
61+
NOT_99 = ", not 99"
62+
DAY_IS_OUT_OF_RANGE = "day \d{1,2} must be in range 1\.\.\d{1,2} for month \d{1,2} in year \d{4}"
63+
else:
64+
NOT_99 = ""
65+
DAY_IS_OUT_OF_RANGE = "day is out of range for month"
66+
6067

6168
class TestTimeConversionFormats:
6269
def test_to_datetime_readonly(self, writable):
@@ -1372,7 +1379,7 @@ def test_datetime_invalid_scalar(self, value, format):
13721379
r'^Given date string "a" not likely a datetime$',
13731380
r'^unconverted data remains when parsing with format "%H:%M:%S": "9". '
13741381
f"{PARSING_ERR_MSG}$",
1375-
r"^second must be in 0..59: 00:01:99$",
1382+
fr"^second must be in 0..59{NOT_99}: 00:01:99$",
13761383
]
13771384
)
13781385
with pytest.raises(ValueError, match=msg):
@@ -1424,7 +1431,7 @@ def test_datetime_invalid_index(self, values, format):
14241431
f"{PARSING_ERR_MSG}$",
14251432
r'^unconverted data remains when parsing with format "%H:%M:%S": "9". '
14261433
f"{PARSING_ERR_MSG}$",
1427-
r"^second must be in 0..59: 00:01:99$",
1434+
fr"^second must be in 0..59{NOT_99}: 00:01:99$",
14281435
]
14291436
)
14301437
with pytest.raises(ValueError, match=msg):
@@ -2851,7 +2858,10 @@ def test_day_not_in_month_coerce(self, cache, arg, format):
28512858
assert isna(to_datetime(arg, errors="coerce", format=format, cache=cache))
28522859

28532860
def test_day_not_in_month_raise(self, cache):
2854-
msg = "day is out of range for month: 2015-02-29"
2861+
if PY314:
2862+
msg = "day 29 must be in range 1..28 for month 2 in year 2015: 2015-02-29"
2863+
else:
2864+
msg = "day is out of range for month: 2015-02-29"
28552865
with pytest.raises(ValueError, match=msg):
28562866
to_datetime("2015-02-29", errors="raise", cache=cache)
28572867

@@ -2861,12 +2871,12 @@ def test_day_not_in_month_raise(self, cache):
28612871
(
28622872
"2015-02-29",
28632873
"%Y-%m-%d",
2864-
f"^day is out of range for month. {PARSING_ERR_MSG}$",
2874+
f"^{DAY_IS_OUT_OF_RANGE}. {PARSING_ERR_MSG}$",
28652875
),
28662876
(
28672877
"2015-29-02",
28682878
"%Y-%d-%m",
2869-
f"^day is out of range for month. {PARSING_ERR_MSG}$",
2879+
f"^{DAY_IS_OUT_OF_RANGE}. {PARSING_ERR_MSG}$",
28702880
),
28712881
(
28722882
"2015-02-32",
@@ -2883,12 +2893,12 @@ def test_day_not_in_month_raise(self, cache):
28832893
(
28842894
"2015-04-31",
28852895
"%Y-%m-%d",
2886-
f"^day is out of range for month. {PARSING_ERR_MSG}$",
2896+
f"^{DAY_IS_OUT_OF_RANGE}. {PARSING_ERR_MSG}$",
28872897
),
28882898
(
28892899
"2015-31-04",
28902900
"%Y-%d-%m",
2891-
f"^day is out of range for month. {PARSING_ERR_MSG}$",
2901+
f"^{DAY_IS_OUT_OF_RANGE}. {PARSING_ERR_MSG}$",
28922902
),
28932903
],
28942904
)

0 commit comments

Comments
 (0)