From f1a9ecada7383b6c1658dbc981604f4147f109ae Mon Sep 17 00:00:00 2001 From: dot Date: Sat, 10 Oct 2026 16:56:19 +0900 Subject: [PATCH] Support pickling slot wrapper descriptors Extract wrapper descriptor reduction from #8954 for Python 3.14. Reduce to getattr on the defining class and cover direct reduction plus one roundtrip in the existing pickle snippet. Preserve canonical expected failures for unrelated staticmethod descriptor behavior. Assisted-by: OpenAI Codex:model identifier unavailable --- crates/vm/src/builtins/descriptor.rs | 10 ++++++++++ extra_tests/snippets/stdlib_pickle.py | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/crates/vm/src/builtins/descriptor.rs b/crates/vm/src/builtins/descriptor.rs index 55c2275f5bb..e8329fbb572 100644 --- a/crates/vm/src/builtins/descriptor.rs +++ b/crates/vm/src/builtins/descriptor.rs @@ -2062,6 +2062,16 @@ impl Callable for PyWrapper { flags(DISALLOW_INSTANTIATION) )] impl Py { + #[pymethod] + fn __reduce__(&self, vm: &VirtualMachine) -> PyResult { + let getattr = vm.builtins.get_attr("getattr", vm)?; + let args = vm.ctx.new_tuple(vec![ + self.typ.to_owned().into(), + self.name.to_owned().into(), + ]); + Ok(vm.ctx.new_tuple(vec![getattr, args.into()]).into()) + } + #[pygetset] fn __qualname__(&self) -> String { format!("{}.{}", self.typ.name(), self.name) diff --git a/extra_tests/snippets/stdlib_pickle.py b/extra_tests/snippets/stdlib_pickle.py index 23d137df43b..855bd79691e 100644 --- a/extra_tests/snippets/stdlib_pickle.py +++ b/extra_tests/snippets/stdlib_pickle.py @@ -9,3 +9,7 @@ assert list(memo) == [1, 7] assert memo[1] is left assert memo[7] is left + +# Slot wrapper descriptors reduce to lookup on their defining class. +assert object.__str__.__reduce__() == (getattr, (object, "__str__")) +assert _pickle.loads(_pickle.dumps(object.__str__)) is object.__str__