8000 Check `value` is `PyType` first by moreal · Pull Request #5227 · RustPython/RustPython · GitHub
[go: up one dir, main page]

Skip to content

Check value is PyType first #5227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 0 additions & 18 deletions Lib/test/test_importlib/test_lazy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -90,57 +88,43 @@ 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):
# Changi 8000 ng an attribute that already existed on the module --
# e.g. __name__ -- should persist.
module = self.new_module()
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.
module = self.new_module()
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)
Expand All @@ -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()
Expand Down
51 changes: 24 additions & 27 deletions vm/src/builtins/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<PyType>()
.map(|t| t.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE))
.unwrap_or(false);
if both_mutable || both_module {
match value.downcast::<PyType>() {
Ok(cls) => {
// FIXME(#1979) cls instances might have a payload
match value.downcast::<PyType>() {
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"
)))
}
}
}

Expand Down
Loading
0