Implemented repr slot

This commit is contained in:
Charles Hubain authored and Jeong YunWon committed 2023-03-18 19:28:05 +09:00
1 parent 21615cb158
commit 23cfdfffba
37 files changed
+808 -512

No files matched your search

+11 -8
View File
@@ -1,4 +1,4 @@
use super::{PyCode, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
use super::{PyCode, PyGenericAlias, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
builtins::PyBaseExceptionRef,
class::PyClassImpl,
@@ -6,7 +6,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
types::{Constructor, IterNext, IterNextIterable, Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -26,7 +26,7 @@ impl PyPayload for PyAsyncGen {
}
}
#[pyclass(with(Constructor))]
#[pyclass(with(Constructor, Representable))]
impl PyAsyncGen {
pub fn as_coro(&self) -> &Coro {
&self.inner
@@ -49,11 +49,6 @@ impl PyAsyncGen {
self.inner.set_name(name)
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)
}
#[pymethod(magic)]
fn aiter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
zelf
@@ -129,6 +124,14 @@ impl PyAsyncGen {
PyGenericAlias::new(cls, args, vm)
}
}
impl Representable for PyAsyncGen {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)).into_ref(vm))
}
}
impl Unconstructible for PyAsyncGen {}
#[pyclass(module = false, name = "async_generator_wrapped_value")]
+27 -12
View File
@@ -5,7 +5,7 @@ use crate::{
function::OptionalArg,
identifier,
protocol::PyNumberMethods,
types::{AsNumber, Constructor},
types::{AsNumber, Constructor, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject,
VirtualMachine,
};
@@ -107,18 +107,8 @@ impl Constructor for PyBool {
}
}
#[pyclass(with(Constructor, AsNumber))]
#[pyclass(with(Constructor, AsNumber, Representable))]
impl PyBool {
#[pymethod(magic)]
fn repr(zelf: bool, vm: &VirtualMachine) -> PyStrRef {
if zelf {
vm.ctx.names.True
} else {
vm.ctx.names.False
}
.to_owned()
}
#[pymethod(magic)]
fn format(obj: PyObjectRef, format_spec: PyStrRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if format_spec.is_empty() {
@@ -189,6 +179,31 @@ impl AsNumber for PyBool {
}
}
impl Representable for PyBool {
#[inline]
fn slot_repr(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if get_value(zelf) {
Ok(vm.ctx.names.True.to_owned())
} else {
Ok(vm.ctx.names.False.to_owned())
}
}
#[inline]
fn __repr__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Self::slot_repr(&zelf, vm)
}
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if get_value(zelf.as_object()) {
Ok(vm.ctx.names.True.to_owned())
} else {
Ok(vm.ctx.names.False.to_owned())
}
}
}
pub(crate) fn init(context: &Context) {
PyBool::extend_class(context, context.types.bool_type);
}
+26 -14
View File
@@ -3,7 +3,7 @@ use crate::{
builtins::PyBoundMethod,
class::PyClassImpl,
function::{FuncArgs, IntoPyNativeFunc, PyNativeFunc},
types::{Callable, Constructor, GetDescriptor, Unconstructible},
types::{Callable, Constructor, GetDescriptor, Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use std::fmt;
@@ -145,10 +145,6 @@ impl PyBuiltinFunction {
fn reduce_ex(&self, _ver: PyObjectRef) -> PyStrRef {
self.name()
}
#[pymethod(magic)]
fn repr(&self) -> String {
format!("<built-in function {}>", self.value.name)
}
#[pygetset(magic)]
fn text_signature(&self) -> Option<String> {
self.value.doc.as_ref().and_then(|doc| {
@@ -157,6 +153,14 @@ impl PyBuiltinFunction {
})
}
}
impl Representable for PyBuiltinFunction {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(format!("<built-in function {}>", zelf.value.name)).into_ref(vm))
}
}
impl Unconstructible for PyBuiltinFunction {}
// `PyBuiltinMethod` is similar to both `PyMethodDescrObject` in
@@ -225,7 +229,10 @@ impl PyBuiltinMethod {
}
}
#[pyclass(with(GetDescriptor, Callable, Constructor), flags(METHOD_DESCR))]
#[pyclass(
with(GetDescriptor, Callable, Constructor, Representable),
flags(METHOD_DESCR)
)]
impl PyBuiltinMethod {
#[pygetset(magic)]
fn name(&self) -> PyStrRef {
@@ -247,14 +254,6 @@ impl PyBuiltinMethod {
})
}
#[pymethod(magic)]
fn repr(&self) -> String {
format!(
"<method '{}' of '{}' objects>",
&self.value.name,
self.class.name()
)
}
#[pymethod(magic)]
fn reduce(
&self,
vm: &VirtualMachine,
@@ -264,6 +263,19 @@ impl PyBuiltinMethod {
(builtins_getattr, (classname, self.value.name.clone()))
}
}
impl Representable for PyBuiltinMethod {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(format!(
"<method '{}' of '{}' objects>",
&zelf.value.name,
zelf.class.name()
))
.into_ref(vm))
}
}
impl Unconstructible for PyBuiltinMethod {}
pub fn init(context: &Context) {
+17 -11
View File
@@ -1,7 +1,7 @@
//! Implementation of the python bytearray object.
use super::{
PositionIterInternal, PyBytes, PyBytesRef, PyDictRef, PyIntRef, PyStrRef, PyTuple, PyTupleRef,
PyType, PyTypeRef,
PositionIterInternal, PyBytes, PyBytesRef, PyDictRef, PyIntRef, PyStr, PyStrRef, PyTuple,
PyTupleRef, PyType, PyTypeRef,
};
use crate::{
anystr::{self, AnyStr},
@@ -31,7 +31,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Initializer,
IterNext, IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
IterNext, IterNextIterable, Iterable, PyComparisonOp, Representable, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
@@ -107,7 +107,8 @@ pub(crate) fn init(context: &Context) {
AsMapping,
AsSequence,
AsNumber,
Iterable
Iterable,
Representable
)
)]
impl PyByteArray {
@@ -126,13 +127,6 @@ impl PyByteArray {
self.inner.write()
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let class = zelf.class();
let class_name = class.name();
zelf.inner().repr(Some(&class_name), vm)
}
#[pymethod(magic)]
fn alloc(&self) -> usize {
self.inner().capacity()
@@ -886,6 +880,17 @@ impl Iterable for PyByteArray {
}
}
impl Representable for PyByteArray {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let class = zelf.class();
let class_name = class.name();
zelf.inner()
.repr(Some(&class_name), vm)
.map(|s| PyStr::from(s).into_ref(vm))
}
}
// fn set_value(obj: &PyObject, value: Vec<u8>) {
// obj.borrow_mut().kind = PyObjectPayload::Bytes { value };
// }
@@ -922,6 +927,7 @@ impl PyByteArrayIterator {
.set_state(state, |obj, pos| pos.min(obj.len()), vm)
}
}
impl Unconstructible for PyByteArrayIterator {}
impl IterNextIterable for PyByteArrayIterator {}
+14 -8
View File
@@ -1,5 +1,6 @@
use super::{
PositionIterInternal, PyDictRef, PyIntRef, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef,
PositionIterInternal, PyDictRef, PyIntRef, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType,
PyTypeRef,
};
use crate::{
anystr::{self, AnyStr},
@@ -21,7 +22,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Hashable,
IterNext, IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
IterNext, IterNextIterable, Iterable, PyComparisonOp, Representable, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
TryFromBorrowedObject, TryFromObject, VirtualMachine,
@@ -125,15 +126,11 @@ impl PyBytes {
AsBuffer,
Iterable,
Constructor,
AsNumber
AsNumber,
Representable,
)
)]
impl PyBytes {
#[pymethod(magic)]
pub(crate) fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
self.inner.repr(None, vm)
}
#[pymethod(magic)]
#[inline]
pub fn len(&self) -> usize {
@@ -689,6 +686,15 @@ impl Iterable for PyBytes {
}
}
impl Representable for PyBytes {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.inner
.repr(None, vm)
.map(|s| PyStr::from(s).into_ref(vm))
}
}
#[pyclass(module = false, name = "bytes_iterator")]
#[derive(Debug)]
pub struct PyBytesIterator {
+28 -23
View File
@@ -1,8 +1,8 @@
use super::{PyBoundMethod, PyStr, PyType, PyTypeRef};
use super::{PyBoundMethod, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
common::lock::PyMutex,
types::{Constructor, GetDescriptor, Initializer},
types::{Constructor, GetDescriptor, Initializer, Representable},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -104,7 +104,10 @@ impl PyClassMethod {
}
}
#[pyclass(with(GetDescriptor, Constructor), flags(BASETYPE, HAS_DICT))]
#[pyclass(
with(GetDescriptor, Constructor, Representable),
flags(BASETYPE, HAS_DICT)
)]
impl PyClassMethod {
#[pygetset(magic)]
fn func(&self) -> PyObjectRef {
@@ -136,26 +139,6 @@ impl PyClassMethod {
self.callable.lock().get_attr("__annotations__", vm)
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> Option<String> {
let callable = self.callable.lock().repr(vm).unwrap();
let class = Self::class(vm);
match (
class
.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => None,
(Some(qualname), Some(module)) if module != "builtins" => {
Some(format!("<{module}.{qualname}({callable})>"))
}
_ => Some(format!("<{}({})>", class.slot_name(), callable)),
}
}
#[pygetset(magic)]
fn isabstractmethod(&self, vm: &VirtualMachine) -> PyObjectRef {
match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") {
@@ -173,6 +156,28 @@ impl PyClassMethod {
}
}
impl Representable for PyClassMethod {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let callable = zelf.callable.lock().repr(vm).unwrap();
let class = Self::class(vm);
match (
class
.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => Err(vm.new_type_error("Unknown qualified name".into())),
(Some(qualname), Some(module)) if module != "builtins" => {
Ok(PyStr::from(format!("<{module}.{qualname}({callable})>")).into_ref(vm))
}
_ => Ok(PyStr::from(format!("<{}({})>", class.slot_name(), callable)).into_ref(vm)),
}
}
}
pub(crate) fn init(context: &Context) {
PyClassMethod::extend_class(context, context.types.classmethod_type);
}
+18 -14
View File
@@ -2,13 +2,14 @@
*/
use super::{PyStrRef, PyTupleRef, PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef};
use crate::{
builtins::PyStrInterned,
bytecode::{self, AsBag, BorrowedConstant, CodeFlags, Constant, ConstantBag},
class::{PyClassImpl, StaticType},
convert::ToPyObject,
function::{FuncArgs, OptionalArg},
types::Representable,
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use num_traits::Zero;
@@ -215,9 +216,24 @@ impl PyPayload for PyCode {
}
}
#[pyclass(with(PyRef))]
#[pyclass(with(PyRef, Representable))]
impl PyCode {}
impl Representable for PyCode {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let code = &zelf.code;
Ok(PyStr::from(format!(
"<code object {} at {:#x} file {:?}, line {}>",
code.obj_name,
zelf.get_id(),
code.source_path.as_str(),
code.first_line_number
))
.into_ref(vm))
}
}
#[pyclass]
impl PyRef<PyCode> {
#[pyslot]
@@ -225,18 +241,6 @@ impl PyRef<PyCode> {
Err(vm.new_type_error("Cannot directly create code object".to_owned()))
}
#[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
)
}
#[pygetset]
fn co_posonlyargcount(self) -> usize {
self.code.posonlyarg_count as usize
+46 -41
View File
@@ -1,4 +1,4 @@
use super::{float, PyStr, PyType, PyTypeRef};
use super::{float, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::{ToPyObject, ToPyResult},
@@ -9,7 +9,7 @@ use crate::{
},
identifier,
protocol::{PyNumber, PyNumberMethods},
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp},
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use num_complex::Complex64;
@@ -211,7 +211,10 @@ impl PyComplex {
}
}
#[pyclass(flags(BASETYPE), with(Comparable, Hashable, Constructor, AsNumber))]
#[pyclass(
flags(BASETYPE),
with(Comparable, Hashable, Constructor, AsNumber, Representable)
)]
impl PyComplex {
#[pymethod(magic)]
fn complex(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<PyComplex> {
@@ -331,44 +334,6 @@ impl PyComplex {
-self.value
}
#[pymethod(magic)]
fn repr(&self) -> String {
// TODO: when you fix this, move it to rustpython_common::complex::repr and update
// ast/src/unparse.rs + impl Display for Constant in ast/src/constant.rs
let Complex64 { re, im } = self.value;
// integer => drop ., fractional => float_ops
let mut im_part = if im.fract() == 0.0 {
im.to_string()
} else {
float_ops::to_string(im)
};
im_part.push('j');
// positive empty => return im_part, integer => drop ., fractional => float_ops
let re_part = if re == 0.0 {
if re.is_sign_positive() {
return im_part;
} else {
re.to_string()
}
} else if re.fract() == 0.0 {
re.to_string()
} else {
float_ops::to_string(re)
};
let mut result = String::with_capacity(
re_part.len() + im_part.len() + 2 + im.is_sign_positive() as usize,
);
result.push('(');
result.push_str(&re_part);
if im.is_sign_positive() || im.is_nan() {
result.push('+');
}
result.push_str(&im_part);
result.push(')');
result
}
#[pymethod(magic)]
fn pow(
&self,
@@ -488,6 +453,46 @@ impl AsNumber for PyComplex {
}
}
impl Representable for PyComplex {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
// TODO: when you fix this, move it to rustpython_common::complex::repr and update
// ast/src/unparse.rs + impl Display for Constant in ast/src/constant.rs
let Complex64 { re, im } = zelf.value;
// integer => drop ., fractional => float_ops
let mut im_part = if im.fract() == 0.0 {
im.to_string()
} else {
float_ops::to_string(im)
};
im_part.push('j');
// positive empty => return im_part, integer => drop ., fractional => float_ops
let re_part = if re == 0.0 {
if re.is_sign_positive() {
return Ok(PyStr::from(im_part).into_ref(vm));
} else {
re.to_string()
}
} else if re.fract() == 0.0 {
re.to_string()
} else {
float_ops::to_string(re)
};
let mut result = String::with_capacity(
re_part.len() + im_part.len() + 2 + im.is_sign_positive() as usize,
);
result.push('(');
result.push_str(&re_part);
if im.is_sign_positive() || im.is_nan() {
result.push('+');
}
result.push_str(&im_part);
result.push(')');
Ok(PyStr::from(result).into_ref(vm))
}
}
impl PyComplex {
fn number_op<F, R>(number: PyNumber, other: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
where
+10 -8
View File
@@ -1,11 +1,11 @@
use super::{PyCode, PyStrRef, PyType};
use super::{PyCode, PyStr, PyStrRef, PyType};
use crate::{
class::PyClassImpl,
coroutine::Coro,
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
types::{Constructor, IterNext, IterNextIterable, Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -22,7 +22,7 @@ impl PyPayload for PyCoroutine {
}
}
#[pyclass(with(Constructor, IterNext))]
#[pyclass(with(Constructor, IterNext, Representable))]
impl PyCoroutine {
pub fn as_coro(&self) -> &Coro {
&self.inner
@@ -44,11 +44,6 @@ impl PyCoroutine {
self.inner.set_name(name)
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)
}
#[pymethod]
fn send(zelf: PyRef<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
zelf.inner.send(zelf.as_object(), value, vm)
@@ -106,6 +101,13 @@ impl PyCoroutine {
}
impl Unconstructible for PyCoroutine {}
impl Representable for PyCoroutine {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)).into_ref(vm))
}
}
impl IterNextIterable for PyCoroutine {}
impl IterNext for PyCoroutine {
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
+15 -12
View File
@@ -1,8 +1,8 @@
use super::{PyStr, PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
function::PySetterValue,
types::{Constructor, GetDescriptor, Unconstructible},
types::{Constructor, GetDescriptor, Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use rustpython_common::lock::PyRwLock;
@@ -100,17 +100,8 @@ fn calculate_qualname(descr: &DescrObject, vm: &VirtualMachine) -> PyResult<Opti
}
}
#[pyclass(with(GetDescriptor, Constructor), flags(BASETYPE))]
#[pyclass(with(GetDescriptor, Constructor, Representable), flags(BASETYPE))]
impl MemberDescrObject {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
format!(
"<member '{}' of '{}' objects>",
zelf.common.name,
zelf.common.typ.name(),
)
}
#[pygetset(magic)]
fn doc(zelf: PyRef<Self>) -> Option<String> {
zelf.member.doc.to_owned()
@@ -197,6 +188,18 @@ fn set_slot_at_object(
impl Unconstructible for MemberDescrObject {}
impl Representable for MemberDescrObject {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(format!(
"<member '{}' of '{}' objects>",
zelf.common.name,
zelf.common.typ.name(),
))
.into_ref(vm))
}
}
impl GetDescriptor for MemberDescrObject {
fn descr_get(
zelf: PyObjectRef,
+46 -39
View File
@@ -1,6 +1,6 @@
use super::{
set::PySetInner, IterStatus, PositionIterInternal, PyBaseExceptionRef, PyGenericAlias,
PyMappingProxy, PySet, PyStr, PyTupleRef, PyType, PyTypeRef,
PyMappingProxy, PySet, PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef,
};
use crate::{
atomic_func,
@@ -20,7 +20,7 @@ use crate::{
recursion::ReprGuard,
types::{
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Initializer, IterNext,
IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
IterNextIterable, Iterable, PyComparisonOp, Representable, Unconstructible,
},
vm::VirtualMachine,
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
@@ -209,7 +209,8 @@ impl PyDict {
Comparable,
Iterable,
AsSequence,
AsNumber
AsNumber,
Representable
),
flags(BASETYPE)
)]
@@ -254,23 +255,6 @@ impl PyDict {
std::mem::size_of::<Self>() + self.entries.sizeof()
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let s = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut str_parts = Vec::with_capacity(zelf.len());
for (key, value) in zelf {
let key_repr = &key.repr(vm)?;
let value_repr = value.repr(vm)?;
str_parts.push(format!("{key_repr}: {value_repr}"));
}
format!("{{{}}}", str_parts.join(", "))
} else {
"{...}".to_owned()
};
Ok(s)
}
#[pymethod(magic)]
fn contains(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
self.entries.contains(vm, &*key)
@@ -520,6 +504,25 @@ impl Iterable for PyDict {
}
}
impl Representable for PyDict {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let s = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut str_parts = Vec::with_capacity(zelf.len());
for (key, value) in zelf {
let key_repr = &key.repr(vm)?;
let value_repr = value.repr(vm)?;
str_parts.push(format!("{key_repr}: {value_repr}"));
}
format!("{{{}}}", str_parts.join(", "))
} else {
"{...}".to_owned()
};
Ok(PyStr::from(s).into_ref(vm))
}
}
impl Py<PyDict> {
#[inline]
fn exact_dict(&self, vm: &VirtualMachine) -> bool {
@@ -727,7 +730,7 @@ impl ExactSizeIterator for DictIter<'_> {
}
#[pyclass]
trait DictView: PyPayload + PyClassDef + Iterable
trait DictView: PyPayload + PyClassDef + Iterable + Representable
where
Self::ReverseIter: PyPayload,
{
@@ -741,21 +744,6 @@ where
self.dict().len()
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let s = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut str_parts = Vec::with_capacity(zelf.len());
for (key, value) in zelf.dict().clone() {
let s = &Self::item(vm, key, value).repr(vm)?;
str_parts.push(s.as_str().to_owned());
}
format!("{}([{}])", Self::NAME, str_parts.join(", "))
} else {
"{...}".to_owned()
};
Ok(s)
}
#[pymethod(magic)]
fn reversed(&self) -> Self::ReverseIter;
}
@@ -802,6 +790,23 @@ macro_rules! dict_view {
}
}
impl Representable for $name {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let s = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let mut str_parts = Vec::with_capacity(zelf.len());
for (key, value) in zelf.dict().clone() {
let s = &Self::item(vm, key, value).repr(vm)?;
str_parts.push(s.as_str().to_owned());
}
format!("{}([{}])", Self::NAME, str_parts.join(", "))
} else {
"{...}".to_owned()
};
Ok(PyStr::from(s).into_ref(vm))
}
}
#[pyclass(module = false, name = $iter_class_name)]
#[derive(Debug)]
pub(crate) struct $iter_name {
@@ -1099,7 +1104,8 @@ impl ViewSetOps for PyDictKeys {}
Iterable,
ViewSetOps,
AsSequence,
AsNumber
AsNumber,
Representable
))]
impl PyDictKeys {
#[pymethod(magic)]
@@ -1203,7 +1209,8 @@ impl ViewSetOps for PyDictItems {}
Iterable,
ViewSetOps,
AsSequence,
AsNumber
AsNumber,
Representable
))]
impl PyDictItems {
#[pymethod(magic)]
@@ -1313,7 +1320,7 @@ impl AsNumber for PyDictItems {
}
}
#[pyclass(with(DictView, Constructor, Iterable, AsSequence))]
#[pyclass(with(DictView, Constructor, Iterable, AsSequence, Representable))]
impl PyDictValues {
#[pygetset]
fn mapping(zelf: PyRef<Self>) -> PyMappingProxy {
+12 -7
View File
@@ -14,7 +14,7 @@ use crate::{
PyComparisonValue,
},
protocol::{PyNumber, PyNumberMethods},
types::{AsNumber, Callable, Comparable, Constructor, Hashable, PyComparisonOp},
types::{AsNumber, Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
TryFromBorrowedObject, TryFromObject, VirtualMachine,
};
@@ -185,7 +185,10 @@ fn float_from_string(val: PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
})
}
#[pyclass(flags(BASETYPE), with(Comparable, Hashable, Constructor, AsNumber))]
#[pyclass(
flags(BASETYPE),
with(Comparable, Hashable, Constructor, AsNumber, Representable)
)]
impl PyFloat {
#[pymethod(magic)]
fn format(&self, spec: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
@@ -356,11 +359,6 @@ impl PyFloat {
self.simple_op(other, |a, b| Ok(b - a), vm)
}
#[pymethod(magic)]
fn repr(&self) -> String {
float_ops::to_string(self.value)
}
#[pymethod(magic)]
fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyArithmeticValue<f64>> {
self.simple_op(other, |a, b| inner_div(a, b, vm), vm)
@@ -580,6 +578,13 @@ impl AsNumber for PyFloat {
}
}
impl Representable for PyFloat {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(float_ops::to_string(zelf.value)).into_ref(vm))
}
}
impl PyFloat {
fn number_op<F, R>(number: PyNumber, other: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
where
+12 -8
View File
@@ -2,12 +2,13 @@
*/
use super::{PyCode, PyDictRef, PyIntRef};
use super::{PyCode, PyDictRef, PyIntRef, PyStr, PyStrRef};
use crate::{
class::PyClassImpl,
frame::{Frame, FrameRef},
function::PySetterValue,
types::{Constructor, Unconstructible},
object::PyPayload,
types::{Constructor, Representable, Unconstructible},
AsObject, Context, PyObjectRef, PyRef, PyResult, VirtualMachine,
};
use num_traits::Zero;
@@ -16,17 +17,20 @@ pub fn init(context: &Context) {
FrameRef::extend_class(context, context.types.frame_type);
}
#[pyclass(with(Constructor, PyRef))]
#[pyclass(with(Constructor, PyRef, Representable))]
impl Frame {}
impl Unconstructible for Frame {}
impl Representable for Frame {
#[inline]
fn repr(_zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from("<frame object at .. >").into_ref(vm))
}
}
#[pyclass]
impl FrameRef {
#[pymethod(magic)]
fn repr(self) -> String {
"<frame object at .. >".to_owned()
}
#[pymethod]
fn clear(self) {
// TODO
+19 -7
View File
@@ -16,7 +16,9 @@ use crate::{
frame::Frame,
function::{FuncArgs, OptionalArg, PyComparisonValue, PySetterValue},
scope::Scope,
types::{Callable, Comparable, Constructor, GetAttr, GetDescriptor, PyComparisonOp},
types::{
Callable, Comparable, Constructor, GetAttr, GetDescriptor, PyComparisonOp, Representable,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use itertools::Itertools;
@@ -337,7 +339,10 @@ impl PyPayload for PyFunction {
}
}
#[pyclass(with(GetDescriptor, Callable), flags(HAS_DICT, METHOD_DESCR))]
#[pyclass(
with(GetDescriptor, Callable, Representable),
flags(HAS_DICT, METHOD_DESCR)
)]
impl PyFunction {
#[pygetset(magic)]
fn code(&self) -> PyRef<PyCode> {
@@ -414,11 +419,6 @@ impl PyFunction {
Ok(())
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
format!("<function {} at {:#x}>", zelf.qualname(), zelf.get_id())
}
#[cfg(feature = "jit")]
#[pymethod(magic)]
fn jit(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
@@ -457,6 +457,18 @@ impl Callable for PyFunction {
}
}
impl Representable for PyFunction {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(format!(
"<function {} at {:#x}>",
zelf.qualname(),
zelf.get_id()
))
.into_ref(vm))
}
}
#[pyclass(module = false, name = "method")]
#[derive(Debug)]
pub struct PyBoundMethod {
+10 -7
View File
@@ -2,14 +2,14 @@
* The mythical generator.
*/
use super::{PyCode, PyStrRef, PyType};
use super::{PyCode, PyStr, PyStrRef, PyType};
use crate::{
class::PyClassImpl,
coroutine::Coro,
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, IterNextIterable, Unconstructible},
types::{Constructor, IterNext, IterNextIterable, Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -47,11 +47,6 @@ impl PyGenerator {
self.inner.set_name(name)
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)
}
#[pymethod]
fn send(zelf: PyRef<Self>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
zelf.inner.send(zelf.as_object(), value, vm)
@@ -96,8 +91,16 @@ impl PyGenerator {
self.inner.frame().yield_from_target()
}
}
impl Unconstructible for PyGenerator {}
impl Representable for PyGenerator {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(zelf.inner.repr(zelf.as_object(), zelf.get_id(), vm)).into_ref(vm))
}
}
impl IterNextIterable for PyGenerator {}
impl IterNext for PyGenerator {
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
+20 -3
View File
@@ -9,7 +9,10 @@ use crate::{
convert::ToPyObject,
function::{FuncArgs, PyComparisonValue},
protocol::PyMappingMethods,
types::{AsMapping, Callable, Comparable, Constructor, GetAttr, Hashable, PyComparisonOp},
types::{
AsMapping, Callable, Comparable, Constructor, GetAttr, Hashable, PyComparisonOp,
Representable,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
};
@@ -60,7 +63,15 @@ impl Constructor for PyGenericAlias {
}
#[pyclass(
with(AsMapping, Callable, Comparable, Constructor, GetAttr, Hashable),
with(
AsMapping,
Callable,
Comparable,
Constructor,
GetAttr,
Hashable,
Representable
),
flags(BASETYPE)
)]
impl PyGenericAlias {
@@ -79,7 +90,6 @@ impl PyGenericAlias {
}
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
fn repr_item(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
if obj.is(&vm.ctx.ellipsis) {
@@ -390,6 +400,13 @@ impl GetAttr for PyGenericAlias {
}
}
impl Representable for PyGenericAlias {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.repr(vm).map(|s| PyStr::from(s).into_ref(vm))
}
}
pub fn init(context: &Context) {
let generic_alias_type = &context.types.generic_alias_type;
PyGenericAlias::extend_class(context, generic_alias_type);
+12 -7
View File
@@ -10,7 +10,7 @@ use crate::{
PyComparisonValue,
},
protocol::{PyNumber, PyNumberMethods},
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp},
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
TryFromBorrowedObject, VirtualMachine,
};
@@ -316,7 +316,10 @@ impl PyInt {
}
}
#[pyclass(flags(BASETYPE), with(Comparable, Hashable, Constructor, AsNumber))]
#[pyclass(
flags(BASETYPE),
with(Comparable, Hashable, Constructor, AsNumber, Representable)
)]
impl PyInt {
#[pymethod(name = "__radd__")]
#[pymethod(magic)]
@@ -555,11 +558,6 @@ impl PyInt {
!(&self.value)
}
#[pymethod(magic)]
pub(crate) fn repr(&self) -> String {
self.value.to_string()
}
#[pymethod(magic)]
fn format(&self, spec: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
FormatSpec::parse(spec.as_str())
@@ -714,6 +712,13 @@ impl Comparable for PyInt {
}
}
impl Representable for PyInt {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from(zelf.value.to_string()).into_ref(vm))
}
}
impl Hashable for PyInt {
#[inline]
fn hash(zelf: &crate::Py<Self>, _vm: &VirtualMachine) -> PyResult<hash::PyHash> {
+25 -15
View File
@@ -1,4 +1,4 @@
use super::{PositionIterInternal, PyGenericAlias, PyTupleRef, PyType, PyTypeRef};
use super::{PositionIterInternal, PyGenericAlias, PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef};
use crate::atomic_func;
use crate::common::lock::{
PyMappedRwLockReadGuard, PyMutex, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard,
@@ -14,7 +14,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
types::{
AsMapping, AsSequence, Comparable, Constructor, Initializer, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,
Iterable, PyComparisonOp, Representable, Unconstructible,
},
utils::collection_repr,
vm::VirtualMachine,
@@ -97,7 +97,15 @@ pub(crate) struct SortOptions {
pub type PyListRef = PyRef<PyList>;
#[pyclass(
with(Constructor, Initializer, AsMapping, Iterable, Comparable, AsSequence),
with(
Constructor,
Initializer,
AsMapping,
Iterable,
Comparable,
AsSequence,
Representable
),
flags(BASETYPE)
)]
impl PyList {
@@ -229,18 +237,6 @@ impl PyList {
self._setitem(&needle, value, vm)
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let s = if zelf.len() == 0 {
"[]".to_owned()
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
collection_repr(None, "[", "]", zelf.borrow_vec().iter(), vm)?
} else {
"[...]".to_owned()
};
Ok(s)
}
#[pymethod(magic)]
#[pymethod(name = "__rmul__")]
fn mul(&self, n: ArgSize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
@@ -493,6 +489,20 @@ impl Comparable for PyList {
}
}
impl Representable for PyList {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let s = if zelf.len() == 0 {
"[]".to_owned()
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
collection_repr(None, "[", "]", zelf.borrow_vec().iter(), vm)?
} else {
"[...]".to_owned()
};
Ok(PyStr::from(s).into_ref(vm))
}
}
fn do_sort(
vm: &VirtualMachine,
values: &mut Vec<PyObjectRef>,
+24 -8
View File
@@ -1,11 +1,16 @@
use super::{PyDict, PyDictRef, PyGenericAlias, PyList, PyTuple, PyType, PyTypeRef};
use super::{
PyDict, PyDictRef, PyGenericAlias, PyList, PyStr, PyStrRef, PyTuple, PyType, PyTypeRef,
};
use crate::{
atomic_func,
class::PyClassImpl,
convert::ToPyObject,
function::{ArgMapping, OptionalArg, PyComparisonValue},
protocol::{PyMapping, PyMappingMethods, PyNumberMethods, PySequenceMethods},
types::{AsMapping, AsNumber, AsSequence, Comparable, Constructor, Iterable, PyComparisonOp},
types::{
AsMapping, AsNumber, AsSequence, Comparable, Constructor, Iterable, PyComparisonOp,
Representable,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use once_cell::sync::Lazy;
@@ -69,7 +74,15 @@ impl Constructor for PyMappingProxy {
}
}
#[pyclass(with(AsMapping, Iterable, Constructor, AsSequence, Comparable, AsNumber))]
#[pyclass(with(
AsMapping,
Iterable,
Constructor,
AsSequence,
Comparable,
AsNumber,
Representable
))]
impl PyMappingProxy {
fn get_inner(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
let opt = match &self.mapping {
@@ -149,11 +162,6 @@ impl PyMappingProxy {
}
}
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let obj = self.to_object(vm)?;
Ok(format!("mappingproxy({})", obj.repr(vm)?))
}
#[pyclassmethod(magic)]
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
@@ -260,6 +268,14 @@ impl Iterable for PyMappingProxy {
}
}
impl Representable for PyMappingProxy {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let obj = zelf.to_object(vm)?;
Ok(PyStr::from(format!("mappingproxy({})", obj.repr(vm)?)).into_ref(vm))
}
}
pub fn init(context: &Context) {
PyMappingProxy::extend_class(context, context.types.mappingproxy_type)
}
+14 -11
View File
@@ -22,7 +22,7 @@ use crate::{
sliceable::SequenceIndexOp,
types::{
AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext,
IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
IterNextIterable, Iterable, PyComparisonOp, Representable, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
TryFromBorrowedObject, TryFromObject, VirtualMachine,
@@ -75,7 +75,8 @@ impl Constructor for PyMemoryView {
AsMapping,
AsSequence,
Constructor,
Iterable
Iterable,
Representable
))]
impl PyMemoryView {
fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult<FormatSpec> {
@@ -593,15 +594,6 @@ impl PyMemoryView {
Ok(other.into_ref(vm))
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
if zelf.released.load() {
format!("<released memory at {:#x}>", zelf.get_id())
} else {
format!("<memory at {:#x}>", zelf.get_id())
}
}
#[pymethod]
fn hex(
&self,
@@ -1058,6 +1050,17 @@ impl PyPayload for PyMemoryView {
}
}
impl Representable for PyMemoryView {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if zelf.released.load() {
Ok(PyStr::from(format!("<released memory at {:#x}>", zelf.get_id())).into_ref(vm))
} else {
Ok(PyStr::from(format!("<memory at {:#x}>", zelf.get_id())).into_ref(vm))
}
}
}
pub(crate) fn init(ctx: &Context) {
PyMemoryView::extend_class(ctx, ctx.types.memoryview_type);
PyMemoryViewIterator::extend_class(ctx, ctx.types.memoryviewiterator_type);
+14 -9
View File
@@ -5,7 +5,7 @@ use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::FuncArgs,
types::{GetAttr, Initializer},
types::{GetAttr, Initializer, Representable},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -26,7 +26,7 @@ pub struct ModuleInitArgs {
doc: Option<PyStrRef>,
}
#[pyclass(with(GetAttr, Initializer), flags(BASETYPE, HAS_DICT))]
#[pyclass(with(GetAttr, Initializer, Representable), flags(BASETYPE, HAS_DICT))]
impl PyModule {
// pub(crate) fn new(d: PyDictRef) -> Self {
// PyModule { dict: d.into() }
@@ -67,13 +67,6 @@ impl PyModule {
.and_then(|obj| obj.downcast::<PyStr>().ok())
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
let importlib = vm.import("_frozen_importlib", None, 0)?;
let module_repr = importlib.get_attr("_module_repr", vm)?;
module_repr.call((zelf,), vm)
}
#[pymethod(magic)]
fn dir(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
let dict = zelf
@@ -147,6 +140,18 @@ impl GetAttr for PyModule {
}
}
impl Representable for PyModule {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let importlib = vm.import("_frozen_importlib", None, 0)?;
let module_repr = importlib.get_attr("_module_repr", vm)?;
module_repr.call((zelf.to_owned(),), vm).and_then(|obj| {
obj.downcast()
.map_err(|_| vm.new_type_error("_module_repr did not return a string".into()))
})
}
}
pub(crate) fn init(context: &Context) {
PyModule::extend_class(context, context.types.module_type);
}
+34 -29
View File
@@ -1,10 +1,10 @@
use super::{PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
builtins::PyDict,
class::PyClassImpl,
function::{FuncArgs, PyComparisonValue},
recursion::ReprGuard,
types::{Comparable, Constructor, Initializer, PyComparisonOp},
types::{Comparable, Constructor, Initializer, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -39,33 +39,11 @@ impl PyNamespace {
}
}
#[pyclass(flags(BASETYPE, HAS_DICT), with(Constructor, Initializer, Comparable))]
impl PyNamespace {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let o = zelf.as_object();
let name = if o.class().is(vm.ctx.types.namespace_type) {
"namespace".to_owned()
} else {
o.class().slot_name()
};
let repr = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let dict = zelf.as_object().dict().unwrap();
let mut parts = Vec::with_capacity(dict.len());
for (key, value) in dict {
let k = &key.repr(vm)?;
let key_str = k.as_str();
let value_repr = value.repr(vm)?;
parts.push(format!("{}={}", &key_str[1..key_str.len() - 1], value_repr));
}
format!("{}({})", name, parts.join(", "))
} else {
format!("{name}(...)")
};
Ok(repr)
}
}
#[pyclass(
flags(BASETYPE, HAS_DICT),
with(Constructor, Initializer, Comparable, Representable)
)]
impl PyNamespace {}
impl Initializer for PyNamespace {
type Args = FuncArgs;
@@ -97,6 +75,33 @@ impl Comparable for PyNamespace {
}
}
impl Representable for PyNamespace {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let o = zelf.as_object();
let name = if o.class().is(vm.ctx.types.namespace_type) {
"namespace".to_owned()
} else {
o.class().slot_name()
};
let repr = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let dict = zelf.as_object().dict().unwrap();
let mut parts = Vec::with_capacity(dict.len());
for (key, value) in dict {
let k = &key.repr(vm)?;
let key_str = k.as_str();
let value_repr = value.repr(vm)?;
parts.push(format!("{}={}", &key_str[1..key_str.len() - 1], value_repr));
}
format!("{}({})", name, parts.join(", "))
} else {
format!("{name}(...)")
};
Ok(PyStr::from(repr).into_ref(vm))
}
}
pub fn init(context: &Context) {
PyNamespace::extend_class(context, context.types.namespace_type);
}
+15 -9
View File
@@ -187,11 +187,9 @@ impl PyBaseObject {
zelf.repr(vm)
}
/// Return repr(self).
#[pymethod(magic)]
fn repr(zelf: PyObjectRef, vm: &VirtualMachine) -> Option<String> {
#[pyslot]
fn slot_repr(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let class = zelf.class();
match (
class
.qualname(vm)
@@ -199,21 +197,29 @@ impl PyBaseObject {
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => None,
(Some(qualname), Some(module)) if module != "builtins" => Some(format!(
(None, _) => Err(vm.new_type_error("Unknown qualified name".into())),
(Some(qualname), Some(module)) if module != "builtins" => Ok(PyStr::from(format!(
"<{}.{} object at {:#x}>",
module,
qualname,
zelf.get_id()
)),
_ => Some(format!(
))
.into_ref(vm)),
_ => Ok(PyStr::from(format!(
"<{} object at {:#x}>",
class.slot_name(),
zelf.get_id()
)),
))
.into_ref(vm)),
}
}
/// Return repr(self).
#[pymethod(magic)]
fn repr(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Self::slot_repr(&zelf, vm)
}
#[pyclassmethod(magic)]
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
vm.ctx.not_implemented()
+19 -12
View File
@@ -1,5 +1,6 @@
use super::{
builtins_iter, tuple::tuple_hash, PyInt, PyIntRef, PySlice, PyTupleRef, PyType, PyTypeRef,
builtins_iter, tuple::tuple_hash, PyInt, PyIntRef, PySlice, PyStr, PyStrRef, PyTupleRef,
PyType, PyTypeRef,
};
use crate::{
atomic_func,
@@ -9,7 +10,7 @@ use crate::{
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
types::{
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,
Iterable, PyComparisonOp, Representable, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
@@ -174,7 +175,7 @@ pub fn init(context: &Context) {
PyRangeIterator::extend_class(context, context.types.range_iterator_type);
}
#[pyclass(with(AsMapping, AsSequence, Hashable, Comparable, Iterable))]
#[pyclass(with(AsMapping, AsSequence, Hashable, Comparable, Iterable, Representable))]
impl PyRange {
fn new(cls: PyTypeRef, stop: ArgIndex, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
PyRange {
@@ -260,15 +261,6 @@ impl PyRange {
self.compute_length()
}
#[pymethod(magic)]
fn repr(&self) -> String {
if self.step.as_bigint().is_one() {
format!("range({}, {})", self.start, self.stop)
} else {
format!("range({}, {}, {})", self.start, self.stop, self.step)
}
}
#[pymethod(magic)]
fn bool(&self) -> bool {
!self.is_empty()
@@ -511,6 +503,21 @@ impl Iterable for PyRange {
}
}
impl Representable for PyRange {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if zelf.step.as_bigint().is_one() {
Ok(PyStr::from(format!("range({}, {})", zelf.start, zelf.stop)).into_ref(vm))
} else {
Ok(PyStr::from(format!(
"range({}, {}, {})",
zelf.start, zelf.stop, zelf.step
))
.into_ref(vm))
}
}
}
// Semantically, this is the same as the previous representation.
//
// Unfortunately, since AtomicCell requires a Copy type, no BigInt implementations can
+60 -40
View File
@@ -2,8 +2,8 @@
* Builtin set type with a sequence of unique items.
*/
use super::{
builtins_iter, IterStatus, PositionIterInternal, PyDict, PyDictRef, PyGenericAlias, PyTupleRef,
PyType, PyTypeRef,
builtins_iter, IterStatus, PositionIterInternal, PyDict, PyDictRef, PyGenericAlias, PyStr,
PyStrRef, PyTupleRef, PyType, PyTypeRef,
};
use crate::{
atomic_func,
@@ -17,7 +17,7 @@ use crate::{
types::AsNumber,
types::{
AsSequence, Comparable, Constructor, Hashable, Initializer, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,
Iterable, PyComparisonOp, Representable, Unconstructible,
},
utils::collection_repr,
vm::VirtualMachine,
@@ -489,7 +489,15 @@ fn reduce_set(
}
#[pyclass(
with(Constructor, Initializer, AsSequence, Comparable, Iterable, AsNumber),
with(
Constructor,
Initializer,
AsSequence,
Comparable,
Iterable,
AsNumber,
Representable
),
flags(BASETYPE)
)]
impl PySet {
@@ -626,26 +634,6 @@ impl PySet {
}
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let class = zelf.class();
let borrowed_name = class.name();
let class_name = borrowed_name.deref();
let s = if zelf.inner.len() == 0 {
format!("{class_name}()")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let name = if class_name != "set" {
Some(class_name)
} else {
None
};
zelf.inner.repr(name, vm)?
} else {
format!("{class_name}(...)")
};
Ok(s)
}
#[pymethod]
pub fn add(&self, item: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.inner.add(item, vm)?;
@@ -888,6 +876,28 @@ impl AsNumber for PySet {
}
}
impl Representable for PySet {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let class = zelf.class();
let borrowed_name = class.name();
let class_name = borrowed_name.deref();
let s = if zelf.inner.len() == 0 {
format!("{class_name}()")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let name = if class_name != "set" {
Some(class_name)
} else {
None
};
zelf.inner.repr(name, vm)?
} else {
format!("{class_name}(...)")
};
Ok(PyStr::from(s).into_ref(vm))
}
}
impl Constructor for PyFrozenSet {
type Args = OptionalArg<PyObjectRef>;
@@ -918,7 +928,15 @@ impl Constructor for PyFrozenSet {
#[pyclass(
flags(BASETYPE),
with(Constructor, AsSequence, Hashable, Comparable, Iterable, AsNumber)
with(
Constructor,
AsSequence,
Hashable,
Comparable,
Iterable,
AsNumber,
Representable
)
)]
impl PyFrozenSet {
#[pymethod(magic)]
@@ -1059,21 +1077,6 @@ impl PyFrozenSet {
}
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let inner = &zelf.inner;
let class = zelf.class();
let class_name = class.name();
let s = if inner.len() == 0 {
format!("{class_name}()")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
inner.repr(Some(&class_name), vm)?
} else {
format!("{class_name}(...)")
};
Ok(s)
}
#[pymethod(magic)]
fn reduce(
zelf: PyRef<Self>,
@@ -1164,6 +1167,23 @@ impl AsNumber for PyFrozenSet {
}
}
impl Representable for PyFrozenSet {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let inner = &zelf.inner;
let class = zelf.class();
let class_name = class.name();
let s = if inner.len() == 0 {
format!("{class_name}()")
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
inner.repr(Some(&class_name), vm)?
} else {
format!("{class_name}(...)")
};
Ok(PyStr::from(s).into_ref(vm))
}
}
struct AnySet {
object: PyObjectRef,
}
+17 -13
View File
@@ -1,9 +1,9 @@
use super::{PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
protocol::PyNumberMethods,
types::{AsNumber, Constructor},
types::{AsNumber, Constructor, Representable},
Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
@@ -42,19 +42,21 @@ impl Constructor for PyNone {
}
}
#[pyclass(with(Constructor, AsNumber))]
#[pyclass(with(Constructor, AsNumber, Representable))]
impl PyNone {
#[pymethod(magic)]
fn repr(&self) -> String {
"None".to_owned()
}
#[pymethod(magic)]
fn bool(&self) -> bool {
false
}
}
impl Representable for PyNone {
#[inline]
fn repr(_zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from("None").into_ref(vm))
}
}
impl AsNumber for PyNone {
fn as_number() -> &'static PyNumberMethods {
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
@@ -93,17 +95,19 @@ impl PyNotImplemented {
true
}
#[pymethod(magic)]
fn repr(&self) -> String {
"NotImplemented".to_owned()
}
#[pymethod(magic)]
fn reduce(&self) -> String {
"NotImplemented".to_owned()
}
}
impl Representable for PyNotImplemented {
#[inline]
fn repr(_zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from("NotImplemented").into_ref(vm))
}
}
pub fn init(context: &Context) {
PyNone::extend_class(context, context.types.none_type);
PyNotImplemented::extend_class(context, context.types.not_implemented_type);
+27 -23
View File
@@ -1,12 +1,12 @@
// sliceobject.{h,c} in CPython
// spell-checker:ignore sliceobject
use super::{PyTupleRef, PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
convert::ToPyObject,
function::{ArgIndex, FuncArgs, OptionalArg, PyComparisonValue},
sliceable::SaturatedSlice,
types::{Comparable, Constructor, PyComparisonOp},
types::{Comparable, Constructor, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use num_bigint::{BigInt, ToBigInt};
@@ -26,7 +26,7 @@ impl PyPayload for PySlice {
}
}
#[pyclass(with(Comparable))]
#[pyclass(with(Comparable, Representable))]
impl PySlice {
#[pygetset]
fn start(&self, vm: &VirtualMachine) -> PyObjectRef {
@@ -57,20 +57,6 @@ impl PySlice {
}
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let start_repr = self.start_ref(vm).repr(vm)?;
let stop_repr = &self.stop.repr(vm)?;
let step_repr = self.step_ref(vm).repr(vm)?;
Ok(format!(
"slice({}, {}, {})",
start_repr.as_str(),
stop_repr.as_str(),
step_repr.as_str()
))
}
pub fn to_saturated(&self, vm: &VirtualMachine) -> PyResult<SaturatedSlice> {
SaturatedSlice::with_slice(self, vm)
}
@@ -258,6 +244,22 @@ impl Comparable for PySlice {
Ok(PyComparisonValue::Implemented(ret))
}
}
impl Representable for PySlice {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let start_repr = zelf.start_ref(vm).repr(vm)?;
let stop_repr = &zelf.stop.repr(vm)?;
let step_repr = zelf.step_ref(vm).repr(vm)?;
Ok(PyStr::from(format!(
"slice({}, {}, {})",
start_repr.as_str(),
stop_repr.as_str(),
step_repr.as_str()
))
.into_ref(vm))
}
}
#[pyclass(module = false, name = "EllipsisType")]
#[derive(Debug)]
@@ -277,19 +279,21 @@ impl Constructor for PyEllipsis {
}
}
#[pyclass(with(Constructor))]
#[pyclass(with(Constructor, Representable))]
impl PyEllipsis {
#[pymethod(magic)]
fn repr(&self) -> String {
"Ellipsis".to_owned()
}
#[pymethod(magic)]
fn reduce(&self) -> String {
"Ellipsis".to_owned()
}
}
impl Representable for PyEllipsis {
#[inline]
fn repr(_zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Ok(PyStr::from("Ellipsis").into_ref(vm))
}
}
pub fn init(ctx: &Context) {
PySlice::extend_class(ctx, ctx.types.slice_type);
PyEllipsis::extend_class(ctx, ctx.types.ellipsis_type);
+25 -23
View File
@@ -1,10 +1,10 @@
use super::{PyStr, PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
builtins::builtin_func::PyBuiltinMethod,
class::PyClassImpl,
common::lock::PyMutex,
function::{FuncArgs, IntoPyNativeFunc},
types::{Callable, Constructor, GetDescriptor, Initializer},
types::{Callable, Constructor, GetDescriptor, Initializer, Representable},
Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -104,7 +104,7 @@ impl Initializer for PyStaticMethod {
}
#[pyclass(
with(Callable, GetDescriptor, Constructor, Initializer),
with(Callable, GetDescriptor, Constructor, Initializer, Representable),
flags(BASETYPE, HAS_DICT)
)]
impl PyStaticMethod {
@@ -138,26 +138,6 @@ impl PyStaticMethod {
self.callable.lock().get_attr("__annotations__", vm)
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> Option<String> {
let callable = self.callable.lock().repr(vm).unwrap();
let class = Self::class(vm);
match (
class
.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => None,
(Some(qualname), Some(module)) if module != "builtins" => {
Some(format!("<{module}.{qualname}({callable})>"))
}
_ => Some(format!("<{}({})>", class.slot_name(), callable)),
}
}
#[pygetset(magic)]
fn isabstractmethod(&self, vm: &VirtualMachine) -> PyObjectRef {
match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") {
@@ -184,6 +164,28 @@ impl Callable for PyStaticMethod {
}
}
impl Representable for PyStaticMethod {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let callable = zelf.callable.lock().repr(vm).unwrap();
let class = Self::class(vm);
match (
class
.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => Err(vm.new_type_error("Unknown qualified name".into())),
(Some(qualname), Some(module)) if module != "builtins" => {
Ok(PyStr::from(format!("<{module}.{qualname}({callable})>")).into_ref(vm))
}
_ => Ok(PyStr::from(format!("<{}({})>", class.slot_name(), callable)).into_ref(vm)),
}
}
}
pub fn init(context: &Context) {
PyStaticMethod::extend_class(context, context.types.staticmethod_type);
}
+12 -3
View File
@@ -20,7 +20,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
AsMapping, AsNumber, AsSequence, Comparable, Constructor, Hashable, IterNext,
IterNextIterable, Iterable, PyComparisonOp, Unconstructible,
IterNextIterable, Iterable, PyComparisonOp, Representable, Unconstructible,
},
AsObject, Context, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
TryFromBorrowedObject, VirtualMachine,
@@ -377,6 +377,7 @@ impl PyStr {
AsMapping,
AsNumber,
AsSequence,
Representable,
Hashable,
Comparable,
Iterable,
@@ -495,11 +496,12 @@ impl PyStr {
zelf
}
#[pymethod(magic)]
pub(crate) fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
#[inline]
pub(crate) fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
rustpython_common::str::repr(self.as_str())
.to_string_checked()
.map_err(|err| vm.new_overflow_error(err.to_string()))
.map(|s| PyStr::from(s).into_ref(vm))
}
#[pymethod]
@@ -1259,6 +1261,13 @@ impl PyStrRef {
}
}
impl Representable for PyStr {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.repr(vm)
}
}
impl Hashable for PyStr {
#[inline]
fn hash(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<hash::PyHash> {
+19 -12
View File
@@ -3,11 +3,11 @@
See also [CPython source code.](https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/Objects/typeobject.c#L7663)
*/
use super::{PyStrRef, PyType, PyTypeRef};
use super::{PyStr, PyStrRef, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
function::{IntoFuncArgs, OptionalArg},
types::{Callable, Constructor, GetAttr, GetDescriptor},
types::{Callable, Constructor, GetAttr, GetDescriptor, Representable},
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
@@ -97,7 +97,7 @@ impl Constructor for PySuper {
}
}
#[pyclass(with(GetAttr, GetDescriptor, Constructor))]
#[pyclass(with(GetAttr, GetDescriptor, Constructor, Representable))]
impl PySuper {
fn new(typ: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
let obj = if vm.is_none(&obj) {
@@ -123,15 +123,6 @@ impl PySuper {
fn __self__(&self) -> Option<PyObjectRef> {
Some(self.obj.as_ref()?.0.clone())
}
#[pymethod(magic)]
fn repr(&self) -> String {
let name = &self.typ.name();
match self.obj {
Some((_, ref ty)) => format!("<super: <class '{}'>, <{} object>>", name, ty.name()),
None => format!("<super: <class '{name}'>, NULL>"),
}
}
}
impl GetAttr for PySuper {
@@ -193,6 +184,22 @@ impl GetDescriptor for PySuper {
}
}
impl Representable for PySuper {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let typname = &zelf.typ.name();
match zelf.obj {
Some((_, ref ty)) => Ok(PyStr::from(format!(
"<super: <class '{}'>, <{} object>>",
typname,
ty.name()
))
.into_ref(vm)),
None => Ok(PyStr::from(format!("<super: <class '{typname}'>, NULL>")).into_ref(vm)),
}
}
}
fn supercheck(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTypeRef> {
if let Ok(cls) = obj.clone().downcast::<PyType>() {
if cls.fast_issubclass(&ty) {
+29 -19
View File
@@ -1,6 +1,6 @@
use once_cell::sync::Lazy;
use super::{PositionIterInternal, PyGenericAlias, PyType, PyTypeRef};
use super::{PositionIterInternal, PyGenericAlias, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::common::{hash::PyHash, lock::PyMutex};
use crate::{
atomic_func,
@@ -14,7 +14,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,
Iterable, PyComparisonOp, Representable, Unconstructible,
},
utils::collection_repr,
vm::VirtualMachine,
@@ -189,7 +189,15 @@ impl PyTuple {
#[pyclass(
flags(BASETYPE),
with(AsMapping, AsSequence, Hashable, Comparable, Iterable, Constructor)
with(
AsMapping,
AsSequence,
Hashable,
Comparable,
Iterable,
Constructor,
Representable
)
)]
impl PyTuple {
#[pymethod(magic)]
@@ -242,22 +250,6 @@ impl PyTuple {
self.elements.is_empty()
}
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
let s = if zelf.len() == 0 {
"()".to_owned()
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
if zelf.len() == 1 {
format!("({},)", zelf.elements[0].repr(vm)?)
} else {
collection_repr(None, "(", ")", zelf.elements.iter(), vm)?
}
} else {
"(...)".to_owned()
};
Ok(s)
}
#[pymethod(name = "__rmul__")]
#[pymethod(magic)]
fn mul(zelf: PyRef<Self>, value: ArgSize, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
@@ -406,6 +398,24 @@ impl Iterable for PyTuple {
}
}
impl Representable for PyTuple {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let s = if zelf.len() == 0 {
"()".to_owned()
} else if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
if zelf.len() == 1 {
format!("({},)", zelf.elements[0].repr(vm)?)
} else {
collection_repr(None, "(", ")", zelf.elements.iter(), vm)?
}
} else {
"(...)".to_owned()
};
Ok(PyStr::from(s).into_ref(vm))
}
}
#[pyclass(module = false, name = "tuple_iterator")]
#[derive(Debug)]
pub(crate) struct PyTupleIterator {
+29 -24
View File
@@ -21,8 +21,7 @@ use crate::{
function::{FuncArgs, KwArgs, OptionalArg, PySetterValue},
identifier,
protocol::{PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
types::AsNumber,
types::{Callable, GetAttr, PyTypeFlags, PyTypeSlots, SetAttr},
types::{AsNumber, Callable, GetAttr, PyTypeFlags, PyTypeSlots, Representable, SetAttr},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use indexmap::{map::Entry, IndexMap};
@@ -375,7 +374,10 @@ impl Py<PyType> {
}
}
#[pyclass(with(GetAttr, SetAttr, Callable, AsNumber), flags(BASETYPE))]
#[pyclass(
with(GetAttr, SetAttr, Callable, AsNumber, Representable),
flags(BASETYPE)
)]
impl PyType {
// bound method for every type
pub(crate) fn __new__(zelf: PyRef<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
@@ -459,27 +461,6 @@ impl PyType {
.into()
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> String {
let module = self.module(vm);
let module = module.downcast_ref::<PyStr>().map(|m| m.as_str());
match module {
Some(module) if module != "builtins" => {
let name = self.name();
format!(
"<class '{}.{}'>",
module,
self.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str())
.unwrap_or_else(|| &name)
)
}
_ => format!("<class '{}'>", self.slot_name()),
}
}
#[pygetset(magic)]
pub fn qualname(&self, vm: &VirtualMachine) -> PyObjectRef {
self.attributes
@@ -1072,6 +1053,30 @@ impl AsNumber for PyType {
}
}
impl Representable for PyType {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let module = zelf.module(vm);
let module = module.downcast_ref::<PyStr>().map(|m| m.as_str());
match module {
Some(module) if module != "builtins" => {
let name = zelf.name();
Ok(PyStr::from(format!(
"<class '{}.{}'>",
module,
zelf.qualname(vm)
.downcast_ref::<PyStr>()
.map(|n| n.as_str())
.unwrap_or_else(|| &name)
))
.into_ref(vm))
}
_ => Ok(PyStr::from(format!("<class '{}'>", zelf.slot_name())).into_ref(vm)),
}
}
}
fn find_base_dict_descr(cls: &Py<PyType>, vm: &VirtualMachine) -> Option<PyObjectRef> {
cls.iter_base_chain().skip(1).find_map(|cls| {
// TODO: should actually be some translation of:
+12 -3
View File
@@ -7,7 +7,7 @@ use crate::{
convert::{ToPyObject, ToPyResult},
function::PyComparisonValue,
protocol::{PyMappingMethods, PyNumberMethods},
types::{AsMapping, AsNumber, Comparable, GetAttr, Hashable, PyComparisonOp},
types::{AsMapping, AsNumber, Comparable, GetAttr, Hashable, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
};
@@ -34,14 +34,16 @@ impl PyPayload for PyUnion {
}
}
#[pyclass(flags(BASETYPE), with(Hashable, Comparable, AsMapping, AsNumber))]
#[pyclass(
flags(BASETYPE),
with(Hashable, Comparable, AsMapping, AsNumber, Representable)
)]
impl PyUnion {
pub fn new(args: PyTupleRef, vm: &VirtualMachine) -> Self {
let parameters = make_parameters(&args, vm);
Self { args, parameters }
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
fn repr_item(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
if obj.is(vm.ctx.types.none_type) {
@@ -307,6 +309,13 @@ impl GetAttr for PyUnion {
}
}
impl Representable for PyUnion {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.repr(vm).map(|s| PyStr::from(s).into_ref(vm))
}
}
pub fn init(context: &Context) {
let union_type = &context.types.union_type;
PyUnion::extend_class(context, union_type);
+20 -7
View File
@@ -6,7 +6,10 @@ use crate::{
class::PyClassImpl,
function::{OptionalArg, PyComparisonValue, PySetterValue},
protocol::{PyMappingMethods, PySequenceMethods},
types::{AsMapping, AsSequence, Comparable, Constructor, GetAttr, PyComparisonOp, SetAttr},
types::{
AsMapping, AsSequence, Comparable, Constructor, GetAttr, PyComparisonOp, Representable,
SetAttr,
},
Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -61,7 +64,15 @@ crate::common::static_cell! {
static WEAK_SUBCLASS: PyTypeRef;
}
#[pyclass(with(GetAttr, SetAttr, Constructor, Comparable, AsSequence, AsMapping))]
#[pyclass(with(
GetAttr,
SetAttr,
Constructor,
Comparable,
AsSequence,
AsMapping,
Representable
))]
impl PyWeakProxy {
fn try_upgrade(&self, vm: &VirtualMachine) -> PyResult {
self.weak.upgrade().ok_or_else(|| new_reference_error(vm))
@@ -86,11 +97,6 @@ impl PyWeakProxy {
self.try_upgrade(vm)?.bytes(vm)
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
self.try_upgrade(vm)?.repr(vm)
}
#[pymethod(magic)]
fn contains(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
self.try_upgrade(vm)?.to_sequence(vm).contains(&needle, vm)
@@ -191,6 +197,13 @@ impl AsMapping for PyWeakProxy {
}
}
impl Representable for PyWeakProxy {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.try_upgrade(vm)?.repr(vm)
}
}
pub fn init(context: &Context) {
PyWeakProxy::extend_class(context, context.types.weakproxy_type);
}
+25 -19
View File
@@ -1,4 +1,4 @@
use super::{PyGenericAlias, PyType, PyTypeRef};
use super::{PyGenericAlias, PyStr, PyStrRef, PyType, PyTypeRef};
use crate::common::{
atomic::{Ordering, Radium},
hash::{self, PyHash},
@@ -6,8 +6,8 @@ use crate::common::{
use crate::{
class::PyClassImpl,
function::OptionalArg,
types::{Callable, Comparable, Constructor, Hashable, PyComparisonOp},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
types::{Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
pub use crate::object::PyWeak;
@@ -47,23 +47,11 @@ impl Constructor for PyWeak {
}
}
#[pyclass(with(Callable, Hashable, Comparable, Constructor), flags(BASETYPE))]
#[pyclass(
with(Callable, Hashable, Comparable, Constructor, Representable),
flags(BASETYPE)
)]
impl PyWeak {
#[pymethod(magic)]
fn repr(zelf: PyRef<Self>) -> String {
let id = zelf.get_id();
if let Some(o) = zelf.upgrade() {
format!(
"<weakref at {:#x}; to '{}' at {:#x}>",
id,
o.class().name(),
o.get_id(),
)
} else {
format!("<weakref at {id:#x}; dead>")
}
}
#[pyclassmethod(magic)]
fn class_getitem(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
PyGenericAlias::new(cls, args, vm)
@@ -114,6 +102,24 @@ impl Comparable for PyWeak {
}
}
impl Representable for PyWeak {
#[inline]
fn repr(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let id = zelf.get_id();
if let Some(o) = zelf.upgrade() {
Ok(PyStr::from(format!(
"<weakref at {:#x}; to '{}' at {:#x}>",
id,
o.class().name(),
o.get_id(),
))
.into_ref(vm))
} else {
Ok(PyStr::from(format!("<weakref at {id:#x}; dead>")).into_ref(vm))
}
}
}
pub fn init(context: &Context) {
PyWeak::extend_class(context, context.types.weakref_type);
}
+6 -2
View File
@@ -317,8 +317,12 @@ impl PyObject {
pub fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
vm.with_recursion("while getting the repr of an object", || {
let repr = vm.call_special_method(self.to_owned(), identifier!(vm, __repr__), ())?;
repr.try_into_value(vm)
match self.class().slots.repr.load() {
Some(slot) => slot(self, vm),
None => vm
.call_special_method(self.to_owned(), identifier!(vm, __repr__), ())?
.try_into_value(vm),
}
})
}
+39 -2
View File
@@ -1,5 +1,7 @@
use crate::{
builtins::{type_::PointerSlot, PyFloat, PyInt, PyStrInterned, PyStrRef, PyType, PyTypeRef},
builtins::{
type_::PointerSlot, PyFloat, PyInt, PyStr, PyStrInterned, PyStrRef, PyType, PyTypeRef,
},
bytecode::ComparisonOperator,
common::{hash::PyHash, lock::PyRwLock},
convert::{ToPyObject, ToPyResult},
@@ -43,7 +45,7 @@ pub struct PyTypeSlots {
// More standard operations (here for binary compatibility)
pub hash: AtomicCell<Option<HashFunc>>,
pub call: AtomicCell<Option<GenericMethod>>,
// tp_str
pub repr: AtomicCell<Option<ReprFunc>>,
pub getattro: AtomicCell<Option<GetattroFunc>>,
pub setattro: AtomicCell<Option<SetattroFunc>>,
@@ -273,6 +275,7 @@ impl Default for PyTypeFlags {
pub(crate) type GenericMethod = fn(&PyObject, FuncArgs, &VirtualMachine) -> PyResult;
pub(crate) type HashFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyHash>;
// CallFunc = GenericMethod
pub(crate) type ReprFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyStrRef>;
pub(crate) type GetattroFunc = fn(&PyObject, PyStrRef, &VirtualMachine) -> PyResult;
pub(crate) type SetattroFunc =
fn(&PyObject, PyStrRef, PySetterValue, &VirtualMachine) -> PyResult<()>;
@@ -369,6 +372,16 @@ fn setitem_wrapper<K: ToPyObject>(
.map(drop)
}
fn repr_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let ret = vm.call_special_method(zelf.to_owned(), identifier!(vm, __repr__), ())?;
ret.downcast::<PyStr>().map_err(|obj| {
vm.new_type_error(format!(
"__repr__ returned non-string (type {})",
obj.class()
))
})
}
fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
let hash_obj = vm.call_special_method(zelf.to_owned(), identifier!(vm, __hash__), ())?;
match hash_obj.payload_if_subclass::<PyInt>(vm) {
@@ -561,6 +574,9 @@ impl PyType {
});
update_pointer_slot!(as_mapping, mapping_methods);
}
_ if name == identifier!(ctx, __repr__) => {
update_slot!(repr, repr_wrapper);
}
_ if name == identifier!(ctx, __hash__) => {
let is_unhashable = self
.attributes
@@ -993,6 +1009,27 @@ pub trait Hashable: PyPayload {
fn hash(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyHash>;
}
#[pyclass]
pub trait Representable: PyPayload {
#[inline]
#[pyslot]
fn slot_repr(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if let Some(zelf) = zelf.downcast_ref() {
Self::repr(zelf, vm)
} else {
Err(vm.new_type_error("unexpected payload for __repr__".to_owned()))
}
}
#[inline]
#[pymethod]
fn __repr__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Self::slot_repr(&zelf, vm)
}
fn repr(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef>;
}
#[pyclass]
pub trait Comparable: PyPayload {
#[inline]