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
15 changes: 15 additions & 0 deletions vm/src/builtins/builtinfunc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fmt;

use super::classmethod::PyClassMethod;
use super::pytype;
use crate::builtins::pystr::PyStrRef;
use crate::builtins::pytype::PyTypeRef;
use crate::function::{FuncArgs, PyNativeFunc};
Expand Down Expand Up @@ -142,6 +143,13 @@ impl PyBuiltinFunction {
fn repr(&self) -> String {
format!("<built-in function {}>", self.value.name)
}
#[pyproperty(magic)]
fn text_signature(&self) -> Option<String> {
self.value.doc.as_ref().and_then(|doc| {
pytype::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
.map(|signature| signature.to_string())
})
}
}

// `PyBuiltinMethod` is similar to both `PyMethodDescrObject` in
Expand Down Expand Up @@ -207,6 +215,13 @@ impl PyBuiltinMethod {
fn doc(&self) -> Option<PyStrRef> {
self.value.doc.clone()
}
#[pyproperty(magic)]
fn text_signature(&self) -> Option<String> {
self.value.doc.as_ref().and_then(|doc| {
pytype::get_text_signature_from_internal_doc(self.value.name.as_str(), doc.as_str())
.map(|signature| signature.to_string())
})
}
#[pymethod(magic)]
fn repr(&self) -> String {
format!(
Expand Down
65 changes: 64 additions & 1 deletion vm/src/builtins/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ use crate::{
PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol,
};

/// The most base type
/// object()
/// --
///
/// The base class of the class hierarchy.
///
/// When called, it accepts no arguments and returns a new featureless
/// instance that has no instance attributes and cannot be given any.
#[pyclass(module = false, name = "object")]
#[derive(Debug)]
pub struct PyBaseObject;
Expand All @@ -27,6 +33,10 @@ impl PyValue for PyBaseObject {

#[pyimpl(flags(BASETYPE))]
impl PyBaseObject {
/// __new__($type, *args, **kwargs)
/// --
///
/// Create and return a new object. See help(type) for accurate signature.
#[pyslot]
fn tp_new(mut args: FuncArgs, vm: &VirtualMachine) -> PyResult {
// more or less __new__ operator
Expand Down Expand Up @@ -82,6 +92,10 @@ impl PyBaseObject {
Ok(res)
}

/// __eq__($self, value, /)
/// --
///
/// Return self==value.
#[pymethod(magic)]
fn eq(
zelf: PyObjectRef,
Expand All @@ -90,6 +104,11 @@ impl PyBaseObject {
) -> PyResult<PyComparisonValue> {
Self::cmp(&zelf, &other, PyComparisonOp::Eq, vm)
}

/// __ne__($self, value, /)
/// --
///
/// Return self!=value.
#[pymethod(magic)]
fn ne(
zelf: PyObjectRef,
Expand All @@ -98,6 +117,11 @@ impl PyBaseObject {
) -> PyResult<PyComparisonValue> {
Self::cmp(&zelf, &other, PyComparisonOp::Ne, vm)
}

/// __lt__($self, value, /)
/// --
///
/// Return self<value.
#[pymethod(magic)]
fn lt(
zelf: PyObjectRef,
Expand All @@ -106,6 +130,11 @@ impl PyBaseObject {
) -> PyResult<PyComparisonValue> {
Self::cmp(&zelf, &other, PyComparisonOp::Lt, vm)
}

/// __le__($self, value, /)
/// --
///
/// Return self<=value.
#[pymethod(magic)]
fn le(
zelf: PyObjectRef,
Expand All @@ -114,6 +143,11 @@ impl PyBaseObject {
) -> PyResult<PyComparisonValue> {
Self::cmp(&zelf, &other, PyComparisonOp::Le, vm)
}

/// __ge__($self, value, /)
/// --
///
/// Return self>=value.
#[pymethod(magic)]
fn ge(
zelf: PyObjectRef,
Expand All @@ -122,6 +156,11 @@ impl PyBaseObject {
) -> PyResult<PyComparisonValue> {
Self::cmp(&zelf, &other, PyComparisonOp::Ge, vm)
}

/// __gt__($self, value, /)
/// --
///
/// Return self>value.
#[pymethod(magic)]
fn gt(
zelf: PyObjectRef,
Expand All @@ -131,6 +170,10 @@ impl PyBaseObject {
Self::cmp(&zelf, &other, PyComparisonOp::Gt, vm)
}

/// __setattr__($self, name, value /)
/// --
///
/// Implement setattr(self, name, value).
#[pymethod]
fn __setattr__(
obj: PyObjectRef,
Expand All @@ -141,6 +184,10 @@ impl PyBaseObject {
setattr(&obj, attr_name, Some(value), vm)
}

/// __delattr__($self, name, /)
/// --
///
/// Implement delattr(self, name).
#[pymethod]
fn __delattr__(obj: PyObjectRef, attr_name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> {
setattr(&obj, attr_name, None, vm)
Expand All @@ -156,11 +203,19 @@ impl PyBaseObject {
setattr(obj, attr_name, value, vm)
}

/// __str__($self, /)
/// --
///
/// Return str(self).
#[pymethod(magic)]
fn str(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
vm.to_repr(&zelf)
}

/// __repr__($self, /)
/// --
///
/// Return repr(self).
#[pymethod(magic)]
fn repr(zelf: PyObjectRef) -> String {
format!("<{} object at {:#x}>", zelf.class().name, zelf.get_id())
Expand Down Expand Up @@ -233,6 +288,10 @@ impl PyBaseObject {
}
}

/// __getattribute__($self, name, /)
/// --
///
/// Return getattr(self, name).
#[pymethod(name = "__getattribute__")]
#[pyslot]
pub(crate) fn getattro(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
Expand Down Expand Up @@ -262,6 +321,10 @@ impl PyBaseObject {
Ok(zelf.get_id() as _)
}

/// __hash__($self, /)
/// --
///
/// Return hash(self).
#[pymethod(magic)]
fn hash(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyHash> {
Self::tp_hash(&zelf, vm)
Expand Down
31 changes: 31 additions & 0 deletions vm/src/builtins/pytype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,37 @@ impl PyType {
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
))
}

#[pyproperty(magic)]
fn text_signature(&self) -> Option<String> {
self.slots
.doc
.and_then(|doc| get_text_signature_from_internal_doc(self.name().as_str(), doc))
.map(|signature| signature.to_string())
}
}

const SIGNATURE_END_MARKER: &str = ")\n--\n\n";
fn get_signature(doc: &str) -> Option<&str> {
doc.find(SIGNATURE_END_MARKER)
.map(|index| &doc[..index + 1])
}

fn find_signature<'a>(name: &str, doc: &'a str) -> Option<&'a str> {
let name = name.rsplit('.').next().unwrap();
let doc = doc.strip_prefix(name)?;
if !doc.starts_with('(') {
None
} else {
Some(doc)
}
}

pub(crate) fn get_text_signature_from_internal_doc<'a>(
name: &str,
internal_doc: &'a str,
) -> Option<&'a str> {
find_signature(name, internal_doc).and_then(get_signature)
}

impl SlotGetattro for PyType {
Expand Down
1 change: 1 addition & 0 deletions vm/src/pyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ pub trait PyClassImpl: PyClassDef {
let mut slots = PyTypeSlots {
flags: Self::TP_FLAGS,
name: PyRwLock::new(Some(Self::TP_NAME.to_owned())),
doc: Self::DOC,
..Default::default()
};
Self::extend_slots(&mut slots);
Expand Down
2 changes: 2 additions & 0 deletions vm/src/slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ pub struct PyTypeSlots {

// Flags to define presence of optional/expanded features
pub flags: PyTpFlags,

// tp_doc
pub doc: Option<&'static str>,

// Strong reference on a heap type, borrowed reference on a static type
// tp_base
Expand Down