Skip to content

Commit aae6bf5

Browse files
authored
Add tp_str (#6495)
* clean up hash * __str__ slot wrapper
1 parent 6dbc8f0 commit aae6bf5

File tree

5 files changed

+17
-23
lines changed

5 files changed

+17
-23
lines changed

Lib/test/test_inspect/test_inspect.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ class NotFuture: pass
409409

410410
coro.close(); gen_coro.close() # silence warnings
411411

412-
@unittest.expectedFailure # TODO: RUSTPYTHON
413412
def test_isroutine(self):
414413
# method
415414
self.assertTrue(inspect.isroutine(git.argue))

crates/vm/src/builtins/descriptor.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ pub fn init(ctx: &Context) {
399399
pub enum SlotFunc {
400400
Init(InitFunc),
401401
Hash(HashFunc),
402+
Str(StringifyFunc),
402403
Repr(StringifyFunc),
403404
Iter(IterFunc),
404405
IterNext(IterNextFunc),
@@ -409,6 +410,7 @@ impl std::fmt::Debug for SlotFunc {
409410
match self {
410411
SlotFunc::Init(_) => write!(f, "SlotFunc::Init(...)"),
411412
SlotFunc::Hash(_) => write!(f, "SlotFunc::Hash(...)"),
413+
SlotFunc::Str(_) => write!(f, "SlotFunc::Str(...)"),
412414
SlotFunc::Repr(_) => write!(f, "SlotFunc::Repr(...)"),
413415
SlotFunc::Iter(_) => write!(f, "SlotFunc::Iter(...)"),
414416
SlotFunc::IterNext(_) => write!(f, "SlotFunc::IterNext(...)"),
@@ -433,11 +435,14 @@ impl SlotFunc {
433435
let hash = func(&obj, vm)?;
434436
Ok(vm.ctx.new_int(hash).into())
435437
}
436-
SlotFunc::Repr(func) => {
438+
SlotFunc::Repr(func) | SlotFunc::Str(func) => {
437439
if !args.args.is_empty() || !args.kwargs.is_empty() {
438-
return Err(
439-
vm.new_type_error("__repr__() takes no arguments (1 given)".to_owned())
440-
);
440+
let name = match self {
441+
SlotFunc::Repr(_) => "__repr__",
442+
SlotFunc::Str(_) => "__str__",
443+
_ => unreachable!(),
444+
};
445+
return Err(vm.new_type_error(format!("{name}() takes no arguments (1 given)")));
441446
}
442447
let s = func(&obj, vm)?;
443448
Ok(s.into())

crates/vm/src/builtins/object.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ impl PyBaseObject {
425425
}
426426

427427
/// Return str(self).
428-
#[pymethod]
429-
fn __str__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
428+
#[pyslot]
429+
fn slot_str(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
430430
// FIXME: try tp_repr first and fallback to object.__repr__
431431
zelf.repr(vm)
432432
}

crates/vm/src/class.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,25 +165,15 @@ pub trait PyClassImpl: PyClassDef {
165165
"Initialize self. See help(type(self)) for accurate signature."
166166
);
167167
add_slot_wrapper!(repr, __repr__, Repr, "Return repr(self).");
168+
add_slot_wrapper!(str, __str__, Str, "Return str(self).");
168169
add_slot_wrapper!(iter, __iter__, Iter, "Implement iter(self).");
169170
add_slot_wrapper!(iternext, __next__, IterNext, "Implement next(self).");
170171

171172
// __hash__ needs special handling: hash_not_implemented sets __hash__ = None
172-
if let Some(hash_func) = class.slots.hash.load() {
173-
if hash_func as usize == hash_not_implemented as usize {
174-
class.set_attr(ctx.names.__hash__, ctx.none.clone().into());
175-
} else {
176-
let hash_name = identifier!(ctx, __hash__);
177-
if !class.attributes.read().contains_key(hash_name) {
178-
let wrapper = PySlotWrapper {
179-
typ: class,
180-
name: ctx.intern_str("__hash__"),
181-
wrapped: SlotFunc::Hash(hash_func),
182-
doc: Some("Return hash(self)."),
183-
};
184-
class.set_attr(hash_name, wrapper.into_ref(ctx).into());
185-
}
186-
}
173+
if class.slots.hash.load().map_or(0, |h| h as usize) == hash_not_implemented as usize {
174+
class.set_attr(ctx.names.__hash__, ctx.none.clone().into());
175+
} else {
176+
add_slot_wrapper!(hash, __hash__, Hash, "Return hash(self).");
187177
}
188178

189179
class.extend_methods(class.slots.methods, ctx);

crates/vm/src/types/slot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub struct PyTypeSlots {
140140
// More standard operations (here for binary compatibility)
141141
pub hash: AtomicCell<Option<HashFunc>>,
142142
pub call: AtomicCell<Option<GenericMethod>>,
143-
// tp_str
143+
pub str: AtomicCell<Option<StringifyFunc>>,
144144
pub repr: AtomicCell<Option<StringifyFunc>>,
145145
pub getattro: AtomicCell<Option<GetattroFunc>>,
146146
pub setattro: AtomicCell<Option<SetattroFunc>>,

0 commit comments

Comments
 (0)