Skip to content

Commit 273193f

Browse files
authored
Merge pull request #3306 from youknowone/object-protocol
Object protocol
2 parents 69f4363 + 79e951b commit 273193f

File tree

5 files changed

+154
-13
lines changed

5 files changed

+154
-13
lines changed

vm/src/bytesinner.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ impl TryFromBorrowedObject for PyBytesInner {
3838
#[derive(FromArgs)]
3939
pub struct ByteInnerNewOptions {
4040
#[pyarg(any, optional)]
41-
source: OptionalArg<PyObjectRef>,
41+
pub source: OptionalArg<PyObjectRef>,
4242
#[pyarg(any, optional)]
43-
encoding: OptionalArg<PyStrRef>,
43+
pub encoding: OptionalArg<PyStrRef>,
4444
#[pyarg(any, optional)]
45-
errors: OptionalArg<PyStrRef>,
45+
pub errors: OptionalArg<PyStrRef>,
4646
}
4747

4848
impl ByteInnerNewOptions {

vm/src/protocol/iter.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,6 @@ impl TryFromObject for PyIter<PyObjectRef> {
129129
}
130130
}
131131

132-
impl PyObjectRef {
133-
/// Takes an object and returns an iterator for it.
134-
/// This is typically a new iterator but if the argument is an iterator, this
135-
/// returns itself.
136-
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
137-
// PyObject_GetIter
138-
PyIter::try_from_object(vm, self)
139-
}
140-
}
141-
142132
pub enum PyIterReturn<T = PyObjectRef> {
143133
Return(T),
144134
StopIteration(Option<PyObjectRef>),

vm/src/protocol/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod buffer;
22
mod iter;
33
mod mapping;
4+
mod object;
45

56
pub use buffer::{BufferInternal, BufferOptions, BufferResizeGuard, PyBuffer};
67
pub use iter::{PyIter, PyIterIter, PyIterReturn};

vm/src/protocol/object.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//! Object Protocol
2+
//! https://docs.python.org/3/c-api/object.html
3+
4+
use crate::{
5+
builtins::{pystr::IntoPyStrRef, PyBytes, PyInt, PyStrRef},
6+
bytesinner::ByteInnerNewOptions,
7+
common::{hash::PyHash, str::to_ascii},
8+
function::OptionalArg,
9+
protocol::PyIter,
10+
pyref_type_error,
11+
types::{Constructor, PyComparisonOp},
12+
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
13+
};
14+
15+
// RustPython doesn't need these items
16+
// PyObject *Py_NotImplemented
17+
// Py_RETURN_NOTIMPLEMENTED
18+
19+
impl PyObjectRef {
20+
// int PyObject_Print(PyObject *o, FILE *fp, int flags)
21+
22+
pub fn has_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<bool> {
23+
self.get_attr(attr_name, vm).map(|o| vm.is_none(&o))
24+
}
25+
26+
pub fn get_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
27+
vm.get_attribute(self, attr_name)
28+
}
29+
30+
// PyObject *PyObject_GenericGetAttr(PyObject *o, PyObject *name)
31+
32+
pub fn set_attr(
33+
&self,
34+
attr_name: impl IntoPyStrRef,
35+
attr_value: impl Into<PyObjectRef>,
36+
vm: &VirtualMachine,
37+
) -> PyResult<()> {
38+
vm.set_attr(self, attr_name, attr_value)
39+
}
40+
41+
// int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
42+
43+
pub fn del_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<()> {
44+
vm.del_attr(self, attr_name)
45+
}
46+
47+
// PyObject *PyObject_GenericGetDict(PyObject *o, void *context)
48+
// int PyObject_GenericSetDict(PyObject *o, PyObject *value, void *context)
49+
50+
pub fn rich_compare(self, other: Self, opid: PyComparisonOp, vm: &VirtualMachine) -> PyResult {
51+
vm.obj_cmp(self, other, opid)
52+
}
53+
54+
pub fn rich_compare_bool(
55+
&self,
56+
other: &Self,
57+
opid: PyComparisonOp,
58+
vm: &VirtualMachine,
59+
) -> PyResult<bool> {
60+
vm.bool_cmp(self, other, opid)
61+
}
62+
63+
pub fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
64+
vm.to_repr(self)
65+
}
66+
67+
pub fn ascii(&self, vm: &VirtualMachine) -> PyResult<ascii::AsciiString> {
68+
let repr = vm.to_repr(self)?;
69+
let ascii = to_ascii(repr.as_str());
70+
Ok(ascii)
71+
}
72+
73+
pub fn str(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
74+
vm.to_str(self)
75+
}
76+
77+
pub fn bytes(self, vm: &VirtualMachine) -> PyResult {
78+
let bytes_type = &vm.ctx.types.bytes_type;
79+
match self.downcast_exact::<PyInt>(vm) {
80+
Ok(int) => Err(pyref_type_error(vm, bytes_type, int.as_object())),
81+
Err(obj) => PyBytes::py_new(
82+
bytes_type.clone(),
83+
ByteInnerNewOptions {
84+
source: OptionalArg::Present(obj),
85+
encoding: OptionalArg::Missing,
86+
errors: OptionalArg::Missing,
87+
},
88+
vm,
89+
),
90+
}
91+
}
92+
93+
pub fn is_subclass(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
94+
vm.issubclass(self, cls)
95+
}
96+
97+
pub fn is_instance(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
98+
vm.isinstance(self, cls)
99+
}
100+
101+
pub fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> {
102+
vm._hash(self)
103+
}
104+
105+
// const hash_not_implemented: fn(&PyObjectRef, &VirtualMachine) ->PyResult<PyHash> = crate::types::Unhashable::slot_hash;
106+
107+
pub fn is_true(self, vm: &VirtualMachine) -> PyResult<bool> {
108+
self.try_to_bool(vm)
109+
}
110+
111+
pub fn not(self, vm: &VirtualMachine) -> PyResult<bool> {
112+
self.is_true(vm).map(|x| !x)
113+
}
114+
115+
// type protocol
116+
// PyObject *PyObject_Type(PyObject *o)
117+
118+
// int PyObject_TypeCheck(PyObject *o, PyTypeObject *type)
119+
120+
pub fn length(&self, vm: &VirtualMachine) -> PyResult<usize> {
121+
vm.obj_len(self)
122+
}
123+
124+
pub fn length_hint(
125+
self,
126+
defaultvalue: Option<usize>,
127+
vm: &VirtualMachine,
128+
) -> PyResult<Option<usize>> {
129+
Ok(vm.length_hint(self)?.or(defaultvalue))
130+
}
131+
132+
// item protocol
133+
// PyObject *PyObject_GetItem(PyObject *o, PyObject *key)
134+
// int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
135+
// int PyObject_DelItem(PyObject *o, PyObject *key)
136+
137+
// PyObject *PyObject_Dir(PyObject *o)
138+
139+
/// Takes an object and returns an iterator for it.
140+
/// This is typically a new iterator but if the argument is an iterator, this
141+
/// returns itself.
142+
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
143+
// PyObject_GetIter
144+
PyIter::try_from_object(vm, self)
145+
}
146+
147+
// PyObject *PyObject_GetAIter(PyObject *o)
148+
}

vm/src/types/slot.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,8 @@ where
502502
fn slot_hash(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<PyHash> {
503503
Err(vm.new_type_error(format!("unhashable type: '{}'", zelf.class().name())))
504504
}
505+
506+
#[cold]
505507
fn hash(_zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyHash> {
506508
unreachable!("slot_hash is implemented for unhashable types");
507509
}

0 commit comments

Comments
 (0)