mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Object protocol
This commit is contained in:
@@ -38,11 +38,11 @@ impl TryFromBorrowedObject for PyBytesInner {
|
||||
#[derive(FromArgs)]
|
||||
pub struct ByteInnerNewOptions {
|
||||
#[pyarg(any, optional)]
|
||||
source: OptionalArg<PyObjectRef>,
|
||||
pub source: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(any, optional)]
|
||||
encoding: OptionalArg<PyStrRef>,
|
||||
pub encoding: OptionalArg<PyStrRef>,
|
||||
#[pyarg(any, optional)]
|
||||
errors: OptionalArg<PyStrRef>,
|
||||
pub errors: OptionalArg<PyStrRef>,
|
||||
}
|
||||
|
||||
impl ByteInnerNewOptions {
|
||||
|
||||
@@ -129,16 +129,6 @@ impl TryFromObject for PyIter<PyObjectRef> {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyObjectRef {
|
||||
/// Takes an object and returns an iterator for it.
|
||||
/// This is typically a new iterator but if the argument is an iterator, this
|
||||
/// returns itself.
|
||||
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
|
||||
// PyObject_GetIter
|
||||
PyIter::try_from_object(vm, self)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PyIterReturn<T = PyObjectRef> {
|
||||
Return(T),
|
||||
StopIteration(Option<PyObjectRef>),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
mod buffer;
|
||||
mod iter;
|
||||
mod mapping;
|
||||
mod object;
|
||||
|
||||
pub use buffer::{BufferInternal, BufferOptions, BufferResizeGuard, PyBuffer};
|
||||
pub use iter::{PyIter, PyIterIter, PyIterReturn};
|
||||
|
||||
148
vm/src/protocol/object.rs
Normal file
148
vm/src/protocol/object.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
//! Object Protocol
|
||||
//! https://docs.python.org/3/c-api/object.html
|
||||
|
||||
use crate::{
|
||||
builtins::{pystr::IntoPyStrRef, PyBytes, PyInt, PyStrRef},
|
||||
bytesinner::ByteInnerNewOptions,
|
||||
common::{hash::PyHash, str::to_ascii},
|
||||
function::OptionalArg,
|
||||
protocol::PyIter,
|
||||
pyref_type_error,
|
||||
types::{Constructor, PyComparisonOp},
|
||||
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
};
|
||||
|
||||
// RustPython doesn't need these items
|
||||
// PyObject *Py_NotImplemented
|
||||
// Py_RETURN_NOTIMPLEMENTED
|
||||
|
||||
impl PyObjectRef {
|
||||
// int PyObject_Print(PyObject *o, FILE *fp, int flags)
|
||||
|
||||
pub fn has_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.get_attr(attr_name, vm).map(|o| vm.is_none(&o))
|
||||
}
|
||||
|
||||
pub fn get_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
vm.get_attribute(self, attr_name)
|
||||
}
|
||||
|
||||
// PyObject *PyObject_GenericGetAttr(PyObject *o, PyObject *name)
|
||||
|
||||
pub fn set_attr(
|
||||
&self,
|
||||
attr_name: impl IntoPyStrRef,
|
||||
attr_value: impl Into<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
vm.set_attr(self, attr_name, attr_value)
|
||||
}
|
||||
|
||||
// int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
|
||||
|
||||
pub fn del_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
vm.del_attr(self, attr_name)
|
||||
}
|
||||
|
||||
// PyObject *PyObject_GenericGetDict(PyObject *o, void *context)
|
||||
// int PyObject_GenericSetDict(PyObject *o, PyObject *value, void *context)
|
||||
|
||||
pub fn rich_compare(self, other: Self, opid: PyComparisonOp, vm: &VirtualMachine) -> PyResult {
|
||||
vm.obj_cmp(self, other, opid)
|
||||
}
|
||||
|
||||
pub fn rich_compare_bool(
|
||||
&self,
|
||||
other: &Self,
|
||||
opid: PyComparisonOp,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<bool> {
|
||||
vm.bool_cmp(self, other, opid)
|
||||
}
|
||||
|
||||
pub fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
vm.to_repr(self)
|
||||
}
|
||||
|
||||
pub fn ascii(&self, vm: &VirtualMachine) -> PyResult<ascii::AsciiString> {
|
||||
let repr = vm.to_repr(self)?;
|
||||
let ascii = to_ascii(repr.as_str());
|
||||
Ok(ascii)
|
||||
}
|
||||
|
||||
pub fn str(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
vm.to_str(self)
|
||||
}
|
||||
|
||||
pub fn bytes(self, vm: &VirtualMachine) -> PyResult {
|
||||
let bytes_type = &vm.ctx.types.bytes_type;
|
||||
match self.downcast_exact::<PyInt>(vm) {
|
||||
Ok(int) => Err(pyref_type_error(vm, bytes_type, int.as_object())),
|
||||
Err(obj) => PyBytes::py_new(
|
||||
bytes_type.clone(),
|
||||
ByteInnerNewOptions {
|
||||
source: OptionalArg::Present(obj),
|
||||
encoding: OptionalArg::Missing,
|
||||
errors: OptionalArg::Missing,
|
||||
},
|
||||
vm,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_subclass(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
vm.issubclass(self, cls)
|
||||
}
|
||||
|
||||
pub fn is_instance(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
vm.isinstance(self, cls)
|
||||
}
|
||||
|
||||
pub fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
vm._hash(self)
|
||||
}
|
||||
|
||||
// const hash_not_implemented: fn(&PyObjectRef, &VirtualMachine) ->PyResult<PyHash> = crate::types::Unhashable::slot_hash;
|
||||
|
||||
pub fn is_true(self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.try_to_bool(vm)
|
||||
}
|
||||
|
||||
pub fn not(self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
self.is_true(vm).map(|x| !x)
|
||||
}
|
||||
|
||||
// type protocol
|
||||
// PyObject *PyObject_Type(PyObject *o)
|
||||
|
||||
// int PyObject_TypeCheck(PyObject *o, PyTypeObject *type)
|
||||
|
||||
pub fn length(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
vm.obj_len(self)
|
||||
}
|
||||
|
||||
pub fn length_hint(
|
||||
self,
|
||||
defaultvalue: Option<usize>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<usize>> {
|
||||
Ok(vm.length_hint(self)?.or(defaultvalue))
|
||||
}
|
||||
|
||||
// item protocol
|
||||
// PyObject *PyObject_GetItem(PyObject *o, PyObject *key)
|
||||
// int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
|
||||
// int PyObject_DelItem(PyObject *o, PyObject *key)
|
||||
|
||||
// PyObject *PyObject_Dir(PyObject *o)
|
||||
|
||||
/// Takes an object and returns an iterator for it.
|
||||
/// This is typically a new iterator but if the argument is an iterator, this
|
||||
/// returns itself.
|
||||
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
|
||||
// PyObject_GetIter
|
||||
PyIter::try_from_object(vm, self)
|
||||
}
|
||||
|
||||
// PyObject *PyObject_GetAIter(PyObject *o)
|
||||
}
|
||||
@@ -502,6 +502,8 @@ where
|
||||
fn slot_hash(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
Err(vm.new_type_error(format!("unhashable type: '{}'", zelf.class().name())))
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn hash(_zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
unreachable!("slot_hash is implemented for unhashable types");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user