diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index e634458e00..98fd839950 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1052,8 +1052,6 @@ class Cdict(object): self.assertEqual(x.foo, 1) self.assertEqual(x.__dict__, {'foo': 1}) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_object_class_assignment_between_heaptypes_and_nonheaptypes(self): class SubType(types.ModuleType): a = 1 diff --git a/Lib/test/test_importlib/test_lazy.py b/Lib/test/test_importlib/test_lazy.py index 7539a8c435..cc993f333e 100644 --- a/Lib/test/test_importlib/test_lazy.py +++ b/Lib/test/test_importlib/test_lazy.py @@ -75,8 +75,6 @@ def new_module(self, source_code=None): self.assertIsNone(loader.loaded) return module - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_e2e(self): # End-to-end test to verify the load is in fact lazy. importer = TestingImporter() @@ -90,24 +88,18 @@ def test_e2e(self): self.assertIsNotNone(importer.loaded) self.assertEqual(module, importer.loaded) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_attr_unchanged(self): # An attribute only mutated as a side-effect of import should not be # changed needlessly. module = self.new_module() self.assertEqual(TestingImporter.mutated_name, module.__name__) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_new_attr(self): # A new attribute should persist. module = self.new_module() module.new_attr = 42 self.assertEqual(42, module.new_attr) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_mutated_preexisting_attr(self): # Changing an attribute that already existed on the module -- # e.g. __name__ -- should persist. @@ -115,8 +107,6 @@ def test_mutated_preexisting_attr(self): module.__name__ = 'bogus' self.assertEqual('bogus', module.__name__) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_mutated_attr(self): # Changing an attribute that comes into existence after an import # should persist. @@ -124,23 +114,17 @@ def test_mutated_attr(self): module.attr = 6 self.assertEqual(6, module.attr) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_delete_eventual_attr(self): # Deleting an attribute should stay deleted. module = self.new_module() del module.attr self.assertFalse(hasattr(module, 'attr')) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_delete_preexisting_attr(self): module = self.new_module() del module.__name__ self.assertFalse(hasattr(module, '__name__')) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_module_substitution_error(self): with test_util.uncache(TestingImporter.module_name): fresh_module = types.ModuleType(TestingImporter.module_name) @@ -149,8 +133,6 @@ def test_module_substitution_error(self): with self.assertRaisesRegex(ValueError, "substituted"): module.__name__ - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_module_already_in_sys(self): with test_util.uncache(TestingImporter.module_name): module = self.new_module() diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index 1fbebf2729..0b00b4422d 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -282,37 +282,34 @@ impl PyBaseObject { #[pygetset(name = "__class__", setter)] fn set_class(instance: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - 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 + match value.downcast::() { + Ok(cls) => { + let both_module = instance.class().fast_issubclass(vm.ctx.types.module_type) + && cls.fast_issubclass(vm.ctx.types.module_type); + let both_mutable = !instance + .class() + .slots + .flags + .has_feature(PyTypeFlags::IMMUTABLETYPE) + && !cls.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE); + // FIXME(#1979) cls instances might have a payload + if both_mutable || both_module { instance.set_class(cls, vm); Ok(()) - } - Err(value) => { - let value_class = value.class(); - let type_repr = &value_class.name(); - Err(vm.new_type_error(format!( - "__class__ must be set to a class, not '{type_repr}' object" - ))) + } else { + Err(vm.new_type_error( + "__class__ assignment only supported for mutable types or ModuleType subclasses" + .to_owned(), + )) } } - } else { - Err(vm.new_type_error( - "__class__ assignment only supported for mutable types or ModuleType subclasses" - .to_owned(), - )) + Err(value) => { + let value_class = value.class(); + let type_repr = &value_class.name(); + Err(vm.new_type_error(format!( + "__class__ must be set to a class, not '{type_repr}' object" + ))) + } } }