8000 Allow update `__class__` for module subclasses · RustPython/RustPython@0f371bb · GitHub
[go: up one dir, main page]

Skip to content

Commit 0f371bb

Browse files
committed
Allow update __class__ for module subclasses
1 parent 8c7b811 commit 0f371bb

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

vm/src/builtins/object.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::{PyDictRef, PyList, PyStr, PyStrRef, PyType, PyTypeRef};
22
use crate::common::hash::PyHash;
3+
use crate::types::PyTypeFlags;
34
use crate::{
45
class::PyClassImpl,
56
function::{Either, FuncArgs, PyArithmeticValue, PyComparisonValue, PySetterValue},
@@ -281,7 +282,18 @@ impl PyBaseObject {
281282

282283
#[pygetset(name = "__class__", setter)]
283284
fn set_class(instance: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
284-
if instance.payload_is::<PyBaseObject>() {
285+
let both_module = instance.class().fast_issubclass(vm.ctx.types.module_type)
286+
&& value.class().fast_issubclass(vm.ctx.types.module_type);
287+
let both_mutable = !instance
288+
.class()
289+
.slots
290+
.flags
291+
.has_feature(PyTypeFlags::IMMUTABLETYPE)
292+
&& !value
293+
.downcast_ref::<PyType>()
294+
.map(|t| t.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE))
295+
.unwrap_or(false);
296+
if both_mutable || both_module {
285297
match value.downcast::<PyType>() {
286298
Ok(cls) => {
287299
// FIXME(#1979) cls instances might have a payload
@@ -298,7 +310,8 @@ impl PyBaseObject {
298310
}
299311
} else {
300312
Err(vm.new_type_error(
301-
"__class__ assignment only supported for types without a payload".to_owned(),
313+
"__class__ assignment only supported for mutable types or ModuleType subclasses"
314+
.to_owned(),
302315
))
303316
}
304317
}

0 commit comments

Comments
 (0)
0