Skip to content
This repository was archived by the owner on May 11, 2023. It is now read-only.

Commit 96a9491

Browse files
haxelionyouknowone
authored andcommitted
Implemented tp_repr slots for more types
1 parent 143036a commit 96a9491

File tree

16 files changed

+450
-340
lines changed

16 files changed

+450
-340
lines changed

stdlib/src/array.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ mod array {
6262
},
6363
types::{
6464
AsBuffer, AsMapping, AsSequence, Comparable, Constructor, IterNext,
65-
IterNextIterable, Iterable, PyComparisonOp,
65+
IterNextIterable, Iterable, PyComparisonOp, Representable,
6666
},
6767
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
6868
},
@@ -721,7 +721,15 @@ mod array {
721721

722722
#[pyclass(
723723
flags(BASETYPE),
724-
with(Comparable, AsBuffer, AsMapping, AsSequence, Iterable, Constructor)
724+
with(
725+
Comparable,
726+
AsBuffer,
727+
AsMapping,
728+
AsSequence,
729+
Iterable,
730+
Constructor,
731+
Representable
732+
)
725733
)]
726734
impl PyArray {
727735
fn read(&self) -> PyRwLockReadGuard<'_, ArrayContentType> {
@@ -1113,23 +1121,6 @@ mod array {
11131121
Ok(zelf)
11141122
}
11151123

1116-
#[pymethod(magic)]
1117-
fn repr(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
1118-
let class = zelf.class();
1119-
let class_name = class.name();
1120-
if zelf.read().typecode() == 'u' {
1121-
if zelf.len() == 0 {
1122-
return Ok(format!("{class_name}('u')"));
1123-
}
1124-
return Ok(format!(
1125-
"{}('u', {})",
1126-
class_name,
1127-
crate::common::str::repr(&zelf.tounicode(vm)?)
1128-
));
1129-
}
1130-
zelf.read().repr(&class_name, vm)
1131-
}
1132-
11331124
#[pymethod(magic)]
11341125
pub(crate) fn len(&self) -> usize {
11351126
self.read().len()
@@ -1292,6 +1283,25 @@ mod array {
12921283
}
12931284
}
12941285

1286+
impl Representable for PyArray {
1287+
#[inline]
1288+
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
1289+
let class = zelf.class();
1290+
let class_name = class.name();
1291+
if zelf.read().typecode() == 'u' {
1292+
if zelf.len() == 0 {
1293+
return Ok(format!("{class_name}('u')"));
1294+
}
1295+
return Ok(format!(
1296+
"{}('u', {})",
1297+
class_name,
1298+
crate::common::str::repr(&zelf.tounicode(vm)?)
1299+
));
1300+
}
1301+
zelf.read().repr(&class_name, vm)
1302+
}
1303+
}
1304+
12951305
static BUFFER_METHODS: BufferMethods = BufferMethods {
12961306
obj_bytes: |buffer| buffer.obj_as::<PyArray>().get_bytes().into(),
12971307
obj_bytes_mut: |buffer| buffer.obj_as::<PyArray>().get_bytes_mut().into(),

stdlib/src/contextvars.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ mod _contextvars {
55
use crate::vm::{
66
builtins::{PyFunction, PyStrRef, PyTypeRef},
77
function::{ArgCallable, FuncArgs, OptionalArg},
8-
types::Initializer,
9-
PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
8+
types::{Initializer, Representable},
9+
Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
1010
};
1111

1212
#[pyattr]
@@ -99,7 +99,7 @@ mod _contextvars {
9999
default: OptionalArg<PyObjectRef>,
100100
}
101101

102-
#[pyclass(with(Initializer))]
102+
#[pyclass(with(Initializer, Representable))]
103103
impl ContextVar {
104104
#[pygetset]
105105
fn name(&self) -> String {
@@ -133,9 +133,19 @@ mod _contextvars {
133133
fn class_getitem(_cls: PyTypeRef, _key: PyStrRef, _vm: &VirtualMachine) -> PyResult<()> {
134134
unimplemented!("ContextVar.__class_getitem__() is currently under construction")
135135
}
136+
}
136137

137-
#[pymethod(magic)]
138-
fn repr(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> String {
138+
impl Initializer for ContextVar {
139+
type Args = ContextVarOptions;
140+
141+
fn init(_obj: PyRef<Self>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<()> {
142+
unimplemented!("ContextVar.__init__() is currently under construction")
143+
}
144+
}
145+
146+
impl Representable for ContextVar {
147+
#[inline]
148+
fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
139149
unimplemented!("<ContextVar name={{}} default={{}} at {{}}")
140150
// format!(
141151
// "<ContextVar name={} default={:?} at {:#x}>",
@@ -146,14 +156,6 @@ mod _contextvars {
146156
}
147157
}
148158

149-
impl Initializer for ContextVar {
150-
type Args = ContextVarOptions;
151-
152-
fn init(_obj: PyRef<Self>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<()> {
153-
unimplemented!("ContextVar.__init__() is currently under construction")
154-
}
155-
}
156-
157159
#[pyattr]
158160
#[pyclass(name = "Token")]
159161
#[derive(Debug, PyPayload)]
@@ -172,7 +174,7 @@ mod _contextvars {
172174
old_value: PyObjectRef,
173175
}
174176

175-
#[pyclass(with(Initializer))]
177+
#[pyclass(with(Initializer, Representable))]
176178
impl ContextToken {
177179
#[pygetset]
178180
fn var(&self, _vm: &VirtualMachine) -> PyObjectRef {
@@ -183,11 +185,6 @@ mod _contextvars {
183185
fn old_value(&self, _vm: &VirtualMachine) -> PyObjectRef {
184186
unimplemented!("Token.old_value() is currently under construction")
185187
}
186-
187-
#[pymethod(magic)]
188-
fn repr(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> String {
189-
unimplemented!("<Token {{}}var={{}} at {{}}>")
190-
}
191188
}
192189

193190
impl Initializer for ContextToken {
@@ -198,6 +195,13 @@ mod _contextvars {
198195
}
199196
}
200197

198+
impl Representable for ContextToken {
199+
#[inline]
200+
fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
201+
unimplemented!("<Token {{}}var={{}} at {{}}>")
202+
}
203+
}
204+
201205
#[pyfunction]
202206
fn copy_context() {}
203207
}

stdlib/src/socket.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ mod _socket {
1515
builtins::{PyBaseExceptionRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef},
1616
convert::{IntoPyException, ToPyObject, TryFromBorrowedObject, TryFromObject},
1717
function::{ArgBytesLike, ArgMemoryBuffer, Either, FsPath, OptionalArg, OptionalOption},
18-
types::{DefaultConstructor, Initializer},
18+
types::{DefaultConstructor, Initializer, Representable},
1919
utils::ToCString,
20-
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
20+
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
2121
};
2222
use crossbeam_utils::atomic::AtomicCell;
2323
use num_traits::ToPrimitive;
@@ -1015,7 +1015,21 @@ mod _socket {
10151015
}
10161016
}
10171017

1018-
#[pyclass(with(DefaultConstructor, Initializer), flags(BASETYPE))]
1018+
impl Representable for PySocket {
1019+
#[inline]
1020+
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
1021+
Ok(format!(
1022+
"<socket object, fd={}, family={}, type={}, proto={}>",
1023+
// cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1
1024+
zelf.fileno() as i64,
1025+
zelf.family.load(),
1026+
zelf.kind.load(),
1027+
zelf.proto.load(),
1028+
))
1029+
}
1030+
}
1031+
1032+
#[pyclass(with(DefaultConstructor, Initializer, Representable), flags(BASETYPE))]
10191033
impl PySocket {
10201034
fn _init(
10211035
zelf: PyRef<Self>,
@@ -1463,18 +1477,6 @@ mod _socket {
14631477
fn proto(&self) -> i32 {
14641478
self.proto.load()
14651479
}
1466-
1467-
#[pymethod(magic)]
1468-
fn repr(&self) -> String {
1469-
format!(
1470-
"<socket object, fd={}, family={}, type={}, proto={}>",
1471-
// cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1
1472-
self.fileno() as i64,
1473-
self.family.load(),
1474-
self.kind.load(),
1475-
self.proto.load(),
1476-
)
1477-
}
14781480
}
14791481

14801482
struct Address {

vm/src/builtins/code.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ impl Representable for PyCode {
230230
}
231231
}
232232

233-
#[pyclass(with(Py))]
233+
#[pyclass(with(Py, Representable))]
234234
impl PyCode {
235235
#[pyslot]
236236
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
@@ -418,18 +418,26 @@ impl PyCode {
418418
}
419419
}
420420

421-
#[pyclass]
422-
impl Py<PyCode> {
423-
#[pymethod(magic)]
424-
fn repr(&self) -> String {
425-
let code = &self.code;
426-
format!(
421+
#[pyclass(with(Representable))]
422+
impl Py<PyCode> {}
423+
424+
impl PyPayload for Py<PyCode> {
425+
fn class(ctx: &Context) -> &'static Py<PyType> {
426+
ctx.types.code_type
427+
}
428+
}
429+
430+
impl Representable for Py<PyCode> {
431+
#[inline]
432+
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
433+
let code = &zelf.code;
434+
Ok(format!(
427435
"<code object {} at {:#x} file {:?}, line {}>",
428436
code.obj_name,
429-
self.get_id(),
437+
zelf.get_id(),
430438
code.source_path.as_str(),
431439
code.first_line_number
432-
)
440+
))
433441
}
434442
}
435443

vm/src/builtins/function.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -549,25 +549,11 @@ impl PyBoundMethod {
549549
}
550550
}
551551

552-
#[pyclass(with(Callable, Comparable, GetAttr, Constructor), flags(HAS_DICT))]
552+
#[pyclass(
553+
with(Callable, Comparable, GetAttr, Constructor, Representable),
554+
flags(HAS_DICT)
555+
)]
553556
impl PyBoundMethod {
554-
#[pymethod(magic)]
555-
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
556-
#[allow(clippy::needless_match)] // False positive on nightly
557-
let funcname =
558-
if let Some(qname) = vm.get_attribute_opt(self.function.clone(), "__qualname__")? {
559-
Some(qname)
560-
} else {
561-
vm.get_attribute_opt(self.function.clone(), "__name__")?
562-
};
563-
let funcname: Option<PyStrRef> = funcname.and_then(|o| o.downcast().ok());
564-
Ok(format!(
565-
"<bound method {} of {}>",
566-
funcname.as_ref().map_or("?", |s| s.as_str()),
567-
&self.object.repr(vm)?.as_str(),
568-
))
569-
}
570-
571557
#[pymethod(magic)]
572558
fn reduce(
573559
&self,
@@ -628,6 +614,25 @@ impl PyPayload for PyBoundMethod {
628614
}
629615
}
630616

617+
impl Representable for PyBoundMethod {
618+
#[inline]
619+
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
620+
#[allow(clippy::needless_match)] // False positive on nightly
621+
let funcname =
622+
if let Some(qname) = vm.get_attribute_opt(zelf.function.clone(), "__qualname__")? {
623+
Some(qname)
624+
} else {
625+
vm.get_attribute_opt(zelf.function.clone(), "__name__")?
626+
};
627+
let funcname: Option<PyStrRef> = funcname.and_then(|o| o.downcast().ok());
628+
Ok(format!(
629+
"<bound method {} of {}>",
630+
funcname.as_ref().map_or("?", |s| s.as_str()),
631+
&zelf.object.repr(vm)?.as_str(),
632+
))
633+
}
634+
}
635+
631636
#[pyclass(module = false, name = "cell")]
632637
#[derive(Debug, Default)]
633638
pub(crate) struct PyCell {

vm/src/builtins/slice.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ impl Comparable for PySlice {
244244
Ok(PyComparisonValue::Implemented(ret))
245245
}
246246
}
247+
247248
impl Representable for PySlice {
248249
#[inline]
249250
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {

vm/src/exceptions.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
py_io::{self, Write},
1212
stdlib::sys,
1313
suggestion::offer_suggestions,
14-
types::{Callable, Constructor, Initializer},
14+
types::{Callable, Constructor, Initializer, Representable},
1515
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
1616
};
1717
use crossbeam_utils::atomic::AtomicCell;
@@ -430,7 +430,10 @@ impl PyBaseException {
430430
}
431431
}
432432

433-
#[pyclass(with(Constructor, Initializer), flags(BASETYPE, HAS_DICT))]
433+
#[pyclass(
434+
with(Constructor, Initializer, Representable),
435+
flags(BASETYPE, HAS_DICT)
436+
)]
434437
impl PyBaseException {
435438
#[pygetset]
436439
pub fn args(&self) -> PyTupleRef {
@@ -502,13 +505,6 @@ impl PyBaseException {
502505
}
503506
}
504507

505-
#[pymethod(magic)]
506-
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
507-
let repr_args = vm.exception_args_as_string(zelf.args(), false);
508-
let cls = zelf.class();
509-
format!("{}({})", cls.name(), repr_args.iter().format(", "))
510-
}
511-
512508
#[pymethod(magic)]
513509
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
514510
if let Some(dict) = zelf.as_object().dict().filter(|x| !x.is_empty()) {
@@ -538,6 +534,15 @@ impl Initializer for PyBaseException {
538534
}
539535
}
540536

537+
impl Representable for PyBaseException {
538+
#[inline]
539+
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
540+
let repr_args = vm.exception_args_as_string(zelf.args(), false);
541+
let cls = zelf.class();
542+
Ok(format!("{}({})", cls.name(), repr_args.iter().format(", ")))
543+
}
544+
}
545+
541546
impl ExceptionZoo {
542547
pub(crate) fn init() -> Self {
543548
use self::types::*;

0 commit comments

Comments
 (0)