Preserve __dict__ and __slots__ state in deque.__reduce__#7699
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [ ] lib: cpython/Lib/collections dependencies:
dependent tests: (302 tests)
Legend:
|
deque.__reduce__ passed None as the unpickle state, so a deque subclass's __dict__ and __slots__ values were dropped across a pickle round-trip. CPython's deque___reduce___impl (Modules/_collectionsmodule.c::deque___reduce___impl) calls _PyObject_GetState, which returns the dict (or a (dict, slots) tuple) so subclass attributes survive. Replace the placeholder with the result of __getstate__() on the instance. object.__getstate__ already implements the dict / dict+slots protocol, matching _PyObject_GetState.
2458408 to
0dea5c4
Compare
Background
pickle.dumps(d)callsd.__reduce__(), which returns a 5-tuple(cls, args, state, listiter, dictiter). Thestateslot is meant to carry whatever__setstate__(or the default attribute-restore path) needs to reconstruct subclass-specific data: typically__dict__, or(__dict__, slots_dict)when__slots__is in play.RustPython's
deque.__reduce__passedNoneforstate, so any attribute set on a deque subclass was lost across a pickle round-trip. CPython'sdeque___reduce___impl(Modules/_collectionsmodule.c::deque___reduce___impl) calls_PyObject_GetStateto get the right value.Repro
Fix
Replace the
vm.ctx.none()placeholder with the result of__getstate__()on the instance.object.__getstate__already handles both__dict__and the dict/slots tuple form, matching CPython's_PyObject_GetState. No code duplication.Tests unmasked
test_deque.TestSubclass.test_copy_pickletest_pickle_recursivestill expected-fails for an unrelated recursion issue and stays marked.Verification
test_deque test_collections test_pickle test_copy test_dataclasses test_descr test_class test_typing test_inspect test_functools(2,562 tests)copy.copy(d)continues to drop attributes (matches CPython — the__copy__path doesn't go through__reduce__)copy.deepcopy(d)preserves attributes via the new__reduce__deque,deque(maxlen=...), and emptydequeround-trip unchangedSummary by CodeRabbit