Add tp_str (#6495)

* clean up hash

* __str__ slot wrapper
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2025-12-25 11:00:53 +09:00
1 parent 6dbc8f0cfa
commit aae6bf566f
5 files changed
+17 -23

No files matched your search

-1
View File
@@ -409,7 +409,6 @@ class TestPredicates(IsTestBase):
coro.close(); gen_coro.close() # silence warnings
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_isroutine(self):
# method
self.assertTrue(inspect.isroutine(git.argue))
+9 -4
View File
@@ -399,6 +399,7 @@ pub fn init(ctx: &Context) {
pub enum SlotFunc {
Init(InitFunc),
Hash(HashFunc),
Str(StringifyFunc),
Repr(StringifyFunc),
Iter(IterFunc),
IterNext(IterNextFunc),
@@ -409,6 +410,7 @@ impl std::fmt::Debug for SlotFunc {
match self {
SlotFunc::Init(_) => write!(f, "SlotFunc::Init(...)"),
SlotFunc::Hash(_) => write!(f, "SlotFunc::Hash(...)"),
SlotFunc::Str(_) => write!(f, "SlotFunc::Str(...)"),
SlotFunc::Repr(_) => write!(f, "SlotFunc::Repr(...)"),
SlotFunc::Iter(_) => write!(f, "SlotFunc::Iter(...)"),
SlotFunc::IterNext(_) => write!(f, "SlotFunc::IterNext(...)"),
@@ -433,11 +435,14 @@ impl SlotFunc {
let hash = func(&obj, vm)?;
Ok(vm.ctx.new_int(hash).into())
}
SlotFunc::Repr(func) => {
SlotFunc::Repr(func) | SlotFunc::Str(func) => {
if !args.args.is_empty() || !args.kwargs.is_empty() {
return Err(
vm.new_type_error("__repr__() takes no arguments (1 given)".to_owned())
);
let name = match self {
SlotFunc::Repr(_) => "__repr__",
SlotFunc::Str(_) => "__str__",
_ => unreachable!(),
};
return Err(vm.new_type_error(format!("{name}() takes no arguments (1 given)")));
}
let s = func(&obj, vm)?;
Ok(s.into())
+2 -2
View File
@@ -425,8 +425,8 @@ impl PyBaseObject {
}
/// Return str(self).
#[pymethod]
fn __str__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
#[pyslot]
fn slot_str(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
// FIXME: try tp_repr first and fallback to object.__repr__
zelf.repr(vm)
}
+5 -15
View File
@@ -165,25 +165,15 @@ pub trait PyClassImpl: PyClassDef {
"Initialize self. See help(type(self)) for accurate signature."
);
add_slot_wrapper!(repr, __repr__, Repr, "Return repr(self).");
add_slot_wrapper!(str, __str__, Str, "Return str(self).");
add_slot_wrapper!(iter, __iter__, Iter, "Implement iter(self).");
add_slot_wrapper!(iternext, __next__, IterNext, "Implement next(self).");
// __hash__ needs special handling: hash_not_implemented sets __hash__ = None
if let Some(hash_func) = class.slots.hash.load() {
if hash_func as usize == hash_not_implemented as usize {
class.set_attr(ctx.names.__hash__, ctx.none.clone().into());
} else {
let hash_name = identifier!(ctx, __hash__);
if !class.attributes.read().contains_key(hash_name) {
let wrapper = PySlotWrapper {
typ: class,
name: ctx.intern_str("__hash__"),
wrapped: SlotFunc::Hash(hash_func),
doc: Some("Return hash(self)."),
};
class.set_attr(hash_name, wrapper.into_ref(ctx).into());
}
}
if class.slots.hash.load().map_or(0, |h| h as usize) == hash_not_implemented as usize {
class.set_attr(ctx.names.__hash__, ctx.none.clone().into());
} else {
add_slot_wrapper!(hash, __hash__, Hash, "Return hash(self).");
}
class.extend_methods(class.slots.methods, ctx);
+1 -1
View File
@@ -140,7 +140,7 @@ pub struct PyTypeSlots {
// More standard operations (here for binary compatibility)
pub hash: AtomicCell<Option<HashFunc>>,
pub call: AtomicCell<Option<GenericMethod>>,
// tp_str
pub str: AtomicCell<Option<StringifyFunc>>,
pub repr: AtomicCell<Option<StringifyFunc>>,
pub getattro: AtomicCell<Option<GetattroFunc>>,
pub setattro: AtomicCell<Option<SetattroFunc>>,