Skip to content

Commit 3989493

Browse files
authored
[BUG] fixed DateOffset pickle bug when months >= 12 (#35258)
1 parent 21eb4e6 commit 3989493

File tree

6 files changed

+14
-210
lines changed

6 files changed

+14
-210
lines changed

doc/source/whatsnew/v1.2.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Datetimelike
172172
^^^^^^^^^^^^
173173
- Bug in :attr:`DatetimeArray.date` where a ``ValueError`` would be raised with a read-only backing array (:issue:`33530`)
174174
- Bug in ``NaT`` comparisons failing to raise ``TypeError`` on invalid inequality comparisons (:issue:`35046`)
175+
- Bug in :class:`DateOffset` where attributes reconstructed from pickle files differ from original objects when input values exceed normal ranges (e.g months=12) (:issue:`34511`)
175176
-
176177

177178
Timedelta

pandas/_libs/tslibs/offsets.pyx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -989,13 +989,6 @@ cdef class RelativeDeltaOffset(BaseOffset):
989989
state["_offset"] = state.pop("offset")
990990
state["kwds"]["offset"] = state["_offset"]
991991

992-
if "_offset" in state and not isinstance(state["_offset"], timedelta):
993-
# relativedelta, we need to populate using its kwds
994-
offset = state["_offset"]
995-
odict = offset.__dict__
996-
kwds = {key: odict[key] for key in odict if odict[key]}
997-
state.update(kwds)
998-
999992
self.n = state.pop("n")
1000993
self.normalize = state.pop("normalize")
1001994
self._cache = state.pop("_cache", {})
Binary file not shown.

pandas/tests/io/generate_legacy_storage_files.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
in ~/pandas
77
88
. activate pandas_0.20.3
9-
cd ~/
9+
cd ~/pandas/pandas
1010
11-
$ python pandas/pandas/tests/io/generate_legacy_storage_files.py \
12-
pandas/pandas/tests/io/data/legacy_pickle/0.20.3/ pickle
11+
$ python -m tests.io.generate_legacy_storage_files \
12+
tests/io/data/legacy_pickle/0.20.3/ pickle
1313
1414
This script generates a storage file for the current arch, system,
1515
and python version
@@ -328,7 +328,7 @@ def write_legacy_pickles(output_dir):
328328
pth = f"{platform_name()}.pickle"
329329

330330
fh = open(os.path.join(output_dir, pth), "wb")
331-
pickle.dump(create_pickle_data(), fh, pickle.HIGHEST_PROTOCOL)
331+
pickle.dump(create_pickle_data(), fh, pickle.DEFAULT_PROTOCOL)
332332
fh.close()
333333

334334
print(f"created pickle file: {pth}")

pandas/tests/tseries/offsets/data/dateoffset_0_15_2.pickle

Lines changed: 0 additions & 183 deletions
This file was deleted.

pandas/tests/tseries/offsets/test_offsets.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -634,22 +634,6 @@ def test_add_empty_datetimeindex(self, offset_types, tz_naive_fixture):
634634
result = offset_s + dta
635635
tm.assert_equal(result, dta)
636636

637-
def test_pickle_v0_15_2(self, datapath):
638-
offsets = {
639-
"DateOffset": DateOffset(years=1),
640-
"MonthBegin": MonthBegin(1),
641-
"Day": Day(1),
642-
"YearBegin": YearBegin(1),
643-
"Week": Week(1),
644-
}
645-
646-
pickle_path = datapath("tseries", "offsets", "data", "dateoffset_0_15_2.pickle")
647-
# This code was executed once on v0.15.2 to generate the pickle:
648-
# with open(pickle_path, 'wb') as f: pickle.dump(offsets, f)
649-
#
650-
result = read_pickle(pickle_path)
651-
tm.assert_dict_equal(offsets, result)
652-
653637
def test_pickle_roundtrip(self, offset_types):
654638
off = self._get_offset(offset_types)
655639
res = tm.round_trip_pickle(off)
@@ -663,6 +647,15 @@ def test_pickle_roundtrip(self, offset_types):
663647
# Make sure nothings got lost from _params (which __eq__) is based on
664648
assert getattr(off, attr) == getattr(res, attr)
665649

650+
def test_pickle_dateoffset_odd_inputs(self):
651+
# GH#34511
652+
off = DateOffset(months=12)
653+
res = tm.round_trip_pickle(off)
654+
assert off == res
655+
656+
base_dt = datetime(2020, 1, 1)
657+
assert base_dt + off == base_dt + res
658+
666659
def test_onOffset_deprecated(self, offset_types):
667660
# GH#30340 use idiomatic naming
668661
off = self._get_offset(offset_types)

0 commit comments

Comments
 (0)