From 0f371bb4382d6e0702c0101c5a7bce50c3eb1fb8 Mon Sep 17 00:00:00 2001 From: Moreal Date: Sat, 13 Apr 2024 02:13:39 +0900 Subject: [PATCH 1/3] Allow update `__class__` for module subclasses --- vm/src/builtins/object.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index fca68a9f34..1fbebf2729 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -1,5 +1,6 @@ use super::{PyDictRef, PyList, PyStr, PyStrRef, PyType, PyTypeRef}; use crate::common::hash::PyHash; +use crate::types::PyTypeFlags; use crate::{ class::PyClassImpl, function::{Either, FuncArgs, PyArithmeticValue, PyComparisonValue, PySetterValue}, @@ -281,7 +282,18 @@ impl PyBaseObject { #[pygetset(name = "__class__", setter)] fn set_class(instance: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - if instance.payload_is::() { + let both_module = instance.class().fast_issubclass(vm.ctx.types.module_type) + && value.class().fast_issubclass(vm.ctx.types.module_type); + let both_mutable = !instance + .class() + .slots + .flags + .has_feature(PyTypeFlags::IMMUTABLETYPE) + && !value + .downcast_ref::() + .map(|t| t.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE)) + .unwrap_or(false); + if both_mutable || both_module { match value.downcast::() { Ok(cls) => { // FIXME(#1979) cls instances might have a payload @@ -298,7 +310,8 @@ impl PyBaseObject { } } else { Err(vm.new_type_error( - "__class__ assignment only supported for types without a payload".to_owned(), + "__class__ assignment only supported for mutable types or ModuleType subclasses" + .to_owned(), )) } } From 42fafcfdbe6ca0ad54b3a82284e155078c9d57c1 Mon Sep 17 00:00:00 2001 From: Moreal Date: Sat, 13 Apr 2024 18:50:04 +0900 Subject: [PATCH 2/3] Set `IMMUTABLETYPE` flag for static classes --- derive-impl/src/pyclass.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/derive-impl/src/pyclass.rs b/derive-impl/src/pyclass.rs index 8f688b366a..a8371d889b 100644 --- a/derive-impl/src/pyclass.rs +++ b/derive-impl/src/pyclass.rs @@ -1497,6 +1497,9 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result Date: Sun, 14 Apr 2024 11:47:44 +0900 Subject: [PATCH 3/3] Unmark fixed tests --- Lib/test/test_opcache.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 978cc93053..8f1f8764b1 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -152,8 +152,6 @@ def f(): for _ in range(1025): self.assertTrue(f()) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_metaclass_swap(self): class OldMetaclass(type): @property @@ -411,8 +409,6 @@ def f(): for _ in range(1025): self.assertTrue(f()) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_metaclass_swap(self): class OldMetaclass(type): @property