mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Implemented repr slot
This commit is contained in:
1 parent
21615cb158
commit
23cfdfffba
37 files changed
+808
-512
No files matched your search
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
@@ -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
@@ -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>,
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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]
|
||||
|
||||
Reference in new issue
Block a user