Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/stdlib/src/ssl/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ pub(crate) use ssl_error::*;
#[pymodule(sub)]
pub(crate) mod ssl_error {
use crate::vm::{
PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{PyBaseExceptionRef, PyOSError, PyStrRef},
Py, PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{PyBaseException, PyOSError, PyStrRef},
types::{Constructor, Initializer},
};

Expand Down Expand Up @@ -42,7 +42,7 @@ pub(crate) mod ssl_error {
impl PySSLError {
// Returns strerror attribute if available, otherwise str(args)
#[pymethod]
fn __str__(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
fn __str__(exc: &Py<PyBaseException>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
use crate::vm::AsObject;
// Try to get strerror attribute first (OSError compatibility)
if let Ok(strerror) = exc.as_object().get_attr("strerror", vm)
Expand Down
14 changes: 12 additions & 2 deletions crates/vm/src/builtins/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
function::{FuncArgs, PyMethodDef, PyMethodFlags, PySetterValue},
types::{
Callable, Comparable, GetDescriptor, HashFunc, Hashable, InitFunc, PyComparisonOp,
Representable,
Representable, StringifyFunc,
},
};
use rustpython_common::lock::PyRwLock;
Expand Down Expand Up @@ -398,13 +398,15 @@ pub fn init(ctx: &Context) {
pub enum SlotFunc {
Init(InitFunc),
Hash(HashFunc),
Repr(StringifyFunc),
}

impl std::fmt::Debug for SlotFunc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SlotFunc::Init(_) => write!(f, "SlotFunc::Init(...)"),
SlotFunc::Hash(_) => write!(f, "SlotFunc::Hash(...)"),
SlotFunc::Repr(_) => write!(f, "SlotFunc::Repr(...)"),
}
}
}
Expand All @@ -426,6 +428,15 @@ impl SlotFunc {
let hash = func(&obj, vm)?;
Ok(vm.ctx.new_int(hash).into())
}
SlotFunc::Repr(func) => {
if !args.args.is_empty() || !args.kwargs.is_empty() {
return Err(
vm.new_type_error("__repr__() takes no arguments (1 given)".to_owned())
);
}
let s = func(&obj, vm)?;
Ok(s.into())
}
}
}
}
Expand Down Expand Up @@ -456,7 +467,6 @@ impl GetDescriptor for PySlotWrapper {
) -> PyResult {
match obj {
None => Ok(zelf),
Some(obj) if vm.is_none(&obj) => Ok(zelf),
Some(obj) => {
let zelf = zelf.downcast::<Self>().unwrap();
Ok(PyMethodWrapper { wrapper: zelf, obj }.into_pyobject(vm))
Expand Down
16 changes: 8 additions & 8 deletions crates/vm/src/builtins/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,6 @@ impl Py<PyStr> {
#[pyclass(
flags(BASETYPE, _MATCH_SELF),
with(
PyRef,
AsMapping,
AsNumber,
AsSequence,
Expand Down Expand Up @@ -1448,15 +1447,16 @@ impl PyStr {
fn __getnewargs__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyObjectRef {
(zelf.as_str(),).to_pyobject(vm)
}
}

#[pyclass]
impl PyRef<PyStr> {
#[pymethod]
fn __str__(self, vm: &VirtualMachine) -> PyRefExact<PyStr> {
self.into_exact_or(&vm.ctx, |zelf| {
PyStr::from(zelf.data.clone()).into_exact_ref(&vm.ctx)
})
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
if zelf.class().is(vm.ctx.types.str_type) {
// Already exact str, just return a reference
Ok(zelf.to_owned())
} else {
// Subclass, create a new exact str
Ok(PyStr::from(zelf.data.clone()).into_ref(&vm.ctx))
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/builtins/weakproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ impl PyWeakProxy {
}

#[pymethod]
fn __str__(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
self.try_upgrade(vm)?.str(vm)
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
zelf.try_upgrade(vm)?.str(vm)
}

fn len(&self, vm: &VirtualMachine) -> PyResult<usize> {
Expand Down
14 changes: 14 additions & 0 deletions crates/vm/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,20 @@ pub trait PyClassImpl: PyClassDef {
class.set_attr(ctx.names.__hash__, ctx.none.clone().into());
}

// Add __repr__ slot wrapper if slot exists and not already in dict
if let Some(repr_func) = class.slots.repr.load() {
let repr_name = identifier!(ctx, __repr__);
if !class.attributes.read().contains_key(repr_name) {
let wrapper = PySlotWrapper {
typ: class,
name: ctx.intern_str("__repr__"),
wrapped: SlotFunc::Repr(repr_func),
doc: Some("Return repr(self)."),
};
class.set_attr(repr_name, wrapper.into_ref(ctx).into());
}
}

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

Expand Down
6 changes: 3 additions & 3 deletions crates/vm/src/exception_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub(super) mod types {
}

#[pymethod]
fn __str__(zelf: PyRef<PyBaseException>, vm: &VirtualMachine) -> PyResult<String> {
fn __str__(zelf: &Py<PyBaseException>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
let message = zelf
.get_arg(0)
.map(|m| m.str(vm))
Expand All @@ -196,10 +196,10 @@ pub(super) mod types {
.unwrap_or(0);

let suffix = if num_excs == 1 { "" } else { "s" };
Ok(format!(
Ok(vm.ctx.new_str(format!(
"{} ({} sub-exception{})",
message, num_excs, suffix
))
)))
}

#[pymethod]
Expand Down
Loading
Loading