Merge pull request #4849 from haxelion/feature/tp_repr_stdlib

Implemented tp_repr slots for more types
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2023-04-20 21:02:55 +09:00
commit 968f2ad7c9
16 files changed
+389 -336

No files matched your search

+29 -19
View File
@@ -62,7 +62,7 @@ mod array {
},
types::{
AsBuffer, AsMapping, AsSequence, Comparable, Constructor, IterNext,
IterNextIterable, Iterable, PyComparisonOp,
IterNextIterable, Iterable, PyComparisonOp, Representable,
},
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
},
@@ -721,7 +721,15 @@ mod array {
#[pyclass(
flags(BASETYPE),
with(Comparable, AsBuffer, AsMapping, AsSequence, Iterable, Constructor)
with(
Comparable,
AsBuffer,
AsMapping,
AsSequence,
Iterable,
Constructor,
Representable
)
)]
impl PyArray {
fn read(&self) -> PyRwLockReadGuard<'_, ArrayContentType> {
@@ -1113,23 +1121,6 @@ mod array {
Ok(zelf)
}
#[pymethod(magic)]
fn repr(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let class = zelf.class();
let class_name = class.name();
if zelf.read().typecode() == 'u' {
if zelf.len() == 0 {
return Ok(format!("{class_name}('u')"));
}
return Ok(format!(
"{}('u', {})",
class_name,
crate::common::str::repr(&zelf.tounicode(vm)?)
));
}
zelf.read().repr(&class_name, vm)
}
#[pymethod(magic)]
pub(crate) fn len(&self) -> usize {
self.read().len()
@@ -1292,6 +1283,25 @@ mod array {
}
}
impl Representable for PyArray {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let class = zelf.class();
let class_name = class.name();
if zelf.read().typecode() == 'u' {
if zelf.len() == 0 {
return Ok(format!("{class_name}('u')"));
}
return Ok(format!(
"{}('u', {})",
class_name,
crate::common::str::repr(&zelf.tounicode(vm)?)
));
}
zelf.read().repr(&class_name, vm)
}
}
static BUFFER_METHODS: BufferMethods = BufferMethods {
obj_bytes: |buffer| buffer.obj_as::<PyArray>().get_bytes().into(),
obj_bytes_mut: |buffer| buffer.obj_as::<PyArray>().get_bytes_mut().into(),
+24 -20
View File
@@ -5,8 +5,8 @@ mod _contextvars {
use crate::vm::{
builtins::{PyFunction, PyStrRef, PyTypeRef},
function::{ArgCallable, FuncArgs, OptionalArg},
types::Initializer,
PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
types::{Initializer, Representable},
Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
#[pyattr]
@@ -99,7 +99,7 @@ mod _contextvars {
default: OptionalArg<PyObjectRef>,
}
#[pyclass(with(Initializer))]
#[pyclass(with(Initializer, Representable))]
impl ContextVar {
#[pygetset]
fn name(&self) -> String {
@@ -133,17 +133,6 @@ mod _contextvars {
fn class_getitem(_cls: PyTypeRef, _key: PyStrRef, _vm: &VirtualMachine) -> PyResult<()> {
unimplemented!("ContextVar.__class_getitem__() is currently under construction")
}
#[pymethod(magic)]
fn repr(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> String {
unimplemented!("<ContextVar name={{}} default={{}} at {{}}")
// format!(
// "<ContextVar name={} default={:?} at {:#x}>",
// zelf.name.as_str(),
// zelf.default.map_or("", |x| PyStr::from(*x).as_str()),
// zelf.get_id()
// )
}
}
impl Initializer for ContextVar {
@@ -154,6 +143,19 @@ mod _contextvars {
}
}
impl Representable for ContextVar {
#[inline]
fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
unimplemented!("<ContextVar name={{}} default={{}} at {{}}")
// format!(
// "<ContextVar name={} default={:?} at {:#x}>",
// zelf.name.as_str(),
// zelf.default.map_or("", |x| PyStr::from(*x).as_str()),
// zelf.get_id()
// )
}
}
#[pyattr]
#[pyclass(name = "Token")]
#[derive(Debug, PyPayload)]
@@ -172,7 +174,7 @@ mod _contextvars {
old_value: PyObjectRef,
}
#[pyclass(with(Initializer))]
#[pyclass(with(Initializer, Representable))]
impl ContextToken {
#[pygetset]
fn var(&self, _vm: &VirtualMachine) -> PyObjectRef {
@@ -183,11 +185,6 @@ mod _contextvars {
fn old_value(&self, _vm: &VirtualMachine) -> PyObjectRef {
unimplemented!("Token.old_value() is currently under construction")
}
#[pymethod(magic)]
fn repr(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> String {
unimplemented!("<Token {{}}var={{}} at {{}}>")
}
}
impl Initializer for ContextToken {
@@ -198,6 +195,13 @@ mod _contextvars {
}
}
impl Representable for ContextToken {
#[inline]
fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
unimplemented!("<Token {{}}var={{}} at {{}}>")
}
}
#[pyfunction]
fn copy_context() {}
}
+17 -15
View File
@@ -15,9 +15,9 @@ mod _socket {
builtins::{PyBaseExceptionRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef},
convert::{IntoPyException, ToPyObject, TryFromBorrowedObject, TryFromObject},
function::{ArgBytesLike, ArgMemoryBuffer, Either, FsPath, OptionalArg, OptionalOption},
types::{DefaultConstructor, Initializer},
types::{DefaultConstructor, Initializer, Representable},
utils::ToCString,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use crossbeam_utils::atomic::AtomicCell;
use num_traits::ToPrimitive;
@@ -1015,7 +1015,21 @@ mod _socket {
}
}
#[pyclass(with(DefaultConstructor, Initializer), flags(BASETYPE))]
impl Representable for PySocket {
#[inline]
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
Ok(format!(
"<socket object, fd={}, family={}, type={}, proto={}>",
// cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1
zelf.fileno() as i64,
zelf.family.load(),
zelf.kind.load(),
zelf.proto.load(),
))
}
}
#[pyclass(with(DefaultConstructor, Initializer, Representable), flags(BASETYPE))]
impl PySocket {
fn _init(
zelf: PyRef<Self>,
@@ -1463,18 +1477,6 @@ mod _socket {
fn proto(&self) -> i32 {
self.proto.load()
}
#[pymethod(magic)]
fn repr(&self) -> String {
format!(
"<socket object, fd={}, family={}, type={}, proto={}>",
// cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1
self.fileno() as i64,
self.family.load(),
self.kind.load(),
self.proto.load(),
)
}
}
struct Address {
+1 -16
View File
@@ -230,7 +230,7 @@ impl Representable for PyCode {
}
}
#[pyclass(with(Py))]
#[pyclass(with(Representable))]
impl PyCode {
#[pyslot]
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
@@ -418,21 +418,6 @@ impl PyCode {
}
}
#[pyclass]
impl Py<PyCode> {
#[pymethod(magic)]
fn repr(&self) -> String {
let code = &self.code;
format!(
"<code object {} at {:#x} file {:?}, line {}>",
code.obj_name,
self.get_id(),
code.source_path.as_str(),
code.first_line_number
)
}
}
impl fmt::Display for PyCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
+23 -18
View File
@@ -549,25 +549,11 @@ impl PyBoundMethod {
}
}
#[pyclass(with(Callable, Comparable, GetAttr, Constructor), flags(HAS_DICT))]
#[pyclass(
with(Callable, Comparable, GetAttr, Constructor, Representable),
flags(HAS_DICT)
)]
impl PyBoundMethod {
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
#[allow(clippy::needless_match)] // False positive on nightly
let funcname =
if let Some(qname) = vm.get_attribute_opt(self.function.clone(), "__qualname__")? {
Some(qname)
} else {
vm.get_attribute_opt(self.function.clone(), "__name__")?
};
let funcname: Option<PyStrRef> = funcname.and_then(|o| o.downcast().ok());
Ok(format!(
"<bound method {} of {}>",
funcname.as_ref().map_or("?", |s| s.as_str()),
&self.object.repr(vm)?.as_str(),
))
}
#[pymethod(magic)]
fn reduce(
&self,
@@ -628,6 +614,25 @@ impl PyPayload for PyBoundMethod {
}
}
impl Representable for PyBoundMethod {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
#[allow(clippy::needless_match)] // False positive on nightly
let funcname =
if let Some(qname) = vm.get_attribute_opt(zelf.function.clone(), "__qualname__")? {
Some(qname)
} else {
vm.get_attribute_opt(zelf.function.clone(), "__name__")?
};
let funcname: Option<PyStrRef> = funcname.and_then(|o| o.downcast().ok());
Ok(format!(
"<bound method {} of {}>",
funcname.as_ref().map_or("?", |s| s.as_str()),
&zelf.object.repr(vm)?.as_str(),
))
}
}
#[pyclass(module = false, name = "cell")]
#[derive(Debug, Default)]
pub(crate) struct PyCell {
+1
View File
@@ -244,6 +244,7 @@ impl Comparable for PySlice {
Ok(PyComparisonValue::Implemented(ret))
}
}
impl Representable for PySlice {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
+14 -9
View File
@@ -11,7 +11,7 @@ use crate::{
py_io::{self, Write},
stdlib::sys,
suggestion::offer_suggestions,
types::{Callable, Constructor, Initializer},
types::{Callable, Constructor, Initializer, Representable},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use crossbeam_utils::atomic::AtomicCell;
@@ -430,7 +430,10 @@ impl PyBaseException {
}
}
#[pyclass(with(Constructor, Initializer), flags(BASETYPE, HAS_DICT))]
#[pyclass(
with(Constructor, Initializer, Representable),
flags(BASETYPE, HAS_DICT)
)]
impl PyBaseException {
#[pygetset]
pub fn args(&self) -> PyTupleRef {
@@ -502,13 +505,6 @@ impl PyBaseException {
}
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
let repr_args = vm.exception_args_as_string(zelf.args(), false);
let cls = zelf.class();
format!("{}({})", cls.name(), repr_args.iter().format(", "))
}
#[pymethod(magic)]
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
if let Some(dict) = zelf.as_object().dict().filter(|x| !x.is_empty()) {
@@ -538,6 +534,15 @@ impl Initializer for PyBaseException {
}
}
impl Representable for PyBaseException {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let repr_args = vm.exception_args_as_string(zelf.args(), false);
let cls = zelf.class();
Ok(format!("{}({})", cls.name(), repr_args.iter().format(", ")))
}
}
impl ExceptionZoo {
pub(crate) fn init() -> Self {
use self::types::*;
+32 -23
View File
@@ -17,7 +17,7 @@ mod _collections {
sliceable::SequenceIndexOp,
types::{
AsSequence, Comparable, Constructor, Initializer, IterNext, IterNextIterable, Iterable,
PyComparisonOp,
PyComparisonOp, Representable,
},
utils::collection_repr,
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
@@ -57,7 +57,14 @@ mod _collections {
#[pyclass(
flags(BASETYPE),
with(Constructor, Initializer, AsSequence, Comparable, Iterable)
with(
Constructor,
Initializer,
AsSequence,
Comparable,
Iterable,
Representable
)
)]
impl PyDeque {
#[pymethod]
@@ -295,27 +302,6 @@ mod _collections {
.ok_or_else(|| vm.new_index_error("deque index out of range".to_owned()))
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let deque = zelf.borrow_deque().clone();
let class = zelf.class();
let class_name = class.name();
let closing_part = zelf
.maxlen
.map(|maxlen| format!("], maxlen={maxlen}"))
.unwrap_or_else(|| "]".to_owned());
let s = if zelf.len() == 0 {
format!("{class_name}([{closing_part})")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
collection_repr(Some(&class_name), "[", &closing_part, deque.iter(), vm)?
} else {
"[...]".to_owned()
};
Ok(s)
}
#[pymethod(magic)]
fn contains(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
self._contains(&needle, vm)
@@ -580,6 +566,29 @@ mod _collections {
}
}
impl Representable for PyDeque {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let deque = zelf.borrow_deque().clone();
let class = zelf.class();
let class_name = class.name();
let closing_part = zelf
.maxlen
.map(|maxlen| format!("], maxlen={maxlen}"))
.unwrap_or_else(|| "]".to_owned());
let s = if zelf.len() == 0 {
format!("{class_name}([{closing_part})")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
collection_repr(Some(&class_name), "[", &closing_part, deque.iter(), vm)?
} else {
"[...]".to_owned()
};
Ok(s)
}
}
#[pyattr]
#[pyclass(name = "_deque_iterator")]
#[derive(Debug, PyPayload)]
+34 -24
View File
@@ -1525,9 +1525,9 @@ mod _io {
vm.call_method(self.lock(vm)?.check_init(vm)?, "isatty", ())
}
#[pymethod(magic)]
fn repr(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
let name_repr = repr_fileobj_name(&zelf, vm)?;
#[pyslot]
fn slot_repr(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let name_repr = repr_fileobj_name(zelf, vm)?;
let cls = zelf.class();
let slot_name = cls.slot_name();
let repr = if let Some(name_repr) = name_repr {
@@ -1535,7 +1535,12 @@ mod _io {
} else {
format!("<{slot_name}>")
};
Ok(repr)
Ok(vm.ctx.new_str(repr))
}
#[pymethod(magic)]
fn repr(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Self::slot_repr(&zelf, vm)
}
fn close_strict(&self, vm: &VirtualMachine) -> PyResult {
@@ -3709,8 +3714,8 @@ mod fileio {
convert::ToPyException,
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
stdlib::os,
types::{DefaultConstructor, Initializer},
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
types::{DefaultConstructor, Initializer, Representable},
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use crossbeam_utils::atomic::AtomicCell;
use std::io::{Read, Write};
@@ -3896,7 +3901,29 @@ mod fileio {
}
}
#[pyclass(with(DefaultConstructor, Initializer), flags(BASETYPE, HAS_DICT))]
impl Representable for FileIO {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fd = zelf.fd.load();
if fd < 0 {
return Ok("<_io.FileIO [closed]>".to_owned());
}
let name_repr = repr_fileobj_name(zelf.as_object(), vm)?;
let mode = zelf.mode();
let closefd = if zelf.closefd.load() { "True" } else { "False" };
let repr = if let Some(name_repr) = name_repr {
format!("<_io.FileIO name={name_repr} mode='{mode}' closefd={closefd}>")
} else {
format!("<_io.FileIO fd={fd} mode='{mode}' closefd={closefd}>")
};
Ok(repr)
}
}
#[pyclass(
with(DefaultConstructor, Initializer, Representable),
flags(BASETYPE, HAS_DICT)
)]
impl FileIO {
#[pygetset]
fn closed(&self) -> bool {
@@ -3956,23 +3983,6 @@ mod fileio {
}
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fd = zelf.fd.load();
if fd < 0 {
return Ok("<_io.FileIO [closed]>".to_owned());
}
let name_repr = repr_fileobj_name(zelf.as_object(), vm)?;
let mode = zelf.mode();
let closefd = if zelf.closefd.load() { "True" } else { "False" };
let repr = if let Some(name_repr) = name_repr {
format!("<_io.FileIO name={name_repr} mode='{mode}' closefd={closefd}>")
} else {
format!("<_io.FileIO fd={fd} mode='{mode}' closefd={closefd}>")
};
Ok(repr)
}
#[pymethod]
fn read(&self, read_byte: OptionalSize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
if !self.mode.load().contains(Mode::READABLE) {
+27 -23
View File
@@ -16,7 +16,7 @@ mod decl {
identifier,
protocol::{PyIter, PyIterReturn, PyNumber},
stdlib::sys,
types::{Constructor, IterNext, IterNextIterable},
types::{Constructor, IterNext, IterNextIterable, Representable},
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, PyWeakRef, TryFromObject,
VirtualMachine,
};
@@ -258,7 +258,7 @@ mod decl {
}
}
#[pyclass(with(IterNext, Constructor))]
#[pyclass(with(IterNext, Constructor, Representable))]
impl PyItertoolsCount {
// TODO: Implement this
// if (lz->cnt == PY_SSIZE_T_MAX)
@@ -267,16 +267,6 @@ mod decl {
fn reduce(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef,)) {
(zelf.class().to_owned(), (zelf.cur.read().clone(),))
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let cur = format!("{}", self.cur.read().clone().repr(vm)?);
let step = &self.step;
if vm.bool_eq(step, vm.ctx.new_int(1).as_object())? {
return Ok(format!("count({cur})"));
}
Ok(format!("count({}, {})", cur, step.repr(vm)?))
}
}
impl IterNextIterable for PyItertoolsCount {}
impl IterNext for PyItertoolsCount {
@@ -289,6 +279,18 @@ mod decl {
}
}
impl Representable for PyItertoolsCount {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let cur = format!("{}", zelf.cur.read().clone().repr(vm)?);
let step = &zelf.step;
if vm.bool_eq(step, vm.ctx.new_int(1).as_object())? {
return Ok(format!("count({cur})"));
}
Ok(format!("count({}, {})", cur, step.repr(vm)?))
}
}
#[pyattr]
#[pyclass(name = "cycle")]
#[derive(Debug, PyPayload)]
@@ -376,7 +378,7 @@ mod decl {
}
}
#[pyclass(with(IterNext, Constructor), flags(BASETYPE))]
#[pyclass(with(IterNext, Constructor, Representable), flags(BASETYPE))]
impl PyItertoolsRepeat {
#[pymethod(magic)]
fn length_hint(&self, vm: &VirtualMachine) -> PyResult<usize> {
@@ -396,16 +398,6 @@ mod decl {
None => vm.new_tuple((cls, (zelf.object.clone(),))),
})
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let mut fmt = format!("{}", &self.object.repr(vm)?);
if let Some(ref times) = self.times {
fmt.push_str(", ");
fmt.push_str(&times.read().to_string());
}
Ok(format!("repeat({fmt})"))
}
}
impl IterNextIterable for PyItertoolsRepeat {}
@@ -422,6 +414,18 @@ mod decl {
}
}
impl Representable for PyItertoolsRepeat {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let mut fmt = format!("{}", &zelf.object.repr(vm)?);
if let Some(ref times) = zelf.times {
fmt.push_str(", ");
fmt.push_str(&times.read().to_string());
}
Ok(format!("repeat({fmt})"))
}
}
#[pyattr]
#[pyclass(name = "starmap")]
#[derive(Debug, PyPayload)]
+67 -61
View File
@@ -10,7 +10,7 @@ mod _operator {
identifier,
protocol::PyIter,
recursion::ReprGuard,
types::{Callable, Constructor, PyComparisonOp},
types::{Callable, Constructor, PyComparisonOp, Representable},
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -356,22 +356,8 @@ mod _operator {
attrs: Vec<PyStrRef>,
}
#[pyclass(with(Callable, Constructor))]
#[pyclass(with(Callable, Constructor, Representable))]
impl PyAttrGetter {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut parts = Vec::with_capacity(zelf.attrs.len());
for part in &zelf.attrs {
parts.push(part.as_object().repr(vm)?.as_str().to_owned());
}
parts.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.attrgetter({fmt})"))
}
#[pymethod(magic)]
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<(PyTypeRef, PyTupleRef)> {
let attrs = vm
@@ -441,6 +427,22 @@ mod _operator {
}
}
impl Representable for PyAttrGetter {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut parts = Vec::with_capacity(zelf.attrs.len());
for part in &zelf.attrs {
parts.push(part.as_object().repr(vm)?.as_str().to_owned());
}
parts.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.attrgetter({fmt})"))
}
}
/// itemgetter(item, ...) --> itemgetter object
///
/// Return a callable object that fetches the given item(s) from its operand.
@@ -453,22 +455,8 @@ mod _operator {
items: Vec<PyObjectRef>,
}
#[pyclass(with(Callable, Constructor))]
#[pyclass(with(Callable, Constructor, Representable))]
impl PyItemGetter {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut items = Vec::with_capacity(zelf.items.len());
for item in &zelf.items {
items.push(item.repr(vm)?.as_str().to_owned());
}
items.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.itemgetter({fmt})"))
}
#[pymethod(magic)]
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyObjectRef {
let items = vm.ctx.new_tuple(zelf.items.to_vec());
@@ -508,6 +496,22 @@ mod _operator {
}
}
impl Representable for PyItemGetter {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut items = Vec::with_capacity(zelf.items.len());
for item in &zelf.items {
items.push(item.repr(vm)?.as_str().to_owned());
}
items.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.itemgetter({fmt})"))
}
}
/// methodcaller(name, ...) --> methodcaller object
///
/// Return a callable object that calls the given method on its operand.
@@ -522,37 +526,8 @@ mod _operator {
args: FuncArgs,
}
#[pyclass(with(Callable, Constructor))]
#[pyclass(with(Callable, Constructor, Representable))]
impl PyMethodCaller {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let args = &zelf.args.args;
let kwargs = &zelf.args.kwargs;
let mut fmt = vec![zelf.name.as_object().repr(vm)?.as_str().to_owned()];
if !args.is_empty() {
let mut parts = Vec::with_capacity(args.len());
for v in args {
parts.push(v.repr(vm)?.as_str().to_owned());
}
fmt.push(parts.join(", "));
}
// build name=value pairs from KwArgs.
if !kwargs.is_empty() {
let mut parts = Vec::with_capacity(kwargs.len());
for (key, value) in kwargs {
let value_repr = value.repr(vm)?;
parts.push(format!("{key}={value_repr}"));
}
fmt.push(parts.join(", "));
}
fmt.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.methodcaller({fmt})"))
}
#[pymethod(magic)]
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
// With no kwargs, return (type(obj), (name, *args)) tuple.
@@ -596,4 +571,35 @@ mod _operator {
vm.call_method(&obj, zelf.name.as_str(), zelf.args.clone())
}
}
impl Representable for PyMethodCaller {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let fmt = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let args = &zelf.args.args;
let kwargs = &zelf.args.kwargs;
let mut fmt = vec![zelf.name.as_object().repr(vm)?.as_str().to_owned()];
if !args.is_empty() {
let mut parts = Vec::with_capacity(args.len());
for v in args {
parts.push(v.repr(vm)?.as_str().to_owned());
}
fmt.push(parts.join(", "));
}
// build name=value pairs from KwArgs.
if !kwargs.is_empty() {
let mut parts = Vec::with_capacity(kwargs.len());
for (key, value) in kwargs {
let value_repr = value.repr(vm)?;
parts.push(format!("{key}={value_repr}"));
}
fmt.push(parts.join(", "));
}
fmt.join(", ")
} else {
"...".to_owned()
};
Ok(format!("operator.methodcaller({fmt})"))
}
}
}
+17 -17
View File
@@ -302,22 +302,20 @@ pub(super) mod _os {
errno_err, DirFd, FollowSymlinks, IOErrorBuilder, OsPath, OsPathOrFd, OutputMode,
SupportFunc,
};
use crate::common::lock::{OnceCell, PyRwLock};
use crate::{
builtins::{
PyBytesRef, PyGenericAlias, PyIntRef, PyStrRef, PyTuple, PyTupleRef, PyTypeRef,
},
common::{
crt_fd::{Fd, Offset},
suppress_iph,
},
common::crt_fd::{Fd, Offset},
common::lock::{OnceCell, PyRwLock},
common::suppress_iph,
convert::{IntoPyException, ToPyObject},
function::{ArgBytesLike, Either, FsPath, FuncArgs, OptionalArg},
protocol::PyIterReturn,
recursion::ReprGuard,
types::{IterNext, IterNextIterable, PyStructSequence},
types::{IterNext, IterNextIterable, PyStructSequence, Representable},
vm::VirtualMachine,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
};
use crossbeam_utils::atomic::AtomicCell;
use itertools::Itertools;
@@ -619,7 +617,7 @@ pub(super) mod _os {
ino: AtomicCell<Option<u64>>,
}
#[pyclass]
#[pyclass(with(Representable))]
impl DirEntry {
#[pygetset]
fn name(&self, vm: &VirtualMachine) -> PyResult {
@@ -747,9 +745,16 @@ pub(super) mod _os {
self.path(vm)
}
#[pymethod(magic)]
fn repr(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
let name = match zelf.get_attr("name", vm) {
#[pyclassmethod(magic)]
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
}
}
impl Representable for DirEntry {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let name = match zelf.as_object().get_attr("name", vm) {
Ok(name) => Some(name),
Err(e)
if e.fast_isinstance(vm.ctx.exceptions.attribute_error)
@@ -760,7 +765,7 @@ pub(super) mod _os {
Err(e) => return Err(e),
};
if let Some(name) = name {
if let Some(_guard) = ReprGuard::enter(vm, &zelf) {
if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let repr = name.repr(vm)?;
Ok(format!("<{} {}>", zelf.class(), repr))
} else {
@@ -773,11 +778,6 @@ pub(super) mod _os {
Ok(format!("<{}>", zelf.class()))
}
}
#[pyclassmethod(magic)]
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
}
}
#[pyattr]
+14 -12
View File
@@ -28,9 +28,9 @@ pub mod module {
errno_err, DirFd, FollowSymlinks, OsPath, OsPathOrFd, SupportFunc, TargetIsDirectory,
_os, fs_metadata, IOErrorBuilder,
},
types::Constructor,
types::{Constructor, Representable},
utils::ToCString,
AsObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
AsObject, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
use bitflags::bitflags;
use nix::{
@@ -540,22 +540,13 @@ pub mod module {
}
}
#[pyclass(with(Constructor))]
#[pyclass(with(Constructor, Representable))]
impl SchedParam {
#[pygetset]
fn sched_priority(&self, vm: &VirtualMachine) -> PyObjectRef {
self.sched_priority.clone().to_pyobject(vm)
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let sched_priority_repr = self.sched_priority.repr(vm)?;
Ok(format!(
"posix.sched_param(sched_priority = {})",
sched_priority_repr.as_str()
))
}
#[cfg(any(
target_os = "linux",
target_os = "netbsd",
@@ -591,6 +582,17 @@ pub mod module {
}
}
impl Representable for SchedParam {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let sched_priority_repr = zelf.sched_priority.repr(vm)?;
Ok(format!(
"posix.sched_param(sched_priority = {})",
sched_priority_repr.as_str()
))
}
}
#[cfg(any(
target_os = "linux",
target_os = "netbsd",
+66 -62
View File
@@ -13,9 +13,9 @@ mod _sre {
function::{ArgCallable, OptionalArg, PosArgs, PyComparisonValue},
protocol::{PyBuffer, PyMappingMethods},
stdlib::sys,
types::{AsMapping, Comparable, Hashable},
PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject, TryFromObject,
VirtualMachine,
types::{AsMapping, Comparable, Hashable, Representable},
Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,
TryFromObject, VirtualMachine,
};
use core::str;
use crossbeam_utils::atomic::AtomicCell;
@@ -151,7 +151,7 @@ mod _sre {
};
}
#[pyclass(with(Hashable, Comparable))]
#[pyclass(with(Hashable, Comparable, Representable))]
impl Pattern {
fn with_str<F, R>(string: &PyObject, vm: &VirtualMachine, f: F) -> PyResult<R>
where
@@ -336,51 +336,6 @@ mod _sre {
})
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let flag_names = [
("re.TEMPLATE", SreFlag::TEMPLATE),
("re.IGNORECASE", SreFlag::IGNORECASE),
("re.LOCALE", SreFlag::LOCALE),
("re.MULTILINE", SreFlag::MULTILINE),
("re.DOTALL", SreFlag::DOTALL),
("re.UNICODE", SreFlag::UNICODE),
("re.VERBOSE", SreFlag::VERBOSE),
("re.DEBUG", SreFlag::DEBUG),
("re.ASCII", SreFlag::ASCII),
];
/* Omit re.UNICODE for valid string patterns. */
let mut flags = self.flags;
if !self.isbytes
&& (flags & (SreFlag::LOCALE | SreFlag::UNICODE | SreFlag::ASCII))
== SreFlag::UNICODE
{
flags &= !SreFlag::UNICODE;
}
let flags = flag_names
.iter()
.filter(|(_, flag)| flags.contains(*flag))
.map(|(name, _)| name)
.join("|");
let pattern = self.pattern.repr(vm)?;
let truncated: String;
let s = if pattern.char_len() > 200 {
truncated = pattern.as_str().chars().take(200).collect();
&truncated
} else {
pattern.as_str()
};
if flags.is_empty() {
Ok(format!("re.compile({s})"))
} else {
Ok(format!("re.compile({s}, {flags})"))
}
}
#[pygetset]
fn flags(&self) -> u16 {
self.flags.bits()
@@ -512,6 +467,53 @@ mod _sre {
}
}
impl Representable for Pattern {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
let flag_names = [
("re.TEMPLATE", SreFlag::TEMPLATE),
("re.IGNORECASE", SreFlag::IGNORECASE),
("re.LOCALE", SreFlag::LOCALE),
("re.MULTILINE", SreFlag::MULTILINE),
("re.DOTALL", SreFlag::DOTALL),
("re.UNICODE", SreFlag::UNICODE),
("re.VERBOSE", SreFlag::VERBOSE),
("re.DEBUG", SreFlag::DEBUG),
("re.ASCII", SreFlag::ASCII),
];
/* Omit re.UNICODE for valid string patterns. */
let mut flags = zelf.flags;
if !zelf.isbytes
&& (flags & (SreFlag::LOCALE | SreFlag::UNICODE | SreFlag::ASCII))
== SreFlag::UNICODE
{
flags &= !SreFlag::UNICODE;
}
let flags = flag_names
.iter()
.filter(|(_, flag)| flags.contains(*flag))
.map(|(name, _)| name)
.join("|");
let pattern = zelf.pattern.repr(vm)?;
let truncated: String;
let s = if pattern.char_len() > 200 {
truncated = pattern.as_str().chars().take(200).collect();
&truncated
} else {
pattern.as_str()
};
if flags.is_empty() {
Ok(format!("re.compile({s})"))
} else {
Ok(format!("re.compile({s}, {flags})"))
}
}
}
#[pyattr]
#[pyclass(name = "Match")]
#[derive(Debug, PyPayload)]
@@ -524,7 +526,7 @@ mod _sre {
regs: Vec<(isize, isize)>,
}
#[pyclass(with(AsMapping))]
#[pyclass(with(AsMapping, Representable))]
impl Match {
pub(crate) fn new<S: StrDrive>(
state: &State<S>,
@@ -703,18 +705,6 @@ mod _sre {
})
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
with_sre_str!(self.pattern, &self.string, vm, |str_drive| {
Ok(format!(
"<re.Match object; span=({}, {}), match={}>",
self.regs[0].0,
self.regs[0].1,
self.get_slice(0, str_drive, vm).unwrap().repr(vm)?
))
})
}
fn get_index(&self, group: PyObjectRef, vm: &VirtualMachine) -> Option<usize> {
let i = if let Ok(i) = group.try_index(vm) {
i
@@ -768,6 +758,20 @@ mod _sre {
}
}
impl Representable for Match {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
with_sre_str!(zelf.pattern, &zelf.string, vm, |str_drive| {
Ok(format!(
"<re.Match object; span=({}, {}), match={}>",
zelf.regs[0].0,
zelf.regs[0].1,
zelf.get_slice(0, str_drive, vm).unwrap().repr(vm)?
))
})
}
}
#[pyattr]
#[pyclass(name = "SRE_Scanner")]
#[derive(Debug, PyPayload)]
+16 -12
View File
@@ -8,7 +8,7 @@ pub(crate) mod _thread {
builtins::{PyDictRef, PyStr, PyTupleRef, PyTypeRef},
convert::ToPyException,
function::{ArgCallable, Either, FuncArgs, KwArgs, OptionalArg, PySetterValue},
types::{Constructor, GetAttr, SetAttr},
types::{Constructor, GetAttr, Representable, SetAttr},
AsObject, Py, PyPayload, PyRef, PyResult, VirtualMachine,
};
use parking_lot::{
@@ -97,12 +97,12 @@ pub(crate) mod _thread {
} else {
"unlocked"
};
format!(
Ok(format!(
"<{} {} object at {:#x}>",
status,
$zelf.class().name(),
$zelf.get_id()
)
))
}};
}
@@ -119,7 +119,7 @@ pub(crate) mod _thread {
}
}
#[pyclass(with(Constructor))]
#[pyclass(with(Constructor, Representable))]
impl Lock {
#[pymethod]
#[pymethod(name = "acquire_lock")]
@@ -146,11 +146,6 @@ pub(crate) mod _thread {
fn locked(&self) -> bool {
self.mu.is_locked()
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
repr_lock_impl!(zelf)
}
}
impl Constructor for Lock {
@@ -160,6 +155,13 @@ pub(crate) mod _thread {
}
}
impl Representable for Lock {
#[inline]
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
repr_lock_impl!(zelf)
}
}
pub type RawRMutex = RawReentrantMutex<RawMutex, RawThreadId>;
#[pyattr]
#[pyclass(module = "thread", name = "RLock")]
@@ -174,7 +176,7 @@ pub(crate) mod _thread {
}
}
#[pyclass]
#[pyclass(with(Representable))]
impl RLock {
#[pyslot]
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
@@ -210,9 +212,11 @@ pub(crate) mod _thread {
fn exit(&self, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
self.release(vm)
}
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
impl Representable for RLock {
#[inline]
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
repr_lock_impl!(zelf)
}
}
+7 -5
View File
@@ -14,7 +14,7 @@ mod _js {
convert::{IntoObject, ToPyObject},
function::{ArgCallable, OptionalArg, OptionalOption, PosArgs},
protocol::PyIterReturn,
types::{IterNext, IterNextIterable},
types::{IterNext, IterNextIterable, Representable},
Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use std::{cell, fmt, future};
@@ -90,7 +90,7 @@ mod _js {
}
}
#[pyclass]
#[pyclass(with(Representable))]
impl PyJsValue {
#[inline]
pub fn new(value: impl Into<JsValue>) -> PyJsValue {
@@ -265,10 +265,12 @@ mod _js {
fn instanceof(&self, rhs: PyJsValueRef, vm: &VirtualMachine) -> PyResult<bool> {
instance_of(&self.value, &rhs.value).map_err(|err| new_js_error(vm, err))
}
}
#[pymethod(magic)]
fn repr(&self) -> String {
format!("{:?}", self.value)
impl Representable for PyJsValue {
#[inline]
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
Ok(format!("{:?}", zelf.value))
}
}