From df6d442ca82f6c9932a4fe217641c2e736591ee6 Mon Sep 17 00:00:00 2001 From: jeffwang0516 Date: Fri, 21 Oct 2022 14:28:15 +0800 Subject: [PATCH 1/2] Add method.__reduce__ --- vm/src/builtins/builtinfunc.rs | 9 +++++++++ vm/src/builtins/function.rs | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/vm/src/builtins/builtinfunc.rs b/vm/src/builtins/builtinfunc.rs index 66437ee5f07..3dea2fa8775 100644 --- a/vm/src/builtins/builtinfunc.rs +++ b/vm/src/builtins/builtinfunc.rs @@ -254,6 +254,15 @@ impl PyBuiltinMethod { self.class.name() ) } + #[pymethod(magic)] + fn reduce( + &self, + vm: &VirtualMachine, + ) -> (Option, (Option, PyStrRef)) { + let builtinfunc_getattr = vm.builtins.get_attr("getattr", vm).ok(); + let classname = vm.builtins.get_attr(self.class.name().to_string(), vm).ok(); + (builtinfunc_getattr, (classname, self.value.name.clone())) + } } impl Unconstructible for PyBuiltinMethod {} diff --git a/vm/src/builtins/function.rs b/vm/src/builtins/function.rs index 460ceb762be..1a3cc2bf07b 100644 --- a/vm/src/builtins/function.rs +++ b/vm/src/builtins/function.rs @@ -552,6 +552,17 @@ impl PyBoundMethod { )) } + #[pymethod(magic)] + fn reduce( + &self, + vm: &VirtualMachine, + ) -> (Option, (PyObjectRef, Option)) { + let builtinfunc_getattr = vm.builtins.get_attr("getattr", vm).ok(); + let funcself = self.object.clone(); + let funcname = self.function.get_attr("__name__", vm).ok(); + (builtinfunc_getattr, (funcself, funcname)) + } + #[pygetset(magic)] fn doc(&self, vm: &VirtualMachine) -> PyResult { self.function.get_attr("__doc__", vm) From aa40195d2422f91f686338e357978a9cecbcd92f Mon Sep 17 00:00:00 2001 From: jeffwang0516 Date: Fri, 21 Oct 2022 14:28:45 +0800 Subject: [PATCH 2/2] Remove expected failures for method related tests --- Lib/test/test_pickle.py | 20 -------------------- Lib/test/test_pickletools.py | 10 ---------- 2 files changed, 30 deletions(-) diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 3312eb6e0bf..bc69f8cb602 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -95,11 +95,6 @@ def test_buffer_callback_error(self): # TODO: RUSTPYTHON, remove when this passe def test_buffers_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_buffers_error() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, TypeError: cannot pickle 'method' object - @unittest.expectedFailure - def test_c_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_c_methods() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, AssertionError @unittest.expectedFailure def test_complex_newobj_ex(self): # TODO: RUSTPYTHON, remove when this passes @@ -130,11 +125,6 @@ def test_optional_frames(self): # TODO: RUSTPYTHON, remove when this passes def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_picklebuffer_error() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, pickle.PicklingError - @unittest.expectedFailure - def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_py_methods() # TODO: RUSTPYTHON, remove when this passes - def dumps(self, arg, proto=None, **kwargs): f = io.BytesIO() p = self.pickler(f, proto, **kwargs) @@ -171,11 +161,6 @@ def test_buffer_callback_error(self): # TODO: RUSTPYTHON, remove when this passe def test_buffers_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_buffers_error() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, TypeError: cannot pickle 'method' object - @unittest.expectedFailure - def test_c_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_c_methods() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, AssertionError @unittest.expectedFailure def test_complex_newobj_ex(self): # TODO: RUSTPYTHON, remove when this passes @@ -216,11 +201,6 @@ def test_optional_frames(self): # TODO: RUSTPYTHON, remove when this passes def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_picklebuffer_error() # TODO: RUSTPYTHON, remove when this passes - # TODO: RUSTPYTHON, pickle.PicklingError - @unittest.expectedFailure - def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_py_methods() # TODO: RUSTPYTHON, remove when this passes - def dumps(self, arg, protocol=None, **kwargs): return pickle.dumps(arg, protocol, **kwargs) diff --git a/Lib/test/test_pickletools.py b/Lib/test/test_pickletools.py index 1d7afb6e883..7dde4b17ed2 100644 --- a/Lib/test/test_pickletools.py +++ b/Lib/test/test_pickletools.py @@ -17,11 +17,6 @@ def test_buffer_callback_error(self): # TODO: RUSTPYTHON, remove when this passe def test_buffers_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_buffers_error() - # TODO: RUSTPYTHON, TypeError: cannot pickle 'method' object - @unittest.expectedFailure - def test_c_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_c_methods() - def test_compat_pickle(self): # TODO: RUSTPYTHON, remove when this passes super().test_compat_pickle() @@ -58,11 +53,6 @@ def test_optional_frames(self): # TODO: RUSTPYTHON, remove when this passes def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes super().test_picklebuffer_error() - # TODO: RUSTPYTHON, pickle.PicklingError - @unittest.expectedFailure - def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes - super().test_py_methods() - def dumps(self, arg, proto=None, **kwargs): return pickletools.optimize(pickle.dumps(arg, proto, **kwargs))