Add `py` prefix to the proc macros and move them into the root module
This is important because `proc_macro_path_invoc` isn't going to be stabilized soon.
This commit is contained in:
parent
562d417517
commit
4013d40897
|
@ -74,12 +74,12 @@ features = ["extension-module"]
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::modinit;
|
use pyo3::pymodinit;
|
||||||
|
|
||||||
// Add bindings to the generated python module
|
// Add bindings to the generated python module
|
||||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||||
/// This module is implemented in Rust.
|
/// This module is implemented in Rust.
|
||||||
#[modinit(rust2py)]
|
#[pymodinit(rust2py)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
#[pyfn(m, "sum_as_string")]
|
#[pyfn(m, "sum_as_string")]
|
||||||
|
@ -97,7 +97,6 @@ fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
fn sum_as_string(a:i64, b:i64) -> String {
|
fn sum_as_string(a:i64, b:i64) -> String {
|
||||||
format!("{}", a + b).to_string()
|
format!("{}", a + b).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||||
|
|
|
@ -6,18 +6,18 @@ extern crate pyo3;
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::{class, methods, modinit};
|
use pyo3::{pyclass, pymethods, pymodinit};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
#[class(dict)]
|
#[pyclass(dict)]
|
||||||
struct WordCounter {
|
struct WordCounter {
|
||||||
path: String,
|
path: String,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl WordCounter {
|
impl WordCounter {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject, path: String) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject, path: String) -> PyResult<()> {
|
||||||
|
@ -79,7 +79,7 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
||||||
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[modinit(_word_count)]
|
#[pymodinit(_word_count)]
|
||||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<WordCounter>()?;
|
m.add_class::<WordCounter>()?;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::io::prelude::*;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::modinit;
|
use pyo3::pymodinit;
|
||||||
|
|
||||||
fn matches(word: &str, search: &str) -> bool {
|
fn matches(word: &str, search: &str) -> bool {
|
||||||
let mut search = search.chars();
|
let mut search = search.chars();
|
||||||
|
@ -50,7 +50,7 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
||||||
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[modinit(_word_count)]
|
#[pymodinit(_word_count)]
|
||||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
#[pyfn(m, "search")]
|
#[pyfn(m, "search")]
|
||||||
fn search(py: Python, path: String, search: String) -> PyResult<i32> {
|
fn search(py: Python, path: String, search: String) -> PyResult<i32> {
|
||||||
|
|
|
@ -1,122 +1,87 @@
|
||||||
# Python Class
|
# Python Class
|
||||||
|
|
||||||
Python class generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) and
|
|
||||||
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) and [Const fn](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)
|
|
||||||
features, so you need to turn on `proc_macro` and `specialization` features:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#![feature(proc_macro, specialization)]
|
|
||||||
|
|
||||||
extern crate pyo3;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Define new class
|
## Define new class
|
||||||
|
|
||||||
To define python custom class, rust struct needs to be annotated with `#[class]` attribute.
|
To define python custom class, rust struct needs to be annotated with `#[pyclass]` attribute.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MyClass {
|
struct MyClass {
|
||||||
num: i32,
|
num: i32,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
token: PyToken,
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The above example generates the following implementations for `MyClass` struct
|
The above example generates implementations for `PyTypeInfo` and `PyTypeObject` for `MyClass`.
|
||||||
|
|
||||||
```rust,ignore
|
If the class has a `PyToken` attribute, implementations for `PyObjectWithToken`, `ToPyObject`, `IntoPyObject` and `ToPyPointer` are also generated. You can only get a `PyToken` instance through the `__new__` method.
|
||||||
impl PyTypeInfo for MyClass { ... }
|
|
||||||
impl PyTypeObject for MyClass { ... }
|
|
||||||
impl PyObjectWithToken for MyClass { ... }
|
|
||||||
impl ToPyObject for MyClass { ... }
|
|
||||||
impl IntoPyObject for MyClass { ... }
|
|
||||||
impl ToPyPointer for MyClass { ... }
|
|
||||||
```
|
|
||||||
|
|
||||||
Following implementations `PyObjectWithToken`, `ToPyObject`, `IntoPyObject`, `ToPyPointer`
|
## Customizing the class
|
||||||
are generated only if struct contains `PyToken` attribute.
|
|
||||||
|
|
||||||
`PyToken` instance available only in `py.init` method.
|
The `#[pyclass]` macro accepts following parameters:
|
||||||
|
|
||||||
TODO - continue
|
* `name=XXX` - Set the class name shown in python code. By default struct name is used as a class name.
|
||||||
|
|
||||||
## The `#[class]` macro
|
|
||||||
|
|
||||||
Python class generation is powered by [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html).
|
|
||||||
To define python custom class, rust struct needs to be annotated with `#[class]` attribute.
|
|
||||||
`class` macro accepts following parameters:
|
|
||||||
|
|
||||||
* `name=XXX` - customize class name visible to python code. By default struct name is used as
|
|
||||||
a class name.
|
|
||||||
* `freelist=XXX` - `freelist` parameter add support of free allocation list to custom class.
|
* `freelist=XXX` - `freelist` parameter add support of free allocation list to custom class.
|
||||||
The performance improvement applies to types that are often created and deleted in a row,
|
The performance improvement applies to types that are often created and deleted in a row,
|
||||||
so that they can benefit from a freelist. `XXX` is a number of items for free list.
|
so that they can benefit from a freelist. `XXX` is a number of items for free list.
|
||||||
* `gc` - adds support for python garbage collector. classes that build with `gc` parameter
|
* `gc` - Classes with the `gc` parameter
|
||||||
participate in python garbage collector. If custom class contains references to other
|
participate in python garbage collector. If a custom class contains references to other
|
||||||
python object that can be collector `PyGCProtocol` trait has to be implemented.
|
python object that can be collected, the `PyGCProtocol` trait has to be implemented.
|
||||||
* `weakref` - adds support for python weak references
|
* `weakref` - adds support for python weak references
|
||||||
* `base=BaseType` - use custom base class. BaseType is type which is
|
* `base=BaseType` - use a custom base class. The base BaseType must implement `PyTypeInfo`.
|
||||||
implements `PyTypeInfo` trait.
|
* `subclass` - Allows Python classes to inherit from this class
|
||||||
* `subclass` - adds subclass support so that Python classes can inherit from this class
|
* `dict` - adds `__dict__` support, the instances of this type have a dictionary containing instance variables. (Incomplete, see [#123](https://github.com/PyO3/pyo3/issues/123))
|
||||||
* `dict` - adds `__dict__` support, the instances of this type have a dictionary containing instance variables.
|
|
||||||
|
|
||||||
|
|
||||||
## Constructor
|
## Constructor
|
||||||
|
|
||||||
By default it is not possible to create instance of custom class from python code.
|
By default it is not possible to create an instance of a custom class from python code.
|
||||||
To declare constructor, you need to define class method and annotate it with `#[new]`
|
To declare a constructor, you need to define a class method and annotate it with `#[new]`
|
||||||
attribute. Only python `__new__` method can be specified, `__init__` is not available.
|
attribute. Only the python `__new__` method can be specified, `__init__` is not available.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
#
|
#
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::class;
|
use pyo3::{pyclass, pymethods};
|
||||||
#
|
|
||||||
# #[class]
|
|
||||||
# struct MyClass {
|
|
||||||
# num: i32,
|
|
||||||
# debug: bool,
|
|
||||||
# token: PyToken,
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
use pyo3::py::methods;
|
|
||||||
|
|
||||||
#[methods]
|
#[pyclass]
|
||||||
|
struct MyClass {
|
||||||
|
num: i32,
|
||||||
|
token: PyToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
|
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject, num: Option<i32>) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject, num: i32) -> PyResult<()> {
|
||||||
obj.init(|token| {
|
obj.init(|token| {
|
||||||
MyClass {
|
MyClass {
|
||||||
num: num.unwrap_or(10),
|
num,
|
||||||
debug: false,
|
token
|
||||||
token: token
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Some rules of `new` method
|
Rules for the `new` method:
|
||||||
|
|
||||||
* If no method marked with `#[new]` is declared, object instances can only be created
|
* If no method marked with `#[new]` is declared, object instances can only be created
|
||||||
from Rust, but not from Python.
|
from Rust, but not from Python.
|
||||||
* The first parameter is the raw object, custom `new` method must initialize object
|
* The first parameter is the raw object and the custom `new` method must initialize the object
|
||||||
with value of struct using `init` method. Type of the object may be the type object of
|
with an instance of the struct using `init` method. The type of the object may be the type object of
|
||||||
a derived class declared in Python.
|
a derived class declared in Python.
|
||||||
* The first parameter implicitly has type `&PyRawObject`.
|
* The first parameter implicitly has type `&PyRawObject`.
|
||||||
* For details on `parameter-list`, see the documentation of `Method arguments` section.
|
* For details on `parameter-list`, see the documentation of `Method arguments` section.
|
||||||
* The return type must be `PyResult<T>` for some `T` that implements `IntoPyObject`.
|
* The return type must be `PyResult<T>` for some `T` that implements `IntoPyObject`. Usually, `T` will be `MyType`.
|
||||||
Usually, `T` will be `MyType`.
|
|
||||||
|
|
||||||
|
|
||||||
## Inheritance
|
## Inheritance
|
||||||
|
@ -130,15 +95,15 @@ with value of custom class struct. Subclass must call parent's `__new__` method.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
#
|
#
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct BaseClass {
|
struct BaseClass {
|
||||||
val1: usize,
|
val1: usize,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl BaseClass {
|
impl BaseClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -150,13 +115,13 @@ impl BaseClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(base=BaseClass)]
|
#[pyclass(base=BaseClass)]
|
||||||
struct SubClass {
|
struct SubClass {
|
||||||
val2: usize,
|
val2: usize,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl SubClass {
|
impl SubClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -177,21 +142,21 @@ base class.
|
||||||
## Object properties
|
## Object properties
|
||||||
|
|
||||||
Descriptor methods can be defined in
|
Descriptor methods can be defined in
|
||||||
`#[methods]` `impl` block only and has to be annotated with `#[getter]` or `[setter]`
|
`#[pymethods]` `impl` block only and has to be annotated with `#[getter]` or `[setter]`
|
||||||
attributes. i.e.
|
attributes. i.e.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
|
|
||||||
#[getter]
|
#[getter]
|
||||||
|
@ -212,14 +177,14 @@ rust's special keywords like `type`.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
|
|
||||||
#[getter]
|
#[getter]
|
||||||
|
@ -244,14 +209,14 @@ If parameter is specified, it is used and property name. i.e.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
|
|
||||||
#[getter(number)]
|
#[getter(number)]
|
||||||
|
@ -275,8 +240,8 @@ For simple cases you can also define getters and setters in your Rust struct fie
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MyClass {
|
struct MyClass {
|
||||||
#[prop(get, set)]
|
#[prop(get, set)]
|
||||||
num: i32
|
num: i32
|
||||||
|
@ -288,7 +253,7 @@ Then it is available from Python code as `self.num`.
|
||||||
## Instance methods
|
## Instance methods
|
||||||
|
|
||||||
To define python compatible method, `impl` block for struct has to be annotated
|
To define python compatible method, `impl` block for struct has to be annotated
|
||||||
with `#[methods]` attribute. `pyo3` library generates python compatible
|
with `#[pymethods]` attribute. `pyo3` library generates python compatible
|
||||||
wrappers for all functions in this block with some variations, like descriptors,
|
wrappers for all functions in this block with some variations, like descriptors,
|
||||||
class method static methods, etc.
|
class method static methods, etc.
|
||||||
|
|
||||||
|
@ -296,14 +261,14 @@ class method static methods, etc.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
|
|
||||||
fn method1(&self) -> PyResult<i32> {
|
fn method1(&self) -> PyResult<i32> {
|
||||||
|
@ -327,15 +292,15 @@ get injected by method wrapper. i.e
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# debug: bool,
|
# debug: bool,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
fn method2(&self, py: Python) -> PyResult<i32> {
|
fn method2(&self, py: Python) -> PyResult<i32> {
|
||||||
Ok(10)
|
Ok(10)
|
||||||
|
@ -354,15 +319,15 @@ with`#[classmethod]` attribute.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# debug: bool,
|
# debug: bool,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[classmethod]
|
#[classmethod]
|
||||||
fn cls_method(cls: &PyType) -> PyResult<i32> {
|
fn cls_method(cls: &PyType) -> PyResult<i32> {
|
||||||
|
@ -389,15 +354,15 @@ for some `T` that implements `IntoPyObject`.
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# debug: bool,
|
# debug: bool,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
fn static_method(param1: i32, param2: &str) -> PyResult<i32> {
|
fn static_method(param1: i32, param2: &str) -> PyResult<i32> {
|
||||||
|
@ -415,15 +380,15 @@ with `#[call]` attribute. Arguments of the method are specified same as for inst
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# debug: bool,
|
# debug: bool,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[call]
|
#[call]
|
||||||
#[args(args="*")]
|
#[args(args="*")]
|
||||||
|
@ -461,15 +426,15 @@ Example:
|
||||||
# #![feature(proc_macro, specialization)]
|
# #![feature(proc_macro, specialization)]
|
||||||
# extern crate pyo3;
|
# extern crate pyo3;
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::py::*;
|
# use pyo3::{pyclass, pymethods};
|
||||||
# #[class]
|
# #[pyclass]
|
||||||
# struct MyClass {
|
# struct MyClass {
|
||||||
# num: i32,
|
# num: i32,
|
||||||
# debug: bool,
|
# debug: bool,
|
||||||
# token: PyToken,
|
# token: PyToken,
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[args(arg1=true, args="*", arg2=10, kwargs="**")]
|
#[args(arg1=true, args="*", arg2=10, kwargs="**")]
|
||||||
fn method(&self, arg1: bool, args: &PyTuple, arg2: i32, kwargs: Option<&PyDict>) -> PyResult<i32> {
|
fn method(&self, arg1: bool, args: &PyTuple, arg2: i32, kwargs: Option<&PyDict>) -> PyResult<i32> {
|
||||||
|
@ -485,7 +450,7 @@ Python object model defines several protocols for different object behavior,
|
||||||
like sequence, mapping or number protocols. pyo3 library defines separate trait for each
|
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
|
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
|
for your struct. Important note, each protocol implementation block has to be annotated
|
||||||
with `#[proto]` attribute.
|
with `#[pyproto]` attribute.
|
||||||
|
|
||||||
### Basic object customization
|
### Basic object customization
|
||||||
|
|
||||||
|
@ -566,15 +531,15 @@ Example:
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::{class, proto};
|
use pyo3::{pyclass, pyproto};
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassWithGCSupport {
|
struct ClassWithGCSupport {
|
||||||
obj: Option<PyObject>,
|
obj: Option<PyObject>,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyGCProtocol for ClassWithGCSupport {
|
impl PyGCProtocol for ClassWithGCSupport {
|
||||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||||
if let Some(ref obj) = self.obj {
|
if let Some(ref obj) = self.obj {
|
||||||
|
@ -592,10 +557,10 @@ impl PyGCProtocol for ClassWithGCSupport {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Special protocol trait implementation has to be annotated with `#[proto]` attribute.
|
Special protocol trait implementation has to be annotated with `#[pyproto]` attribute.
|
||||||
|
|
||||||
It is also possible to enable gc for custom class using `gc` parameter for `class` annotation.
|
It is also possible to enable gc for custom class using `gc` parameter for `class` annotation.
|
||||||
i.e. `#[class(gc)]`. In that case instances of custom class participate in python garbage
|
i.e. `#[pyclass(gc)]`. In that case instances of custom class participate in python garbage
|
||||||
collector, and it is possible to track them with `gc` module methods.
|
collector, and it is possible to track them with `gc` module methods.
|
||||||
|
|
||||||
### Iterator Types
|
### Iterator Types
|
||||||
|
@ -609,20 +574,21 @@ It includes two methods `__iter__` and `__next__`:
|
||||||
Returning `Ok(None)` from `__next__` indicates that that there are no further items.
|
Returning `Ok(None)` from `__next__` indicates that that there are no further items.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#![feature(proc_macro, specialization)]
|
#![feature(proc_macro, specialization)]
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::*;
|
use pyo3::{pyclass, pyproto};
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MyIterator {
|
struct MyIterator {
|
||||||
iter: Box<Iterator<Item=PyObject> + Send>,
|
iter: Box<Iterator<Item=PyObject> + Send>,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyIterProtocol for MyIterator {
|
impl PyIterProtocol for MyIterator {
|
||||||
|
|
||||||
fn __iter__(&mut self) -> PyResult<PyObject> {
|
fn __iter__(&mut self) -> PyResult<PyObject> {
|
||||||
|
@ -632,5 +598,4 @@ impl PyIterProtocol for MyIterator {
|
||||||
Ok(self.iter.next())
|
Ok(self.iter.next())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# fn main() {}
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Debugging
|
# Debugging
|
||||||
|
|
||||||
Pyo3's attributes, `#[class]`, `#[modinit]`, etc. are [procedural macros](https://doc.rust-lang.org/unstable-book/language-features/proc-macro.html), which means that rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things:
|
Pyo3's attributes, `#[pyclass]`, `#[pymodinit]`, etc. are [procedural macros](https://doc.rust-lang.org/unstable-book/language-features/proc-macro.html), which means that rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo rustc -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs
|
cargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
(You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.)
|
(You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.)
|
||||||
|
@ -11,5 +11,7 @@ cargo rustc -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expa
|
||||||
You can also debug classic `!`-macros by adding -Z trace-macros`:
|
You can also debug classic `!`-macros by adding -Z trace-macros`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo rustc -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs
|
cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate version of those commands.
|
||||||
|
|
|
@ -9,10 +9,10 @@ One way is defining the function in the module definition.
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
use pyo3::{py, PyResult, Python, PyModule};
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::modint;
|
use pyo3::pymodinit;
|
||||||
|
|
||||||
#[modinit(rust2py)]
|
#[pymodinit(rust2py)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
// Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
// Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
||||||
|
@ -38,17 +38,16 @@ as third.
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
use pyo3::{py, PyResult, Python, PyModule};
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::function as pyfunction;
|
use pyo3::{pyfunction, pymodinit};
|
||||||
use pyo3::py::modint;
|
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn double(x: usize) -> usize {
|
fn double(x: usize) -> usize {
|
||||||
x * 2
|
x * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
#[modinit(module_with_functions)]
|
#[pymodinit(module_with_functions)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_function(wrap_function!(double)).unwrap();
|
m.add_function(wrap_function!(double)).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@ As shown in the Getting Started chapter, you can create a module as follows:
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
use pyo3::{py, PyResult, Python, PyModule};
|
use pyo3::{PyResult, Python, PyModule};
|
||||||
|
|
||||||
use pyo3::py::modint;
|
use pyo3::pymodinit;
|
||||||
|
|
||||||
// add bindings to the generated python module
|
// add bindings to the generated python module
|
||||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||||
/// This module is implemented in Rust.
|
/// This module is implemented in Rust.
|
||||||
#[modinit(rust2py)]
|
#[pymodinit(rust2py)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
// pyo3 aware function. All of our python interface could be declared in a separate module.
|
// pyo3 aware function. All of our python interface could be declared in a separate module.
|
||||||
|
@ -36,7 +36,7 @@ fn sum_as_string(a:i64, b:i64) -> String {
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `modinit` procedural macro attribute takes care of exporting the initialization function of your module to Python. It takes one argument as the name of your module, it must be the name of the `.so` or `.pyd` file.
|
The `#[pymodinit}` procedural macro attribute takes care of exporting the initialization function of your module to Python. It takes one argument as the name of your module, it must be the name of the `.so` or `.pyd` file.
|
||||||
|
|
||||||
The [Rust doc comments](https://doc.rust-lang.org/stable/book/first-edition/comments.html) of the module initialization function will be applied automatically as the Python doc string of your module.
|
The [Rust doc comments](https://doc.rust-lang.org/stable/book/first-edition/comments.html) of the module initialization function will be applied automatically as the Python doc string of your module.
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,12 @@ features = ["extension-module"]
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::modint;
|
use pyo3::pymodinit;
|
||||||
|
|
||||||
// Add bindings to the generated python module
|
// Add bindings to the generated python module
|
||||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||||
/// This module is implemented in Rust.
|
/// This module is implemented in Rust.
|
||||||
#[modinit(rust2py)]
|
#[pymodinit(rust2py)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
#[pyfn(m, "sum_as_string")]
|
#[pyfn(m, "sum_as_string")]
|
||||||
|
|
|
@ -28,7 +28,7 @@ Then in the Python bridge, we have a function `search` exposed to Python runtime
|
||||||
`Python::allow_threads` method to enable true parallelism:
|
`Python::allow_threads` method to enable true parallelism:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
#[modinit(_word_count)]
|
#[pymodinit(_word_count)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
|
|
||||||
#[pyfn(m, "search")]
|
#[pyfn(m, "search")]
|
||||||
|
|
|
@ -30,14 +30,14 @@ py_class!(class MyClass |py| {
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::{class, methods};
|
use pyo3::{pyclass, pymethods};
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MyClass {
|
struct MyClass {
|
||||||
num: u32,
|
num: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject, num: u32) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject, num: u32) -> PyResult<()> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pyo3-derive-backend"
|
name = "pyo3-derive-backend"
|
||||||
version = "0.2.5"
|
version = "0.3.0"
|
||||||
description = "Code generation for PyO3 package"
|
description = "Code generation for PyO3 package"
|
||||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||||
keywords = ["pyo3", "python", "cpython", "ffi"]
|
keywords = ["pyo3", "python", "cpython", "ffi"]
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds and takes care of the #[pyfn(...)] in #[modinit(...)]
|
/// Finds and takes care of the #[pyfn(...)] in #[pymodinit(...)]
|
||||||
pub fn process_functions_in_module(func: &mut syn::ItemFn) {
|
pub fn process_functions_in_module(func: &mut syn::ItemFn) {
|
||||||
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn build_py_class(class: &mut syn::ItemStruct, attr: &Vec<syn::Expr>) -> Tok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("#[class] can only be used with C-style structs")
|
panic!("#[pyclass] can only be used with C-style structs")
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_class(&class.ident, &base, token, doc, params, flags, descriptors)
|
impl_class(&class.ident, &base, token, doc, params, flags, descriptors)
|
||||||
|
|
|
@ -7,7 +7,7 @@ use py_method;
|
||||||
|
|
||||||
pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream {
|
pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream {
|
||||||
if ast.trait_.is_some() {
|
if ast.trait_.is_some() {
|
||||||
panic!("#[methods] can not be used only with trait impl block");
|
panic!("#[pymethods] can not be used only with trait impl block");
|
||||||
} else {
|
} else {
|
||||||
impl_methods(&ast.self_ty, &mut ast.items)
|
impl_methods(&ast.self_ty, &mut ast.items)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,12 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> TokenStream {
|
||||||
"PyBufferProtocol" => impl_proto_impl(ty, items, &defs::BUFFER),
|
"PyBufferProtocol" => impl_proto_impl(ty, items, &defs::BUFFER),
|
||||||
"PyGCProtocol" => impl_proto_impl(ty, items, &defs::GC),
|
"PyGCProtocol" => impl_proto_impl(ty, items, &defs::GC),
|
||||||
_ => {
|
_ => {
|
||||||
warn!("#[proto] can not be used with this block");
|
warn!("#[pyproto] can not be used with this block");
|
||||||
return TokenStream::new();
|
return TokenStream::new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("#[proto] can only be used with protocol trait implementations")
|
panic!("#[pyproto] can only be used with protocol trait implementations")
|
||||||
};
|
};
|
||||||
|
|
||||||
// attach lifetime
|
// attach lifetime
|
||||||
|
@ -42,7 +42,7 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> TokenStream {
|
||||||
|
|
||||||
tokens
|
tokens
|
||||||
} else {
|
} else {
|
||||||
panic!("#[proto] can only be used with protocol trait implementations")
|
panic!("#[pyproto] can only be used with protocol trait implementations")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn mod2init(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
// Parse the token stream into a syntax tree
|
// Parse the token stream into a syntax tree
|
||||||
let mut ast: syn::ItemFn = syn::parse(input).expect("#[modinit] must be used on a function");
|
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodinit] must be used on a function");
|
||||||
|
|
||||||
// Extract the mod name
|
// Extract the mod name
|
||||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||||
|
@ -47,7 +47,7 @@ pub fn mod3init(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
// Parse the token stream into a syntax tree
|
// Parse the token stream into a syntax tree
|
||||||
let mut ast: syn::ItemFn = syn::parse(input).expect("#[modinit] must be used on a `fn` block");
|
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodinit] must be used on a `fn` block");
|
||||||
|
|
||||||
// Extract the mod name
|
// Extract the mod name
|
||||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||||
|
@ -65,13 +65,13 @@ pub fn mod3init(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn proto(
|
pub fn pyproto(
|
||||||
_: proc_macro::TokenStream,
|
_: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
// Parse the token stream into a syntax tree
|
// Parse the token stream into a syntax tree
|
||||||
let mut ast: syn::ItemImpl =
|
let mut ast: syn::ItemImpl =
|
||||||
syn::parse(input).expect("#[proto] must be used on an `impl` block");
|
syn::parse(input).expect("#[pyproto] must be used on an `impl` block");
|
||||||
|
|
||||||
// Build the output
|
// Build the output
|
||||||
let expanded = py_proto::build_py_proto(&mut ast);
|
let expanded = py_proto::build_py_proto(&mut ast);
|
||||||
|
@ -83,12 +83,12 @@ pub fn proto(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn class(
|
pub fn pyclass(
|
||||||
attr: proc_macro::TokenStream,
|
attr: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
// Parse the token stream into a syntax tree
|
// Parse the token stream into a syntax tree
|
||||||
let mut ast: syn::ItemStruct = syn::parse(input).expect("#[class] must be used on a `struct`");
|
let mut ast: syn::ItemStruct = syn::parse(input).expect("#[pyclass] must be used on a `struct`");
|
||||||
|
|
||||||
// Parse the macro arguments into a list of expressions
|
// Parse the macro arguments into a list of expressions
|
||||||
let args: Vec<syn::Expr> = {
|
let args: Vec<syn::Expr> = {
|
||||||
|
@ -110,13 +110,13 @@ pub fn class(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn methods(
|
pub fn pymethods(
|
||||||
_: proc_macro::TokenStream,
|
_: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
// Parse the token stream into a syntax tree
|
// Parse the token stream into a syntax tree
|
||||||
let mut ast: syn::ItemImpl =
|
let mut ast: syn::ItemImpl =
|
||||||
syn::parse(input.clone()).expect("#[methods] must be used on an `impl` block");
|
syn::parse(input.clone()).expect("#[pymethods] must be used on an `impl` block");
|
||||||
|
|
||||||
// Build the output
|
// Build the output
|
||||||
let expanded = py_impl::build_py_methods(&mut ast);
|
let expanded = py_impl::build_py_methods(&mut ast);
|
||||||
|
@ -128,7 +128,7 @@ pub fn methods(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn function(
|
pub fn pyfunction(
|
||||||
_: proc_macro::TokenStream,
|
_: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ffi;
|
||||||
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
||||||
|
|
||||||
/// `PyMethodDefType` represents different types of python callable objects.
|
/// `PyMethodDefType` represents different types of python callable objects.
|
||||||
/// It is used by `#[methods]` and `#[proto]` annotations.
|
/// It is used by `#[pymethods]` and `#[pyproto]` annotations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PyMethodDefType {
|
pub enum PyMethodDefType {
|
||||||
/// Represents class `__new__` method
|
/// Represents class `__new__` method
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub use self::methods::{PyMethodDef, PyMethodDefType, PyMethodType,
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
|
|
||||||
|
/// Operators for the __richcmp__ method
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CompareOp {
|
pub enum CompareOp {
|
||||||
Lt = ffi::Py_LT as isize,
|
Lt = ffi::Py_LT as isize,
|
||||||
|
|
90
src/lib.rs
90
src/lib.rs
|
@ -29,22 +29,21 @@
|
||||||
//! # Example
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
//! #![feature(proc_macro, specialization)]
|
||||||
|
//!
|
||||||
//! extern crate pyo3;
|
//! extern crate pyo3;
|
||||||
//!
|
//!
|
||||||
//! use pyo3::{Python, PyDict, PyResult, ObjectProtocol};
|
//! use pyo3::prelude::*;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() -> PyResult<()> {
|
||||||
//! let gil = Python::acquire_gil();
|
//! let gil = Python::acquire_gil();
|
||||||
//! hello(gil.python()).unwrap();
|
//! let py = gil.python();
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn hello(py: Python) -> PyResult<()> {
|
|
||||||
//! let sys = py.import("sys")?;
|
//! let sys = py.import("sys")?;
|
||||||
//! let version: String = sys.get("version")?.extract()?;
|
//! let version: String = sys.get("version")?.extract()?;
|
||||||
//!
|
//!
|
||||||
//! let locals = PyDict::new(py);
|
//! let locals = PyDict::new(py);
|
||||||
//! locals.set_item("os", py.import("os")?)?;
|
//! locals.set_item("os", py.import("os")?)?;
|
||||||
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(locals))?.extract()?;
|
//! let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract()?;
|
||||||
//!
|
//!
|
||||||
//! println!("Hello {}, I'm Python {}", user, version);
|
//! println!("Hello {}, I'm Python {}", user, version);
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
|
@ -54,10 +53,10 @@
|
||||||
//! # Python extension
|
//! # Python extension
|
||||||
//!
|
//!
|
||||||
//! To allow Python to load the rust code as a Python extension
|
//! To allow Python to load the rust code as a Python extension
|
||||||
//! module, you need provide initialization function and annotate it with `#[modinit(name)]`.
|
//! module, you need provide initialization function and annotate it with `#[pymodinit(name)]`.
|
||||||
//! `pymodinit` expands to an `extern "C"` function.
|
//! `pymodinit` expands to an `extern "C"` function.
|
||||||
//!
|
//!
|
||||||
//! Macro syntax: `#[modinit(name)]`
|
//! Macro syntax: `#[pymodinit(name)]`
|
||||||
//!
|
//!
|
||||||
//! 1. `name`: The module name as a Rust identifier
|
//! 1. `name`: The module name as a Rust identifier
|
||||||
//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`.
|
//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`.
|
||||||
|
@ -80,28 +79,30 @@
|
||||||
//! extern crate pyo3;
|
//! extern crate pyo3;
|
||||||
//! use pyo3::prelude::*;
|
//! use pyo3::prelude::*;
|
||||||
//!
|
//!
|
||||||
//! use pyo3::py::modinit;
|
//! use pyo3::pymodinit;
|
||||||
//!
|
//!
|
||||||
//! // add bindings to the generated python module
|
//! // Add bindings to the generated python module
|
||||||
//! // N.B: names: "libhello" must be the name of the `.so` or `.pyd` file
|
//! // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||||
|
//! /// This module is implemented in Rust.
|
||||||
|
//! #[pymodinit(rust2py)]
|
||||||
|
//! fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
//!
|
//!
|
||||||
//! /// Module documentation string
|
//! #[pyfn(m, "sum_as_string")]
|
||||||
//! #[modinit(hello)]
|
//! // ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||||
//! fn init_module(py: Python, m: &PyModule) -> PyResult<()> {
|
//! // and the Rust return value back into a Python object.
|
||||||
//!
|
//! fn sum_as_string_py(a:i64, b:i64) -> PyResult<String> {
|
||||||
//! // pyo3 aware function. All of our python interface could be declared
|
//! let out = sum_as_string(a, b);
|
||||||
//! // in a separate module.
|
//! Ok(out)
|
||||||
//! // Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
|
||||||
//! // Python objects to Rust values; and the Rust return value back into a Python object.
|
|
||||||
//! #[pyfn(m, "run_rust_func")]
|
|
||||||
//! fn run(name: &PyString) -> PyResult<()> {
|
|
||||||
//! println!("Rust says: Hello {} of Python!", name);
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
//! // The logic can be implemented as a normal rust function
|
||||||
|
//! fn sum_as_string(a:i64, b:i64) -> String {
|
||||||
|
//! format!("{}", a + b).to_string()
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
//! # fn main() {}
|
//! # fn main() {}
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -113,29 +114,19 @@
|
||||||
//! features = ["extension-module"]
|
//! features = ["extension-module"]
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The full example project can be found at:
|
//! On windows and linux, you can build normally with `cargo build --release`. On Mac Os, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
|
||||||
//! <https://github.com/PyO3/setuptools-rust/tree/master/example/>
|
|
||||||
//!
|
//!
|
||||||
//! Rust will compile the code into a file named `libhello.so`, but we have to
|
//! ```toml
|
||||||
//! rename the file in order to use it with Python:
|
//! [target.x86_64-apple-darwin]
|
||||||
//!
|
//! rustflags = [
|
||||||
//! ```bash
|
//! "-C", "link-arg=-undefined",
|
||||||
//! cp ./target/debug/libhello.so ./hello.so
|
//! "-C", "link-arg=dynamic_lookup",
|
||||||
|
//! ]
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! (Note: on macOS you will have to rename `libhello.dynlib` to `libhello.so`.
|
//! Also on macOS, you will need to rename the output from \*.dylib to \*.so. On Windows, you will need to rename the output from \*.dll to \*.pyd.
|
||||||
//! To build on macOS, use `-C link-arg=-undefined -C link-arg=dynamic_lookup`
|
|
||||||
//! is required to build the library.
|
|
||||||
//! `setuptools-rust` includes this by default.
|
|
||||||
//! See [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count).)
|
|
||||||
//!
|
//!
|
||||||
//! The extension module can then be imported into Python:
|
//! [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) can be used to generate a python package and includes the commands above by default. See [examples/word-count](examples/word-count) and the associated setup.py.
|
||||||
//!
|
|
||||||
//! ```python,ignore
|
|
||||||
//! >>> import hello
|
|
||||||
//! >>> hello.run_rust_func("test")
|
|
||||||
//! Rust says: Hello Python!
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate spin;
|
extern crate spin;
|
||||||
|
@ -172,16 +163,13 @@ pub use conversion::{FromPyObject, PyTryFrom, PyTryInto,
|
||||||
pub mod class;
|
pub mod class;
|
||||||
pub use class::*;
|
pub use class::*;
|
||||||
|
|
||||||
/// Procedural macros
|
pub use pyo3cls::{pyproto, pyclass, pymethods, pyfunction};
|
||||||
pub mod py {
|
|
||||||
pub use pyo3cls::{proto, class, methods, function};
|
|
||||||
|
|
||||||
#[cfg(Py_3)]
|
#[cfg(Py_3)]
|
||||||
pub use pyo3cls::mod3init as modinit;
|
pub use pyo3cls::mod3init as pymodinit;
|
||||||
|
|
||||||
#[cfg(not(Py_3))]
|
#[cfg(not(Py_3))]
|
||||||
pub use pyo3cls::mod2init as modinit;
|
pub use pyo3cls::mod2init as pymodinit;
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs a `&'static CStr` literal.
|
/// Constructs a `&'static CStr` literal.
|
||||||
macro_rules! cstr {
|
macro_rules! cstr {
|
||||||
|
|
|
@ -169,7 +169,7 @@ impl PyModule {
|
||||||
|
|
||||||
/// Adds a function to a module, using the functions __name__ as name.
|
/// Adds a function to a module, using the functions __name__ as name.
|
||||||
///
|
///
|
||||||
/// Use this together with the`#[function]` and [wrap_function!] macro.
|
/// Use this together with the`#[pyfunction]` and [wrap_function!] macro.
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// m.add_function(wrap_function!(double));
|
/// m.add_function(wrap_function!(double));
|
||||||
|
@ -178,7 +178,7 @@ impl PyModule {
|
||||||
/// You can also add a function with a custom name using [add](PyModule::add):
|
/// You can also add a function with a custom name using [add](PyModule::add):
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// m.add("also_double", wrap_function!(double)(py));
|
/// m.add("also_double", wrap_function!(double)(py));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_function(&self, wrapper: &Fn(Python) -> PyObject) -> PyResult<()> {
|
pub fn add_function(&self, wrapper: &Fn(Python) -> PyObject) -> PyResult<()> {
|
||||||
let function = wrapper(self.py());
|
let function = wrapper(self.py());
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
//! use pyo3::prelude::*;
|
//! use pyo3::prelude::*;
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
pub use super::py;
|
|
||||||
pub use class::*;
|
pub use class::*;
|
||||||
pub use objects::*;
|
pub use objects::*;
|
||||||
pub use objectprotocol::ObjectProtocol;
|
pub use objectprotocol::ObjectProtocol;
|
||||||
|
|
|
@ -27,7 +27,7 @@ static START_PYO3: sync::Once = sync::ONCE_INIT;
|
||||||
/// thread (the thread which originally initialized Python) also initializes
|
/// thread (the thread which originally initialized Python) also initializes
|
||||||
/// threading.
|
/// threading.
|
||||||
///
|
///
|
||||||
/// When writing an extension module, the `#[modinit(..)]` macro
|
/// When writing an extension module, the `#[pymodinit(..)]` macro
|
||||||
/// will ensure that Python threading is initialized.
|
/// will ensure that Python threading is initialized.
|
||||||
///
|
///
|
||||||
pub fn prepare_freethreaded_python() {
|
pub fn prepare_freethreaded_python() {
|
||||||
|
|
|
@ -103,15 +103,14 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
||||||
///
|
///
|
||||||
/// Example of custom class implementation with `__new__` method:
|
/// Example of custom class implementation with `__new__` method:
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// use pyo3::py::class;
|
/// use pyo3::{pyclass, pymethods};
|
||||||
/// use pyo3::py::methods;
|
|
||||||
///
|
///
|
||||||
/// #[class]
|
/// #[pyclass]
|
||||||
/// struct MyClass {
|
/// struct MyClass {
|
||||||
/// token: PyToken
|
/// token: PyToken
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[methods]
|
/// #[pymethods]
|
||||||
/// impl MyClass {
|
/// impl MyClass {
|
||||||
/// #[new]
|
/// #[new]
|
||||||
/// fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
/// fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -212,7 +211,7 @@ impl PyObjectWithToken for PyRawObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Python object allocator that is usable as a base type for #[class]
|
/// A Python object allocator that is usable as a base type for #[pyclass]
|
||||||
pub trait PyObjectAlloc<T> {
|
pub trait PyObjectAlloc<T> {
|
||||||
|
|
||||||
/// Allocates a new object (usually by calling ty->tp_alloc),
|
/// Allocates a new object (usually by calling ty->tp_alloc),
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::{class, proto};
|
use pyo3::{pyclass, pyproto};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct UnaryArithmetic {
|
struct UnaryArithmetic {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyNumberProtocol for UnaryArithmetic {
|
impl PyNumberProtocol for UnaryArithmetic {
|
||||||
fn __neg__(&self) -> PyResult<&'static str> {
|
fn __neg__(&self) -> PyResult<&'static str> {
|
||||||
Ok("neg")
|
Ok("neg")
|
||||||
|
@ -44,32 +44,32 @@ fn unary_arithmetic() {
|
||||||
py_run!(py, c, "assert ~c == 'invert'");
|
py_run!(py, c, "assert ~c == 'invert'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct BinaryArithmetic {
|
struct BinaryArithmetic {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyObjectProtocol for BinaryArithmetic {
|
impl PyObjectProtocol for BinaryArithmetic {
|
||||||
fn __repr__(&self) -> PyResult<&'static str> {
|
fn __repr__(&self) -> PyResult<&'static str> {
|
||||||
Ok("BA")
|
Ok("BA")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct InPlaceOperations {
|
struct InPlaceOperations {
|
||||||
value: u32,
|
value: u32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyObjectProtocol for InPlaceOperations {
|
impl PyObjectProtocol for InPlaceOperations {
|
||||||
fn __repr__(&self) -> PyResult<String> {
|
fn __repr__(&self) -> PyResult<String> {
|
||||||
Ok(format!("IPO({:?})", self.value))
|
Ok(format!("IPO({:?})", self.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyNumberProtocol for InPlaceOperations {
|
impl PyNumberProtocol for InPlaceOperations {
|
||||||
fn __iadd__(&mut self, other: u32) -> PyResult<()> {
|
fn __iadd__(&mut self, other: u32) -> PyResult<()> {
|
||||||
self.value += other;
|
self.value += other;
|
||||||
|
@ -132,7 +132,7 @@ fn inplace_operations() {
|
||||||
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyNumberProtocol for BinaryArithmetic {
|
impl PyNumberProtocol for BinaryArithmetic {
|
||||||
fn __add__(lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult<String> {
|
fn __add__(lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult<String> {
|
||||||
Ok(format!("{:?} + {:?}", lhs, rhs))
|
Ok(format!("{:?} + {:?}", lhs, rhs))
|
||||||
|
@ -193,12 +193,12 @@ fn binary_arithmetic() {
|
||||||
py_run!(py, c, "assert 1 | c == '1 | BA'");
|
py_run!(py, c, "assert 1 | c == '1 | BA'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct RichComparisons {
|
struct RichComparisons {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyObjectProtocol for RichComparisons {
|
impl PyObjectProtocol for RichComparisons {
|
||||||
fn __repr__(&self) -> PyResult<&'static str> {
|
fn __repr__(&self) -> PyResult<&'static str> {
|
||||||
Ok("RC")
|
Ok("RC")
|
||||||
|
@ -216,12 +216,12 @@ impl PyObjectProtocol for RichComparisons {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct RichComparisons2 {
|
struct RichComparisons2 {
|
||||||
py: PyToken,
|
py: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyObjectProtocol for RichComparisons2 {
|
impl PyObjectProtocol for RichComparisons2 {
|
||||||
fn __repr__(&self) -> PyResult<&'static str> {
|
fn __repr__(&self) -> PyResult<&'static str> {
|
||||||
Ok("RC2")
|
Ok("RC2")
|
||||||
|
|
|
@ -8,16 +8,16 @@ use std::ptr;
|
||||||
use pyo3::ffi;
|
use pyo3::ffi;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::proto;
|
use pyo3::pyproto;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct TestClass {
|
struct TestClass {
|
||||||
vec: Vec<u8>,
|
vec: Vec<u8>,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyBufferProtocol for TestClass {
|
impl PyBufferProtocol for TestClass {
|
||||||
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
||||||
if view.is_null() {
|
if view.is_null() {
|
||||||
|
|
|
@ -4,12 +4,12 @@ extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct EmptyClass {}
|
struct EmptyClass {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -27,7 +27,7 @@ fn empty_class() {
|
||||||
///Line2
|
///Line2
|
||||||
/// Line3
|
/// Line3
|
||||||
// this is not doc string
|
// this is not doc string
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassWithDocs {}
|
struct ClassWithDocs {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -44,7 +44,7 @@ fn class_with_docstr() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(name=CustomName)]
|
#[pyclass(name=CustomName)]
|
||||||
struct EmptyClass2 {}
|
struct EmptyClass2 {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -55,7 +55,7 @@ fn custom_class_name() {
|
||||||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct EmptyClassInModule {}
|
struct EmptyClassInModule {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -4,15 +4,15 @@ extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct EmptyClassWithNew {
|
struct EmptyClassWithNew {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl EmptyClassWithNew {
|
impl EmptyClassWithNew {
|
||||||
#[__new__]
|
#[__new__]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -34,13 +34,13 @@ fn empty_class_with_new() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct NewWithOneArg {
|
struct NewWithOneArg {
|
||||||
_data: i32,
|
_data: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl NewWithOneArg {
|
impl NewWithOneArg {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject, arg: i32) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject, arg: i32) -> PyResult<()> {
|
||||||
|
@ -61,7 +61,7 @@ fn new_with_one_arg() {
|
||||||
assert_eq!(obj._data, 42);
|
assert_eq!(obj._data, 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct NewWithTwoArgs {
|
struct NewWithTwoArgs {
|
||||||
_data1: i32,
|
_data1: i32,
|
||||||
_data2: i32,
|
_data2: i32,
|
||||||
|
@ -69,7 +69,7 @@ struct NewWithTwoArgs {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl NewWithTwoArgs {
|
impl NewWithTwoArgs {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject, arg1: i32, arg2: i32) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject, arg1: i32, arg2: i32) -> PyResult<()> {
|
||||||
|
|
|
@ -6,20 +6,20 @@ use pyo3::ffi;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use std::{isize, iter};
|
use std::{isize, iter};
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
use pyo3::py::proto;
|
use pyo3::pyproto;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
pub struct Len {
|
pub struct Len {
|
||||||
l: usize,
|
l: usize,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyMappingProtocol for Len {
|
impl PyMappingProtocol for Len {
|
||||||
fn __len__(&self) -> PyResult<usize> {
|
fn __len__(&self) -> PyResult<usize> {
|
||||||
Ok(self.l)
|
Ok(self.l)
|
||||||
|
@ -45,13 +45,13 @@ fn len() {
|
||||||
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Iterator {
|
struct Iterator {
|
||||||
iter: Box<iter::Iterator<Item = i32> + Send>,
|
iter: Box<iter::Iterator<Item = i32> + Send>,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyIterProtocol for Iterator {
|
impl PyIterProtocol for Iterator {
|
||||||
fn __iter__(&mut self) -> PyResult<Py<Iterator>> {
|
fn __iter__(&mut self) -> PyResult<Py<Iterator>> {
|
||||||
Ok(self.into())
|
Ok(self.into())
|
||||||
|
@ -75,12 +75,12 @@ fn iterator() {
|
||||||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct StringMethods {
|
struct StringMethods {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
||||||
fn __str__(&self) -> PyResult<&'static str> {
|
fn __str__(&self) -> PyResult<&'static str> {
|
||||||
Ok("str")
|
Ok("str")
|
||||||
|
@ -129,13 +129,13 @@ fn string_methods() {
|
||||||
py_assert!(py, obj, "'{0:x}'.format(obj) == 'format(x)'");
|
py_assert!(py, obj, "'{0:x}'.format(obj) == 'format(x)'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Comparisons {
|
struct Comparisons {
|
||||||
val: i32,
|
val: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyObjectProtocol for Comparisons {
|
impl PyObjectProtocol for Comparisons {
|
||||||
fn __hash__(&self) -> PyResult<isize> {
|
fn __hash__(&self) -> PyResult<isize> {
|
||||||
Ok(self.val as isize)
|
Ok(self.val as isize)
|
||||||
|
@ -162,12 +162,12 @@ fn comparisons() {
|
||||||
py_assert!(py, zero, "not zero");
|
py_assert!(py, zero, "not zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Sequence {
|
struct Sequence {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PySequenceProtocol for Sequence {
|
impl PySequenceProtocol for Sequence {
|
||||||
fn __len__(&self) -> PyResult<usize> {
|
fn __len__(&self) -> PyResult<usize> {
|
||||||
Ok(5)
|
Ok(5)
|
||||||
|
@ -191,12 +191,12 @@ fn sequence() {
|
||||||
py_expect_exception!(py, c, "c['abc']", TypeError);
|
py_expect_exception!(py, c, "c['abc']", TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Callable {
|
struct Callable {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl Callable {
|
impl Callable {
|
||||||
#[__call__]
|
#[__call__]
|
||||||
fn __call__(&self, arg: i32) -> PyResult<i32> {
|
fn __call__(&self, arg: i32) -> PyResult<i32> {
|
||||||
|
@ -217,14 +217,14 @@ fn callable() {
|
||||||
py_assert!(py, nc, "not callable(nc)");
|
py_assert!(py, nc, "not callable(nc)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct SetItem {
|
struct SetItem {
|
||||||
key: i32,
|
key: i32,
|
||||||
val: i32,
|
val: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyMappingProtocol<'a> for SetItem {
|
impl PyMappingProtocol<'a> for SetItem {
|
||||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||||
self.key = key;
|
self.key = key;
|
||||||
|
@ -250,13 +250,13 @@ fn setitem() {
|
||||||
py_expect_exception!(py, c, "del c[1]", NotImplementedError);
|
py_expect_exception!(py, c, "del c[1]", NotImplementedError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct DelItem {
|
struct DelItem {
|
||||||
key: i32,
|
key: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyMappingProtocol<'a> for DelItem {
|
impl PyMappingProtocol<'a> for DelItem {
|
||||||
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
||||||
self.key = key;
|
self.key = key;
|
||||||
|
@ -275,13 +275,13 @@ fn delitem() {
|
||||||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct SetDelItem {
|
struct SetDelItem {
|
||||||
val: Option<i32>,
|
val: Option<i32>,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyMappingProtocol for SetDelItem {
|
impl PyMappingProtocol for SetDelItem {
|
||||||
fn __setitem__(&mut self, _key: i32, val: i32) -> PyResult<()> {
|
fn __setitem__(&mut self, _key: i32, val: i32) -> PyResult<()> {
|
||||||
self.val = Some(val);
|
self.val = Some(val);
|
||||||
|
@ -310,12 +310,12 @@ fn setdelitem() {
|
||||||
assert_eq!(c.val, None);
|
assert_eq!(c.val, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Reversed {
|
struct Reversed {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyMappingProtocol for Reversed {
|
impl PyMappingProtocol for Reversed {
|
||||||
fn __reversed__(&self) -> PyResult<&'static str> {
|
fn __reversed__(&self) -> PyResult<&'static str> {
|
||||||
Ok("I am reversed")
|
Ok("I am reversed")
|
||||||
|
@ -331,12 +331,12 @@ fn reversed() {
|
||||||
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Contains {
|
struct Contains {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PySequenceProtocol for Contains {
|
impl PySequenceProtocol for Contains {
|
||||||
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
||||||
Ok(item >= 0)
|
Ok(item >= 0)
|
||||||
|
@ -354,13 +354,13 @@ fn contains() {
|
||||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", TypeError);
|
py_expect_exception!(py, c, "assert 'wrong type' not in c", TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ContextManager {
|
struct ContextManager {
|
||||||
exit_called: bool,
|
exit_called: bool,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl<'p> PyContextProtocol<'p> for ContextManager {
|
impl<'p> PyContextProtocol<'p> for ContextManager {
|
||||||
fn __enter__(&mut self) -> PyResult<i32> {
|
fn __enter__(&mut self) -> PyResult<i32> {
|
||||||
Ok(42)
|
Ok(42)
|
||||||
|
@ -421,12 +421,12 @@ fn test_basics() {
|
||||||
assert_eq!(5, indices.slicelength);
|
assert_eq!(5, indices.slicelength);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct Test {
|
struct Test {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl<'p> PyMappingProtocol<'p> for Test {
|
impl<'p> PyMappingProtocol<'p> for Test {
|
||||||
fn __getitem__(&self, idx: &PyObjectRef) -> PyResult<PyObject> {
|
fn __getitem__(&self, idx: &PyObjectRef) -> PyResult<PyObject> {
|
||||||
if let Ok(slice) = idx.cast_as::<PySlice>() {
|
if let Ok(slice) = idx.cast_as::<PySlice>() {
|
||||||
|
@ -457,7 +457,7 @@ fn test_cls_impl() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(dict)]
|
#[pyclass(dict)]
|
||||||
struct DunderDictSupport {
|
struct DunderDictSupport {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ fn dunder_dict_support() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(weakref, dict)]
|
#[pyclass(weakref, dict)]
|
||||||
struct WeakRefDunderDictSupport {
|
struct WeakRefDunderDictSupport {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,14 @@ use std::cell::RefCell;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
use pyo3::py::proto;
|
use pyo3::pyproto;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class(freelist = 2)]
|
#[pyclass(freelist = 2)]
|
||||||
struct ClassWithFreelist {
|
struct ClassWithFreelist {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ impl Drop for TestDropCall {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct DataIsDropped {
|
struct DataIsDropped {
|
||||||
member1: TestDropCall,
|
member1: TestDropCall,
|
||||||
member2: TestDropCall,
|
member2: TestDropCall,
|
||||||
|
@ -89,7 +89,7 @@ fn data_is_dropped() {
|
||||||
assert!(drop_called2.load(Ordering::Relaxed));
|
assert!(drop_called2.load(Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassWithDrop {
|
struct ClassWithDrop {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
@ -136,14 +136,14 @@ fn create_pointers_in_drop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct GCIntegration {
|
struct GCIntegration {
|
||||||
self_ref: RefCell<PyObject>,
|
self_ref: RefCell<PyObject>,
|
||||||
dropped: TestDropCall,
|
dropped: TestDropCall,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proto]
|
#[pyproto]
|
||||||
impl PyGCProtocol for GCIntegration {
|
impl PyGCProtocol for GCIntegration {
|
||||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||||
visit.call(&*self.self_ref.borrow())
|
visit.call(&*self.self_ref.borrow())
|
||||||
|
@ -178,7 +178,7 @@ fn gc_integration() {
|
||||||
assert!(drop_called.load(Ordering::Relaxed));
|
assert!(drop_called.load(Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(gc)]
|
#[pyclass(gc)]
|
||||||
struct GCIntegration2 {
|
struct GCIntegration2 {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ fn gc_integration2() {
|
||||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(weakref)]
|
#[pyclass(weakref)]
|
||||||
struct WeakRefSupport {
|
struct WeakRefSupport {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
@ -206,13 +206,13 @@ fn weakref_support() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct BaseClassWithDrop {
|
struct BaseClassWithDrop {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
data: Option<Arc<AtomicBool>>,
|
data: Option<Arc<AtomicBool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl BaseClassWithDrop {
|
impl BaseClassWithDrop {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -231,13 +231,13 @@ impl Drop for BaseClassWithDrop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(base=BaseClassWithDrop)]
|
#[pyclass(base=BaseClassWithDrop)]
|
||||||
struct SubClassWithDrop {
|
struct SubClassWithDrop {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
data: Option<Arc<AtomicBool>>,
|
data: Option<Arc<AtomicBool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl SubClassWithDrop {
|
impl SubClassWithDrop {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
|
|
@ -5,19 +5,19 @@ extern crate pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use std::isize;
|
use std::isize;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassWithProperties {
|
struct ClassWithProperties {
|
||||||
num: i32,
|
num: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl ClassWithProperties {
|
impl ClassWithProperties {
|
||||||
fn get_num(&self) -> PyResult<i32> {
|
fn get_num(&self) -> PyResult<i32> {
|
||||||
Ok(self.num)
|
Ok(self.num)
|
||||||
|
@ -50,7 +50,7 @@ fn class_with_properties() {
|
||||||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct GetterSetter {
|
struct GetterSetter {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
#[prop(get, set)]
|
#[prop(get, set)]
|
||||||
|
@ -59,7 +59,7 @@ struct GetterSetter {
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl GetterSetter {
|
impl GetterSetter {
|
||||||
fn get_num2(&self) -> PyResult<i32> {
|
fn get_num2(&self) -> PyResult<i32> {
|
||||||
Ok(self.num)
|
Ok(self.num)
|
||||||
|
|
|
@ -5,18 +5,18 @@ extern crate pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use std::isize;
|
use std::isize;
|
||||||
|
|
||||||
use pyo3::py::{class, methods};
|
use pyo3::{pyclass, pymethods};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct BaseClass {
|
struct BaseClass {
|
||||||
#[prop(get)]
|
#[prop(get)]
|
||||||
val1: usize,
|
val1: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(subclass)]
|
#[pyclass(subclass)]
|
||||||
struct SubclassAble {}
|
struct SubclassAble {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -35,7 +35,7 @@ fn subclass() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl BaseClass {
|
impl BaseClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -43,13 +43,13 @@ impl BaseClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class(base=BaseClass)]
|
#[pyclass(base=BaseClass)]
|
||||||
struct SubClass {
|
struct SubClass {
|
||||||
#[prop(get)]
|
#[prop(get)]
|
||||||
val2: usize,
|
val2: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl SubClass {
|
impl SubClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
|
|
@ -4,19 +4,19 @@ extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct InstanceMethod {
|
struct InstanceMethod {
|
||||||
member: i32,
|
member: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl InstanceMethod {
|
impl InstanceMethod {
|
||||||
/// Test method
|
/// Test method
|
||||||
fn method(&self) -> PyResult<i32> {
|
fn method(&self) -> PyResult<i32> {
|
||||||
|
@ -42,13 +42,13 @@ fn instance_method() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct InstanceMethodWithArgs {
|
struct InstanceMethodWithArgs {
|
||||||
member: i32,
|
member: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl InstanceMethodWithArgs {
|
impl InstanceMethodWithArgs {
|
||||||
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
||||||
Ok(self.member * multiplier)
|
Ok(self.member * multiplier)
|
||||||
|
@ -74,12 +74,12 @@ fn instance_method_with_args() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassMethod {
|
struct ClassMethod {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl ClassMethod {
|
impl ClassMethod {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -111,12 +111,12 @@ fn class_method() {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct ClassMethodWithArgs {
|
struct ClassMethodWithArgs {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl ClassMethodWithArgs {
|
impl ClassMethodWithArgs {
|
||||||
#[classmethod]
|
#[classmethod]
|
||||||
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
|
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
|
||||||
|
@ -139,12 +139,12 @@ fn class_method_with_args() {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct StaticMethod {
|
struct StaticMethod {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl StaticMethod {
|
impl StaticMethod {
|
||||||
#[new]
|
#[new]
|
||||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||||
|
@ -177,12 +177,12 @@ fn static_method() {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct StaticMethodWithArgs {
|
struct StaticMethodWithArgs {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl StaticMethodWithArgs {
|
impl StaticMethodWithArgs {
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
fn method(_py: Python, input: i32) -> PyResult<String> {
|
fn method(_py: Python, input: i32) -> PyResult<String> {
|
||||||
|
@ -204,12 +204,12 @@ fn static_method_with_args() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MethArgs {
|
struct MethArgs {
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MethArgs {
|
impl MethArgs {
|
||||||
#[args(test)]
|
#[args(test)]
|
||||||
fn get_optional(&self, test: Option<i32>) -> PyResult<i32> {
|
fn get_optional(&self, test: Option<i32>) -> PyResult<i32> {
|
||||||
|
|
|
@ -4,22 +4,22 @@
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py::{class, function, modinit};
|
use pyo3::{pyclass, pyfunction, pymodinit};
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct EmptyClass {}
|
struct EmptyClass {}
|
||||||
|
|
||||||
fn sum_as_string(a: i64, b: i64) -> String {
|
fn sum_as_string(a: i64, b: i64) -> String {
|
||||||
format!("{}", a + b).to_string()
|
format!("{}", a + b).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function]
|
#[pyfunction]
|
||||||
fn double(x: usize) -> usize {
|
fn double(x: usize) -> usize {
|
||||||
x * 2
|
x * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This module is implemented in Rust.
|
/// This module is implemented in Rust.
|
||||||
#[modinit(module_with_functions)]
|
#[pymodinit(module_with_functions)]
|
||||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
#[pyfn(m, "sum_as_string")]
|
#[pyfn(m, "sum_as_string")]
|
||||||
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> PyResult<String> {
|
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> PyResult<String> {
|
||||||
|
|
|
@ -5,19 +5,19 @@ extern crate pyo3;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use std::isize;
|
use std::isize;
|
||||||
|
|
||||||
use pyo3::py::class;
|
use pyo3::pyclass;
|
||||||
use pyo3::py::methods;
|
use pyo3::pymethods;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[class]
|
#[pyclass]
|
||||||
struct MutRefArg {
|
struct MutRefArg {
|
||||||
n: i32,
|
n: i32,
|
||||||
token: PyToken,
|
token: PyToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[methods]
|
#[pymethods]
|
||||||
impl MutRefArg {
|
impl MutRefArg {
|
||||||
fn get(&self) -> PyResult<i32> {
|
fn get(&self) -> PyResult<i32> {
|
||||||
Ok(self.n)
|
Ok(self.n)
|
||||||
|
|
Loading…
Reference in New Issue