Implement missing slots for NoneType (#7437)

* Define only wrapper_descriptor

* Implement missing slots for NoneType
This commit is contained in:
Lee Dogeon authored and GitHub committed 2026-03-16 11:58:40 +09:00
1 parent 03b7c4ebb8
commit 97790a88b2
5 files changed
+38 -113

No files matched your search

-2
View File
@@ -630,7 +630,6 @@ class TypesTests(unittest.TestCase):
self.assertGreater(object.__basicsize__, 0)
self.assertGreater(tuple.__itemsize__, 0)
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <method '__lt__' of 'int' objects> is not an instance of <class 'wrapper_descriptor'>
def test_slot_wrapper_types(self):
self.assertIsInstance(object.__init__, types.WrapperDescriptorType)
self.assertIsInstance(object.__str__, types.WrapperDescriptorType)
@@ -646,7 +645,6 @@ class TypesTests(unittest.TestCase):
# gh-93021: Second parameter is optional
self.assertIs(sig.parameters["owner"].default, None)
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <built-in method __lt__ of int object at 0xad6c41080> is not an instance of <class 'method-wrapper'>
def test_method_wrapper_types(self):
self.assertIsInstance(object().__init__, types.MethodWrapperType)
self.assertIsInstance(object().__str__, types.MethodWrapperType)
+24 -3
View File
@@ -2,10 +2,11 @@ use super::{PyStrRef, PyType, PyTypeRef};
use crate::{
Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
class::PyClassImpl,
common::hash::PyHash,
convert::ToPyObject,
function::FuncArgs,
function::{FuncArgs, PyComparisonValue},
protocol::PyNumberMethods,
types::{AsNumber, Constructor, Representable},
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
};
#[pyclass(module = false, name = "NoneType")]
@@ -49,7 +50,7 @@ impl Constructor for PyNone {
}
}
#[pyclass(with(Constructor, AsNumber, Representable))]
#[pyclass(with(Constructor, AsNumber, Comparable, Hashable, Representable))]
impl PyNone {}
impl Representable for PyNone {
@@ -74,6 +75,26 @@ impl AsNumber for PyNone {
}
}
impl Comparable for PyNone {
fn cmp(
zelf: &Py<Self>,
other: &crate::PyObject,
op: PyComparisonOp,
_vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Ok(op
.identical_optimization(zelf, other)
.map(PyComparisonValue::Implemented)
.unwrap_or(PyComparisonValue::NotImplemented))
}
}
impl Hashable for PyNone {
fn hash(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<PyHash> {
Ok(0xFCA86420)
}
}
#[pyclass(module = false, name = "NotImplementedType")]
#[derive(Debug)]
pub struct PyNotImplemented;
+2 -103
View File
@@ -3,13 +3,11 @@ use crate::common::lock::{
};
use crate::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{PyInt, PyStr, PyStrInterned, PyStrRef, PyType, PyTypeRef},
builtins::{PyInt, PyStr, PyStrInterned, PyType, PyTypeRef},
bytecode::ComparisonOperator,
common::hash::{PyHash, fix_sentinel, hash_bigint},
convert::ToPyObject,
function::{
Either, FromArgs, FuncArgs, OptionalArg, PyComparisonValue, PyMethodDef, PySetterValue,
},
function::{Either, FromArgs, FuncArgs, PyComparisonValue, PyMethodDef, PySetterValue},
protocol::{
PyBuffer, PyIterReturn, PyMapping, PyMappingMethods, PyMappingSlots, PyNumber,
PyNumberMethods, PyNumberSlots, PySequence, PySequenceMethods, PySequenceSlots,
@@ -1681,11 +1679,6 @@ pub trait Destructor: PyPayload {
Self::del(zelf, vm)
}
#[pymethod]
fn __del__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
Self::slot_del(&zelf, vm)
}
fn del(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<()>;
}
@@ -1711,11 +1704,6 @@ pub trait Callable: PyPayload {
Self::call(zelf, args, vm)
}
#[inline]
#[pymethod]
fn __call__(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Self::slot_call(&zelf, args.bind(vm)?, vm)
}
fn call(zelf: &Py<Self>, args: Self::Args, vm: &VirtualMachine) -> PyResult;
}
@@ -1729,17 +1717,6 @@ pub trait GetDescriptor: PyPayload {
vm: &VirtualMachine,
) -> PyResult;
#[inline]
#[pymethod]
fn __get__(
zelf: PyObjectRef,
obj: PyObjectRef,
cls: OptionalArg<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult {
Self::descr_get(zelf, Some(obj), cls.into_option(), vm)
}
#[inline]
fn _as_pyref<'a>(zelf: &'a PyObject, vm: &VirtualMachine) -> PyResult<&'a Py<Self>> {
zelf.try_to_value(vm)
@@ -1847,61 +1824,6 @@ pub trait Comparable: PyPayload {
op: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue>;
#[inline]
#[pymethod]
fn __eq__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Eq, vm)
}
#[inline]
#[pymethod]
fn __ne__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Ne, vm)
}
#[inline]
#[pymethod]
fn __lt__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Lt, vm)
}
#[inline]
#[pymethod]
fn __le__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Le, vm)
}
#[inline]
#[pymethod]
fn __ge__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Ge, vm)
}
#[inline]
#[pymethod]
fn __gt__(
zelf: &Py<Self>,
other: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
Self::cmp(zelf, &other, PyComparisonOp::Gt, vm)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -2013,12 +1935,6 @@ pub trait GetAttr: PyPayload {
}
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult;
#[inline]
#[pymethod]
fn __getattribute__(zelf: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
Self::slot_getattro(&zelf, &name, vm)
}
}
#[pyclass]
@@ -2043,23 +1959,6 @@ pub trait SetAttr: PyPayload {
value: PySetterValue,
vm: &VirtualMachine,
) -> PyResult<()>;
#[inline]
#[pymethod]
fn __setattr__(
zelf: PyObjectRef,
name: PyStrRef,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
Self::slot_setattro(&zelf, &name, PySetterValue::Assign(value), vm)
}
#[inline]
#[pymethod]
fn __delattr__(zelf: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
Self::slot_setattro(&zelf, &name, PySetterValue::Delete, vm)
}
}
#[pyclass]
-5
View File
@@ -243,11 +243,6 @@ pub trait PyStructSequence: StaticType + PyClassImpl + Sized + 'static {
Ok(vm.ctx.new_str(repr_str))
}
#[pymethod]
fn __repr__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Self::slot_repr(&zelf, vm)
}
#[pymethod]
fn __replace__(zelf: PyRef<PyTuple>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
if !args.args.is_empty() {
+12
View File
@@ -26,3 +26,15 @@ assert None.__eq__(3) is NotImplemented
assert None.__ne__(3) is NotImplemented
assert None.__eq__(None) is True
assert None.__ne__(None) is False
assert None.__lt__(3) is NotImplemented
assert None.__le__(3) is NotImplemented
assert None.__gt__(3) is NotImplemented
assert None.__ge__(3) is NotImplemented
none_type_dict = type(None).__dict__
for name in ("__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__hash__"):
assert name in none_type_dict
assert none_type_dict[name] is not object.__dict__[name]
assert type(none_type_dict[name]).__name__ == "wrapper_descriptor"
assert hash(None) & 0xFFFFFFFF == 0xFCA86420