Skip to content

Commit 134bec4

Browse files
jschendeljreback
authored andcommitted
BUG: Preserve CategoricalDtype._ordered_from_sentinel with pickle (#27317)
1 parent 298c7cc commit 134bec4

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

pandas/core/dtypes/dtypes.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class CategoricalDtype(PandasExtensionDtype, ExtensionDtype):
219219
kind = "O" # type: str_type
220220
str = "|O08"
221221
base = np.dtype("O")
222-
_metadata = ("categories", "ordered")
222+
_metadata = ("categories", "ordered", "_ordered_from_sentinel")
223223
_cache = {} # type: Dict[str_type, PandasExtensionDtype]
224224

225225
def __init__(self, categories=None, ordered: OrderedType = ordered_sentinel):
@@ -356,6 +356,7 @@ def __setstate__(self, state: Dict[str_type, Any]) -> None:
356356
# pickle -> need to set the settable private ones here (see GH26067)
357357
self._categories = state.pop("categories", None)
358358
self._ordered = state.pop("ordered", False)
359+
self._ordered_from_sentinel = state.pop("_ordered_from_sentinel", False)
359360

360361
def __hash__(self) -> int:
361362
# _hash_categories returns a uint64, so use the negative

pandas/tests/dtypes/test_dtypes.py

+13
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,19 @@ def test_ordered_none_default_deprecated(self, ordered):
903903
with tm.assert_produces_warning(warning):
904904
dtype.ordered
905905

906+
@pytest.mark.parametrize("ordered", [True, False, None, ordered_sentinel])
907+
def test_pickle_ordered_from_sentinel(self, ordered):
908+
# GH 27295: can remove test when _ordered_from_sentinel is removed (GH 26403)
909+
dtype = CategoricalDtype(categories=list("abc"), ordered=ordered)
910+
911+
warning = FutureWarning if ordered is ordered_sentinel else None
912+
with tm.assert_produces_warning(warning, check_stacklevel=False):
913+
dtype_from_pickle = tm.round_trip_pickle(dtype)
914+
915+
result = dtype_from_pickle._ordered_from_sentinel
916+
expected = ordered is ordered_sentinel
917+
assert result is expected
918+
906919

907920
@pytest.mark.parametrize(
908921
"dtype", [CategoricalDtype, IntervalDtype, DatetimeTZDtype, PeriodDtype]

pandas/tests/series/test_io.py

+9
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,15 @@ def test_pickle_preserve_name(self):
226226
unpickled = self._pickle_roundtrip_name(tm.makeTimeSeries(name=n))
227227
assert unpickled.name == n
228228

229+
def test_pickle_categorical_ordered_from_sentinel(self):
230+
# GH 27295: can remove test when _ordered_from_sentinel is removed (GH 26403)
231+
s = Series(["a", "b", "c", "a"], dtype="category")
232+
result = tm.round_trip_pickle(s)
233+
result = result.astype("category")
234+
235+
tm.assert_series_equal(result, s)
236+
assert result.dtype._ordered_from_sentinel is False
237+
229238
def _pickle_roundtrip_name(self, obj):
230239

231240
with ensure_clean() as path:

0 commit comments

Comments
 (0)