Fix metaclass check classcell (#3986)

This commit is contained in:
YeonWoo authored and GitHub committed 2022-08-13 17:20:13 +09:00
1 parent 2b2ed5a5fc
commit e513bf11fe
4 files changed
+27 -8

No files matched your search

-6
View File
@@ -143,8 +143,6 @@ class TestSuper(unittest.TestCase):
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
@@ -263,8 +261,6 @@ class TestSuper(unittest.TestCase):
def f(self):
return __class__
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test___classcell___overwrite(self):
# See issue #23722
# Overwriting __classcell__ with nonsense is explicitly prohibited
@@ -279,8 +275,6 @@ class TestSuper(unittest.TestCase):
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
+13 -1
View File
@@ -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;
@@ -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
+13 -1
View File
@@ -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)
+1
View File
@@ -87,6 +87,7 @@ declare_const_name! {
__ceil__,
__cformat__,
__class__,
__classcell__,
__class_getitem__,
__complex__,
__contains__,