Skip to content

Commit a14868e

Browse files
Fix: Ensure non-ISO deprecation warnings trigger in slice_indexer and add test suppressions
1 parent a627889 commit a14868e

File tree

14 files changed

+68
-77
lines changed

14 files changed

+68
-77
lines changed

pandas/core/indexes/datetimes.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,22 @@ def _is_iso_format_string(date_str: str) -> bool:
116116
Check if a date string follows ISO8601 format.
117117
118118
ISO format must start with a 4-digit year (YYYY), optionally followed by
119-
month and day with consistent separators.
119+
hyphen-separated month and day or 'T' for time component.
120120
121121
Examples of ISO format (True):
122+
- 2024
123+
- 2024-01
122124
- 2024-01-10
123-
- 2024/01/10
124-
- 2024 01 10
125125
- 2024-01-10T00:00:00
126126
127127
Examples of non-ISO format (False):
128+
- 2024/01/10 (/ separator)
129+
- 2024 01 10 (space separator)
128130
- 01/10/2024 (MM/DD/YYYY)
129131
- 10/01/2024 (DD/MM/YYYY)
130132
- 01-10-2024 (MM-DD-YYYY)
131133
"""
132-
# ISO format must start with 4-digit year followed by separator (-, /, ., or space)
133-
return re.match(r"^\d{4}[-/. ]", date_str) is not None
134+
return re.match(r"^\d{4}(?:-|T|$)", date_str) is not None
134135

135136

136137
@inherit_names(
@@ -722,6 +723,23 @@ def check_str_or_none(point) -> bool:
722723
# GH#33146 if start and end are combinations of str and None and Index is not
723724
# monotonic, we can not use Index.slice_indexer because it does not honor the
724725
# actual elements, is only searching for start and end
726+
# GH#58302 - Deprecate non-ISO string formats in .loc indexing
727+
if isinstance(start, str) and not _is_iso_format_string(start):
728+
msg = (
729+
"Parsing non-ISO datetime strings in .loc is deprecated "
730+
"and will be removed in a future version. Use ISO format "
731+
f"(YYYY-MM-DD) instead. Got '{start}'."
732+
)
733+
warnings.warn(msg, Pandas4Warning, stacklevel=find_stack_level())
734+
735+
if isinstance(end, str) and not _is_iso_format_string(end):
736+
msg = (
737+
"Parsing non-ISO datetime strings in .loc is deprecated "
738+
"and will be removed in a future version. Use ISO format "
739+
f"(YYYY-MM-DD) instead. Got '{end}'."
740+
)
741+
warnings.warn(msg, Pandas4Warning, stacklevel=find_stack_level())
742+
725743
if (
726744
check_str_or_none(start)
727745
or check_str_or_none(end)
@@ -733,31 +751,12 @@ def check_str_or_none(point) -> bool:
733751
in_index = True
734752
if start is not None:
735753
start_casted = self._maybe_cast_slice_bound(start, "left")
736-
737-
# GH#58302 - Deprecate non-ISO string formats in .loc indexing
738-
if isinstance(start, str) and not _is_iso_format_string(start):
739-
msg = (
740-
"Parsing non-ISO datetime strings in .loc is deprecated "
741-
"and will be removed in a future version. Use ISO format "
742-
f"(YYYY-MM-DD) instead. Got '{start}'."
743-
)
744-
warnings.warn(msg, Pandas4Warning, stacklevel=find_stack_level())
745-
746754
mask = start_casted <= self
747755
in_index &= (start_casted == self).any()
748756

749757
if end is not None:
750758
end_casted = self._maybe_cast_slice_bound(end, "right")
751759

752-
# GH#58302 - Deprecate non-ISO string formats in .loc indexing
753-
if isinstance(end, str) and not _is_iso_format_string(end):
754-
msg = (
755-
"Parsing non-ISO datetime strings in .loc is deprecated "
756-
"and will be removed in a future version. Use ISO format "
757-
f"(YYYY-MM-DD) instead. Got '{end}'."
758-
)
759-
warnings.warn(msg, Pandas4Warning, stacklevel=find_stack_level())
760-
761760
mask = (self <= end_casted) & mask
762761
in_index &= (end_casted == self).any()
763762

pandas/tests/groupby/test_groupby.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,7 @@
2828
from pandas.core.arrays import BooleanArray
2929
import pandas.core.common as com
3030

31-
pytestmark = [
32-
pytest.mark.filterwarnings("ignore:Mean of empty slice:RuntimeWarning"),
33-
pytest.mark.filterwarnings(
34-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
35-
),
36-
]
31+
pytestmark = pytest.mark.filterwarnings("ignore:Mean of empty slice:RuntimeWarning")
3732

3833

3934
def test_repr():

pandas/tests/indexes/datetimes/test_indexing.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@
2626

2727
from pandas.tseries.frequencies import to_offset
2828

29-
pytestmark = pytest.mark.filterwarnings(
30-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
31-
)
32-
3329
START, END = datetime(2009, 1, 1), datetime(2010, 1, 1)
3430

3531

@@ -493,6 +489,9 @@ def test_get_loc_timedelta_invalid_key(self, key):
493489
with pytest.raises(TypeError, match=msg):
494490
dti.get_loc(key)
495491

492+
@pytest.mark.filterwarnings(
493+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
494+
)
496495
def test_get_loc_reasonable_key_error(self):
497496
# GH#1062
498497
index = DatetimeIndex(["1/3/2000"])

pandas/tests/indexes/datetimes/test_partial_slicing.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,11 @@ def test_loc_indexing_non_iso_single_key_deprecation(self, ser_daily, date_strin
501501
@pytest.mark.parametrize(
502502
"date_string,expected",
503503
[
504-
("2024-01-10", 9), # YYYY-MM-DD (dash)
505-
("2024/01/10", 9), # YYYY/MM/DD (slash)
506-
("2024 01 10", 9), # YYYY MM DD (space)
504+
("2024-01-10", 9), # YYYY-MM-DD (ISO format)
507505
],
508506
)
509507
def test_loc_indexing_iso_format_no_warning(self, ser_daily, date_string, expected):
510-
# GH#58302 - ISO formats should NOT warn
508+
# GH#58302 - ISO format (YYYY-MM-DD) should NOT warn
511509
with tm.assert_produces_warning(None):
512510
result = ser_daily.loc[date_string]
513511
assert result == expected

pandas/tests/indexes/multi/test_partial_indexing.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
)
1010
import pandas._testing as tm
1111

12-
pytestmark = pytest.mark.filterwarnings(
13-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
14-
)
15-
1612

1713
@pytest.fixture
1814
def df():

pandas/tests/indexes/period/test_indexing.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
)
2222
import pandas._testing as tm
2323

24-
pytestmark = pytest.mark.filterwarnings(
25-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
26-
)
27-
2824
dti4 = date_range("2016-01-01", periods=4)
2925
dti = dti4[:-1]
3026
rng = pd.Index(range(3))
@@ -176,6 +172,9 @@ def test_getitem_list_periods(self):
176172
tm.assert_series_equal(ts[[Period("2012-01-02", freq="D")]], exp)
177173

178174
@pytest.mark.arm_slow
175+
@pytest.mark.filterwarnings(
176+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
177+
)
179178
def test_getitem_seconds(self):
180179
# GH#6716
181180
didx = date_range(start="2013/01/01 09:00:00", freq="s", periods=4000)
@@ -210,6 +209,9 @@ def test_getitem_seconds(self):
210209
period_range,
211210
],
212211
)
212+
@pytest.mark.filterwarnings(
213+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
214+
)
213215
def test_getitem_day(self, idx_range):
214216
# GH#6716
215217
# Confirm DatetimeIndex and PeriodIndex works identically

pandas/tests/indexes/period/test_partial_slicing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
)
1111
import pandas._testing as tm
1212

13-
pytestmark = pytest.mark.filterwarnings(
14-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
15-
)
16-
1713

1814
class TestPeriodIndex:
15+
pytestmark = pytest.mark.filterwarnings(
16+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
17+
)
18+
1919
def test_getitem_periodindex_duplicates_string_slice(self):
2020
# monotonic
2121
idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="Y-JUN")

pandas/tests/indexing/multiindex/test_slice.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919
import pandas._testing as tm
2020
from pandas.tests.indexing.common import _mklbl
2121

22-
pytestmark = pytest.mark.filterwarnings(
23-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
24-
)
25-
2622

2723
class TestMultiIndexSlicers:
2824
def test_per_axis_per_level_getitem(self):

pandas/tests/indexing/test_loc.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@
4444
from pandas.core.indexing import _one_ellipsis_message
4545
from pandas.tests.indexing.common import check_indexing_smoketest_or_raises
4646

47-
pytestmark = pytest.mark.filterwarnings(
48-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
49-
)
50-
5147

5248
@pytest.mark.parametrize(
5349
"series, new_series, expected_ser",

pandas/tests/resample/test_datetime_index.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@
3838
from pandas.tseries.frequencies import to_offset
3939
from pandas.tseries.offsets import Minute
4040

41-
pytestmark = pytest.mark.filterwarnings(
42-
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
43-
)
44-
4541

4642
@pytest.fixture
4743
def simple_date_range_series():
@@ -331,6 +327,9 @@ def test_resample_rounding(unit):
331327
tm.assert_frame_equal(result, expected)
332328

333329

330+
@pytest.mark.filterwarnings(
331+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
332+
)
334333
def test_resample_basic_from_daily(unit):
335334
# from daily
336335
dti = date_range(
@@ -555,6 +554,9 @@ def test_resample_ohlc(unit):
555554
assert xs["close"] == s.iloc[4]
556555

557556

557+
@pytest.mark.filterwarnings(
558+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
559+
)
558560
def test_resample_ohlc_result(unit):
559561
# GH 12332
560562
index = date_range("1-1-2000", "2-15-2000", freq="h").as_unit(unit)
@@ -666,6 +668,9 @@ def test_resample_timestamp_to_period(
666668
tm.assert_series_equal(result, expected)
667669

668670

671+
@pytest.mark.filterwarnings(
672+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
673+
)
669674
def test_ohlc_5min(unit):
670675
def _ohlc(group):
671676
if isna(group).all():
@@ -1580,6 +1585,9 @@ def test_resample_dst_anchor(unit):
15801585
)
15811586

15821587

1588+
@pytest.mark.filterwarnings(
1589+
"ignore:Parsing non-ISO datetime strings:pandas.errors.Pandas4Warning"
1590+
)
15831591
def test_resample_dst_anchor2(unit):
15841592
dti = date_range(
15851593
"2013-09-30", "2013-11-02", freq="30Min", tz="Europe/Paris"

0 commit comments

Comments
 (0)