more docs

This commit is contained in:
Nikolay Kim 2017-07-18 14:15:44 -07:00
parent 01d688fc98
commit c6067b90c1
3 changed files with 194 additions and 12 deletions

View File

@ -4,7 +4,7 @@ Python class generation is powered by unstable [Procedural Macros](https://doc.r
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) features, so you need to turn on `proc_macro` and `specialization` features:
```rust
#![feature(proc_macro, specialization, associated_consts)]
#![feature(proc_macro, specialization)]
extern crate pyo3;
```
@ -223,11 +223,7 @@ impl MyClass {
}
```
## Method arguments
## Class customizations
### Callable object
## Callable object
To specify custom `__call__` method for custom class, call method needs to be annotated
with `#[call]` attribute. Arguments of the method are speficied same as for instance method.
@ -243,3 +239,187 @@ impl MyClass {
Ok(self.num)
}
}
```
## Method arguments
By default pyo3 library uses function signature to determine which arguments are required.
Then it scans incoming `args` parameter and then incoming `kwargs` parameter. If it can not
find all required parameters, it raises `TypeError` exception.
It is possible to override default bahavior with `#[args(...)]` attribute. `args` attribute
accept comma separated list of parameters in form `attr_name="default value"`. Each parameter
has to match method parameter by name.
Each parameter could one of following type:
* "\*": var arguments separator, each parameter defined after "*" is keyword only paramters.
coresponds to python's `def meth(*, arg1.., arg2=..)`
* args="\*": "args" is var args, coresponds to python's `def meth(*args)`. Type of `args`
parameter has to be `&PyTuple`.
* kwargs="\*\*": "kwargs" is kwyword arguments, coresponds to python's `def meth(**kwargs)`.
Type of `kwargs` parameter has to be `Option<&PyDict>`.
* arg="Value": arguments with default value. coresponds to python's `def meth(arg=Value)`.
if `arg` argument is defined after var arguments it is treated as keyword argument.
Note that `Value` has to be valid rust code, pyo3 just inserts it into generated
code unmodified.
Example:
```rust
#[py::methods]
impl MyClass {
#[args(arg1=true, args="*", arg2=10, kwargs="**")]
fn method(&self, arg1: bool, args: &PyTuple, arg2: i32, kwargs: Option<&PyTuple>) -> PyResult<i32> {
Ok(1)
}
}
```
## Class customizations
Python object model defines several protocols for different object behavior,
like sequence, mapping or number protocols. pyo3 library defines separate trait for each
of them. To provide specific python object behavior you need to implement specific trait
for your struct. Important note, each protocol implementation block has to be annotated
with `#[py::proto]` attribute.
### Basic object customization
[`PyObjectProtocol`](https://pyo3.github.io/pyo3/pyo3/class/basic/trait.PyObjectProtocol.html) trait provide several basic customizations.
#### Attribute access
To customize object attribute access define following methods:
* `fn __getattr__(&self, name: FromPyObject) -> PyResult<impl IntoPyObject>`
* `fn __setattr__(&mut self, name: FromPyObject, value: FromPyObject) -> PyResult<()>`
* `fn __delattr__(&mut self, name: FromPyObject) -> PyResult<()>`
Each methods coresponds to python's `self.attr`, `self.attr = value` and `del self.attr` code.
#### String Conversions
* `fn __repr__(&self) -> PyResult<impl ToPyObject<ObjectType=PyString>>`
* `fn __str__(&self) -> PyResult<impl ToPyObject<ObjectType=PyString>>`
Possible return types for `__str__` and `__repr__` are `PyResult<String>` or `PyResult<PyString>`.
In Python 2.7, Unicode strings returned by `__str__` and `__repr__` will be converted to byte strings
by the Python runtime, which results in an exception if the string contains non-ASCII characters.
* `fn __bytes__(&self) -> PyResult<PyBytes>`
On Python 3.x, provides the conversion to `bytes`.
On Python 2.7, `__bytes__` is allowed but has no effect.
* `fn __unicode__(&self) -> PyResult<PyUnicode>`
On Python 2.7, provides the conversion to `unicode`.
On Python 3.x, `__unicode__` is allowed but has no effect.
* `fn __format__(&self, format_spec: &str) -> PyResult<impl ToPyObject<ObjectType=PyString>>`
Special method that is used by the `format()` builtin and the `str.format()` method.
Possible return types are `PyResult<String>` or `PyResult<PyString>`.
#### Comparison operators
* `fn __richcmp__(&self, other: impl FromPyObject, op: CompareOp) -> PyResult<impl ToPyObject>`
Overloads Python comparison operations (`==`, `!=`, `<`, `<=`, `>`, and `>=`).
The `op` argument indicates the comparison operation being performed.
The return type will normally be `PyResult<bool>`, but any Python object can be returned.
If `other` is not of the type specified in the signature, the generated code will
automatically `return NotImplemented`.
* `fn __hash__(&self) -> PyResult<impl PrimInt>`
Objects that compare equal must have the same hash value.
The return type must be `PyResult<T>` where `T` is one of Rust's primitive integer types.
#### Other methods
* `fn __bool__(&self) -> PyResult<bool>`
Determines the "truthyness" of the object.
This method works for both python 3 and python 2,
even on Python 2.7 where the Python spelling was `__nonzero__`.
### Garbage Collector Integration
If your type owns references to other python objects, you will need to
integrate with Python's garbage collector so that the GC is aware of
those references.
To do this, implement [`PyGCProtocol`](https://pyo3.github.io/pyo3/pyo3/class/gc/trait.PyGCProtocol.html) trait for your struct.
It includes two methods `__traverse__` and `__clear__`.
These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API.
`__traverse__` must call `visit.call()` for each reference to another python object.
`__clear__` must clear out any mutable references to other python objects
(thus breaking reference cycles). Immutable references do not have to be cleared,
as every cycle must contain at least one mutable reference.
Example:
```rust
#![feature(proc_macro, specialization)]
extern crate pyo3;
use pyo3::{py, PyObject, PyGCProtocol, PyVisit, PyTraverseError};
#[py::class]
struct ClassWithGCSupport {
obj: Option<PyObject>,
}
#[py::proto]
impl PyGCProtocol for ClassWithGCSupport {
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
if let Some(ref obj) = self.obj {
visit.call(obj)?
}
Ok(())
}
fn __clear__(&mut self) {
if let Some(obj) = self.obj.take() {
// Release reference, this decrements ref counter.
self.py().release(obj);
}
}
}
```
Special protocol trait implementation has to be annotated with `#[py::proto]` attribute.
### Iterator Types
Iterators can be defined using the
[`PyIterProtocol`](https://pyo3.github.io/pyo3/pyo3/class/iter/trait.PyIterProtocol.html) trait.
It includes two methods `__iter__` and `__next__`:
* `fn __iter__(&mut self) -> PyResult<impl IntoPyObject>`
* `fn __next__(&mut self) -> PyResult<Option<impl IntoPyObject>>`
Returning `Ok(None)` from `__next__` indicates that that there are no further items.
Example:
```rust
#![feature(proc_macro, specialization)]
extern crate pyo3;
use pyo3::{py, PyObject, PyResult, PyIterProtocol};
#[py::class]
struct MyIterator {
iter: Box<Iterator<Item=PyObject> + Send>
}
#[py::proto]
impl PyIterProtocol {
fn __iter__(&mut self) -> PyResult<PyObject> {
Ok(self.into())
}
fn __next__(&mut self) -> PyResult<Option<PyObject>> {
Ok(self.iter.next())
}
}
# fn main() {}
```

View File

@ -15,6 +15,9 @@ use callback::UnitCallbackConverter;
/// Buffer protocol interface
///
/// more information on buffer protocol can be found
/// https://docs.python.org/3/c-api/buffer.html
#[allow(unused_variables)]
pub trait PyBufferProtocol<'p> : PyTypeInfo + PyDowncastFrom
{

View File

@ -1,10 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! Python Iterator Interface
//! Python Iterator Interface.
//! Trait and support implementation for implementing iterators
//!
//! more information
//! https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter
use std::ptr;
@ -16,7 +12,10 @@ use conversion::IntoPyObject;
use callback::{CallbackConverter, PyObjectCallbackConverter};
/// Iterator protocol
/// Python Iterator Interface.
///
/// more information
/// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter
#[allow(unused_variables)]
pub trait PyIterProtocol<'p> : PyTypeInfo + PyDowncastFrom {
fn __iter__(&'p mut self)