Skip to content
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
6 changes: 0 additions & 6 deletions Lib/test/test_super.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ def f():
return __class__
self.assertIs(X.f(), X)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test___class___new(self):
# See issue #23722
# Ensure zero-arg super() works as soon as type.__new__() is completed
Expand Down Expand Up @@ -263,8 +261,6 @@ class WithClassRef(metaclass=Meta):
def f(self):
return __class__

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test___classcell___overwrite(self):
# See issue #23722
# Overwriting __classcell__ with nonsense is explicitly prohibited
Expand All @@ -279,8 +275,6 @@ def __new__(cls, name, bases, namespace, cell):
class A(metaclass=Meta, cell=bad_cell):
pass

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test___classcell___wrong_cell(self):
# See issue #23722
# Pointing the cell reference at the wrong class is also prohibited
Expand Down
14 changes: 13 additions & 1 deletion vm/src/builtins/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ use crate::common::{
lock::{PyRwLock, PyRwLockReadGuard},
};
use crate::{
builtins::function::PyCellRef,
builtins::PyBaseExceptionRef,
class::{PyClassImpl, StaticType},
convert::ToPyObject,
function::{FuncArgs, KwArgs, OptionalArg, PySetterValue},
identifier,
protocol::PyNumberMethods,
types::{Callable, GetAttr, PyTypeFlags, PyTypeSlots, SetAttr},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use indexmap::{map::Entry, IndexMap};
use itertools::Itertools;
Expand Down Expand Up @@ -622,6 +624,16 @@ impl PyType {
let typ = Self::new_verbose_ref(name.as_str(), base, bases, attributes, slots, metatype)
.map_err(|e| vm.new_type_error(e))?;

if let Some(cell) = typ.attributes.write().get(identifier!(vm, __classcell__)) {
let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| {
vm.new_type_error(format!(
"__classcell__ must be a nonlocal cell, not {}",
cell.class().name()
))
})?;
cell.set(Some(typ.clone().to_pyobject(vm)));
};

// avoid deadlock
let attributes = typ
.attributes
Expand Down
14 changes: 13 additions & 1 deletion vm/src/stdlib/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,19 @@ mod builtins {
)?;

if let Some(ref classcell) = classcell {
classcell.set(Some(class.clone()));
let classcell = classcell.get().ok_or_else(|| {
vm.new_type_error(format!(
"__class__ not set defining {:?} as {:?}. Was __classcell__ propagated to type.__new__?",
meta_name, class
))
})?;

if !classcell.is(&class) {
return Err(vm.new_type_error(format!(
"__class__ set to {:?} defining {:?} as {:?}",
classcell, meta_name, class
)));
}
}

Ok(class)
Expand Down
1 change: 1 addition & 0 deletions vm/src/vm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ declare_const_name! {
__ceil__,
__cformat__,
__class__,
__classcell__,
__class_getitem__,
__complex__,
__contains__,
Expand Down