diff --git a/.gitignore b/.gitignore index 439ac2ae..c8f2d01b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ dist/ .eggs/ venv* guide/book/ -examples/*/py +examples/*/py* *.so *.out diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e6cbe3..b2333925 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - * Added a `wrap_module!` macro similar to the existing `wrap_function!` macro. Only available on python 3 + * Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3 + * Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details. ### Changed * Renamed `add_function` to `add_wrapped` as it now also supports modules. * Renamed `#[pymodinit]` to `#[pymodule]`. * Renamed `py_exception` to `create_exception` and refactored the error macros. + * Renamed `wrap_function!` to `wrap_pyfunction!` + * Migrated to the 2018 edition ### Removed diff --git a/Cargo.toml b/Cargo.toml index eed58666..3c699d8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3" -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" description = "Bindings to Python interpreter" authors = ["PyO3 Project and Contributors "] readme = "README.md" @@ -12,6 +12,7 @@ categories = ["api-bindings", "development-tools::ffi"] license = "Apache-2.0" exclude = ["/.gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] build = "build.rs" +edition = "2018" [badges] travis-ci = { repository = "PyO3/pyo3", branch = "master" } @@ -22,7 +23,7 @@ codecov = { repository = "PyO3/pyo3", branch = "master", service = "github" } libc = "0.2.43" spin = "0.5.0" num-traits = "0.2.6" -pyo3cls = { path = "pyo3cls", version = "=0.6.0-alpha.1" } +pyo3cls = { path = "pyo3cls", version = "=0.6.0-alpha.2" } mashup = "0.1.9" num-complex = { version = "0.2.1", optional = true } diff --git a/README.md b/README.md index 0a0c71a7..e338d4d9 100644 --- a/README.md +++ b/README.md @@ -31,19 +31,20 @@ sudo apt install python3-dev python-dev Pyo3 can be used to generate a native python module. -**`Cargo.toml`:** +**`Cargo.toml`** ```toml [package] name = "string-sum" version = "0.1.0" +edition = "2018" [lib] name = "string_sum" crate-type = ["cdylib"] [dependencies.pyo3] -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" features = ["extension-module"] ``` @@ -52,10 +53,8 @@ features = ["extension-module"] ```rust #![feature(specialization)] -#[macro_use] -extern crate pyo3; - use pyo3::prelude::*; +use pyo3::wrap_pyfunction; #[pyfunction] /// Formats the sum of two numbers as string @@ -66,7 +65,7 @@ fn sum_as_string(a: usize, b: usize) -> PyResult { /// This module is a python module implemented in Rust. #[pymodule] fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(sum_as_string))?; + m.add_wrapped(wrap_pyfunction!(sum_as_string))?; Ok(()) } @@ -92,7 +91,7 @@ Add `pyo3` this to your `Cargo.toml`: ```toml [dependencies] -pyo3 = "0.5" +pyo3 = "0.6.0-alpha.2" ``` Example program displaying the value of `sys.version`: @@ -100,8 +99,6 @@ Example program displaying the value of `sys.version`: ```rust #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::PyDict; @@ -110,11 +107,10 @@ fn main() -> 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 code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; + let user: String = py.eval(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) } diff --git a/benches/bench_dict.rs b/benches/bench_dict.rs index 114f38eb..9c3944e5 100644 --- a/benches/bench_dict.rs +++ b/benches/bench_dict.rs @@ -1,9 +1,9 @@ #![feature(test)] -extern crate pyo3; -extern crate test; -use test::Bencher; -use pyo3::{prelude::*, types::IntoPyDict}; +extern crate test; +use pyo3::prelude::*; +use pyo3::types::IntoPyDict; +use test::Bencher; #[bench] fn iter_dict(b: &mut Bencher) { diff --git a/build.rs b/build.rs index 7c49e197..fc1593ed 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,3 @@ -extern crate regex; -extern crate version_check; - use regex::Regex; use std::collections::HashMap; use std::convert::AsRef; diff --git a/ci/travis/test.sh b/ci/travis/test.sh index 7d119da0..5f7db37b 100755 --- a/ci/travis/test.sh +++ b/ci/travis/test.sh @@ -2,8 +2,8 @@ set -ex cargo fmt --all -- --check -cargo test --features "$FEATURES" -cargo clippy --features "$FEATURES" +cargo test --features "$FEATURES num-complex" +cargo clippy --features "$FEATURES num-complex" for example_dir in examples/*; do tox -c "$example_dir/tox.ini" -e py diff --git a/examples/rustapi_module/Cargo.toml b/examples/rustapi_module/Cargo.toml index abff4443..98e728ee 100644 --- a/examples/rustapi_module/Cargo.toml +++ b/examples/rustapi_module/Cargo.toml @@ -3,6 +3,7 @@ authors = ["PyO3 Authors"] name = "rustapi-module" version = "0.1.0" description = "A Python wrapper for the Rust API for purposes of testing" +edition = "2018" [dependencies] diff --git a/examples/rustapi_module/src/datetime.rs b/examples/rustapi_module/src/datetime.rs index 3503f78e..e59319d4 100644 --- a/examples/rustapi_module/src/datetime.rs +++ b/examples/rustapi_module/src/datetime.rs @@ -3,14 +3,15 @@ use pyo3::types::{ PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple, PyTzInfo, }; +use pyo3::wrap_pyfunction; #[pyfunction] -fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult> { +fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult> { PyDate::new(py, year, month, day) } #[pyfunction] -fn get_date_tuple(py: Python, d: &PyDate) -> Py { +fn get_date_tuple(py: Python<'_>, d: &PyDate) -> Py { PyTuple::new( py, &[d.get_year(), d.get_month() as i32, d.get_day() as i32], @@ -18,13 +19,13 @@ fn get_date_tuple(py: Python, d: &PyDate) -> Py { } #[pyfunction] -fn date_from_timestamp(py: Python, timestamp: i64) -> PyResult> { +fn date_from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult> { PyDate::from_timestamp(py, timestamp) } #[pyfunction] fn make_time( - py: Python, + py: Python<'_>, hour: u8, minute: u8, second: u8, @@ -64,7 +65,7 @@ fn time_with_fold( } #[pyfunction] -fn get_time_tuple(py: Python, dt: &PyTime) -> Py { +fn get_time_tuple(py: Python<'_>, dt: &PyTime) -> Py { PyTuple::new( py, &[ @@ -92,12 +93,12 @@ fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py { } #[pyfunction] -fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResult> { +fn make_delta(py: Python<'_>, days: i32, seconds: i32, microseconds: i32) -> PyResult> { PyDelta::new(py, days, seconds, microseconds, true) } #[pyfunction] -fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py { +fn get_delta_tuple(py: Python<'_>, delta: &PyDelta) -> Py { PyTuple::new( py, &[ @@ -110,7 +111,7 @@ fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py { #[pyfunction] fn make_datetime( - py: Python, + py: Python<'_>, year: i32, month: u8, day: u8, @@ -134,7 +135,7 @@ fn make_datetime( } #[pyfunction] -fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py { +fn get_datetime_tuple(py: Python<'_>, dt: &PyDateTime) -> Py { PyTuple::new( py, &[ @@ -168,7 +169,11 @@ fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py { } #[pyfunction] -fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult> { +fn datetime_from_timestamp( + py: Python<'_>, + ts: f64, + tz: Option<&PyTzInfo>, +) -> PyResult> { PyDateTime::from_timestamp(py, ts, tz) } @@ -189,41 +194,41 @@ impl TzClass { obj.init(|| TzClass {}) } - fn utcoffset(&self, py: Python, _dt: &PyDateTime) -> PyResult> { + fn utcoffset(&self, py: Python<'_>, _dt: &PyDateTime) -> PyResult> { PyDelta::new(py, 0, 3600, 0, true) } - fn tzname(&self, _py: Python, _dt: &PyDateTime) -> PyResult { + fn tzname(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult { Ok(String::from("+01:00")) } - fn dst(&self, _py: Python, _dt: &PyDateTime) -> PyResult> { + fn dst(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult> { Ok(None) } } #[pymodule] -fn datetime(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(make_date))?; - m.add_wrapped(wrap_function!(get_date_tuple))?; - m.add_wrapped(wrap_function!(date_from_timestamp))?; - m.add_wrapped(wrap_function!(make_time))?; - m.add_wrapped(wrap_function!(get_time_tuple))?; - m.add_wrapped(wrap_function!(make_delta))?; - m.add_wrapped(wrap_function!(get_delta_tuple))?; - m.add_wrapped(wrap_function!(make_datetime))?; - m.add_wrapped(wrap_function!(get_datetime_tuple))?; - m.add_wrapped(wrap_function!(datetime_from_timestamp))?; +fn datetime(_py: Python<'_>, m: &PyModule) -> PyResult<()> { + m.add_wrapped(wrap_pyfunction!(make_date))?; + m.add_wrapped(wrap_pyfunction!(get_date_tuple))?; + m.add_wrapped(wrap_pyfunction!(date_from_timestamp))?; + m.add_wrapped(wrap_pyfunction!(make_time))?; + m.add_wrapped(wrap_pyfunction!(get_time_tuple))?; + m.add_wrapped(wrap_pyfunction!(make_delta))?; + m.add_wrapped(wrap_pyfunction!(get_delta_tuple))?; + m.add_wrapped(wrap_pyfunction!(make_datetime))?; + m.add_wrapped(wrap_pyfunction!(get_datetime_tuple))?; + m.add_wrapped(wrap_pyfunction!(datetime_from_timestamp))?; // Python 3.6+ functions #[cfg(Py_3_6)] { - m.add_wrapped(wrap_function!(time_with_fold))?; - m.add_wrapped(wrap_function!(get_time_tuple_fold))?; - m.add_wrapped(wrap_function!(get_datetime_tuple_fold))?; + m.add_wrapped(wrap_pyfunction!(time_with_fold))?; + m.add_wrapped(wrap_pyfunction!(get_time_tuple_fold))?; + m.add_wrapped(wrap_pyfunction!(get_datetime_tuple_fold))?; } - m.add_wrapped(wrap_function!(issue_219))?; + m.add_wrapped(wrap_pyfunction!(issue_219))?; m.add_class::()?; Ok(()) diff --git a/examples/rustapi_module/src/dict_iter.rs b/examples/rustapi_module/src/dict_iter.rs index 5fdc9944..beae602a 100644 --- a/examples/rustapi_module/src/dict_iter.rs +++ b/examples/rustapi_module/src/dict_iter.rs @@ -1,10 +1,9 @@ -use pyo3::prelude::*; - use pyo3::exceptions::RuntimeError; +use pyo3::prelude::*; use pyo3::types::PyDict; #[pymodule] -fn test_dict(_py: Python, m: &PyModule) -> PyResult<()> { +fn test_dict(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; Ok(()) } @@ -21,7 +20,7 @@ impl DictSize { obj.init(|| DictSize { expected }) } - fn iter_dict(&mut self, _py: Python, dict: &PyDict) -> PyResult { + fn iter_dict(&mut self, _py: Python<'_>, dict: &PyDict) -> PyResult { let mut seen = 0u32; for (sym, values) in dict.iter() { seen += 1; diff --git a/examples/rustapi_module/src/lib.rs b/examples/rustapi_module/src/lib.rs index 36f8a7b3..3afa1978 100644 --- a/examples/rustapi_module/src/lib.rs +++ b/examples/rustapi_module/src/lib.rs @@ -1,8 +1,5 @@ #![feature(specialization)] -#[macro_use] -extern crate pyo3; - pub mod datetime; pub mod dict_iter; pub mod othermod; diff --git a/examples/rustapi_module/src/othermod.rs b/examples/rustapi_module/src/othermod.rs index 4302d17e..613416de 100644 --- a/examples/rustapi_module/src/othermod.rs +++ b/examples/rustapi_module/src/othermod.rs @@ -3,6 +3,7 @@ //! The code below just tries to use the most important code generation paths use pyo3::prelude::*; +use pyo3::wrap_pyfunction; #[pyclass] pub struct ModClass { @@ -29,8 +30,8 @@ fn double(x: i32) -> i32 { } #[pymodule] -fn othermod(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(double))?; +fn othermod(_py: Python<'_>, m: &PyModule) -> PyResult<()> { + m.add_wrapped(wrap_pyfunction!(double))?; m.add_class::()?; m.add("USIZE_MIN", usize::min_value())?; diff --git a/examples/rustapi_module/src/subclassing.rs b/examples/rustapi_module/src/subclassing.rs index b0fa42ac..9a36b007 100644 --- a/examples/rustapi_module/src/subclassing.rs +++ b/examples/rustapi_module/src/subclassing.rs @@ -14,7 +14,7 @@ impl Subclassable { } #[pymodule] -fn subclassing(_py: Python, m: &PyModule) -> PyResult<()> { +fn subclassing(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; Ok(()) } diff --git a/examples/word-count/Cargo.toml b/examples/word-count/Cargo.toml index 62602589..70f82bdd 100644 --- a/examples/word-count/Cargo.toml +++ b/examples/word-count/Cargo.toml @@ -2,6 +2,7 @@ authors = ["Messense Lv "] name = "word-count" version = "0.1.0" +edition = "2018" [dependencies] rayon = "1.0.2" diff --git a/examples/word-count/src/lib.rs b/examples/word-count/src/lib.rs index 796451a9..9044073b 100644 --- a/examples/word-count/src/lib.rs +++ b/examples/word-count/src/lib.rs @@ -2,11 +2,8 @@ // https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs #![feature(specialization)] -#[macro_use] -extern crate pyo3; -extern crate rayon; - use pyo3::prelude::*; +use pyo3::wrap_pyfunction; use rayon::prelude::*; use std::fs; use std::path::PathBuf; @@ -27,7 +24,7 @@ impl WordCounter { } /// Searches for the word, parallelized by rayon - fn search(&self, py: Python, search: String) -> PyResult { + fn search(&self, py: Python<'_>, search: String) -> PyResult { let contents = fs::read_to_string(&self.path)?; let count = py.allow_threads(move || { @@ -79,8 +76,8 @@ fn count_line(line: &str, needle: &str) -> usize { } #[pymodule] -fn word_count(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(count_line))?; +fn word_count(_py: Python<'_>, m: &PyModule) -> PyResult<()> { + m.add_wrapped(wrap_pyfunction!(count_line))?; m.add_class::()?; Ok(()) diff --git a/guide/src/class.md b/guide/src/class.md index beabbcf2..0c2fa168 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -6,7 +6,6 @@ To define python custom class, rust struct needs to be annotated with `#[pyclass ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] @@ -45,7 +44,6 @@ attribute. Only the python `__new__` method can be specified, `__init__` is not ```rust # #![feature(specialization)] # -# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::PyRawObject; @@ -89,7 +87,6 @@ with value of custom class struct. Subclass must call parent's `__new__` method. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::PyRawObject; #[pyclass] @@ -140,7 +137,6 @@ attributes. i.e. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -166,7 +162,6 @@ rust's special keywords like `type`. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -196,7 +191,6 @@ If parameter is specified, it is used and property name. i.e. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -225,7 +219,6 @@ For simple cases you can also define getters and setters in your Rust struct fie ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] struct MyClass { @@ -245,7 +238,6 @@ class method static methods, etc. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -274,7 +266,6 @@ get injected by method wrapper. i.e ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -299,7 +290,6 @@ with`#[classmethod]` attribute. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -332,7 +322,6 @@ for some `T` that implements `IntoPyObject`. ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -356,7 +345,6 @@ with `#[call]` attribute. Arguments of the method are specified same as for inst ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -400,7 +388,6 @@ Each parameter could one of following type: Example: ```rust # #![feature(specialization)] -# extern crate pyo3; # use pyo3::prelude::*; # # #[pyclass] @@ -429,7 +416,7 @@ with `#[pyproto]` attribute. ### Basic object customization -[`PyObjectProtocol`](https://docs.rs/pyo3/0.5.2/class/basic/trait.PyObjectProtocol.html) trait provide several basic customizations. +[`PyObjectProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/basic/trait.PyObjectProtocol.html) trait provide several basic customizations. #### Attribute access @@ -493,7 +480,7 @@ Each methods corresponds to python's `self.attr`, `self.attr = value` and `del s If your type owns references to other python objects, you will need to integrate with Python's garbage collector so that the GC is aware of those references. -To do this, implement [`PyGCProtocol`](https://docs.rs/pyo3/0.5.2/class/gc/trait.PyGCProtocol.html) trait for your struct. +To do this, implement [`PyGCProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/gc/trait.PyGCProtocol.html) trait for your struct. It includes two methods `__traverse__` and `__clear__`. These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. `__traverse__` must call `visit.call()` for each reference to another python object. @@ -503,7 +490,6 @@ as every cycle must contain at least one mutable reference. Example: ```rust #![feature(specialization)] -extern crate pyo3; use pyo3::prelude::*; @@ -540,7 +526,7 @@ collector, and it is possible to track them with `gc` module methods. ### Iterator Types Iterators can be defined using the -[`PyIterProtocol`](https://docs.rs/pyo3/0.5.2/class/iter/trait.PyIterProtocol.html) trait. +[`PyIterProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/iter/trait.PyIterProtocol.html) trait. It includes two methods `__iter__` and `__next__`: * `fn __iter__(&mut self) -> PyResult` * `fn __next__(&mut self) -> PyResult>` @@ -552,8 +538,6 @@ Example: ```rust #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; #[pyclass] diff --git a/guide/src/conversions.md b/guide/src/conversions.md index 21dccbda..7494d732 100644 --- a/guide/src/conversions.md +++ b/guide/src/conversions.md @@ -17,7 +17,6 @@ The easiest way to convert a python object to a rust value is using `.extract()? For example, [`IntoPyTuple`][IntoPyTuple] trait is implemented for `()` so that you can convert it into a empty [`PyTuple`][PyTuple] ```rust -extern crate pyo3; use pyo3::{Python, IntoPyTuple}; fn main() { @@ -43,16 +42,15 @@ Both methods accept `args` and `kwargs` arguments. `args` argument is generate o rust tuple with up to 10 elements. Or `NoArgs` object which represents empty tuple object. ```rust -extern crate pyo3; use pyo3::prelude::*; -# struct SomeObject; -# impl SomeObject { -# fn new(py: Python) -> PyObject { -# pyo3::PyDict::new(py).to_object(py) -# } -# } -# +struct SomeObject; +impl SomeObject { + fn new(py: Python) -> PyObject { + pyo3::PyDict::new(py).to_object(py) + } +} + fn main() { # let arg1 = "arg1"; # let arg2 = "arg2"; @@ -80,22 +78,23 @@ fn main() { [`IntoPyDict`][IntoPyDict] trait to convert other dict-like containers, e.g. `HashMap`, `BTreeMap` as well as tuples with up to 10 elements and `Vec`s where each element is a two element tuple. ```rust -extern crate pyo3; - -use std::collections::HashMap; use pyo3::prelude::*; +use pyo3::types::{IntoPyDict, PyDict}; +use std::collections::HashMap; + +struct SomeObject; + +impl SomeObject { + fn new(py: Python) -> PyObject { + PyDict::new(py).to_object(py) + } +} -# struct SomeObject; -# impl SomeObject { -# fn new(py: Python) -> PyObject { -# pyo3::PyDict::new(py).to_object(py) -# } -# } fn main() { - # let key1 = "key1"; - # let val1 = 1; - # let key2 = "key2"; - # let val2 = 2; + let key1 = "key1"; + let val1 = 1; + let key2 = "key2"; + let val2 = 2; let gil = Python::acquire_gil(); let py = gil.python(); @@ -105,26 +104,25 @@ fn main() { // call object with PyDict let kwargs = PyDict::new(py); kwargs.set_item(key1, val1); - obj.call(py, NoArgs, kwargs); + obj.call(py, NoArgs, Some(kwargs)); - // pass arguments as rust tuple - let kwargs = ((key1, val1), (key2, val2)); - obj.call(py, NoArgs, kwargs); + // pass arguments as Vec + let kwargs = vec![(key1, val1), (key2, val2)]; + obj.call(py, NoArgs, Some(kwargs.into_py_dict(py))); // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); - obj.call(py, NoArgs, kwargs); + obj.call(py, NoArgs, Some(kwargs.into_py_dict(py))); } ``` - TODO -[`ToPyObject`]: https://docs.rs/pyo3/0.5.2/trait.ToPyObject.html -[IntoPyObject]: https://docs.rs/pyo3/0.5.2/trait.IntoPyObject.html -[PyObject]: https://docs.rs/pyo3/0.5.2/struct.PyObject.html -[IntoPyTuple]: https://docs.rs/pyo3/0.5.2/trait.IntoPyTuple.html -[PyTuple]: https://docs.rs/pyo3/0.5.2/struct.PyTuple.html -[ObjectProtocol]: https://docs.rs/pyo3/0.5.2/trait.ObjectProtocol.html -[IntoPyDict]: https://docs.rs/pyo3/0.5.2/trait.IntoPyDict.html +[`ToPyObject`]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ToPyObject.html +[IntoPyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyObject.html +[PyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyObject.html +[IntoPyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyTuple.html +[PyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyTuple.html +[ObjectProtocol]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ObjectProtocol.html +[IntoPyDict]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyDict.html diff --git a/guide/src/exception.md b/guide/src/exception.md index e534c2c2..5aa7068c 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -5,7 +5,7 @@ You can use the `create_exception!` macro to define a new exception type: ```rust -#[macro_use] extern crate pyo3; +use pyo3::import_exception; create_exception!(module, MyError, pyo3::exceptions::Exception); ``` @@ -16,9 +16,8 @@ create_exception!(module, MyError, pyo3::exceptions::Exception); For example: ```rust -#[macro_use] extern crate pyo3; - -use pyo3::Python; +use pyo3::prelude::*; +use pyo3::create_exception; use pyo3::types::PyDict; use pyo3::exceptions::Exception; @@ -41,8 +40,6 @@ fn main() { To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html), then call [`PyErr::restore()`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state. ```rust -extern crate pyo3; - use pyo3::{Python, PyErr, exc}; fn main() { @@ -66,7 +63,6 @@ has corresponding rust type, exceptions defined by `create_exception!` and `impo have rust type as well. ```rust -# extern crate pyo3; # use pyo3::prelude::*; # fn check_for_error() -> bool {false} fn my_func(arg: PyObject) -> PyResult<()> { @@ -84,8 +80,6 @@ Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#is in `PyO3` there is a [`Python::is_instance()`](https://docs.rs/pyo3/0.2.7/struct.Python.html#method.is_instance) method which does the same thing. ```rust -extern crate pyo3; - use pyo3::{Python, PyBool, PyList}; fn main() { @@ -103,7 +97,6 @@ fn main() { To check the type of an exception, you can simply do: ```rust -# extern crate pyo3; # use pyo3::prelude::*; # fn main() { # let gil = Python::acquire_gil(); @@ -134,7 +127,6 @@ until `Python` object is available. ```rust,ignore #![feature(specialization)] -extern crate pyo3; use std::net::TcpListener; use pyo3::{PyErr, PyResult, exc}; @@ -157,7 +149,6 @@ The code snippet above will raise `OSError` in Python if `TcpListener::bind()` r types so `try!` macro or `?` operator can be used. ```rust -# extern crate pyo3; use pyo3::prelude::*; fn parse_int(s: String) -> PyResult { @@ -175,8 +166,8 @@ It is possible to use exception defined in python code as native rust types. for that exception. ```rust -#[macro_use] extern crate pyo3; use pyo3::prelude::*; +use pyo3::import_exception; import_exception!(io, UnsupportedOperation); diff --git a/guide/src/function.md b/guide/src/function.md index 3a30b992..aabdf249 100644 --- a/guide/src/function.md +++ b/guide/src/function.md @@ -6,12 +6,8 @@ the function to a [module](./module.md) One way is defining the function in the module definition. ```rust -#![feature(proc_macro)] - -extern crate pyo3; use pyo3::prelude::*; - #[pymodule] fn rust2py(py: Python, m: &PyModule) -> PyResult<()> { @@ -36,9 +32,8 @@ as third. ```rust #![feature(specialization)] -#[macro_use] -extern crate pyo3; use pyo3::prelude::*; +use pyo3::wrap_pyfunction; #[pyfunction] fn double(x: usize) -> usize { @@ -47,7 +42,7 @@ fn double(x: usize) -> usize { #[pymodule] fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(double)).unwrap(); + m.add_wrapped(wrap_pyfunction!(double)).unwrap(); Ok(()) } @@ -95,5 +90,5 @@ You can use `ObjectProtocol::is_callable` to check if you got a callable, which ### Calling rust `Fn`s in python -If you have a static function, you can expose it with `#[pyfunction]` and use `wrap_function!` to get the corresponding `PyObject`. For dynamic functions, e.g. lambda and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a box. (Long-Term a special container similar to wasm-bindgen's `Closure` should take care of that). You can than use a `#[pyclass]` struct with that container as field as a way to pass the function over the ffi-barrier. You can even make that class callable with `__call__` so it looks like a function in python code. +If you have a static function, you can expose it with `#[pyfunction]` and use `wrap_pyfunction!` to get the corresponding `PyObject`. For dynamic functions, e.g. lambda and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a box. (Long-Term a special container similar to wasm-bindgen's `Closure` should take care of that). You can than use a `#[pyclass]` struct with that container as field as a way to pass the function over the ffi-barrier. You can even make that class callable with `__call__` so it looks like a function in python code. diff --git a/guide/src/get_started.md b/guide/src/get_started.md index 077dc981..b1336ab3 100644 --- a/guide/src/get_started.md +++ b/guide/src/get_started.md @@ -47,10 +47,8 @@ features = ["extension-module"] ```rust #![feature(specialization)] -#[macro_use] -extern crate pyo3; - use pyo3::prelude::*; +use pyo3::wrap_pyfunction; #[pyfunction] /// Formats the sum of two numbers as string @@ -61,7 +59,7 @@ fn sum_as_string(a: usize, b: usize) -> PyResult { /// This module is a python module implemented in Rust. #[pymodule] fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { - m.add_wrapped(wrap_function!(sum_as_string))?; + m.add_wrapped(wrap_pyfunction!(sum_as_string))?; Ok(()) } @@ -95,8 +93,6 @@ Example program displaying the value of `sys.version`: ```rust #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::PyDict; diff --git a/guide/src/module.md b/guide/src/module.md index c0b2a0cc..5e51b033 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -3,10 +3,7 @@ As shown in the Getting Started chapter, you can create a module as follows: ```rust -#![feature(proc_macro)] - -extern crate pyo3; -use pyo3::{PyResult, Python, PyModule}; +use pyo3::prelude::*; // add bindings to the generated python module // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file @@ -62,20 +59,20 @@ fn subfunction() -> String { #[pymodule] fn submodule(_py: Python, module: &PyModule) -> PyResult<()> { - module.add_wrapped(wrap_function!(subfunction))?; + module.add_wrapped(wrap_pyfunction!(subfunction))?; Ok(()) } #[pymodule] fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> { - module.add_wrapped(wrap_module!(submodule))?; + module.add_wrapped(wrap_pymodule!(submodule))?; Ok(()) } fn nested_call() { let gil = GILGuard::acquire(); let py = gil.python(); - let supermodule = wrap_module!(supermodule)(py); + let supermodule = wrap_pymodule!(supermodule)(py); ctx.set_item("supermodule", supermodule); py.run("assert supermodule.submodule.subfuntion() == 'Subfunction'", None, Some(&ctx)).unwrap(); diff --git a/guide/src/rust-cpython.md b/guide/src/rust-cpython.md index 51f6e9e1..d46a4732 100644 --- a/guide/src/rust-cpython.md +++ b/guide/src/rust-cpython.md @@ -27,8 +27,6 @@ py_class!(class MyClass |py| { ```rust #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::PyRawObject; diff --git a/pyo3-derive-backend/Cargo.toml b/pyo3-derive-backend/Cargo.toml index 61277871..45fea178 100644 --- a/pyo3-derive-backend/Cargo.toml +++ b/pyo3-derive-backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3-derive-backend" -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" description = "Code generation for PyO3 package" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] @@ -8,6 +8,7 @@ homepage = "https://github.com/pyo3/pyo3" repository = "https://github.com/pyo3/pyo3" categories = ["api-bindings", "development-tools::ffi"] license = "Apache-2.0" +edition = "2018" [dependencies] quote = "0.6.9" diff --git a/pyo3-derive-backend/src/args.rs b/pyo3-derive-backend/src/args.rs index dc8ca2fa..80b6a385 100644 --- a/pyo3-derive-backend/src/args.rs +++ b/pyo3-derive-backend/src/args.rs @@ -1,4 +1,6 @@ // Copyright (c) 2017-present PyO3 Project and Contributors + +use quote::quote; use syn; #[derive(Debug, Clone, PartialEq)] @@ -179,12 +181,12 @@ pub fn parse_arguments(items: &[syn::NestedMeta]) -> Vec { #[cfg(test)] mod test { - use args::{parse_arguments, Argument}; + use crate::args::{parse_arguments, Argument}; use proc_macro2::TokenStream; use syn; fn items(s: TokenStream) -> Vec { - let dummy: syn::ItemFn = parse_quote! {#s fn dummy() {}}; + let dummy: syn::ItemFn = syn::parse_quote! {#s fn dummy() {}}; match dummy.attrs[0].interpret_meta() { Some(syn::Meta::List(syn::MetaList { nested, .. })) => { nested.iter().map(Clone::clone).collect() @@ -208,9 +210,9 @@ mod test { let args = parse_arguments(&items(quote! {#[args(test1, test2, test3="None")]})); assert!( args == vec![ - Argument::Arg(parse_quote! {test1}, None), - Argument::Arg(parse_quote! {test2}, None), - Argument::Arg(parse_quote! {test3}, Some("None".to_owned())), + Argument::Arg(syn::parse_quote! {test1}, None), + Argument::Arg(syn::parse_quote! {test2}, None), + Argument::Arg(syn::parse_quote! {test3}, Some("None".to_owned())), ] ); } @@ -222,10 +224,10 @@ mod test { )); assert!( args == vec![ - Argument::Arg(parse_quote! {test1}, None), - Argument::Arg(parse_quote! {test2}, Some("None".to_owned())), + Argument::Arg(syn::parse_quote! {test1}, None), + Argument::Arg(syn::parse_quote! {test2}, Some("None".to_owned())), Argument::VarArgsSeparator, - Argument::Kwarg(parse_quote! {test3}, "None".to_owned()), + Argument::Kwarg(syn::parse_quote! {test3}, "None".to_owned()), ] ); } @@ -237,11 +239,11 @@ mod test { )); assert!( args == vec![ - Argument::Arg(parse_quote! {test1}, None), - Argument::Arg(parse_quote! {test2}, Some("None".to_owned())), - Argument::VarArgs(parse_quote! {args}), - Argument::Kwarg(parse_quote! {test3}, "None".to_owned()), - Argument::KeywordArgs(parse_quote! {kwargs}), + Argument::Arg(syn::parse_quote! {test1}, None), + Argument::Arg(syn::parse_quote! {test2}, Some("None".to_owned())), + Argument::VarArgs(syn::parse_quote! {args}), + Argument::Kwarg(syn::parse_quote! {test3}, "None".to_owned()), + Argument::KeywordArgs(syn::parse_quote! {kwargs}), ] ); } diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs index 0534aba9..48238bac 100644 --- a/pyo3-derive-backend/src/defs.rs +++ b/pyo3-derive-backend/src/defs.rs @@ -1,5 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use func::MethodProto; +use crate::func::MethodProto; pub struct Proto { pub name: &'static str, diff --git a/pyo3-derive-backend/src/func.rs b/pyo3-derive-backend/src/func.rs index 5cd579d0..69b96822 100644 --- a/pyo3-derive-backend/src/func.rs +++ b/pyo3-derive-backend/src/func.rs @@ -1,7 +1,8 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +use crate::utils::print_err; use proc_macro2::{Span, TokenStream}; +use quote::quote; use syn; -use utils::print_err; // TODO: // Add lifetime support for args with Rptr @@ -87,7 +88,7 @@ pub fn impl_method_proto( let p: syn::Path = syn::parse_str(proto).unwrap(); let (ty, succ) = get_res_success(ty); - let tmp: syn::ItemFn = parse_quote! { + let tmp: syn::ItemFn = syn::parse_quote! { fn test(&self) -> <#cls as #p<'p>>::Result {} }; sig.decl.output = tmp.decl.output; @@ -124,11 +125,11 @@ pub fn impl_method_proto( let arg_ty = get_arg_ty(sig, 1); let (ty, succ) = get_res_success(ty); - let tmp = extract_decl(parse_quote! { + let tmp = extract_decl(syn::parse_quote! { fn test(&self,arg: <#cls as #p<'p>>::#arg_name)-> <#cls as #p<'p>>::Result {} }); - let tmp2 = extract_decl(parse_quote! { + let tmp2 = extract_decl(syn::parse_quote! { fn test( &self, arg: Option<<#cls as #p<'p>>::#arg_name>) -> <#cls as #p<'p>>::Result {} }); @@ -171,11 +172,11 @@ pub fn impl_method_proto( let (ty, succ) = get_res_success(ty); // rewrite ty - let tmp = extract_decl(parse_quote! {fn test( + let tmp = extract_decl(syn::parse_quote! {fn test( arg1: <#cls as #p<'p>>::#arg1_name, arg2: <#cls as #p<'p>>::#arg2_name) -> <#cls as #p<'p>>::Result {}}); - let tmp2 = extract_decl(parse_quote! {fn test( + let tmp2 = extract_decl(syn::parse_quote! {fn test( arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg2: Option<<#cls as #p<'p>>::#arg2_name>) -> <#cls as #p<'p>>::Result {}}); @@ -220,12 +221,12 @@ pub fn impl_method_proto( let (ty, succ) = get_res_success(ty); // rewrite ty - let tmp = extract_decl(parse_quote! {fn test( + let tmp = extract_decl(syn::parse_quote! {fn test( &self, arg1: <#cls as #p<'p>>::#arg1_name, arg2: <#cls as #p<'p>>::#arg2_name) -> <#cls as #p<'p>>::Result {}}); - let tmp2 = extract_decl(parse_quote! {fn test( + let tmp2 = extract_decl(syn::parse_quote! {fn test( &self, arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg2: Option<<#cls as #p<'p>>::#arg2_name>) @@ -275,12 +276,12 @@ pub fn impl_method_proto( let (ty, succ) = get_res_success(ty); // rewrite ty - let tmp = extract_decl(parse_quote! {fn test( + let tmp = extract_decl(syn::parse_quote! {fn test( arg1: <#cls as #p<'p>>::#arg1_name, arg2: <#cls as #p<'p>>::#arg2_name, arg3: <#cls as #p<'p>>::#arg3_name) -> <#cls as #p<'p>>::Result {}}); - let tmp2 = extract_decl(parse_quote! {fn test( + let tmp2 = extract_decl(syn::parse_quote! {fn test( arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg2: Option<<#cls as #p<'p>>::#arg2_name>, arg3: Option<<#cls as #p<'p>>::#arg3_name>) @@ -331,13 +332,13 @@ pub fn impl_method_proto( let (ty, succ) = get_res_success(ty); // rewrite ty - let tmp = extract_decl(parse_quote! {fn test( + let tmp = extract_decl(syn::parse_quote! {fn test( &self, arg1: <#cls as #p<'p>>::#arg1_name, arg2: <#cls as #p<'p>>::#arg2_name, arg3: <#cls as #p<'p>>::#arg3_name) -> <#cls as #p<'p>>::Result {}}); - let tmp2 = extract_decl(parse_quote! {fn test( + let tmp2 = extract_decl(syn::parse_quote! {fn test( &self, arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg2: Option<<#cls as #p<'p>>::#arg2_name>, @@ -395,7 +396,7 @@ fn get_arg_ty(sig: &syn::MethodSig, idx: usize) -> syn::Type { // Add a lifetime if there is none if let syn::Type::Reference(ref mut r) = ty { - r.lifetime.get_or_insert(parse_quote! {'p}); + r.lifetime.get_or_insert(syn::parse_quote! {'p}); } ty @@ -492,7 +493,7 @@ fn modify_arg_ty(sig: &mut syn::MethodSig, idx: usize, decl1: &syn::FnDecl, decl fn modify_self_ty(sig: &mut syn::MethodSig) { if let syn::FnArg::SelfRef(ref mut r) = sig.decl.inputs[0] { - r.lifetime = Some(parse_quote! {'p}); + r.lifetime = Some(syn::parse_quote! {'p}); } else { panic!("not supported") } diff --git a/pyo3-derive-backend/src/lib.rs b/pyo3-derive-backend/src/lib.rs index 9d0e8f1b..4c32f63c 100644 --- a/pyo3-derive-backend/src/lib.rs +++ b/pyo3-derive-backend/src/lib.rs @@ -3,13 +3,6 @@ #![recursion_limit = "1024"] -#[macro_use] -extern crate quote; -#[macro_use] -extern crate syn; -extern crate proc_macro; -extern crate proc_macro2; - pub mod args; pub mod defs; pub mod func; diff --git a/pyo3-derive-backend/src/method.rs b/pyo3-derive-backend/src/method.rs index 027ab789..5d1211d5 100644 --- a/pyo3-derive-backend/src/method.rs +++ b/pyo3-derive-backend/src/method.rs @@ -1,10 +1,10 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use syn; - -use args::{parse_arguments, Argument}; +use crate::args::{parse_arguments, Argument}; use proc_macro2::TokenStream; +use quote::quote; use quote::ToTokens; +use syn; #[derive(Clone, PartialEq, Debug)] pub struct FnArg<'a> { @@ -39,7 +39,7 @@ pub struct FnSpec<'a> { pub fn get_return_info(output: &syn::ReturnType) -> syn::Type { match output { - syn::ReturnType::Default => syn::Type::Infer(parse_quote! {_}), + syn::ReturnType::Default => syn::Type::Infer(syn::parse_quote! {_}), syn::ReturnType::Type(_, ref ty) => *ty.clone(), } } diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index 24851ca0..76b77526 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -1,13 +1,13 @@ // Copyright (c) 2017-present PyO3 Project and Contributors //! Code generation for the function that initializes a python module and adds classes and function. -use args; -use method; -use py_method; -use syn; -use utils; - +use crate::args; +use crate::method; +use crate::py_method; +use crate::utils; use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn; /// Generates the function that is called by the python interpreter to initialize the native /// module @@ -48,7 +48,7 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) { { let function_to_python = add_fn_to_module(func, &python_name, pyfn_attrs); let function_wrapper_ident = function_wrapper_ident(&func.ident); - let item: syn::ItemFn = parse_quote! { + let item: syn::ItemFn = syn::parse_quote! { fn block_wrapper() { #function_to_python #module_name.add_wrapped(&#function_wrapper_ident)?; @@ -145,7 +145,7 @@ fn extract_pyfn_attrs( /// Coordinates the naming of a the add-function-to-python-module function fn function_wrapper_ident(name: &syn::Ident) -> syn::Ident { - // Make sure this ident matches the one of wrap_function + // Make sure this ident matches the one of wrap_pyfunction // The trim_start_matches("r#") is for https://github.com/dtolnay/syn/issues/478 syn::Ident::new( &format!( @@ -214,7 +214,7 @@ pub fn add_fn_to_module( } /// Generate static function wrapper (PyCFunction, PyCFunctionWithKeywords) -fn function_c_wrapper(name: &syn::Ident, spec: &method::FnSpec) -> TokenStream { +fn function_c_wrapper(name: &syn::Ident, spec: &method::FnSpec<'_>) -> TokenStream { let names: Vec = spec .args .iter() diff --git a/pyo3-derive-backend/src/py_class.rs b/pyo3-derive-backend/src/py_class.rs index 84c46641..548d111b 100644 --- a/pyo3-derive-backend/src/py_class.rs +++ b/pyo3-derive-backend/src/py_class.rs @@ -1,11 +1,14 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use method::{FnArg, FnSpec, FnType}; +use crate::method::{FnArg, FnSpec, FnType}; +use crate::py_method::{ + impl_py_getter_def, impl_py_setter_def, impl_wrap_getter, impl_wrap_setter, +}; +use crate::utils; use proc_macro2::{Span, TokenStream}; -use py_method::{impl_py_getter_def, impl_py_setter_def, impl_wrap_getter, impl_wrap_setter}; +use quote::quote; use std::collections::HashMap; use syn; -use utils; pub fn build_py_class(class: &mut syn::ItemStruct, attr: &Vec) -> TokenStream { let (params, flags, base) = parse_attribute(attr); @@ -115,9 +118,9 @@ fn impl_class( let mut has_dict = false; for f in flags.iter() { if let syn::Expr::Path(ref epath) = f { - if epath.path == parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} { + if epath.path == syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} { has_weakref = true; - } else if epath.path == parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} { + } else if epath.path == syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} { has_dict = true; } } @@ -265,7 +268,7 @@ fn impl_descriptors(cls: &syn::Type, descriptors: Vec<(syn::Field, Vec)> py: true, reference: false, }], - output: parse_quote!(PyResult<()>), + output: syn::parse_quote!(PyResult<()>), }; impl_py_setter_def( &name, @@ -305,8 +308,8 @@ fn parse_attribute( let mut params = HashMap::new(); // We need the 0 as value for the constant we're later building using quote for when there // are no other flags - let mut flags = vec![parse_quote! {0}]; - let mut base: syn::TypePath = parse_quote! {::pyo3::types::PyObjectRef}; + let mut flags = vec![syn::parse_quote! {0}]; + let mut base: syn::TypePath = syn::parse_quote! {::pyo3::types::PyObjectRef}; for expr in args.iter() { match expr { @@ -315,16 +318,16 @@ fn parse_attribute( let flag = exp.path.segments.first().unwrap().value().ident.to_string(); let path = match flag.as_str() { "gc" => { - parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC} + syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC} } "weakref" => { - parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} + syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} } "subclass" => { - parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE} + syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE} } "dict" => { - parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} + syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} } param => panic!("Unsupported parameter: {}", param), }; diff --git a/pyo3-derive-backend/src/py_impl.rs b/pyo3-derive-backend/src/py_impl.rs index a20e26a6..6e70acd7 100644 --- a/pyo3-derive-backend/src/py_impl.rs +++ b/pyo3-derive-backend/src/py_impl.rs @@ -1,7 +1,8 @@ // Copyright (c) 2017-present PyO3 Project and Contributors +use crate::py_method; use proc_macro2::TokenStream; -use py_method; +use quote::quote; use syn; pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream { diff --git a/pyo3-derive-backend/src/py_method.rs b/pyo3-derive-backend/src/py_method.rs index 61789ecf..6b064ed2 100644 --- a/pyo3-derive-backend/src/py_method.rs +++ b/pyo3-derive-backend/src/py_method.rs @@ -1,12 +1,12 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use method::{FnArg, FnSpec, FnType}; +use crate::method::{FnArg, FnSpec, FnType}; +use crate::utils; +use proc_macro2::{Span, TokenStream}; +use quote::quote; use quote::ToTokens; use syn; -use proc_macro2::{Span, TokenStream}; -use utils; - pub fn gen_py_method<'a>( cls: &syn::Type, name: &syn::Ident, @@ -42,7 +42,7 @@ fn check_generic(name: &syn::Ident, sig: &syn::MethodSig) { } } -pub fn body_to_result(body: &TokenStream, spec: &FnSpec) -> TokenStream { +pub fn body_to_result(body: &TokenStream, spec: &FnSpec<'_>) -> TokenStream { let output = &spec.output; quote! { let _result: ::pyo3::PyResult<<#output as ::pyo3::ReturnTypeIntoPyResult>::Inner> = { @@ -52,7 +52,12 @@ pub fn body_to_result(body: &TokenStream, spec: &FnSpec) -> TokenStream { } /// Generate function wrapper (PyCFunction, PyCFunctionWithKeywords) -pub fn impl_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec, noargs: bool) -> TokenStream { +pub fn impl_wrap( + cls: &syn::Type, + name: &syn::Ident, + spec: &FnSpec<'_>, + noargs: bool, +) -> TokenStream { let body = impl_call(cls, name, &spec); if spec.args.is_empty() && noargs { @@ -100,7 +105,7 @@ pub fn impl_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec, noargs: bool } /// Generate function wrapper for protocol method (PyCFunction, PyCFunctionWithKeywords) -pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let cb = impl_call(cls, name, &spec); let body = impl_arg_params(&spec, cb); @@ -128,7 +133,7 @@ pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok } /// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords) -pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let names: Vec = spec .args .iter() @@ -185,11 +190,11 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Token } /// Generate function wrapper for ffi::initproc -fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let cb = impl_call(cls, name, &spec); let output = &spec.output; - let result_empty: syn::Type = parse_quote!(PyResult<()>); - let empty: syn::Type = parse_quote!(()); + let result_empty: syn::Type = syn::parse_quote!(PyResult<()>); + let empty: syn::Type = syn::parse_quote!(()); if output != &result_empty || output != &empty { panic!("Constructor must return PyResult<()> or a ()"); } @@ -202,7 +207,7 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStr unsafe extern "C" fn __wrap( _slf: *mut ::pyo3::ffi::PyObject, _args: *mut ::pyo3::ffi::PyObject, - _kwargs: *mut ::pyo3::ffi::PyObject) -> ::pyo3::libc::c_int + _kwargs: *mut ::pyo3::ffi::PyObject) -> libc::c_int { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()"); let _pool = ::pyo3::GILPool::new(); @@ -224,7 +229,7 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStr } /// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords) -pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let names: Vec = spec .args .iter() @@ -266,7 +271,7 @@ pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok } /// Generate static method wrapper (PyCFunction, PyCFunctionWithKeywords) -pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let names: Vec = spec .args .iter() @@ -332,7 +337,11 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident) -> TokenStrea } /// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords) -pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream { +pub(crate) fn impl_wrap_setter( + cls: &syn::Type, + name: &syn::Ident, + spec: &FnSpec<'_>, +) -> TokenStream { if spec.args.len() < 1 { println!( "Not enough arguments for setter {}::{}", @@ -346,7 +355,7 @@ pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec #[allow(unused_mut)] unsafe extern "C" fn __wrap( _slf: *mut ::pyo3::ffi::PyObject, - _value: *mut ::pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> ::pyo3::libc::c_int + _value: *mut ::pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> libc::c_int { const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()"); let _pool = ::pyo3::GILPool::new(); @@ -369,7 +378,7 @@ pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec } } -fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec) -> TokenStream { +fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream { let names: Vec = spec .args .iter() @@ -387,8 +396,8 @@ fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec) -> TokenStream } } -pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream { - let args: Vec = spec +pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream { + let args: Vec> = spec .args .iter() .filter(|item| !item.py) @@ -474,7 +483,12 @@ pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream { } } -fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &TokenStream, idx: usize) -> TokenStream { +fn impl_arg_param( + arg: &FnArg<'_>, + spec: &FnSpec<'_>, + body: &TokenStream, + idx: usize, +) -> TokenStream { if arg.py { return body.clone(); } @@ -562,7 +576,7 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &TokenStream, idx: usize) -> pub fn impl_py_method_def( name: &syn::Ident, doc: syn::Lit, - spec: &FnSpec, + spec: &FnSpec<'_>, wrapper: &TokenStream, ) -> TokenStream { if spec.args.is_empty() { diff --git a/pyo3-derive-backend/src/py_proto.rs b/pyo3-derive-backend/src/py_proto.rs index 3098b986..f80b69cd 100644 --- a/pyo3-derive-backend/src/py_proto.rs +++ b/pyo3-derive-backend/src/py_proto.rs @@ -1,10 +1,11 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use defs; -use func::impl_method_proto; -use method::FnSpec; +use crate::defs; +use crate::func::impl_method_proto; +use crate::method::FnSpec; +use crate::py_method; use proc_macro2::TokenStream; -use py_method; +use quote::quote; use quote::ToTokens; use syn; @@ -32,9 +33,9 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> TokenStream { // attach lifetime let mut seg = path.segments.pop().unwrap().into_value(); - seg.arguments = syn::PathArguments::AngleBracketed(parse_quote! {<'p>}); + seg.arguments = syn::PathArguments::AngleBracketed(syn::parse_quote! {<'p>}); path.segments.push(seg); - ast.generics.params = parse_quote! {'p}; + ast.generics.params = syn::parse_quote! {'p}; tokens } else { diff --git a/pyo3cls/Cargo.toml b/pyo3cls/Cargo.toml index e7a6a1fc..69a894d4 100644 --- a/pyo3cls/Cargo.toml +++ b/pyo3cls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3cls" -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" description = "Proc macros for PyO3 package" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] @@ -8,6 +8,7 @@ homepage = "https://github.com/pyo3/pyo3" repository = "https://github.com/pyo3/pyo3" categories = ["api-bindings", "development-tools::ffi"] license = "Apache-2.0" +edition = "2018" [lib] proc-macro = true @@ -16,4 +17,4 @@ proc-macro = true quote= "0.6.9" proc-macro2 = "0.4.20" syn = { version = "0.15.15", features = ["full", "extra-traits"] } -pyo3-derive-backend = { path = "../pyo3-derive-backend", version = "=0.6.0-alpha.1" } +pyo3-derive-backend = { path = "../pyo3-derive-backend", version = "=0.6.0-alpha.2" } diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index 08b98f18..a4f7ee54 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -2,26 +2,18 @@ //! This crate declares only the proc macro attributes, as a crate defining proc macro attributes //! must not contain any other public items. -#![recursion_limit = "1024"] - extern crate proc_macro; -extern crate proc_macro2; -extern crate pyo3_derive_backend; -#[macro_use] -extern crate quote; -#[macro_use] -extern crate syn; - +use proc_macro::TokenStream; use proc_macro2::Span; -use pyo3_derive_backend::*; +use pyo3_derive_backend::{module, py_class, py_impl, py_proto, utils}; +use quote::quote; +use syn; use syn::parse::Parser; use syn::punctuated::Punctuated; +use syn::Token; #[proc_macro_attribute] -pub fn pymodule2( - attr: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pymodule2(attr: TokenStream, input: TokenStream) -> TokenStream { // Parse the token stream into a syntax tree let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodule] must be used on a function"); @@ -46,10 +38,7 @@ pub fn pymodule2( } #[proc_macro_attribute] -pub fn pymodule3( - attr: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pymodule3(attr: TokenStream, input: TokenStream) -> TokenStream { // Parse the token stream into a syntax tree let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodule] must be used on a `fn` block"); @@ -74,10 +63,7 @@ pub fn pymodule3( } #[proc_macro_attribute] -pub fn pyproto( - _: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pyproto(_: TokenStream, input: TokenStream) -> TokenStream { // Parse the token stream into a syntax tree let mut ast: syn::ItemImpl = syn::parse(input).expect("#[pyproto] must be used on an `impl` block"); @@ -93,10 +79,7 @@ pub fn pyproto( } #[proc_macro_attribute] -pub fn pyclass( - attr: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream { // Parse the token stream into a syntax tree let mut ast: syn::ItemStruct = syn::parse(input).expect("#[pyclass] must be used on a `struct`"); @@ -121,10 +104,7 @@ pub fn pyclass( } #[proc_macro_attribute] -pub fn pymethods( - _: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pymethods(_: TokenStream, input: TokenStream) -> TokenStream { // Parse the token stream into a syntax tree let mut ast: syn::ItemImpl = syn::parse(input.clone()).expect("#[pymethods] must be used on an `impl` block"); @@ -140,10 +120,7 @@ pub fn pymethods( } #[proc_macro_attribute] -pub fn pyfunction( - _: proc_macro::TokenStream, - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn pyfunction(_: TokenStream, input: TokenStream) -> TokenStream { let mut ast: syn::ItemFn = syn::parse(input).expect("#[function] must be used on a `fn` block"); // Workaround for https://github.com/dtolnay/syn/issues/478 diff --git a/rust-toolchain b/rust-toolchain index ccaec8d4..07ade694 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2019-01-12 \ No newline at end of file +nightly \ No newline at end of file diff --git a/src/buffer.rs b/src/buffer.rs index 935b2027..e8fb14ff 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -663,7 +663,6 @@ mod test { use super::PyBuffer; use crate::ffi; use crate::python::Python; - use std; #[allow(unused_imports)] use crate::objectprotocol::ObjectProtocol; diff --git a/src/class/macros.rs b/src/class/macros.rs index e625cf6e..ded39c02 100644 --- a/src/class/macros.rs +++ b/src/class/macros.rs @@ -160,7 +160,7 @@ macro_rules! py_binary_self_func { } Err(e) => { e.restore(py); - $crate::std::ptr::null_mut() + std::ptr::null_mut() } } } @@ -302,7 +302,7 @@ macro_rules! py_ternary_self_func { Ok(_) => slf, Err(e) => { e.restore(py); - $crate::std::ptr::null_mut() + std::ptr::null_mut() } } } @@ -317,7 +317,7 @@ macro_rules! py_func_set { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::libc::c_int + ) -> libc::c_int where T: for<'p> $trait_name<'p>, { @@ -365,7 +365,7 @@ macro_rules! py_func_del { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::libc::c_int + ) -> libc::c_int where U: for<'p> $trait_name<'p>, { @@ -407,7 +407,7 @@ macro_rules! py_func_set_del { slf: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, - ) -> $crate::libc::c_int + ) -> libc::c_int where T: for<'p> $trait1<'p> + for<'p> $trait2<'p>, { diff --git a/src/class/methods.rs b/src/class/methods.rs index ef65fee2..fc0d0b48 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -2,7 +2,6 @@ use crate::ffi; use libc::c_int; -use std; use std::ffi::CString; /// `PyMethodDefType` represents different types of python callable objects. diff --git a/src/err.rs b/src/err.rs index 6112edd9..d00810c9 100644 --- a/src/err.rs +++ b/src/err.rs @@ -8,7 +8,6 @@ use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::typeob::PyTypeObject; use crate::types::{exceptions, PyObjectRef, PyType}; use libc::c_int; -use std; use std::error::Error; use std::ffi::CString; use std::io; diff --git a/src/instance.rs b/src/instance.rs index 865080fa..ce905947 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,9 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use std; -use std::mem; -use std::ptr::NonNull; - use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject}; use crate::err::{PyErr, PyResult}; use crate::ffi; @@ -15,6 +11,8 @@ use crate::pythonrun; use crate::typeob::PyTypeCreate; use crate::typeob::{PyTypeInfo, PyTypeObject}; use crate::types::PyObjectRef; +use std::mem; +use std::ptr::NonNull; /// Any instance that is managed Python can have access to `gil`. /// @@ -234,7 +232,7 @@ impl AsPyRefDispatch for Py { unsafe { &*(self as *const instance::Py as *const T) } } fn as_mut_dispatch(&mut self, _py: Python) -> &mut T { - unsafe { &mut *(self as *const _ as *mut T) } + unsafe { &mut *(self as *mut _ as *mut T) } } } diff --git a/src/lib.rs b/src/lib.rs index 89868f22..eca4b0bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,10 @@ //! Rust bindings to the Python interpreter. //! +//! Look at [the guide](https://pyo3.rs/) for a detailed introduction. +//! //! # Ownership and Lifetimes +//! //! In Python, all objects are implicitly reference counted. //! In rust, we will use the `PyObject` type to represent a reference to a Python object. //! @@ -28,10 +31,77 @@ //! //! # Example //! +//! ## Using rust from python +//! +//! Pyo3 can be used to generate a native python module. +//! +//! **`Cargo.toml`** +//! +//! ```toml +//! [package] +//! name = "string-sum" +//! version = "0.1.0" +//! edition = "2018" +//! +//! [lib] +//! name = "string_sum" +//! crate-type = ["cdylib"] +//! +//! [dependencies.pyo3] +//! version = "0.6.0-alpha.2" +//! features = ["extension-module"] +//! ``` +//! +//! **`src/lib.rs`** +//! //! ```rust //! #![feature(specialization)] //! -//! extern crate pyo3; +//! use pyo3::prelude::*; +//! use pyo3::wrap_pyfunction; +//! +//! #[pyfunction] +//! /// Formats the sum of two numbers as string +//! fn sum_as_string(a: usize, b: usize) -> PyResult { +//! Ok((a + b).to_string()) +//! } +//! +//! /// This module is a python module implemented in Rust. +//! #[pymodule] +//! fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { +//! m.add_wrapped(wrap_pyfunction!(sum_as_string))?; +//! +//! Ok(()) +//! } +//! ``` +//! +//! On windows and linux, you can build normally with `cargo build --release`. On macOS, 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: +//! +//! ```toml +//! [target.x86_64-apple-darwin] +//! rustflags = [ +//! "-C", "link-arg=-undefined", +//! "-C", "link-arg=dynamic_lookup", +//! ] +//! ``` +//! +//! For developing, you can copy and rename the shared library from the target folder: On macOS, rename `libstring_sum.dylib` to `string_sum.so`, on windows `libstring_sum.dll` to `string_sum.pyd` and on linux `libstring_sum.so` to `string_sum.so`. Then open a python shell in the same folder and you'll be able to `import string_sum`. +//! +//! To build, test and publish your crate as python module, you can use [pyo3-pack](https://github.com/PyO3/pyo3-pack) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while pyo3-pack should work on your crate without any configuration. +//! +//! ## Using python from rust +//! +//! Add `pyo3` this to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! pyo3 = "0.6.0-alpha.2" +//! ``` +//! +//! Example program displaying the value of `sys.version`: +//! +//! ```rust +//! #![feature(specialization)] //! //! use pyo3::prelude::*; //! use pyo3::types::PyDict; @@ -51,91 +121,6 @@ //! Ok(()) //! } //! ``` -//! -//! # Python extension -//! -//! To allow Python to load the rust code as a Python extension -//! module, you need an initialization function with `Fn(Python, &PyModule) -> PyResult<()>` -//! that is annotates with `#[pymodule]`. By default the function name will become the module name, -//! but you can override that with `#[pymodule(name)]`. -//! -//! To creates a Python callable object that invokes a Rust function, specify rust -//! function and decorate it with `#[pyfn()]` attribute. `pyfn()` accepts three parameters. -//! -//! 1. `m`: The module name. -//! 2. name of function visible to Python code. -//! 3. comma separated arguments, i.e. param="None", "*", param3="55" -//! -//! -//! # Example -//! -//! ```rust -//! #![feature(specialization)] -//! -//! extern crate pyo3; -//! use pyo3::prelude::*; -//! -//! // 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. -//! #[pymodule] -//! fn rust2py(py: Python, m: &PyModule) -> PyResult<()> { -//! -//! #[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() {} -//! ``` -//! -//! In your `Cargo.toml`, use the `extension-module` feature for the `pyo3` dependency: -//! -//! ```cargo -//! [dependencies.pyo3] -//! version = "*" -//! features = ["extension-module"] -//! ``` -//! -//! 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: -//! -//! ```toml -//! [target.x86_64-apple-darwin] -//! rustflags = [ -//! "-C", "link-arg=-undefined", -//! "-C", "link-arg=dynamic_lookup", -//! ] -//! ``` -//! -//! 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. -//! -//! [`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. - -#[cfg(test)] -#[macro_use] -extern crate assert_approx_eq; -#[cfg(test)] -#[macro_use] -extern crate indoc; -// We need those types in the macro exports -#[doc(hidden)] -pub extern crate libc; -// We need that reexport for wrap_function -#[doc(hidden)] -pub extern crate mashup; -extern crate pyo3cls; -extern crate spin; pub use crate::class::*; pub use crate::conversion::{ @@ -152,6 +137,13 @@ pub use crate::pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GIL pub use crate::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo}; pub use crate::types::exceptions; +// We need those types in the macro exports +#[doc(hidden)] +pub use libc; +// We need that reexport for wrap_function +#[doc(hidden)] +pub use mashup; + /// Rust FFI declarations for Python pub mod ffi; @@ -203,7 +195,7 @@ pub mod proc_macro { /// /// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped]. #[macro_export] -macro_rules! wrap_function { +macro_rules! wrap_pyfunction { ($function_name:ident) => {{ // Get the mashup macro and its helpers into scope use $crate::mashup::*; @@ -224,7 +216,7 @@ macro_rules! wrap_function { /// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped]. #[cfg(Py_3)] #[macro_export] -macro_rules! wrap_module { +macro_rules! wrap_pymodule { ($module_name:ident) => {{ use $crate::mashup::*; diff --git a/src/object.rs b/src/object.rs index e614034d..cfd7c771 100644 --- a/src/object.rs +++ b/src/object.rs @@ -1,6 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use std; use std::ptr::NonNull; use crate::conversion::{ @@ -18,7 +17,7 @@ use crate::types::{PyDict, PyObjectRef, PyTuple}; /// The python object's lifetime is managed by python's garbage /// collector. /// -/// Technically, it is a safe wrapper around the unsafe `*mut ffi::PyObject` pointer. +/// Technically, it is a safe wrapper around `NonNull`. #[derive(Debug)] #[repr(transparent)] pub struct PyObject(NonNull); @@ -258,11 +257,11 @@ impl PyObject { impl AsPyRef for PyObject { #[inline] fn as_ref(&self, _py: Python) -> &PyObjectRef { - unsafe { &*(self as *const _ as *mut PyObjectRef) } + unsafe { &*(self as *const _ as *const PyObjectRef) } } #[inline] fn as_mut(&mut self, _py: Python) -> &mut PyObjectRef { - unsafe { &mut *(self as *const _ as *mut PyObjectRef) } + unsafe { &mut *(self as *mut _ as *mut PyObjectRef) } } } diff --git a/src/objectprotocol.rs b/src/objectprotocol.rs index ab6df74f..a4bf2372 100644 --- a/src/objectprotocol.rs +++ b/src/objectprotocol.rs @@ -9,7 +9,6 @@ use crate::object::PyObject; use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::typeob::PyTypeInfo; use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType}; -use std; use std::cmp::Ordering; use std::os::raw::c_int; diff --git a/src/prelude.rs b/src/prelude.rs index c22efb15..3be12758 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -22,7 +22,6 @@ pub use crate::pythonrun::GILGuard; pub use crate::types::PyModule; // This is required for the constructor pub use crate::PyRawObject; - pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; #[cfg(Py_3)] diff --git a/src/python.rs b/src/python.rs index 3ca04cf3..4907aac9 100644 --- a/src/python.rs +++ b/src/python.rs @@ -11,7 +11,6 @@ use crate::pythonrun::{self, GILGuard}; use crate::typeob::PyTypeCreate; use crate::typeob::{PyTypeInfo, PyTypeObject}; use crate::types::{PyDict, PyModule, PyObjectRef, PyType}; -use std; use std::ffi::CString; use std::marker::PhantomData; use std::os::raw::c_int; @@ -293,6 +292,7 @@ impl<'p> Python<'p> { } } + #[allow(clippy::cast_ref_to_mut)] // FIXME unsafe fn unchecked_mut_downcast(self, ob: &PyObjectRef) -> &'p mut T { if T::OFFSET == 0 { &mut *(ob as *const _ as *mut T) @@ -307,10 +307,7 @@ impl<'p> Python<'p> { where T: PyTypeInfo, { - let p; - unsafe { - p = pythonrun::register_owned(self, obj.into_nonnull()); - } + let p = unsafe { pythonrun::register_owned(self, obj.into_nonnull()) }; ::try_from(p) } diff --git a/src/typeob.rs b/src/typeob.rs index ef660c9b..700902ed 100644 --- a/src/typeob.rs +++ b/src/typeob.rs @@ -2,11 +2,6 @@ //! Python type object information -use std; -use std::collections::HashMap; -use std::ffi::CString; -use std::os::raw::c_void; - use crate::class::methods::PyMethodDefType; use crate::err::{PyErr, PyResult}; use crate::instance::{Py, PyObjectWithGIL}; @@ -15,6 +10,9 @@ use crate::python::{IntoPyPointer, Python}; use crate::types::PyObjectRef; use crate::types::PyType; use crate::{class, ffi, pythonrun}; +use std::collections::HashMap; +use std::ffi::CString; +use std::os::raw::c_void; /// Python type information. pub trait PyTypeInfo { diff --git a/src/types/complex.rs b/src/types/complex.rs index 4d5c81c0..0ce80b45 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -116,13 +116,13 @@ impl<'py> Neg for &'py PyComplex { #[cfg(feature = "num-complex")] mod complex_conversion { - extern crate num_complex; - use self::num_complex::Complex; use super::*; - use conversion::{FromPyObject, IntoPyObject, ToPyObject}; - use err::PyErr; - use types::PyObjectRef; - use PyResult; + use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject}; + use crate::err::PyErr; + use crate::types::PyObjectRef; + use crate::PyResult; + use num_complex::Complex; + impl PyComplex { /// Creates a new Python `PyComplex` object from num_complex::Complex. pub fn from_complex<'py, F: Into>( @@ -153,6 +153,7 @@ mod complex_conversion { } } #[cfg(any(not(Py_LIMITED_API), not(Py_3)))] + #[allow(clippy::float_cmp)] // The comparison is for an error value impl<'source> FromPyObject<'source> for Complex<$float> { fn extract(obj: &'source PyObjectRef) -> PyResult> { unsafe { @@ -166,6 +167,7 @@ mod complex_conversion { } } #[cfg(all(Py_LIMITED_API, Py_3))] + #[allow(clippy::float_cmp)] // The comparison is for an error value impl<'source> FromPyObject<'source> for Complex<$float> { fn extract(obj: &'source PyObjectRef) -> PyResult> { unsafe { @@ -214,6 +216,8 @@ mod complex_conversion { mod test { use super::PyComplex; use crate::python::Python; + use assert_approx_eq::assert_approx_eq; + #[test] fn test_from_double() { let gil = Python::acquire_gil(); diff --git a/src/types/dict.rs b/src/types/dict.rs index 194cc4d1..a6e6a755 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -7,7 +7,6 @@ use crate::instance::PyObjectWithGIL; use crate::object::PyObject; use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::types::{PyList, PyObjectRef}; -use std; use std::{cmp, collections, hash, mem}; /// Represents a Python `dict`. diff --git a/src/types/exceptions.rs b/src/types/exceptions.rs index 8e7fed3b..543f2940 100644 --- a/src/types/exceptions.rs +++ b/src/types/exceptions.rs @@ -44,6 +44,7 @@ macro_rules! impl_exception_boilerplate { /// Defines rust type for exception defined in Python code. /// /// # Syntax +/// /// `import_exception!(module, MyError)` /// /// * `module` is the name of the containing module. @@ -51,26 +52,25 @@ macro_rules! impl_exception_boilerplate { /// /// # Example /// ``` -///extern crate pyo3; +/// use pyo3::import_exception; +/// use pyo3::types::PyDict; +/// use pyo3::Python; /// -///use pyo3::import_exception; -///use pyo3::types::PyDict; -///use pyo3::Python; -///import_exception!(socket, gaierror); +/// import_exception!(socket, gaierror); /// -///fn main() { -/// let gil = Python::acquire_gil(); -/// let py = gil.python(); -/// let ctx = PyDict::new(py); +/// fn main() { +/// let gil = Python::acquire_gil(); +/// let py = gil.python(); +/// let ctx = PyDict::new(py); /// -/// ctx.set_item("gaierror", py.get_type::()).unwrap(); -/// py.run( -/// "import socket; assert gaierror is socket.gaierror", -/// None, -/// Some(ctx), -/// ) -/// .unwrap(); -///} +/// ctx.set_item("gaierror", py.get_type::()).unwrap(); +/// py.run( +/// "import socket; assert gaierror is socket.gaierror", +/// None, +/// Some(ctx), +/// ) +/// .unwrap(); +/// } /// /// ``` #[macro_export] @@ -142,10 +142,8 @@ macro_rules! import_exception_type_object { /// /// # Example /// ``` -/// #[macro_use] -/// extern crate pyo3; -/// /// use pyo3::prelude::*; +/// use pyo3::create_exception; /// use pyo3::types::PyDict; /// use pyo3::exceptions::Exception; /// @@ -360,6 +358,7 @@ impl UnicodeDecodeError { } } + #[allow(clippy::range_plus_one)] // False positive, ..= returns the wrong type pub fn new_utf8<'p>( py: Python<'p>, input: &[u8], diff --git a/src/types/iterator.rs b/src/types/iterator.rs index 3f500a1a..0a74dfe8 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -83,6 +83,8 @@ impl<'p> Drop for PyIterator<'p> { #[cfg(test)] mod tests { + use indoc::indoc; + use crate::conversion::{PyTryFrom, ToPyObject}; use crate::instance::AsPyRef; use crate::objectprotocol::ObjectProtocol; diff --git a/src/types/list.rs b/src/types/list.rs index 44c32257..2bf25d3e 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -2,8 +2,6 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -use std; - use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject}; use crate::err::{self, PyResult}; use crate::ffi::{self, Py_ssize_t}; diff --git a/src/types/module.rs b/src/types/module.rs index d494f6e7..24e29f26 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -171,18 +171,18 @@ impl PyModule { /// Adds a function or a (sub)module to a module, using the functions __name__ as name. /// - /// Use this together with the`#[pyfunction]` and [wrap_function!] or `#[pymodule]` and - /// [wrap_module!]. + /// Use this together with the`#[pyfunction]` and [wrap_pyfunction!] or `#[pymodule]` and + /// [wrap_pymodule!]. /// /// ```rust,ignore - /// m.add_wrapped(wrap_function!(double)); - /// m.add_wrapped(wrap_module!(utils)); + /// m.add_wrapped(wrap_pyfunction!(double)); + /// m.add_wrapped(wrap_pymodule!(utils)); /// ``` /// /// 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_pyfunction!(double)(py)); /// ``` pub fn add_wrapped(&self, wrapper: &Fn(Python) -> PyObject) -> PyResult<()> { let function = wrapper(self.py()); diff --git a/src/types/num2.rs b/src/types/num2.rs index 322b2c26..93c59aaa 100644 --- a/src/types/num2.rs +++ b/src/types/num2.rs @@ -2,18 +2,15 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -use std::os::raw::{c_long, c_uchar}; - -extern crate num_traits; -use self::num_traits::cast::cast; - use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN}; use conversion::{FromPyObject, IntoPyObject, ToPyObject}; use err::{PyErr, PyResult}; use ffi; use instance::{Py, PyObjectWithGIL}; +use num_traits::cast::cast; use object::PyObject; use python::{IntoPyPointer, Python, ToPyPointer}; +use std::os::raw::{c_long, c_uchar}; use types::{exceptions, PyObjectRef}; /// Represents a Python `int` object. diff --git a/src/types/num3.rs b/src/types/num3.rs index ce3b9e7b..766da083 100644 --- a/src/types/num3.rs +++ b/src/types/num3.rs @@ -2,9 +2,6 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -extern crate num_traits; - -use self::num_traits::cast::cast; use super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN}; use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject}; use crate::err::{PyErr, PyResult}; @@ -13,6 +10,7 @@ use crate::instance::PyObjectWithGIL; use crate::object::PyObject; use crate::python::{Python, ToPyPointer}; use crate::types::{exceptions, PyObjectRef}; +use num_traits::cast::cast; use std::i64; use std::os::raw::{c_long, c_uchar}; diff --git a/src/types/num_common.rs b/src/types/num_common.rs index 06749798..6d331667 100644 --- a/src/types/num_common.rs +++ b/src/types/num_common.rs @@ -105,8 +105,6 @@ pub(super) const IS_LITTLE_ENDIAN: c_int = 0; #[cfg(test)] mod test { - use std; - use crate::conversion::ToPyObject; use crate::python::Python; diff --git a/src/types/string.rs b/src/types/string.rs index 78473ce6..73d10348 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -1,10 +1,5 @@ // Copyright (c) 2017-present PyO3 Project and Contributors -use std; -use std::borrow::Cow; -use std::os::raw::c_char; -use std::{mem, str}; - use crate::err::{PyErr, PyResult}; use crate::ffi; use crate::instance::{Py, PyObjectWithGIL}; @@ -12,6 +7,9 @@ use crate::object::PyObject; use crate::python::{Python, ToPyPointer}; use crate::types::exceptions; use crate::types::PyObjectRef; +use std::borrow::Cow; +use std::os::raw::c_char; +use std::{mem, str}; /// Represents a Python `string`. #[repr(transparent)] diff --git a/src/types/string2.rs b/src/types/string2.rs index 7a37b9fe..af405dcc 100644 --- a/src/types/string2.rs +++ b/src/types/string2.rs @@ -2,11 +2,6 @@ // // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython -use std; -use std::borrow::Cow; -use std::os::raw::c_char; -use std::str; - use err::{PyErr, PyResult}; use ffi; use instance::{Py, PyObjectWithGIL}; @@ -14,6 +9,9 @@ use object::PyObject; use objectprotocol::ObjectProtocol; use python::IntoPyPointer; use python::{Python, ToPyPointer}; +use std::borrow::Cow; +use std::os::raw::c_char; +use std::str; use types::exceptions; use super::PyObjectRef; diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rs index aa7bc3ab..f450db51 100644 --- a/tests/test_arithmetics.rs +++ b/tests/test_arithmetics.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::class::*; use pyo3::prelude::*; use pyo3::types::PyObjectRef; diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index fe844233..1cb802cf 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -1,15 +1,12 @@ #![feature(specialization)] -extern crate pyo3; - -use std::os::raw::{c_int, c_void}; -use std::ptr; - use pyo3::class::PyBufferProtocol; use pyo3::exceptions::BufferError; use pyo3::ffi; use pyo3::prelude::*; use pyo3::types::PyDict; +use std::os::raw::{c_int, c_void}; +use std::ptr; #[pyclass] struct TestClass { diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs index 70a4e76a..f4e1c421 100644 --- a/tests/test_class_basics.rs +++ b/tests/test_class_basics.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; #[macro_use] diff --git a/tests/test_class_new.rs b/tests/test_class_new.rs index 7f58a8c2..89d01b34 100644 --- a/tests/test_class_new.rs +++ b/tests/test_class_new.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::PyRawObject; diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index c4a10cca..3d2ca7c2 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -1,7 +1,5 @@ #![feature(concat_idents)] -extern crate pyo3; - use pyo3::ffi::*; use pyo3::prelude::*; use pyo3::types::{PyDate, PyDateTime, PyDict, PyObjectRef, PyTime}; diff --git a/tests/test_dict_iter.rs b/tests/test_dict_iter.rs index f4e36017..778c2a20 100644 --- a/tests/test_dict_iter.rs +++ b/tests/test_dict_iter.rs @@ -1,6 +1,5 @@ -extern crate pyo3; - -use pyo3::{prelude::*, types::IntoPyDict}; +use pyo3::prelude::*; +use pyo3::types::IntoPyDict; #[test] fn iter_dict_nosegv() { diff --git a/tests/test_doc.rs b/tests/test_doc.rs index 55bb5de0..2042d5c7 100644 --- a/tests/test_doc.rs +++ b/tests/test_doc.rs @@ -1,4 +1,4 @@ -extern crate docmatic; +use docmatic; use std::default::Default; use std::path::{Path, PathBuf}; diff --git a/tests/test_dunder.rs b/tests/test_dunder.rs index d1fa1dc6..b0b4815a 100644 --- a/tests/test_dunder.rs +++ b/tests/test_dunder.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use std::{isize, iter}; use pyo3::class::{ diff --git a/tests/test_gc.rs b/tests/test_gc.rs index 5a102ea2..72856d60 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -1,11 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - -use std::cell::RefCell; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; - use pyo3::class::PyGCProtocol; use pyo3::class::PyTraverseError; use pyo3::class::PyVisit; @@ -15,6 +9,9 @@ use pyo3::python::ToPyPointer; use pyo3::types::PyObjectRef; use pyo3::types::PyTuple; use pyo3::PyRawObject; +use std::cell::RefCell; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; #[macro_use] mod common; diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index 8530fc7c..ea95b842 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use std::isize; diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index 6533fdbc..ba67fd5b 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::PyDict; use std::isize; diff --git a/tests/test_methods.rs b/tests/test_methods.rs index a6e2fb39..0b05ae93 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -1,7 +1,5 @@ #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::{PyDict, PyString, PyTuple, PyType}; use pyo3::PyRawObject; diff --git a/tests/test_module.rs b/tests/test_module.rs index bd09da8a..5e132c76 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -1,9 +1,7 @@ #![feature(specialization)] -#[macro_use] -extern crate pyo3; - use pyo3::prelude::*; +use pyo3::{wrap_pyfunction, wrap_pymodule}; #[cfg(Py_3)] use pyo3::types::PyDict; @@ -47,8 +45,8 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> { m.add("foo", "bar").unwrap(); - m.add_wrapped(wrap_function!(double)).unwrap(); - m.add("also_double", wrap_function!(double)(py)).unwrap(); + m.add_wrapped(wrap_pyfunction!(double)).unwrap(); + m.add("also_double", wrap_pyfunction!(double)(py)).unwrap(); Ok(()) } @@ -62,7 +60,7 @@ fn test_module_with_functions() { let d = PyDict::new(py); d.set_item( "module_with_functions", - wrap_module!(module_with_functions)(py), + wrap_pymodule!(module_with_functions)(py), ) .unwrap(); @@ -141,7 +139,7 @@ fn r#move() -> usize { #[pymodule] #[cfg(Py_3)] fn raw_ident_module(_py: Python, module: &PyModule) -> PyResult<()> { - module.add_wrapped(wrap_function!(r#move)) + module.add_wrapped(wrap_pyfunction!(r#move)) } #[test] @@ -150,7 +148,7 @@ fn test_raw_idents() { let gil = Python::acquire_gil(); let py = gil.python(); - let module = wrap_module!(raw_ident_module)(py); + let module = wrap_pymodule!(raw_ident_module)(py); py_assert!(py, module, "module.move() == 42"); } @@ -164,7 +162,7 @@ fn subfunction() -> String { #[cfg(Py_3)] #[pymodule] fn submodule(_py: Python, module: &PyModule) -> PyResult<()> { - module.add_wrapped(wrap_function!(subfunction))?; + module.add_wrapped(wrap_pyfunction!(subfunction))?; Ok(()) } @@ -177,8 +175,8 @@ fn superfunction() -> String { #[cfg(Py_3)] #[pymodule] fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> { - module.add_wrapped(wrap_function!(superfunction))?; - module.add_wrapped(wrap_module!(submodule))?; + module.add_wrapped(wrap_pyfunction!(superfunction))?; + module.add_wrapped(wrap_pymodule!(submodule))?; Ok(()) } @@ -187,7 +185,7 @@ fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> { fn test_module_nesting() { let gil = GILGuard::acquire(); let py = gil.python(); - let supermodule = wrap_module!(supermodule)(py); + let supermodule = wrap_pymodule!(supermodule)(py); py_assert!( py, diff --git a/tests/test_variable_arguments.rs b/tests/test_variable_arguments.rs index 5dde81cc..133d576d 100644 --- a/tests/test_variable_arguments.rs +++ b/tests/test_variable_arguments.rs @@ -1,8 +1,5 @@ -#![feature(custom_attribute)] #![feature(specialization)] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; diff --git a/tests/test_various.rs b/tests/test_various.rs index ffdcf13e..5679f40a 100644 --- a/tests/test_various.rs +++ b/tests/test_various.rs @@ -1,10 +1,8 @@ #![feature(specialization)] -#[macro_use] -extern crate pyo3; - use pyo3::prelude::*; use pyo3::types::PyDict; +use pyo3::wrap_pyfunction; use std::isize; #[macro_use] @@ -63,6 +61,6 @@ fn return_custom_class() { assert_eq!(get_zero().unwrap().value, 0); // Using from python - let get_zero = wrap_function!(get_zero)(py); + let get_zero = wrap_pyfunction!(get_zero)(py); py_assert!(py, get_zero, "get_zero().value == 0"); }