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;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::modinit;
|
||||
use pyo3::pymodinit;
|
||||
|
||||
// Add bindings to the generated python module
|
||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||
/// This module is implemented in Rust.
|
||||
#[modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[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 {
|
||||
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:
|
||||
|
|
|
@ -6,18 +6,18 @@ extern crate pyo3;
|
|||
extern crate rayon;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::{class, methods, modinit};
|
||||
use pyo3::{pyclass, pymethods, pymodinit};
|
||||
use rayon::prelude::*;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
#[class(dict)]
|
||||
#[pyclass(dict)]
|
||||
struct WordCounter {
|
||||
path: String,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl WordCounter {
|
||||
#[new]
|
||||
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()
|
||||
}
|
||||
|
||||
#[modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<WordCounter>()?;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::io::prelude::*;
|
|||
use pyo3::prelude::*;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use pyo3::py::modinit;
|
||||
use pyo3::pymodinit;
|
||||
|
||||
fn matches(word: &str, search: &str) -> bool {
|
||||
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()
|
||||
}
|
||||
|
||||
#[modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "search")]
|
||||
fn search(py: Python, path: String, search: String) -> PyResult<i32> {
|
||||
|
|
|
@ -1,122 +1,87 @@
|
|||
# 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
|
||||
|
||||
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
|
||||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
use pyo3::py::class;
|
||||
use pyo3::pyclass;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
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
|
||||
impl PyTypeInfo for MyClass { ... }
|
||||
impl PyTypeObject for MyClass { ... }
|
||||
impl PyObjectWithToken for MyClass { ... }
|
||||
impl ToPyObject for MyClass { ... }
|
||||
impl IntoPyObject for MyClass { ... }
|
||||
impl ToPyPointer for MyClass { ... }
|
||||
```
|
||||
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.
|
||||
|
||||
Following implementations `PyObjectWithToken`, `ToPyObject`, `IntoPyObject`, `ToPyPointer`
|
||||
are generated only if struct contains `PyToken` attribute.
|
||||
## Customizing the class
|
||||
|
||||
`PyToken` instance available only in `py.init` method.
|
||||
The `#[pyclass]` macro accepts following parameters:
|
||||
|
||||
TODO - continue
|
||||
|
||||
## 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.
|
||||
* `name=XXX` - Set the class name shown in 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.
|
||||
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.
|
||||
* `gc` - adds support for python garbage collector. classes that build with `gc` parameter
|
||||
participate in python garbage collector. If custom class contains references to other
|
||||
python object that can be collector `PyGCProtocol` trait has to be implemented.
|
||||
* `gc` - Classes with the `gc` parameter
|
||||
participate in python garbage collector. If a custom class contains references to other
|
||||
python object that can be collected, the `PyGCProtocol` trait has to be implemented.
|
||||
* `weakref` - adds support for python weak references
|
||||
* `base=BaseType` - use custom base class. BaseType is type which is
|
||||
implements `PyTypeInfo` trait.
|
||||
* `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.
|
||||
* `base=BaseType` - use a custom base class. The base BaseType must implement `PyTypeInfo`.
|
||||
* `subclass` - Allows Python classes to 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))
|
||||
|
||||
|
||||
## Constructor
|
||||
|
||||
By default it is not possible to create instance of custom class from python code.
|
||||
To declare constructor, you need to define class method and annotate it with `#[new]`
|
||||
attribute. Only python `__new__` method can be specified, `__init__` is not available.
|
||||
By default it is not possible to create an instance of a custom class from python code.
|
||||
To declare a constructor, you need to define a class method and annotate it with `#[new]`
|
||||
attribute. Only the python `__new__` method can be specified, `__init__` is not available.
|
||||
|
||||
```rust
|
||||
# #![feature(proc_macro, specialization)]
|
||||
#
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::class;
|
||||
#
|
||||
# #[class]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
use pyo3::py::methods;
|
||||
use pyo3::{pyclass, pymethods};
|
||||
|
||||
#[methods]
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
num: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, num: Option<i32>) -> PyResult<()> {
|
||||
fn __new__(obj: &PyRawObject, num: i32) -> PyResult<()> {
|
||||
obj.init(|token| {
|
||||
MyClass {
|
||||
num: num.unwrap_or(10),
|
||||
debug: false,
|
||||
token: token
|
||||
num,
|
||||
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
|
||||
from Rust, but not from Python.
|
||||
* The first parameter is the raw object, custom `new` method must initialize object
|
||||
with value of struct using `init` method. Type of the object may be the type object of
|
||||
* The first parameter is the raw object and the custom `new` method must initialize the object
|
||||
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.
|
||||
* The first parameter implicitly has type `&PyRawObject`.
|
||||
* 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`.
|
||||
Usually, `T` will be `MyType`.
|
||||
* The return type must be `PyResult<T>` for some `T` that implements `IntoPyObject`. Usually, `T` will be `MyType`.
|
||||
|
||||
|
||||
## Inheritance
|
||||
|
@ -130,15 +95,15 @@ with value of custom class struct. Subclass must call parent's `__new__` method.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
#
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct BaseClass {
|
||||
val1: usize,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl BaseClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -150,13 +115,13 @@ impl BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
#[class(base=BaseClass)]
|
||||
#[pyclass(base=BaseClass)]
|
||||
struct SubClass {
|
||||
val2: usize,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl SubClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -177,21 +142,21 @@ base class.
|
|||
## Object properties
|
||||
|
||||
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.
|
||||
|
||||
```rust
|
||||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
|
||||
#[getter]
|
||||
|
@ -212,14 +177,14 @@ rust's special keywords like `type`.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
|
||||
#[getter]
|
||||
|
@ -244,14 +209,14 @@ If parameter is specified, it is used and property name. i.e.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
|
||||
#[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)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
#[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
#[prop(get, set)]
|
||||
num: i32
|
||||
|
@ -288,7 +253,7 @@ Then it is available from Python code as `self.num`.
|
|||
## Instance methods
|
||||
|
||||
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,
|
||||
class method static methods, etc.
|
||||
|
||||
|
@ -296,14 +261,14 @@ class method static methods, etc.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
|
||||
fn method1(&self) -> PyResult<i32> {
|
||||
|
@ -327,15 +292,15 @@ get injected by method wrapper. i.e
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
fn method2(&self, py: Python) -> PyResult<i32> {
|
||||
Ok(10)
|
||||
|
@ -354,15 +319,15 @@ with`#[classmethod]` attribute.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
#[classmethod]
|
||||
fn cls_method(cls: &PyType) -> PyResult<i32> {
|
||||
|
@ -389,15 +354,15 @@ for some `T` that implements `IntoPyObject`.
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
#[staticmethod]
|
||||
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)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
#[call]
|
||||
#[args(args="*")]
|
||||
|
@ -461,15 +426,15 @@ Example:
|
|||
# #![feature(proc_macro, specialization)]
|
||||
# extern crate pyo3;
|
||||
# use pyo3::prelude::*;
|
||||
# use pyo3::py::*;
|
||||
# #[class]
|
||||
# use pyo3::{pyclass, pymethods};
|
||||
# #[pyclass]
|
||||
# struct MyClass {
|
||||
# num: i32,
|
||||
# debug: bool,
|
||||
# token: PyToken,
|
||||
# }
|
||||
#
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
#[args(arg1=true, args="*", arg2=10, kwargs="**")]
|
||||
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
|
||||
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 `#[proto]` attribute.
|
||||
with `#[pyproto]` attribute.
|
||||
|
||||
### Basic object customization
|
||||
|
||||
|
@ -566,15 +531,15 @@ Example:
|
|||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::{class, proto};
|
||||
use pyo3::{pyclass, pyproto};
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassWithGCSupport {
|
||||
obj: Option<PyObject>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyGCProtocol for ClassWithGCSupport {
|
||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
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.
|
||||
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.
|
||||
|
||||
### 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.
|
||||
|
||||
Example:
|
||||
|
||||
```rust
|
||||
#![feature(proc_macro, specialization)]
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::*;
|
||||
use pyo3::{pyclass, pyproto};
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct MyIterator {
|
||||
iter: Box<Iterator<Item=PyObject> + Send>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyIterProtocol for MyIterator {
|
||||
|
||||
fn __iter__(&mut self) -> PyResult<PyObject> {
|
||||
|
@ -632,5 +598,4 @@ impl PyIterProtocol for MyIterator {
|
|||
Ok(self.iter.next())
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# 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
|
||||
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.)
|
||||
|
@ -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`:
|
||||
|
||||
```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)]
|
||||
|
||||
extern crate pyo3;
|
||||
use pyo3::{py, PyResult, Python, PyModule};
|
||||
use pyo3::py::modint;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::pymodinit;
|
||||
|
||||
#[modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
// Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
||||
|
@ -38,17 +38,16 @@ as third.
|
|||
|
||||
#[macro_use]
|
||||
extern crate pyo3;
|
||||
use pyo3::{py, PyResult, Python, PyModule};
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::function as pyfunction;
|
||||
use pyo3::py::modint;
|
||||
use pyo3::{pyfunction, pymodinit};
|
||||
|
||||
#[pyfunction]
|
||||
fn double(x: usize) -> usize {
|
||||
x * 2
|
||||
}
|
||||
|
||||
#[modinit(module_with_functions)]
|
||||
#[pymodinit(module_with_functions)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
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)]
|
||||
|
||||
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
|
||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||
/// This module is implemented in Rust.
|
||||
#[modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
// 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() {}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -64,12 +64,12 @@ features = ["extension-module"]
|
|||
extern crate pyo3;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::modint;
|
||||
use pyo3::pymodinit;
|
||||
|
||||
// Add bindings to the generated python module
|
||||
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
|
||||
/// This module is implemented in Rust.
|
||||
#[modinit(rust2py)]
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[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:
|
||||
|
||||
```rust,ignore
|
||||
#[modinit(_word_count)]
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "search")]
|
||||
|
|
|
@ -30,14 +30,14 @@ py_class!(class MyClass |py| {
|
|||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::{class, methods};
|
||||
use pyo3::{pyclass, pymethods};
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct MyClass {
|
||||
num: u32,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MyClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, num: u32) -> PyResult<()> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3-derive-backend"
|
||||
version = "0.2.5"
|
||||
version = "0.3.0"
|
||||
description = "Code generation for PyO3 package"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
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) {
|
||||
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 {
|
||||
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)
|
||||
|
|
|
@ -7,7 +7,7 @@ use py_method;
|
|||
|
||||
pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream {
|
||||
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 {
|
||||
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),
|
||||
"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();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("#[proto] can only be used with protocol trait implementations")
|
||||
panic!("#[pyproto] can only be used with protocol trait implementations")
|
||||
};
|
||||
|
||||
// attach lifetime
|
||||
|
@ -42,7 +42,7 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> TokenStream {
|
|||
|
||||
tokens
|
||||
} 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,
|
||||
) -> proc_macro::TokenStream {
|
||||
// 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
|
||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||
|
@ -47,7 +47,7 @@ pub fn mod3init(
|
|||
input: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
// 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
|
||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||
|
@ -65,13 +65,13 @@ pub fn mod3init(
|
|||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn proto(
|
||||
pub fn pyproto(
|
||||
_: proc_macro::TokenStream,
|
||||
input: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
// Parse the token stream into a syntax tree
|
||||
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
|
||||
let expanded = py_proto::build_py_proto(&mut ast);
|
||||
|
@ -83,12 +83,12 @@ pub fn proto(
|
|||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn class(
|
||||
pub fn pyclass(
|
||||
attr: proc_macro::TokenStream,
|
||||
input: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
// 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
|
||||
let args: Vec<syn::Expr> = {
|
||||
|
@ -110,13 +110,13 @@ pub fn class(
|
|||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn methods(
|
||||
pub fn pymethods(
|
||||
_: proc_macro::TokenStream,
|
||||
input: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
// Parse the token stream into a syntax tree
|
||||
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
|
||||
let expanded = py_impl::build_py_methods(&mut ast);
|
||||
|
@ -128,7 +128,7 @@ pub fn methods(
|
|||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn function(
|
||||
pub fn pyfunction(
|
||||
_: proc_macro::TokenStream,
|
||||
input: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
|
|
|
@ -8,7 +8,7 @@ use ffi;
|
|||
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
||||
|
||||
/// `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)]
|
||||
pub enum PyMethodDefType {
|
||||
/// Represents class `__new__` method
|
||||
|
|
|
@ -32,6 +32,7 @@ pub use self::methods::{PyMethodDef, PyMethodDefType, PyMethodType,
|
|||
|
||||
use ffi;
|
||||
|
||||
/// Operators for the __richcmp__ method
|
||||
#[derive(Debug)]
|
||||
pub enum CompareOp {
|
||||
Lt = ffi::Py_LT as isize,
|
||||
|
|
90
src/lib.rs
90
src/lib.rs
|
@ -29,22 +29,21 @@
|
|||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! #![feature(proc_macro, specialization)]
|
||||
//!
|
||||
//! extern crate pyo3;
|
||||
//!
|
||||
//! use pyo3::{Python, PyDict, PyResult, ObjectProtocol};
|
||||
//! use pyo3::prelude::*;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! fn main() -> PyResult<()> {
|
||||
//! let gil = Python::acquire_gil();
|
||||
//! hello(gil.python()).unwrap();
|
||||
//! }
|
||||
//!
|
||||
//! fn hello(py: Python) -> PyResult<()> {
|
||||
//! let py = gil.python();
|
||||
//! let sys = py.import("sys")?;
|
||||
//! let version: String = sys.get("version")?.extract()?;
|
||||
//!
|
||||
//! let locals = PyDict::new(py);
|
||||
//! 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);
|
||||
//! Ok(())
|
||||
|
@ -54,10 +53,10 @@
|
|||
//! # 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.
|
||||
//!
|
||||
//! Macro syntax: `#[modinit(name)]`
|
||||
//! Macro syntax: `#[pymodinit(name)]`
|
||||
//!
|
||||
//! 1. `name`: The module name as a Rust identifier
|
||||
//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`.
|
||||
|
@ -80,28 +79,30 @@
|
|||
//! extern crate pyo3;
|
||||
//! use pyo3::prelude::*;
|
||||
//!
|
||||
//! use pyo3::py::modinit;
|
||||
//! use pyo3::pymodinit;
|
||||
//!
|
||||
//! // add bindings to the generated python module
|
||||
//! // N.B: names: "libhello" must be the name of the `.so` or `.pyd` file
|
||||
//! // Add bindings to the generated python module
|
||||
//! // 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
|
||||
//! #[modinit(hello)]
|
||||
//! fn init_module(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
//!
|
||||
//! // pyo3 aware function. All of our python interface could be declared
|
||||
//! // in a separate module.
|
||||
//! // 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(())
|
||||
//! #[pyfn(m, "sum_as_string")]
|
||||
//! // ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||
//! // and the Rust return value back into a Python object.
|
||||
//! fn sum_as_string_py(a:i64, b:i64) -> PyResult<String> {
|
||||
//! let out = sum_as_string(a, b);
|
||||
//! Ok(out)
|
||||
//! }
|
||||
//!
|
||||
//! 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() {}
|
||||
//! ```
|
||||
//!
|
||||
|
@ -113,29 +114,19 @@
|
|||
//! features = ["extension-module"]
|
||||
//! ```
|
||||
//!
|
||||
//! The full example project can be found at:
|
||||
//! <https://github.com/PyO3/setuptools-rust/tree/master/example/>
|
||||
//! 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:
|
||||
//!
|
||||
//! Rust will compile the code into a file named `libhello.so`, but we have to
|
||||
//! rename the file in order to use it with Python:
|
||||
//!
|
||||
//! ```bash
|
||||
//! cp ./target/debug/libhello.so ./hello.so
|
||||
//! ```toml
|
||||
//! [target.x86_64-apple-darwin]
|
||||
//! rustflags = [
|
||||
//! "-C", "link-arg=-undefined",
|
||||
//! "-C", "link-arg=dynamic_lookup",
|
||||
//! ]
|
||||
//! ```
|
||||
//!
|
||||
//! (Note: on macOS you will have to rename `libhello.dynlib` to `libhello.so`.
|
||||
//! 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).)
|
||||
//! 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.
|
||||
//!
|
||||
//! The extension module can then be imported into Python:
|
||||
//!
|
||||
//! ```python,ignore
|
||||
//! >>> import hello
|
||||
//! >>> hello.run_rust_func("test")
|
||||
//! Rust says: Hello 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.
|
||||
|
||||
extern crate libc;
|
||||
extern crate spin;
|
||||
|
@ -172,16 +163,13 @@ pub use conversion::{FromPyObject, PyTryFrom, PyTryInto,
|
|||
pub mod class;
|
||||
pub use class::*;
|
||||
|
||||
/// Procedural macros
|
||||
pub mod py {
|
||||
pub use pyo3cls::{proto, class, methods, function};
|
||||
pub use pyo3cls::{pyproto, pyclass, pymethods, pyfunction};
|
||||
|
||||
#[cfg(Py_3)]
|
||||
pub use pyo3cls::mod3init as modinit;
|
||||
#[cfg(Py_3)]
|
||||
pub use pyo3cls::mod3init as pymodinit;
|
||||
|
||||
#[cfg(not(Py_3))]
|
||||
pub use pyo3cls::mod2init as modinit;
|
||||
}
|
||||
#[cfg(not(Py_3))]
|
||||
pub use pyo3cls::mod2init as pymodinit;
|
||||
|
||||
/// Constructs a `&'static CStr` literal.
|
||||
macro_rules! cstr {
|
||||
|
|
|
@ -169,7 +169,7 @@ impl PyModule {
|
|||
|
||||
/// 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
|
||||
/// m.add_function(wrap_function!(double));
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//! use pyo3::prelude::*;
|
||||
//! ```
|
||||
|
||||
pub use super::py;
|
||||
pub use class::*;
|
||||
pub use objects::*;
|
||||
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
|
||||
/// threading.
|
||||
///
|
||||
/// When writing an extension module, the `#[modinit(..)]` macro
|
||||
/// When writing an extension module, the `#[pymodinit(..)]` macro
|
||||
/// will ensure that Python threading is initialized.
|
||||
///
|
||||
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:
|
||||
/// ```rust,ignore
|
||||
/// use pyo3::py::class;
|
||||
/// use pyo3::py::methods;
|
||||
/// use pyo3::{pyclass, pymethods};
|
||||
///
|
||||
/// #[class]
|
||||
/// #[pyclass]
|
||||
/// struct MyClass {
|
||||
/// token: PyToken
|
||||
/// }
|
||||
///
|
||||
/// #[methods]
|
||||
/// #[pymethods]
|
||||
/// impl MyClass {
|
||||
/// #[new]
|
||||
/// 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> {
|
||||
|
||||
/// Allocates a new object (usually by calling ty->tp_alloc),
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::{class, proto};
|
||||
use pyo3::{pyclass, pyproto};
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct UnaryArithmetic {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for UnaryArithmetic {
|
||||
fn __neg__(&self) -> PyResult<&'static str> {
|
||||
Ok("neg")
|
||||
|
@ -44,32 +44,32 @@ fn unary_arithmetic() {
|
|||
py_run!(py, c, "assert ~c == 'invert'");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct BinaryArithmetic {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for BinaryArithmetic {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("BA")
|
||||
}
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct InPlaceOperations {
|
||||
value: u32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for InPlaceOperations {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("IPO({:?})", self.value))
|
||||
}
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for InPlaceOperations {
|
||||
fn __iadd__(&mut self, other: u32) -> PyResult<()> {
|
||||
self.value += other;
|
||||
|
@ -132,7 +132,7 @@ fn inplace_operations() {
|
|||
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyNumberProtocol for BinaryArithmetic {
|
||||
fn __add__(lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult<String> {
|
||||
Ok(format!("{:?} + {:?}", lhs, rhs))
|
||||
|
@ -193,12 +193,12 @@ fn binary_arithmetic() {
|
|||
py_run!(py, c, "assert 1 | c == '1 | BA'");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct RichComparisons {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for RichComparisons {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC")
|
||||
|
@ -216,12 +216,12 @@ impl PyObjectProtocol for RichComparisons {
|
|||
}
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct RichComparisons2 {
|
||||
py: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for RichComparisons2 {
|
||||
fn __repr__(&self) -> PyResult<&'static str> {
|
||||
Ok("RC2")
|
||||
|
|
|
@ -8,16 +8,16 @@ use std::ptr;
|
|||
use pyo3::ffi;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::proto;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pyproto;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct TestClass {
|
||||
vec: Vec<u8>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyBufferProtocol for TestClass {
|
||||
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
|
||||
if view.is_null() {
|
||||
|
|
|
@ -4,12 +4,12 @@ extern crate pyo3;
|
|||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::pyclass;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct EmptyClass {}
|
||||
|
||||
#[test]
|
||||
|
@ -27,7 +27,7 @@ fn empty_class() {
|
|||
///Line2
|
||||
/// Line3
|
||||
// this is not doc string
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassWithDocs {}
|
||||
|
||||
#[test]
|
||||
|
@ -44,7 +44,7 @@ fn class_with_docstr() {
|
|||
}
|
||||
}
|
||||
|
||||
#[class(name=CustomName)]
|
||||
#[pyclass(name=CustomName)]
|
||||
struct EmptyClass2 {}
|
||||
|
||||
#[test]
|
||||
|
@ -55,7 +55,7 @@ fn custom_class_name() {
|
|||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct EmptyClassInModule {}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -4,15 +4,15 @@ extern crate pyo3;
|
|||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct EmptyClassWithNew {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -34,13 +34,13 @@ fn empty_class_with_new() {
|
|||
);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct NewWithOneArg {
|
||||
_data: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, arg: i32) -> PyResult<()> {
|
||||
|
@ -61,7 +61,7 @@ fn new_with_one_arg() {
|
|||
assert_eq!(obj._data, 42);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct NewWithTwoArgs {
|
||||
_data1: i32,
|
||||
_data2: i32,
|
||||
|
@ -69,7 +69,7 @@ struct NewWithTwoArgs {
|
|||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject, arg1: i32, arg2: i32) -> PyResult<()> {
|
||||
|
|
|
@ -6,20 +6,20 @@ use pyo3::ffi;
|
|||
use pyo3::prelude::*;
|
||||
use std::{isize, iter};
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::py::proto;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
use pyo3::pyproto;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
pub struct Len {
|
||||
l: usize,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for Len {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(self.l)
|
||||
|
@ -45,13 +45,13 @@ fn len() {
|
|||
py_expect_exception!(py, inst, "len(inst)", OverflowError);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Iterator {
|
||||
iter: Box<iter::Iterator<Item = i32> + Send>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyIterProtocol for Iterator {
|
||||
fn __iter__(&mut self) -> PyResult<Py<Iterator>> {
|
||||
Ok(self.into())
|
||||
|
@ -75,12 +75,12 @@ fn iterator() {
|
|||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct StringMethods {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyObjectProtocol<'p> for StringMethods {
|
||||
fn __str__(&self) -> PyResult<&'static str> {
|
||||
Ok("str")
|
||||
|
@ -129,13 +129,13 @@ fn string_methods() {
|
|||
py_assert!(py, obj, "'{0:x}'.format(obj) == 'format(x)'");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Comparisons {
|
||||
val: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for Comparisons {
|
||||
fn __hash__(&self) -> PyResult<isize> {
|
||||
Ok(self.val as isize)
|
||||
|
@ -162,12 +162,12 @@ fn comparisons() {
|
|||
py_assert!(py, zero, "not zero");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Sequence {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PySequenceProtocol for Sequence {
|
||||
fn __len__(&self) -> PyResult<usize> {
|
||||
Ok(5)
|
||||
|
@ -191,12 +191,12 @@ fn sequence() {
|
|||
py_expect_exception!(py, c, "c['abc']", TypeError);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Callable {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl Callable {
|
||||
#[__call__]
|
||||
fn __call__(&self, arg: i32) -> PyResult<i32> {
|
||||
|
@ -217,14 +217,14 @@ fn callable() {
|
|||
py_assert!(py, nc, "not callable(nc)");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct SetItem {
|
||||
key: i32,
|
||||
val: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol<'a> for SetItem {
|
||||
fn __setitem__(&mut self, key: i32, val: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
|
@ -250,13 +250,13 @@ fn setitem() {
|
|||
py_expect_exception!(py, c, "del c[1]", NotImplementedError);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct DelItem {
|
||||
key: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol<'a> for DelItem {
|
||||
fn __delitem__(&mut self, key: i32) -> PyResult<()> {
|
||||
self.key = key;
|
||||
|
@ -275,13 +275,13 @@ fn delitem() {
|
|||
py_expect_exception!(py, c, "c[1] = 2", NotImplementedError);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct SetDelItem {
|
||||
val: Option<i32>,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for SetDelItem {
|
||||
fn __setitem__(&mut self, _key: i32, val: i32) -> PyResult<()> {
|
||||
self.val = Some(val);
|
||||
|
@ -310,12 +310,12 @@ fn setdelitem() {
|
|||
assert_eq!(c.val, None);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Reversed {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyMappingProtocol for Reversed {
|
||||
fn __reversed__(&self) -> PyResult<&'static str> {
|
||||
Ok("I am reversed")
|
||||
|
@ -331,12 +331,12 @@ fn reversed() {
|
|||
py_run!(py, c, "assert reversed(c) == 'I am reversed'");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Contains {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PySequenceProtocol for Contains {
|
||||
fn __contains__(&self, item: i32) -> PyResult<bool> {
|
||||
Ok(item >= 0)
|
||||
|
@ -354,13 +354,13 @@ fn contains() {
|
|||
py_expect_exception!(py, c, "assert 'wrong type' not in c", TypeError);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ContextManager {
|
||||
exit_called: bool,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyContextProtocol<'p> for ContextManager {
|
||||
fn __enter__(&mut self) -> PyResult<i32> {
|
||||
Ok(42)
|
||||
|
@ -421,12 +421,12 @@ fn test_basics() {
|
|||
assert_eq!(5, indices.slicelength);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct Test {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl<'p> PyMappingProtocol<'p> for Test {
|
||||
fn __getitem__(&self, idx: &PyObjectRef) -> PyResult<PyObject> {
|
||||
if let Ok(slice) = idx.cast_as::<PySlice>() {
|
||||
|
@ -457,7 +457,7 @@ fn test_cls_impl() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[class(dict)]
|
||||
#[pyclass(dict)]
|
||||
struct DunderDictSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ fn dunder_dict_support() {
|
|||
);
|
||||
}
|
||||
|
||||
#[class(weakref, dict)]
|
||||
#[pyclass(weakref, dict)]
|
||||
struct WeakRefDunderDictSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@ use std::cell::RefCell;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::py::proto;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
use pyo3::pyproto;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class(freelist = 2)]
|
||||
#[pyclass(freelist = 2)]
|
||||
struct ClassWithFreelist {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ impl Drop for TestDropCall {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct DataIsDropped {
|
||||
member1: TestDropCall,
|
||||
member2: TestDropCall,
|
||||
|
@ -89,7 +89,7 @@ fn data_is_dropped() {
|
|||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassWithDrop {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -136,14 +136,14 @@ fn create_pointers_in_drop() {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct GCIntegration {
|
||||
self_ref: RefCell<PyObject>,
|
||||
dropped: TestDropCall,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[proto]
|
||||
#[pyproto]
|
||||
impl PyGCProtocol for GCIntegration {
|
||||
fn __traverse__(&self, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
visit.call(&*self.self_ref.borrow())
|
||||
|
@ -178,7 +178,7 @@ fn gc_integration() {
|
|||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[class(gc)]
|
||||
#[pyclass(gc)]
|
||||
struct GCIntegration2 {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ fn gc_integration2() {
|
|||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
}
|
||||
|
||||
#[class(weakref)]
|
||||
#[pyclass(weakref)]
|
||||
struct WeakRefSupport {
|
||||
token: PyToken,
|
||||
}
|
||||
|
@ -206,13 +206,13 @@ fn weakref_support() {
|
|||
);
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct BaseClassWithDrop {
|
||||
token: PyToken,
|
||||
data: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl BaseClassWithDrop {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -231,13 +231,13 @@ impl Drop for BaseClassWithDrop {
|
|||
}
|
||||
}
|
||||
|
||||
#[class(base=BaseClassWithDrop)]
|
||||
#[pyclass(base=BaseClassWithDrop)]
|
||||
struct SubClassWithDrop {
|
||||
token: PyToken,
|
||||
data: Option<Arc<AtomicBool>>,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl SubClassWithDrop {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
|
|
@ -5,19 +5,19 @@ extern crate pyo3;
|
|||
use pyo3::prelude::*;
|
||||
use std::isize;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassWithProperties {
|
||||
num: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl ClassWithProperties {
|
||||
fn get_num(&self) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
|
@ -50,7 +50,7 @@ fn class_with_properties() {
|
|||
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct GetterSetter {
|
||||
token: PyToken,
|
||||
#[prop(get, set)]
|
||||
|
@ -59,7 +59,7 @@ struct GetterSetter {
|
|||
text: String,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl GetterSetter {
|
||||
fn get_num2(&self) -> PyResult<i32> {
|
||||
Ok(self.num)
|
||||
|
|
|
@ -5,18 +5,18 @@ extern crate pyo3;
|
|||
use pyo3::prelude::*;
|
||||
use std::isize;
|
||||
|
||||
use pyo3::py::{class, methods};
|
||||
use pyo3::{pyclass, pymethods};
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct BaseClass {
|
||||
#[prop(get)]
|
||||
val1: usize,
|
||||
}
|
||||
|
||||
#[class(subclass)]
|
||||
#[pyclass(subclass)]
|
||||
struct SubclassAble {}
|
||||
|
||||
#[test]
|
||||
|
@ -35,7 +35,7 @@ fn subclass() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl BaseClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -43,13 +43,13 @@ impl BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
#[class(base=BaseClass)]
|
||||
#[pyclass(base=BaseClass)]
|
||||
struct SubClass {
|
||||
#[prop(get)]
|
||||
val2: usize,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl SubClass {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
|
|
@ -4,19 +4,19 @@ extern crate pyo3;
|
|||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct InstanceMethod {
|
||||
member: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl InstanceMethod {
|
||||
/// Test method
|
||||
fn method(&self) -> PyResult<i32> {
|
||||
|
@ -42,13 +42,13 @@ fn instance_method() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct InstanceMethodWithArgs {
|
||||
member: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl InstanceMethodWithArgs {
|
||||
fn method(&self, multiplier: i32) -> PyResult<i32> {
|
||||
Ok(self.member * multiplier)
|
||||
|
@ -74,12 +74,12 @@ fn instance_method_with_args() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassMethod {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl ClassMethod {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -111,12 +111,12 @@ fn class_method() {
|
|||
).unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct ClassMethodWithArgs {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl ClassMethodWithArgs {
|
||||
#[classmethod]
|
||||
fn method(cls: &PyType, input: &PyString) -> PyResult<String> {
|
||||
|
@ -139,12 +139,12 @@ fn class_method_with_args() {
|
|||
).unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct StaticMethod {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(obj: &PyRawObject) -> PyResult<()> {
|
||||
|
@ -177,12 +177,12 @@ fn static_method() {
|
|||
).unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct StaticMethodWithArgs {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl StaticMethodWithArgs {
|
||||
#[staticmethod]
|
||||
fn method(_py: Python, input: i32) -> PyResult<String> {
|
||||
|
@ -204,12 +204,12 @@ fn static_method_with_args() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct MethArgs {
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MethArgs {
|
||||
#[args(test)]
|
||||
fn get_optional(&self, test: Option<i32>) -> PyResult<i32> {
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::py::{class, function, modinit};
|
||||
use pyo3::{pyclass, pyfunction, pymodinit};
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct EmptyClass {}
|
||||
|
||||
fn sum_as_string(a: i64, b: i64) -> String {
|
||||
format!("{}", a + b).to_string()
|
||||
}
|
||||
|
||||
#[function]
|
||||
#[pyfunction]
|
||||
fn double(x: usize) -> usize {
|
||||
x * 2
|
||||
}
|
||||
|
||||
/// This module is implemented in Rust.
|
||||
#[modinit(module_with_functions)]
|
||||
#[pymodinit(module_with_functions)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "sum_as_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 std::isize;
|
||||
|
||||
use pyo3::py::class;
|
||||
use pyo3::py::methods;
|
||||
use pyo3::pyclass;
|
||||
use pyo3::pymethods;
|
||||
|
||||
#[macro_use]
|
||||
mod common;
|
||||
|
||||
#[class]
|
||||
#[pyclass]
|
||||
struct MutRefArg {
|
||||
n: i32,
|
||||
token: PyToken,
|
||||
}
|
||||
|
||||
#[methods]
|
||||
#[pymethods]
|
||||
impl MutRefArg {
|
||||
fn get(&self) -> PyResult<i32> {
|
||||
Ok(self.n)
|
||||
|
|
Loading…
Reference in New Issue