From 4013d40897a7ba96ab9a81fb45d452ffe2dc38fe Mon Sep 17 00:00:00 2001 From: konstin Date: Sun, 8 Jul 2018 23:33:48 +0200 Subject: [PATCH] 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. --- README.md | 5 +- examples/word-count-cls/src/lib.rs | 8 +- examples/word-count/src/lib.rs | 4 +- guide/src/class.md | 191 ++++++++++++---------------- guide/src/debugging.md | 8 +- guide/src/function.md | 13 +- guide/src/module.md | 8 +- guide/src/overview.md | 4 +- guide/src/parallelism.md | 2 +- guide/src/rust-cpython.md | 6 +- pyo3-derive-backend/Cargo.toml | 2 +- pyo3-derive-backend/src/module.rs | 2 +- pyo3-derive-backend/src/py_class.rs | 2 +- pyo3-derive-backend/src/py_impl.rs | 2 +- pyo3-derive-backend/src/py_proto.rs | 6 +- pyo3cls/src/lib.rs | 18 +-- src/class/methods.rs | 2 +- src/class/mod.rs | 1 + src/lib.rs | 90 ++++++------- src/objects/module.rs | 4 +- src/prelude.rs | 1 - src/pythonrun.rs | 2 +- src/typeob.rs | 9 +- tests/test_arithmetics.rs | 26 ++-- tests/test_buffer_protocol.rs | 8 +- tests/test_class_basics.rs | 10 +- tests/test_class_new.rs | 16 +-- tests/test_dunder.rs | 62 ++++----- tests/test_gc.rs | 28 ++-- tests/test_getter_setter.rs | 12 +- tests/test_inheritance.rs | 12 +- tests/test_methods.rs | 32 ++--- tests/test_module.rs | 8 +- tests/test_various.rs | 8 +- 34 files changed, 282 insertions(+), 330 deletions(-) diff --git a/README.md b/README.md index e15f5060..aac13fe8 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/examples/word-count-cls/src/lib.rs b/examples/word-count-cls/src/lib.rs index 05dc61a3..f7771538 100644 --- a/examples/word-count-cls/src/lib.rs +++ b/examples/word-count-cls/src/lib.rs @@ -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::()?; diff --git a/examples/word-count/src/lib.rs b/examples/word-count/src/lib.rs index 11c870a3..14e5b209 100644 --- a/examples/word-count/src/lib.rs +++ b/examples/word-count/src/lib.rs @@ -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 { diff --git a/guide/src/class.md b/guide/src/class.md index 64430b7a..0e5f31fc 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -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) -> 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` for some `T` that implements `IntoPyObject`. - Usually, `T` will be `MyType`. +* The return type must be `PyResult` 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 { @@ -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 { 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 { @@ -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 { @@ -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 { @@ -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, 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 + Send>, token: PyToken, } -#[proto] +#[pyproto] impl PyIterProtocol for MyIterator { fn __iter__(&mut self) -> PyResult { @@ -632,5 +598,4 @@ impl PyIterProtocol for MyIterator { Ok(self.iter.next()) } } -# fn main() {} ``` diff --git a/guide/src/debugging.md b/guide/src/debugging.md index 114d8942..e85451ae 100644 --- a/guide/src/debugging.md +++ b/guide/src/debugging.md @@ -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. diff --git a/guide/src/function.md b/guide/src/function.md index e791a376..ff4c5a7c 100644 --- a/guide/src/function.md +++ b/guide/src/function.md @@ -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(); diff --git a/guide/src/module.md b/guide/src/module.md index 6bd2182f..2bf4cbed 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -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. diff --git a/guide/src/overview.md b/guide/src/overview.md index bc62f945..0b47166b 100644 --- a/guide/src/overview.md +++ b/guide/src/overview.md @@ -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")] diff --git a/guide/src/parallelism.md b/guide/src/parallelism.md index 12d6d675..86a4f8d3 100644 --- a/guide/src/parallelism.md +++ b/guide/src/parallelism.md @@ -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")] diff --git a/guide/src/rust-cpython.md b/guide/src/rust-cpython.md index 73310b3c..38ebf7c4 100644 --- a/guide/src/rust-cpython.md +++ b/guide/src/rust-cpython.md @@ -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<()> { diff --git a/pyo3-derive-backend/Cargo.toml b/pyo3-derive-backend/Cargo.toml index 0f709445..212af3b2 100644 --- a/pyo3-derive-backend/Cargo.toml +++ b/pyo3-derive-backend/Cargo.toml @@ -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 "] keywords = ["pyo3", "python", "cpython", "ffi"] diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index e59f1fa0..aefde6bc 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -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 = Vec::new(); diff --git a/pyo3-derive-backend/src/py_class.rs b/pyo3-derive-backend/src/py_class.rs index c1b6914f..81cfd783 100644 --- a/pyo3-derive-backend/src/py_class.rs +++ b/pyo3-derive-backend/src/py_class.rs @@ -29,7 +29,7 @@ pub fn build_py_class(class: &mut syn::ItemStruct, attr: &Vec) -> 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) diff --git a/pyo3-derive-backend/src/py_impl.rs b/pyo3-derive-backend/src/py_impl.rs index ed1c8358..c39b7731 100644 --- a/pyo3-derive-backend/src/py_impl.rs +++ b/pyo3-derive-backend/src/py_impl.rs @@ -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) } diff --git a/pyo3-derive-backend/src/py_proto.rs b/pyo3-derive-backend/src/py_proto.rs index 88a35e93..b87eece5 100644 --- a/pyo3-derive-backend/src/py_proto.rs +++ b/pyo3-derive-backend/src/py_proto.rs @@ -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") } } diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index 71831586..1f7116da 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -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 = { @@ -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 { diff --git a/src/class/methods.rs b/src/class/methods.rs index 42cefdc2..fefac7b7 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -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 diff --git a/src/class/mod.rs b/src/class/mod.rs index 538dc1a4..dc5f87d6 100644 --- a/src/class/mod.rs +++ b/src/class/mod.rs @@ -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, diff --git a/src/lib.rs b/src/lib.rs index 9551d8b8..1bbe8612 100644 --- a/src/lib.rs +++ b/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 { +//! 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: -//! +//! 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 { diff --git a/src/objects/module.rs b/src/objects/module.rs index 3f15c5aa..6567d44f 100644 --- a/src/objects/module.rs +++ b/src/objects/module.rs @@ -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)); @@ -178,7 +178,7 @@ impl PyModule { /// You can also add a function with a custom name using [add](PyModule::add): /// /// ```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<()> { let function = wrapper(self.py()); diff --git a/src/prelude.rs b/src/prelude.rs index bef998c0..323fd750 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,7 +10,6 @@ //! use pyo3::prelude::*; //! ``` -pub use super::py; pub use class::*; pub use objects::*; pub use objectprotocol::ObjectProtocol; diff --git a/src/pythonrun.rs b/src/pythonrun.rs index 3459b521..9d375006 100644 --- a/src/pythonrun.rs +++ b/src/pythonrun.rs @@ -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() { diff --git a/src/typeob.rs b/src/typeob.rs index 1e29c3f6..bee1f2c4 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -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 { /// Allocates a new object (usually by calling ty->tp_alloc), diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index 035cbab0..b7ea6f27 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -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 { 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 { 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") diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index a1b937d5..516414dd 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -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, 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() { diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs index 69381bdb..3556dfac 100644 --- a/tests/test_class_basics.rs +++ b/tests/test_class_basics.rs @@ -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] diff --git a/tests/test_class_new.rs b/tests/test_class_new.rs index 2f47981b..ac4baab0 100644 --- a/tests/test_class_new.rs +++ b/tests/test_class_new.rs @@ -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<()> { diff --git a/tests/test_dunder.rs b/tests/test_dunder.rs index e13cd92e..4bb428a0 100644 --- a/tests/test_dunder.rs +++ b/tests/test_dunder.rs @@ -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 { Ok(self.l) @@ -45,13 +45,13 @@ fn len() { py_expect_exception!(py, inst, "len(inst)", OverflowError); } -#[class] +#[pyclass] struct Iterator { iter: Box + Send>, token: PyToken, } -#[proto] +#[pyproto] impl PyIterProtocol for Iterator { fn __iter__(&mut self) -> PyResult> { 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 { 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 { 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 { @@ -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, 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 { 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 { 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 { if let Ok(slice) = idx.cast_as::() { @@ -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, } diff --git a/tests/test_gc.rs b/tests/test_gc.rs index d2bf5804..ef8f7b9b 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -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, 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>, } -#[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>, } -#[methods] +#[pymethods] impl SubClassWithDrop { #[new] fn __new__(obj: &PyRawObject) -> PyResult<()> { diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index cbc274d7..fa6dff3a 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -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 { 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 { Ok(self.num) diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index ea6b0fe3..7702be84 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -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<()> { diff --git a/tests/test_methods.rs b/tests/test_methods.rs index 220a54ab..896e99b5 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -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 { @@ -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 { 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 { @@ -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 { @@ -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) -> PyResult { diff --git a/tests/test_module.rs b/tests/test_module.rs index d30eb5a4..99ae7c27 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -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 { diff --git a/tests/test_various.rs b/tests/test_various.rs index 85b2599c..e6f2c75e 100644 --- a/tests/test_various.rs +++ b/tests/test_various.rs @@ -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 { Ok(self.n)