Migrate to rust 2018

This commit is contained in:
konstin 2019-02-01 14:01:18 +01:00
parent 423b5d1099
commit 936f0153e8
73 changed files with 398 additions and 507 deletions

2
.gitignore vendored
View File

@ -14,7 +14,7 @@ dist/
.eggs/ .eggs/
venv* venv*
guide/book/ guide/book/
examples/*/py examples/*/py*
*.so *.so
*.out *.out

View File

@ -8,13 +8,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added ### 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 ### Changed
* Renamed `add_function` to `add_wrapped` as it now also supports modules. * Renamed `add_function` to `add_wrapped` as it now also supports modules.
* Renamed `#[pymodinit]` to `#[pymodule]`. * Renamed `#[pymodinit]` to `#[pymodule]`.
* Renamed `py_exception` to `create_exception` and refactored the error macros. * Renamed `py_exception` to `create_exception` and refactored the error macros.
* Renamed `wrap_function!` to `wrap_pyfunction!`
* Migrated to the 2018 edition
### Removed ### Removed

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3" name = "pyo3"
version = "0.6.0-alpha.1" version = "0.6.0-alpha.2"
description = "Bindings to Python interpreter" description = "Bindings to Python interpreter"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
readme = "README.md" readme = "README.md"
@ -12,6 +12,7 @@ categories = ["api-bindings", "development-tools::ffi"]
license = "Apache-2.0" license = "Apache-2.0"
exclude = ["/.gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] exclude = ["/.gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
build = "build.rs" build = "build.rs"
edition = "2018"
[badges] [badges]
travis-ci = { repository = "PyO3/pyo3", branch = "master" } travis-ci = { repository = "PyO3/pyo3", branch = "master" }
@ -22,7 +23,7 @@ codecov = { repository = "PyO3/pyo3", branch = "master", service = "github" }
libc = "0.2.43" libc = "0.2.43"
spin = "0.5.0" spin = "0.5.0"
num-traits = "0.2.6" 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" mashup = "0.1.9"
num-complex = { version = "0.2.1", optional = true } num-complex = { version = "0.2.1", optional = true }

View File

@ -31,19 +31,20 @@ sudo apt install python3-dev python-dev
Pyo3 can be used to generate a native python module. Pyo3 can be used to generate a native python module.
**`Cargo.toml`:** **`Cargo.toml`**
```toml ```toml
[package] [package]
name = "string-sum" name = "string-sum"
version = "0.1.0" version = "0.1.0"
edition = "2018"
[lib] [lib]
name = "string_sum" name = "string_sum"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies.pyo3] [dependencies.pyo3]
version = "0.6.0-alpha.1" version = "0.6.0-alpha.2"
features = ["extension-module"] features = ["extension-module"]
``` ```
@ -52,10 +53,8 @@ features = ["extension-module"]
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction] #[pyfunction]
/// Formats the sum of two numbers as string /// Formats the sum of two numbers as string
@ -66,7 +65,7 @@ fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
/// This module is a python module implemented in Rust. /// This module is a python module implemented in Rust.
#[pymodule] #[pymodule]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { 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(()) Ok(())
} }
@ -92,7 +91,7 @@ Add `pyo3` this to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
pyo3 = "0.5" pyo3 = "0.6.0-alpha.2"
``` ```
Example program displaying the value of `sys.version`: Example program displaying the value of `sys.version`:
@ -100,8 +99,6 @@ Example program displaying the value of `sys.version`:
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;
@ -110,11 +107,10 @@ fn main() -> PyResult<()> {
let py = gil.python(); let py = gil.python();
let sys = py.import("sys")?; let sys = py.import("sys")?;
let version: String = sys.get("version")?.extract()?; let version: String = sys.get("version")?.extract()?;
let locals = PyDict::new(py); let locals = PyDict::new(py);
locals.set_item("os", py.import("os")?)?; locals.set_item("os", py.import("os")?)?;
let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract()?; let 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); println!("Hello {}, I'm Python {}", user, version);
Ok(()) Ok(())
} }

View File

@ -1,9 +1,9 @@
#![feature(test)] #![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] #[bench]
fn iter_dict(b: &mut Bencher) { fn iter_dict(b: &mut Bencher) {

View File

@ -1,6 +1,3 @@
extern crate regex;
extern crate version_check;
use regex::Regex; use regex::Regex;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::AsRef; use std::convert::AsRef;

View File

@ -2,8 +2,8 @@
set -ex set -ex
cargo fmt --all -- --check cargo fmt --all -- --check
cargo test --features "$FEATURES" cargo test --features "$FEATURES num-complex"
cargo clippy --features "$FEATURES" cargo clippy --features "$FEATURES num-complex"
for example_dir in examples/*; do for example_dir in examples/*; do
tox -c "$example_dir/tox.ini" -e py tox -c "$example_dir/tox.ini" -e py

View File

@ -3,6 +3,7 @@ authors = ["PyO3 Authors"]
name = "rustapi-module" name = "rustapi-module"
version = "0.1.0" version = "0.1.0"
description = "A Python wrapper for the Rust API for purposes of testing" description = "A Python wrapper for the Rust API for purposes of testing"
edition = "2018"
[dependencies] [dependencies]

View File

@ -3,14 +3,15 @@ use pyo3::types::{
PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple, PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple,
PyTzInfo, PyTzInfo,
}; };
use pyo3::wrap_pyfunction;
#[pyfunction] #[pyfunction]
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> { fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
PyDate::new(py, year, month, day) PyDate::new(py, year, month, day)
} }
#[pyfunction] #[pyfunction]
fn get_date_tuple(py: Python, d: &PyDate) -> Py<PyTuple> { fn get_date_tuple(py: Python<'_>, d: &PyDate) -> Py<PyTuple> {
PyTuple::new( PyTuple::new(
py, py,
&[d.get_year(), d.get_month() as i32, d.get_day() as i32], &[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<PyTuple> {
} }
#[pyfunction] #[pyfunction]
fn date_from_timestamp(py: Python, timestamp: i64) -> PyResult<Py<PyDate>> { fn date_from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult<Py<PyDate>> {
PyDate::from_timestamp(py, timestamp) PyDate::from_timestamp(py, timestamp)
} }
#[pyfunction] #[pyfunction]
fn make_time( fn make_time(
py: Python, py: Python<'_>,
hour: u8, hour: u8,
minute: u8, minute: u8,
second: u8, second: u8,
@ -64,7 +65,7 @@ fn time_with_fold(
} }
#[pyfunction] #[pyfunction]
fn get_time_tuple(py: Python, dt: &PyTime) -> Py<PyTuple> { fn get_time_tuple(py: Python<'_>, dt: &PyTime) -> Py<PyTuple> {
PyTuple::new( PyTuple::new(
py, py,
&[ &[
@ -92,12 +93,12 @@ fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
} }
#[pyfunction] #[pyfunction]
fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResult<Py<PyDelta>> { fn make_delta(py: Python<'_>, days: i32, seconds: i32, microseconds: i32) -> PyResult<Py<PyDelta>> {
PyDelta::new(py, days, seconds, microseconds, true) PyDelta::new(py, days, seconds, microseconds, true)
} }
#[pyfunction] #[pyfunction]
fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> { fn get_delta_tuple(py: Python<'_>, delta: &PyDelta) -> Py<PyTuple> {
PyTuple::new( PyTuple::new(
py, py,
&[ &[
@ -110,7 +111,7 @@ fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> {
#[pyfunction] #[pyfunction]
fn make_datetime( fn make_datetime(
py: Python, py: Python<'_>,
year: i32, year: i32,
month: u8, month: u8,
day: u8, day: u8,
@ -134,7 +135,7 @@ fn make_datetime(
} }
#[pyfunction] #[pyfunction]
fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py<PyTuple> { fn get_datetime_tuple(py: Python<'_>, dt: &PyDateTime) -> Py<PyTuple> {
PyTuple::new( PyTuple::new(
py, py,
&[ &[
@ -168,7 +169,11 @@ fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
} }
#[pyfunction] #[pyfunction]
fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult<Py<PyDateTime>> { fn datetime_from_timestamp(
py: Python<'_>,
ts: f64,
tz: Option<&PyTzInfo>,
) -> PyResult<Py<PyDateTime>> {
PyDateTime::from_timestamp(py, ts, tz) PyDateTime::from_timestamp(py, ts, tz)
} }
@ -189,41 +194,41 @@ impl TzClass {
obj.init(|| TzClass {}) obj.init(|| TzClass {})
} }
fn utcoffset(&self, py: Python, _dt: &PyDateTime) -> PyResult<Py<PyDelta>> { fn utcoffset(&self, py: Python<'_>, _dt: &PyDateTime) -> PyResult<Py<PyDelta>> {
PyDelta::new(py, 0, 3600, 0, true) PyDelta::new(py, 0, 3600, 0, true)
} }
fn tzname(&self, _py: Python, _dt: &PyDateTime) -> PyResult<String> { fn tzname(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult<String> {
Ok(String::from("+01:00")) Ok(String::from("+01:00"))
} }
fn dst(&self, _py: Python, _dt: &PyDateTime) -> PyResult<Option<&PyDelta>> { fn dst(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult<Option<&PyDelta>> {
Ok(None) Ok(None)
} }
} }
#[pymodule] #[pymodule]
fn datetime(_py: Python, m: &PyModule) -> PyResult<()> { fn datetime(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_function!(make_date))?; m.add_wrapped(wrap_pyfunction!(make_date))?;
m.add_wrapped(wrap_function!(get_date_tuple))?; m.add_wrapped(wrap_pyfunction!(get_date_tuple))?;
m.add_wrapped(wrap_function!(date_from_timestamp))?; m.add_wrapped(wrap_pyfunction!(date_from_timestamp))?;
m.add_wrapped(wrap_function!(make_time))?; m.add_wrapped(wrap_pyfunction!(make_time))?;
m.add_wrapped(wrap_function!(get_time_tuple))?; m.add_wrapped(wrap_pyfunction!(get_time_tuple))?;
m.add_wrapped(wrap_function!(make_delta))?; m.add_wrapped(wrap_pyfunction!(make_delta))?;
m.add_wrapped(wrap_function!(get_delta_tuple))?; m.add_wrapped(wrap_pyfunction!(get_delta_tuple))?;
m.add_wrapped(wrap_function!(make_datetime))?; m.add_wrapped(wrap_pyfunction!(make_datetime))?;
m.add_wrapped(wrap_function!(get_datetime_tuple))?; m.add_wrapped(wrap_pyfunction!(get_datetime_tuple))?;
m.add_wrapped(wrap_function!(datetime_from_timestamp))?; m.add_wrapped(wrap_pyfunction!(datetime_from_timestamp))?;
// Python 3.6+ functions // Python 3.6+ functions
#[cfg(Py_3_6)] #[cfg(Py_3_6)]
{ {
m.add_wrapped(wrap_function!(time_with_fold))?; m.add_wrapped(wrap_pyfunction!(time_with_fold))?;
m.add_wrapped(wrap_function!(get_time_tuple_fold))?; m.add_wrapped(wrap_pyfunction!(get_time_tuple_fold))?;
m.add_wrapped(wrap_function!(get_datetime_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::<TzClass>()?; m.add_class::<TzClass>()?;
Ok(()) Ok(())

View File

@ -1,10 +1,9 @@
use pyo3::prelude::*;
use pyo3::exceptions::RuntimeError; use pyo3::exceptions::RuntimeError;
use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;
#[pymodule] #[pymodule]
fn test_dict(_py: Python, m: &PyModule) -> PyResult<()> { fn test_dict(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<DictSize>()?; m.add_class::<DictSize>()?;
Ok(()) Ok(())
} }
@ -21,7 +20,7 @@ impl DictSize {
obj.init(|| DictSize { expected }) obj.init(|| DictSize { expected })
} }
fn iter_dict(&mut self, _py: Python, dict: &PyDict) -> PyResult<u32> { fn iter_dict(&mut self, _py: Python<'_>, dict: &PyDict) -> PyResult<u32> {
let mut seen = 0u32; let mut seen = 0u32;
for (sym, values) in dict.iter() { for (sym, values) in dict.iter() {
seen += 1; seen += 1;

View File

@ -1,8 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
pub mod datetime; pub mod datetime;
pub mod dict_iter; pub mod dict_iter;
pub mod othermod; pub mod othermod;

View File

@ -3,6 +3,7 @@
//! The code below just tries to use the most important code generation paths //! The code below just tries to use the most important code generation paths
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyclass] #[pyclass]
pub struct ModClass { pub struct ModClass {
@ -29,8 +30,8 @@ fn double(x: i32) -> i32 {
} }
#[pymodule] #[pymodule]
fn othermod(_py: Python, m: &PyModule) -> PyResult<()> { fn othermod(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_function!(double))?; m.add_wrapped(wrap_pyfunction!(double))?;
m.add_class::<ModClass>()?; m.add_class::<ModClass>()?;
m.add("USIZE_MIN", usize::min_value())?; m.add("USIZE_MIN", usize::min_value())?;

View File

@ -14,7 +14,7 @@ impl Subclassable {
} }
#[pymodule] #[pymodule]
fn subclassing(_py: Python, m: &PyModule) -> PyResult<()> { fn subclassing(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<Subclassable>()?; m.add_class::<Subclassable>()?;
Ok(()) Ok(())
} }

View File

@ -2,6 +2,7 @@
authors = ["Messense Lv <messense@icloud.com>"] authors = ["Messense Lv <messense@icloud.com>"]
name = "word-count" name = "word-count"
version = "0.1.0" version = "0.1.0"
edition = "2018"
[dependencies] [dependencies]
rayon = "1.0.2" rayon = "1.0.2"

View File

@ -2,11 +2,8 @@
// https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs // https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
extern crate rayon;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use rayon::prelude::*; use rayon::prelude::*;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
@ -27,7 +24,7 @@ impl WordCounter {
} }
/// Searches for the word, parallelized by rayon /// Searches for the word, parallelized by rayon
fn search(&self, py: Python, search: String) -> PyResult<usize> { fn search(&self, py: Python<'_>, search: String) -> PyResult<usize> {
let contents = fs::read_to_string(&self.path)?; let contents = fs::read_to_string(&self.path)?;
let count = py.allow_threads(move || { let count = py.allow_threads(move || {
@ -79,8 +76,8 @@ fn count_line(line: &str, needle: &str) -> usize {
} }
#[pymodule] #[pymodule]
fn word_count(_py: Python, m: &PyModule) -> PyResult<()> { fn word_count(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_function!(count_line))?; m.add_wrapped(wrap_pyfunction!(count_line))?;
m.add_class::<WordCounter>()?; m.add_class::<WordCounter>()?;
Ok(()) Ok(())

View File

@ -6,7 +6,6 @@ To define python custom class, rust struct needs to be annotated with `#[pyclass
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
#[pyclass] #[pyclass]
@ -45,7 +44,6 @@ attribute. Only the python `__new__` method can be specified, `__init__` is not
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# #
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# use pyo3::PyRawObject; # use pyo3::PyRawObject;
@ -89,7 +87,6 @@ with value of custom class struct. Subclass must call parent's `__new__` method.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# use pyo3::PyRawObject; # use pyo3::PyRawObject;
#[pyclass] #[pyclass]
@ -140,7 +137,6 @@ attributes. i.e.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -166,7 +162,6 @@ rust's special keywords like `type`.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -196,7 +191,6 @@ If parameter is specified, it is used and property name. i.e.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -225,7 +219,6 @@ For simple cases you can also define getters and setters in your Rust struct fie
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
#[pyclass] #[pyclass]
struct MyClass { struct MyClass {
@ -245,7 +238,6 @@ class method static methods, etc.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -274,7 +266,6 @@ get injected by method wrapper. i.e
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -299,7 +290,6 @@ with`#[classmethod]` attribute.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -332,7 +322,6 @@ for some `T` that implements `IntoPyObject`.
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -356,7 +345,6 @@ with `#[call]` attribute. Arguments of the method are specified same as for inst
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #[pyclass] # #[pyclass]
# struct MyClass { # struct MyClass {
@ -400,7 +388,6 @@ Each parameter could one of following type:
Example: Example:
```rust ```rust
# #![feature(specialization)] # #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# #
# #[pyclass] # #[pyclass]
@ -429,7 +416,7 @@ with `#[pyproto]` attribute.
### Basic object customization ### 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 #### 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 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 integrate with Python's garbage collector so that the GC is aware of
those references. 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__`. It includes two methods `__traverse__` and `__clear__`.
These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. 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. `__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: Example:
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
@ -540,7 +526,7 @@ collector, and it is possible to track them with `gc` module methods.
### Iterator Types ### Iterator Types
Iterators can be defined using the 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__`: It includes two methods `__iter__` and `__next__`:
* `fn __iter__(&mut self) -> PyResult<impl IntoPyObject>` * `fn __iter__(&mut self) -> PyResult<impl IntoPyObject>`
* `fn __next__(&mut self) -> PyResult<Option<impl IntoPyObject>>` * `fn __next__(&mut self) -> PyResult<Option<impl IntoPyObject>>`
@ -552,8 +538,6 @@ Example:
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
#[pyclass] #[pyclass]

View File

@ -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] For example, [`IntoPyTuple`][IntoPyTuple] trait is implemented for `()` so that you can convert it into a empty [`PyTuple`][PyTuple]
```rust ```rust
extern crate pyo3;
use pyo3::{Python, IntoPyTuple}; use pyo3::{Python, IntoPyTuple};
fn main() { 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 tuple with up to 10 elements. Or `NoArgs` object which represents empty tuple object.
```rust ```rust
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
# struct SomeObject; struct SomeObject;
# impl SomeObject { impl SomeObject {
# fn new(py: Python) -> PyObject { fn new(py: Python) -> PyObject {
# pyo3::PyDict::new(py).to_object(py) pyo3::PyDict::new(py).to_object(py)
# } }
# } }
#
fn main() { fn main() {
# let arg1 = "arg1"; # let arg1 = "arg1";
# let arg2 = "arg2"; # 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. [`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 ```rust
extern crate pyo3;
use std::collections::HashMap;
use pyo3::prelude::*; 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() { fn main() {
# let key1 = "key1"; let key1 = "key1";
# let val1 = 1; let val1 = 1;
# let key2 = "key2"; let key2 = "key2";
# let val2 = 2; let val2 = 2;
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
@ -105,26 +104,25 @@ fn main() {
// call object with PyDict // call object with PyDict
let kwargs = PyDict::new(py); let kwargs = PyDict::new(py);
kwargs.set_item(key1, val1); kwargs.set_item(key1, val1);
obj.call(py, NoArgs, kwargs); obj.call(py, NoArgs, Some(kwargs));
// pass arguments as rust tuple // pass arguments as Vec
let kwargs = ((key1, val1), (key2, val2)); let kwargs = vec![(key1, val1), (key2, val2)];
obj.call(py, NoArgs, kwargs); obj.call(py, NoArgs, Some(kwargs.into_py_dict(py)));
// pass arguments as HashMap // pass arguments as HashMap
let mut kwargs = HashMap::<&str, i32>::new(); let mut kwargs = HashMap::<&str, i32>::new();
kwargs.insert(key1, 1); kwargs.insert(key1, 1);
obj.call(py, NoArgs, kwargs); obj.call(py, NoArgs, Some(kwargs.into_py_dict(py)));
} }
``` ```
TODO TODO
[`ToPyObject`]: https://docs.rs/pyo3/0.5.2/trait.ToPyObject.html [`ToPyObject`]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ToPyObject.html
[IntoPyObject]: https://docs.rs/pyo3/0.5.2/trait.IntoPyObject.html [IntoPyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyObject.html
[PyObject]: https://docs.rs/pyo3/0.5.2/struct.PyObject.html [PyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyObject.html
[IntoPyTuple]: https://docs.rs/pyo3/0.5.2/trait.IntoPyTuple.html [IntoPyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyTuple.html
[PyTuple]: https://docs.rs/pyo3/0.5.2/struct.PyTuple.html [PyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.5.2/trait.ObjectProtocol.html [ObjectProtocol]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ObjectProtocol.html
[IntoPyDict]: https://docs.rs/pyo3/0.5.2/trait.IntoPyDict.html [IntoPyDict]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyDict.html

View File

@ -5,7 +5,7 @@
You can use the `create_exception!` macro to define a new exception type: You can use the `create_exception!` macro to define a new exception type:
```rust ```rust
#[macro_use] extern crate pyo3; use pyo3::import_exception;
create_exception!(module, MyError, pyo3::exceptions::Exception); create_exception!(module, MyError, pyo3::exceptions::Exception);
``` ```
@ -16,9 +16,8 @@ create_exception!(module, MyError, pyo3::exceptions::Exception);
For example: For example:
```rust ```rust
#[macro_use] extern crate pyo3; use pyo3::prelude::*;
use pyo3::create_exception;
use pyo3::Python;
use pyo3::types::PyDict; use pyo3::types::PyDict;
use pyo3::exceptions::Exception; 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. 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 ```rust
extern crate pyo3;
use pyo3::{Python, PyErr, exc}; use pyo3::{Python, PyErr, exc};
fn main() { fn main() {
@ -66,7 +63,6 @@ has corresponding rust type, exceptions defined by `create_exception!` and `impo
have rust type as well. have rust type as well.
```rust ```rust
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# fn check_for_error() -> bool {false} # fn check_for_error() -> bool {false}
fn my_func(arg: PyObject) -> PyResult<()> { 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. 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 ```rust
extern crate pyo3;
use pyo3::{Python, PyBool, PyList}; use pyo3::{Python, PyBool, PyList};
fn main() { fn main() {
@ -103,7 +97,6 @@ fn main() {
To check the type of an exception, you can simply do: To check the type of an exception, you can simply do:
```rust ```rust
# extern crate pyo3;
# use pyo3::prelude::*; # use pyo3::prelude::*;
# fn main() { # fn main() {
# let gil = Python::acquire_gil(); # let gil = Python::acquire_gil();
@ -134,7 +127,6 @@ until `Python` object is available.
```rust,ignore ```rust,ignore
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use std::net::TcpListener; use std::net::TcpListener;
use pyo3::{PyErr, PyResult, exc}; 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. types so `try!` macro or `?` operator can be used.
```rust ```rust
# extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
fn parse_int(s: String) -> PyResult<usize> { fn parse_int(s: String) -> PyResult<usize> {
@ -175,8 +166,8 @@ It is possible to use exception defined in python code as native rust types.
for that exception. for that exception.
```rust ```rust
#[macro_use] extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::import_exception;
import_exception!(io, UnsupportedOperation); import_exception!(io, UnsupportedOperation);

View File

@ -6,12 +6,8 @@ the function to a [module](./module.md)
One way is defining the function in the module definition. One way is defining the function in the module definition.
```rust ```rust
#![feature(proc_macro)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
#[pymodule] #[pymodule]
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> { fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
@ -36,9 +32,8 @@ as third.
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction] #[pyfunction]
fn double(x: usize) -> usize { fn double(x: usize) -> usize {
@ -47,7 +42,7 @@ fn double(x: usize) -> usize {
#[pymodule] #[pymodule]
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> { fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_function!(double)).unwrap(); m.add_wrapped(wrap_pyfunction!(double)).unwrap();
Ok(()) 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 ### 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.

View File

@ -47,10 +47,8 @@ features = ["extension-module"]
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction] #[pyfunction]
/// Formats the sum of two numbers as string /// Formats the sum of two numbers as string
@ -61,7 +59,7 @@ fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
/// This module is a python module implemented in Rust. /// This module is a python module implemented in Rust.
#[pymodule] #[pymodule]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { 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(()) Ok(())
} }
@ -95,8 +93,6 @@ Example program displaying the value of `sys.version`:
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;

View File

@ -3,10 +3,7 @@
As shown in the Getting Started chapter, you can create a module as follows: As shown in the Getting Started chapter, you can create a module as follows:
```rust ```rust
#![feature(proc_macro)] use pyo3::prelude::*;
extern crate pyo3;
use pyo3::{PyResult, Python, PyModule};
// add bindings to the generated python module // add bindings to the generated python module
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
@ -62,20 +59,20 @@ fn subfunction() -> String {
#[pymodule] #[pymodule]
fn submodule(_py: Python, module: &PyModule) -> PyResult<()> { fn submodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_function!(subfunction))?; module.add_wrapped(wrap_pyfunction!(subfunction))?;
Ok(()) Ok(())
} }
#[pymodule] #[pymodule]
fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> { fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_module!(submodule))?; module.add_wrapped(wrap_pymodule!(submodule))?;
Ok(()) Ok(())
} }
fn nested_call() { fn nested_call() {
let gil = GILGuard::acquire(); let gil = GILGuard::acquire();
let py = gil.python(); let py = gil.python();
let supermodule = wrap_module!(supermodule)(py); let supermodule = wrap_pymodule!(supermodule)(py);
ctx.set_item("supermodule", supermodule); ctx.set_item("supermodule", supermodule);
py.run("assert supermodule.submodule.subfuntion() == 'Subfunction'", None, Some(&ctx)).unwrap(); py.run("assert supermodule.submodule.subfuntion() == 'Subfunction'", None, Some(&ctx)).unwrap();

View File

@ -27,8 +27,6 @@ py_class!(class MyClass |py| {
```rust ```rust
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::PyRawObject; use pyo3::PyRawObject;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3-derive-backend" name = "pyo3-derive-backend"
version = "0.6.0-alpha.1" version = "0.6.0-alpha.2"
description = "Code generation for PyO3 package" description = "Code generation for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]
@ -8,6 +8,7 @@ homepage = "https://github.com/pyo3/pyo3"
repository = "https://github.com/pyo3/pyo3" repository = "https://github.com/pyo3/pyo3"
categories = ["api-bindings", "development-tools::ffi"] categories = ["api-bindings", "development-tools::ffi"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2018"
[dependencies] [dependencies]
quote = "0.6.9" quote = "0.6.9"

View File

@ -1,4 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use quote::quote;
use syn; use syn;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -179,12 +181,12 @@ pub fn parse_arguments(items: &[syn::NestedMeta]) -> Vec<Argument> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use args::{parse_arguments, Argument}; use crate::args::{parse_arguments, Argument};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use syn; use syn;
fn items(s: TokenStream) -> Vec<syn::NestedMeta> { fn items(s: TokenStream) -> Vec<syn::NestedMeta> {
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() { match dummy.attrs[0].interpret_meta() {
Some(syn::Meta::List(syn::MetaList { nested, .. })) => { Some(syn::Meta::List(syn::MetaList { nested, .. })) => {
nested.iter().map(Clone::clone).collect() nested.iter().map(Clone::clone).collect()
@ -208,9 +210,9 @@ mod test {
let args = parse_arguments(&items(quote! {#[args(test1, test2, test3="None")]})); let args = parse_arguments(&items(quote! {#[args(test1, test2, test3="None")]}));
assert!( assert!(
args == vec![ args == vec![
Argument::Arg(parse_quote! {test1}, None), Argument::Arg(syn::parse_quote! {test1}, None),
Argument::Arg(parse_quote! {test2}, None), Argument::Arg(syn::parse_quote! {test2}, None),
Argument::Arg(parse_quote! {test3}, Some("None".to_owned())), Argument::Arg(syn::parse_quote! {test3}, Some("None".to_owned())),
] ]
); );
} }
@ -222,10 +224,10 @@ mod test {
)); ));
assert!( assert!(
args == vec![ args == vec![
Argument::Arg(parse_quote! {test1}, None), Argument::Arg(syn::parse_quote! {test1}, None),
Argument::Arg(parse_quote! {test2}, Some("None".to_owned())), Argument::Arg(syn::parse_quote! {test2}, Some("None".to_owned())),
Argument::VarArgsSeparator, 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!( assert!(
args == vec![ args == vec![
Argument::Arg(parse_quote! {test1}, None), Argument::Arg(syn::parse_quote! {test1}, None),
Argument::Arg(parse_quote! {test2}, Some("None".to_owned())), Argument::Arg(syn::parse_quote! {test2}, Some("None".to_owned())),
Argument::VarArgs(parse_quote! {args}), Argument::VarArgs(syn::parse_quote! {args}),
Argument::Kwarg(parse_quote! {test3}, "None".to_owned()), Argument::Kwarg(syn::parse_quote! {test3}, "None".to_owned()),
Argument::KeywordArgs(parse_quote! {kwargs}), Argument::KeywordArgs(syn::parse_quote! {kwargs}),
] ]
); );
} }

View File

@ -1,5 +1,5 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use func::MethodProto; use crate::func::MethodProto;
pub struct Proto { pub struct Proto {
pub name: &'static str, pub name: &'static str,

View File

@ -1,7 +1,8 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::utils::print_err;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn; use syn;
use utils::print_err;
// TODO: // TODO:
// Add lifetime support for args with Rptr // 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 p: syn::Path = syn::parse_str(proto).unwrap();
let (ty, succ) = get_res_success(ty); 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 {} fn test(&self) -> <#cls as #p<'p>>::Result {}
}; };
sig.decl.output = tmp.decl.output; sig.decl.output = tmp.decl.output;
@ -124,11 +125,11 @@ pub fn impl_method_proto(
let arg_ty = get_arg_ty(sig, 1); let arg_ty = get_arg_ty(sig, 1);
let (ty, succ) = get_res_success(ty); 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 {} 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 {} 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); let (ty, succ) = get_res_success(ty);
// rewrite 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, arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name) arg2: <#cls as #p<'p>>::#arg2_name)
-> <#cls as #p<'p>>::Result {}}); -> <#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>, arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>) arg2: Option<<#cls as #p<'p>>::#arg2_name>)
-> <#cls as #p<'p>>::Result {}}); -> <#cls as #p<'p>>::Result {}});
@ -220,12 +221,12 @@ pub fn impl_method_proto(
let (ty, succ) = get_res_success(ty); let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
&self, &self,
arg1: <#cls as #p<'p>>::#arg1_name, arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name) arg2: <#cls as #p<'p>>::#arg2_name)
-> <#cls as #p<'p>>::Result {}}); -> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test( let tmp2 = extract_decl(syn::parse_quote! {fn test(
&self, &self,
arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_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); let (ty, succ) = get_res_success(ty);
// rewrite 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, arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name, arg2: <#cls as #p<'p>>::#arg2_name,
arg3: <#cls as #p<'p>>::#arg3_name) arg3: <#cls as #p<'p>>::#arg3_name)
-> <#cls as #p<'p>>::Result {}}); -> <#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>, arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>, arg2: Option<<#cls as #p<'p>>::#arg2_name>,
arg3: Option<<#cls as #p<'p>>::#arg3_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); let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
&self, &self,
arg1: <#cls as #p<'p>>::#arg1_name, arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name, arg2: <#cls as #p<'p>>::#arg2_name,
arg3: <#cls as #p<'p>>::#arg3_name) arg3: <#cls as #p<'p>>::#arg3_name)
-> <#cls as #p<'p>>::Result {}}); -> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test( let tmp2 = extract_decl(syn::parse_quote! {fn test(
&self, &self,
arg1: Option<<#cls as #p<'p>>::#arg1_name>, arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_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 // Add a lifetime if there is none
if let syn::Type::Reference(ref mut r) = ty { 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 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) { fn modify_self_ty(sig: &mut syn::MethodSig) {
if let syn::FnArg::SelfRef(ref mut r) = sig.decl.inputs[0] { 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 { } else {
panic!("not supported") panic!("not supported")
} }

View File

@ -3,13 +3,6 @@
#![recursion_limit = "1024"] #![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 args;
pub mod defs; pub mod defs;
pub mod func; pub mod func;

View File

@ -1,10 +1,10 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use syn; use crate::args::{parse_arguments, Argument};
use args::{parse_arguments, Argument};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote;
use quote::ToTokens; use quote::ToTokens;
use syn;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub struct FnArg<'a> { pub struct FnArg<'a> {
@ -39,7 +39,7 @@ pub struct FnSpec<'a> {
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type { pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
match output { 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(), syn::ReturnType::Type(_, ref ty) => *ty.clone(),
} }
} }

View File

@ -1,13 +1,13 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
//! Code generation for the function that initializes a python module and adds classes and function. //! Code generation for the function that initializes a python module and adds classes and function.
use args; use crate::args;
use method; use crate::method;
use py_method; use crate::py_method;
use syn; use crate::utils;
use utils;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn;
/// Generates the function that is called by the python interpreter to initialize the native /// Generates the function that is called by the python interpreter to initialize the native
/// module /// 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_to_python = add_fn_to_module(func, &python_name, pyfn_attrs);
let function_wrapper_ident = function_wrapper_ident(&func.ident); 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() { fn block_wrapper() {
#function_to_python #function_to_python
#module_name.add_wrapped(&#function_wrapper_ident)?; #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 /// Coordinates the naming of a the add-function-to-python-module function
fn function_wrapper_ident(name: &syn::Ident) -> syn::Ident { 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 // The trim_start_matches("r#") is for https://github.com/dtolnay/syn/issues/478
syn::Ident::new( syn::Ident::new(
&format!( &format!(
@ -214,7 +214,7 @@ pub fn add_fn_to_module(
} }
/// Generate static function wrapper (PyCFunction, PyCFunctionWithKeywords) /// 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<syn::Ident> = spec let names: Vec<syn::Ident> = spec
.args .args
.iter() .iter()

View File

@ -1,11 +1,14 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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 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 std::collections::HashMap;
use syn; use syn;
use utils;
pub fn build_py_class(class: &mut syn::ItemStruct, attr: &Vec<syn::Expr>) -> TokenStream { pub fn build_py_class(class: &mut syn::ItemStruct, attr: &Vec<syn::Expr>) -> TokenStream {
let (params, flags, base) = parse_attribute(attr); let (params, flags, base) = parse_attribute(attr);
@ -115,9 +118,9 @@ fn impl_class(
let mut has_dict = false; let mut has_dict = false;
for f in flags.iter() { for f in flags.iter() {
if let syn::Expr::Path(ref epath) = f { 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; 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; has_dict = true;
} }
} }
@ -265,7 +268,7 @@ fn impl_descriptors(cls: &syn::Type, descriptors: Vec<(syn::Field, Vec<FnType>)>
py: true, py: true,
reference: false, reference: false,
}], }],
output: parse_quote!(PyResult<()>), output: syn::parse_quote!(PyResult<()>),
}; };
impl_py_setter_def( impl_py_setter_def(
&name, &name,
@ -305,8 +308,8 @@ fn parse_attribute(
let mut params = HashMap::new(); let mut params = HashMap::new();
// We need the 0 as value for the constant we're later building using quote for when there // We need the 0 as value for the constant we're later building using quote for when there
// are no other flags // are no other flags
let mut flags = vec![parse_quote! {0}]; let mut flags = vec![syn::parse_quote! {0}];
let mut base: syn::TypePath = parse_quote! {::pyo3::types::PyObjectRef}; let mut base: syn::TypePath = syn::parse_quote! {::pyo3::types::PyObjectRef};
for expr in args.iter() { for expr in args.iter() {
match expr { match expr {
@ -315,16 +318,16 @@ fn parse_attribute(
let flag = exp.path.segments.first().unwrap().value().ident.to_string(); let flag = exp.path.segments.first().unwrap().value().ident.to_string();
let path = match flag.as_str() { let path = match flag.as_str() {
"gc" => { "gc" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC} syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_GC}
} }
"weakref" => { "weakref" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF} syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_WEAKREF}
} }
"subclass" => { "subclass" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE} syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_BASETYPE}
} }
"dict" => { "dict" => {
parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT} syn::parse_quote! {::pyo3::typeob::PY_TYPE_FLAG_DICT}
} }
param => panic!("Unsupported parameter: {}", param), param => panic!("Unsupported parameter: {}", param),
}; };

View File

@ -1,7 +1,8 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use crate::py_method;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use py_method; use quote::quote;
use syn; use syn;
pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream { pub fn build_py_methods(ast: &mut syn::ItemImpl) -> TokenStream {

View File

@ -1,12 +1,12 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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 quote::ToTokens;
use syn; use syn;
use proc_macro2::{Span, TokenStream};
use utils;
pub fn gen_py_method<'a>( pub fn gen_py_method<'a>(
cls: &syn::Type, cls: &syn::Type,
name: &syn::Ident, 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; let output = &spec.output;
quote! { quote! {
let _result: ::pyo3::PyResult<<#output as ::pyo3::ReturnTypeIntoPyResult>::Inner> = { 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) /// 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); let body = impl_call(cls, name, &spec);
if spec.args.is_empty() && noargs { 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) /// 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 cb = impl_call(cls, name, &spec);
let body = impl_arg_params(&spec, cb); 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) /// 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<syn::Ident> = spec let names: Vec<syn::Ident> = spec
.args .args
.iter() .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 /// 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 cb = impl_call(cls, name, &spec);
let output = &spec.output; let output = &spec.output;
let result_empty: syn::Type = parse_quote!(PyResult<()>); let result_empty: syn::Type = syn::parse_quote!(PyResult<()>);
let empty: syn::Type = parse_quote!(()); let empty: syn::Type = syn::parse_quote!(());
if output != &result_empty || output != &empty { if output != &result_empty || output != &empty {
panic!("Constructor must return PyResult<()> or a ()"); 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( unsafe extern "C" fn __wrap(
_slf: *mut ::pyo3::ffi::PyObject, _slf: *mut ::pyo3::ffi::PyObject,
_args: *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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = ::pyo3::GILPool::new(); 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) /// 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<syn::Ident> = spec let names: Vec<syn::Ident> = spec
.args .args
.iter() .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) /// 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<syn::Ident> = spec let names: Vec<syn::Ident> = spec
.args .args
.iter() .iter()
@ -332,7 +337,11 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident) -> TokenStrea
} }
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords) /// 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 { if spec.args.len() < 1 {
println!( println!(
"Not enough arguments for setter {}::{}", "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)] #[allow(unused_mut)]
unsafe extern "C" fn __wrap( unsafe extern "C" fn __wrap(
_slf: *mut ::pyo3::ffi::PyObject, _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),"()"); const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = ::pyo3::GILPool::new(); 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<syn::Ident> = spec let names: Vec<syn::Ident> = spec
.args .args
.iter() .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 { pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
let args: Vec<FnArg> = spec let args: Vec<FnArg<'_>> = spec
.args .args
.iter() .iter()
.filter(|item| !item.py) .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 { if arg.py {
return body.clone(); 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( pub fn impl_py_method_def(
name: &syn::Ident, name: &syn::Ident,
doc: syn::Lit, doc: syn::Lit,
spec: &FnSpec, spec: &FnSpec<'_>,
wrapper: &TokenStream, wrapper: &TokenStream,
) -> TokenStream { ) -> TokenStream {
if spec.args.is_empty() { if spec.args.is_empty() {

View File

@ -1,10 +1,11 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use defs; use crate::defs;
use func::impl_method_proto; use crate::func::impl_method_proto;
use method::FnSpec; use crate::method::FnSpec;
use crate::py_method;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use py_method; use quote::quote;
use quote::ToTokens; use quote::ToTokens;
use syn; use syn;
@ -32,9 +33,9 @@ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> TokenStream {
// attach lifetime // attach lifetime
let mut seg = path.segments.pop().unwrap().into_value(); 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); path.segments.push(seg);
ast.generics.params = parse_quote! {'p}; ast.generics.params = syn::parse_quote! {'p};
tokens tokens
} else { } else {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pyo3cls" name = "pyo3cls"
version = "0.6.0-alpha.1" version = "0.6.0-alpha.2"
description = "Proc macros for PyO3 package" description = "Proc macros for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"] authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"] keywords = ["pyo3", "python", "cpython", "ffi"]
@ -8,6 +8,7 @@ homepage = "https://github.com/pyo3/pyo3"
repository = "https://github.com/pyo3/pyo3" repository = "https://github.com/pyo3/pyo3"
categories = ["api-bindings", "development-tools::ffi"] categories = ["api-bindings", "development-tools::ffi"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2018"
[lib] [lib]
proc-macro = true proc-macro = true
@ -16,4 +17,4 @@ proc-macro = true
quote= "0.6.9" quote= "0.6.9"
proc-macro2 = "0.4.20" proc-macro2 = "0.4.20"
syn = { version = "0.15.15", features = ["full", "extra-traits"] } 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" }

View File

@ -2,26 +2,18 @@
//! This crate declares only the proc macro attributes, as a crate defining proc macro attributes //! This crate declares only the proc macro attributes, as a crate defining proc macro attributes
//! must not contain any other public items. //! must not contain any other public items.
#![recursion_limit = "1024"]
extern crate proc_macro; extern crate proc_macro;
extern crate proc_macro2; use proc_macro::TokenStream;
extern crate pyo3_derive_backend;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
use proc_macro2::Span; 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::parse::Parser;
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
use syn::Token;
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn pymodule2( pub fn pymodule2(attr: TokenStream, input: TokenStream) -> TokenStream {
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse the token stream into a syntax tree // Parse the token stream into a syntax tree
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodule] must be used on a function"); 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] #[proc_macro_attribute]
pub fn pymodule3( pub fn pymodule3(attr: TokenStream, input: TokenStream) -> TokenStream {
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse the token stream into a syntax tree // Parse the token stream into a syntax tree
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodule] must be used on a `fn` block"); 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] #[proc_macro_attribute]
pub fn pyproto( pub fn pyproto(_: TokenStream, input: TokenStream) -> TokenStream {
_: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse the token stream into a syntax tree // Parse the token stream into a syntax tree
let mut ast: syn::ItemImpl = let mut ast: syn::ItemImpl =
syn::parse(input).expect("#[pyproto] must be used on an `impl` block"); syn::parse(input).expect("#[pyproto] must be used on an `impl` block");
@ -93,10 +79,7 @@ pub fn pyproto(
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn pyclass( pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream {
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse the token stream into a syntax tree // Parse the token stream into a syntax tree
let mut ast: syn::ItemStruct = let mut ast: syn::ItemStruct =
syn::parse(input).expect("#[pyclass] must be used on a `struct`"); syn::parse(input).expect("#[pyclass] must be used on a `struct`");
@ -121,10 +104,7 @@ pub fn pyclass(
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn pymethods( pub fn pymethods(_: TokenStream, input: TokenStream) -> TokenStream {
_: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
// Parse the token stream into a syntax tree // Parse the token stream into a syntax tree
let mut ast: syn::ItemImpl = let mut ast: syn::ItemImpl =
syn::parse(input.clone()).expect("#[pymethods] must be used on an `impl` block"); syn::parse(input.clone()).expect("#[pymethods] must be used on an `impl` block");
@ -140,10 +120,7 @@ pub fn pymethods(
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn pyfunction( pub fn pyfunction(_: TokenStream, input: TokenStream) -> TokenStream {
_: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let mut ast: syn::ItemFn = syn::parse(input).expect("#[function] must be used on a `fn` block"); 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 // Workaround for https://github.com/dtolnay/syn/issues/478

View File

@ -1 +1 @@
nightly-2019-01-12 nightly

View File

@ -663,7 +663,6 @@ mod test {
use super::PyBuffer; use super::PyBuffer;
use crate::ffi; use crate::ffi;
use crate::python::Python; use crate::python::Python;
use std;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;

View File

@ -160,7 +160,7 @@ macro_rules! py_binary_self_func {
} }
Err(e) => { Err(e) => {
e.restore(py); e.restore(py);
$crate::std::ptr::null_mut() std::ptr::null_mut()
} }
} }
} }
@ -302,7 +302,7 @@ macro_rules! py_ternary_self_func {
Ok(_) => slf, Ok(_) => slf,
Err(e) => { Err(e) => {
e.restore(py); 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, slf: *mut $crate::ffi::PyObject,
name: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject,
value: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject,
) -> $crate::libc::c_int ) -> libc::c_int
where where
T: for<'p> $trait_name<'p>, T: for<'p> $trait_name<'p>,
{ {
@ -365,7 +365,7 @@ macro_rules! py_func_del {
slf: *mut $crate::ffi::PyObject, slf: *mut $crate::ffi::PyObject,
name: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject,
value: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject,
) -> $crate::libc::c_int ) -> libc::c_int
where where
U: for<'p> $trait_name<'p>, U: for<'p> $trait_name<'p>,
{ {
@ -407,7 +407,7 @@ macro_rules! py_func_set_del {
slf: *mut $crate::ffi::PyObject, slf: *mut $crate::ffi::PyObject,
name: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject,
value: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject,
) -> $crate::libc::c_int ) -> libc::c_int
where where
T: for<'p> $trait1<'p> + for<'p> $trait2<'p>, T: for<'p> $trait1<'p> + for<'p> $trait2<'p>,
{ {

View File

@ -2,7 +2,6 @@
use crate::ffi; use crate::ffi;
use libc::c_int; use libc::c_int;
use std;
use std::ffi::CString; use std::ffi::CString;
/// `PyMethodDefType` represents different types of python callable objects. /// `PyMethodDefType` represents different types of python callable objects.

View File

@ -8,7 +8,6 @@ use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeObject; use crate::typeob::PyTypeObject;
use crate::types::{exceptions, PyObjectRef, PyType}; use crate::types::{exceptions, PyObjectRef, PyType};
use libc::c_int; use libc::c_int;
use std;
use std::error::Error; use std::error::Error;
use std::ffi::CString; use std::ffi::CString;
use std::io; use std::io;

View File

@ -1,9 +1,5 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
@ -15,6 +11,8 @@ use crate::pythonrun;
use crate::typeob::PyTypeCreate; use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject}; use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use std::mem;
use std::ptr::NonNull;
/// Any instance that is managed Python can have access to `gil`. /// Any instance that is managed Python can have access to `gil`.
/// ///
@ -234,7 +232,7 @@ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
unsafe { &*(self as *const instance::Py<T> as *const T) } unsafe { &*(self as *const instance::Py<T> as *const T) }
} }
fn as_mut_dispatch(&mut self, _py: Python) -> &mut 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) }
} }
} }

View File

@ -2,7 +2,10 @@
//! Rust bindings to the Python interpreter. //! Rust bindings to the Python interpreter.
//! //!
//! Look at [the guide](https://pyo3.rs/) for a detailed introduction.
//!
//! # Ownership and Lifetimes //! # Ownership and Lifetimes
//!
//! In Python, all objects are implicitly reference counted. //! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object. //! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//! //!
@ -28,10 +31,77 @@
//! //!
//! # Example //! # 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 //! ```rust
//! #![feature(specialization)] //! #![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<String> {
//! 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::prelude::*;
//! use pyo3::types::PyDict; //! use pyo3::types::PyDict;
@ -51,91 +121,6 @@
//! Ok(()) //! 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<String> {
//! let out = sum_as_string(a, b);
//! Ok(out)
//! }
//!
//! Ok(())
//! }
//!
//! // The logic can be implemented as a normal rust function
//! fn sum_as_string(a:i64, b:i64) -> String {
//! format!("{}", a + b).to_string()
//! }
//!
//! # fn main() {}
//! ```
//!
//! 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::class::*;
pub use crate::conversion::{ 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::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::types::exceptions; 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 /// Rust FFI declarations for Python
pub mod ffi; pub mod ffi;
@ -203,7 +195,7 @@ pub mod proc_macro {
/// ///
/// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped]. /// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped].
#[macro_export] #[macro_export]
macro_rules! wrap_function { macro_rules! wrap_pyfunction {
($function_name:ident) => {{ ($function_name:ident) => {{
// Get the mashup macro and its helpers into scope // Get the mashup macro and its helpers into scope
use $crate::mashup::*; use $crate::mashup::*;
@ -224,7 +216,7 @@ macro_rules! wrap_function {
/// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped]. /// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped].
#[cfg(Py_3)] #[cfg(Py_3)]
#[macro_export] #[macro_export]
macro_rules! wrap_module { macro_rules! wrap_pymodule {
($module_name:ident) => {{ ($module_name:ident) => {{
use $crate::mashup::*; use $crate::mashup::*;

View File

@ -1,6 +1,5 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use std::ptr::NonNull; use std::ptr::NonNull;
use crate::conversion::{ use crate::conversion::{
@ -18,7 +17,7 @@ use crate::types::{PyDict, PyObjectRef, PyTuple};
/// The python object's lifetime is managed by python's garbage /// The python object's lifetime is managed by python's garbage
/// collector. /// collector.
/// ///
/// Technically, it is a safe wrapper around the unsafe `*mut ffi::PyObject` pointer. /// Technically, it is a safe wrapper around `NonNull<ffi::PyObject>`.
#[derive(Debug)] #[derive(Debug)]
#[repr(transparent)] #[repr(transparent)]
pub struct PyObject(NonNull<ffi::PyObject>); pub struct PyObject(NonNull<ffi::PyObject>);
@ -258,11 +257,11 @@ impl PyObject {
impl AsPyRef<PyObjectRef> for PyObject { impl AsPyRef<PyObjectRef> for PyObject {
#[inline] #[inline]
fn as_ref(&self, _py: Python) -> &PyObjectRef { fn as_ref(&self, _py: Python) -> &PyObjectRef {
unsafe { &*(self as *const _ as *mut PyObjectRef) } unsafe { &*(self as *const _ as *const PyObjectRef) }
} }
#[inline] #[inline]
fn as_mut(&mut self, _py: Python) -> &mut PyObjectRef { 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) }
} }
} }

View File

@ -9,7 +9,6 @@ use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeInfo; use crate::typeob::PyTypeInfo;
use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType}; use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType};
use std;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::os::raw::c_int; use std::os::raw::c_int;

View File

@ -22,7 +22,6 @@ pub use crate::pythonrun::GILGuard;
pub use crate::types::PyModule; pub use crate::types::PyModule;
// This is required for the constructor // This is required for the constructor
pub use crate::PyRawObject; pub use crate::PyRawObject;
pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto}; pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto};
#[cfg(Py_3)] #[cfg(Py_3)]

View File

@ -11,7 +11,6 @@ use crate::pythonrun::{self, GILGuard};
use crate::typeob::PyTypeCreate; use crate::typeob::PyTypeCreate;
use crate::typeob::{PyTypeInfo, PyTypeObject}; use crate::typeob::{PyTypeInfo, PyTypeObject};
use crate::types::{PyDict, PyModule, PyObjectRef, PyType}; use crate::types::{PyDict, PyModule, PyObjectRef, PyType};
use std;
use std::ffi::CString; use std::ffi::CString;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::os::raw::c_int; 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<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p mut T { unsafe fn unchecked_mut_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p mut T {
if T::OFFSET == 0 { if T::OFFSET == 0 {
&mut *(ob as *const _ as *mut T) &mut *(ob as *const _ as *mut T)
@ -307,10 +307,7 @@ impl<'p> Python<'p> {
where where
T: PyTypeInfo, T: PyTypeInfo,
{ {
let p; let p = unsafe { pythonrun::register_owned(self, obj.into_nonnull()) };
unsafe {
p = pythonrun::register_owned(self, obj.into_nonnull());
}
<T as PyTryFrom>::try_from(p) <T as PyTryFrom>::try_from(p)
} }

View File

@ -2,11 +2,6 @@
//! Python type object information //! 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::class::methods::PyMethodDefType;
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyObjectWithGIL};
@ -15,6 +10,9 @@ use crate::python::{IntoPyPointer, Python};
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use crate::types::PyType; use crate::types::PyType;
use crate::{class, ffi, pythonrun}; use crate::{class, ffi, pythonrun};
use std::collections::HashMap;
use std::ffi::CString;
use std::os::raw::c_void;
/// Python type information. /// Python type information.
pub trait PyTypeInfo { pub trait PyTypeInfo {

View File

@ -116,13 +116,13 @@ impl<'py> Neg for &'py PyComplex {
#[cfg(feature = "num-complex")] #[cfg(feature = "num-complex")]
mod complex_conversion { mod complex_conversion {
extern crate num_complex;
use self::num_complex::Complex;
use super::*; use super::*;
use conversion::{FromPyObject, IntoPyObject, ToPyObject}; use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use err::PyErr; use crate::err::PyErr;
use types::PyObjectRef; use crate::types::PyObjectRef;
use PyResult; use crate::PyResult;
use num_complex::Complex;
impl PyComplex { impl PyComplex {
/// Creates a new Python `PyComplex` object from num_complex::Complex. /// Creates a new Python `PyComplex` object from num_complex::Complex.
pub fn from_complex<'py, F: Into<c_double>>( pub fn from_complex<'py, F: Into<c_double>>(
@ -153,6 +153,7 @@ mod complex_conversion {
} }
} }
#[cfg(any(not(Py_LIMITED_API), not(Py_3)))] #[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> { impl<'source> FromPyObject<'source> for Complex<$float> {
fn extract(obj: &'source PyObjectRef) -> PyResult<Complex<$float>> { fn extract(obj: &'source PyObjectRef) -> PyResult<Complex<$float>> {
unsafe { unsafe {
@ -166,6 +167,7 @@ mod complex_conversion {
} }
} }
#[cfg(all(Py_LIMITED_API, Py_3))] #[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> { impl<'source> FromPyObject<'source> for Complex<$float> {
fn extract(obj: &'source PyObjectRef) -> PyResult<Complex<$float>> { fn extract(obj: &'source PyObjectRef) -> PyResult<Complex<$float>> {
unsafe { unsafe {
@ -214,6 +216,8 @@ mod complex_conversion {
mod test { mod test {
use super::PyComplex; use super::PyComplex;
use crate::python::Python; use crate::python::Python;
use assert_approx_eq::assert_approx_eq;
#[test] #[test]
fn test_from_double() { fn test_from_double() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();

View File

@ -7,7 +7,6 @@ use crate::instance::PyObjectWithGIL;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer}; use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::types::{PyList, PyObjectRef}; use crate::types::{PyList, PyObjectRef};
use std;
use std::{cmp, collections, hash, mem}; use std::{cmp, collections, hash, mem};
/// Represents a Python `dict`. /// Represents a Python `dict`.

View File

@ -44,6 +44,7 @@ macro_rules! impl_exception_boilerplate {
/// Defines rust type for exception defined in Python code. /// Defines rust type for exception defined in Python code.
/// ///
/// # Syntax /// # Syntax
///
/// `import_exception!(module, MyError)` /// `import_exception!(module, MyError)`
/// ///
/// * `module` is the name of the containing module. /// * `module` is the name of the containing module.
@ -51,11 +52,10 @@ macro_rules! impl_exception_boilerplate {
/// ///
/// # Example /// # Example
/// ``` /// ```
///extern crate pyo3;
///
/// use pyo3::import_exception; /// use pyo3::import_exception;
/// use pyo3::types::PyDict; /// use pyo3::types::PyDict;
/// use pyo3::Python; /// use pyo3::Python;
///
/// import_exception!(socket, gaierror); /// import_exception!(socket, gaierror);
/// ///
/// fn main() { /// fn main() {
@ -142,10 +142,8 @@ macro_rules! import_exception_type_object {
/// ///
/// # Example /// # Example
/// ``` /// ```
/// #[macro_use]
/// extern crate pyo3;
///
/// use pyo3::prelude::*; /// use pyo3::prelude::*;
/// use pyo3::create_exception;
/// use pyo3::types::PyDict; /// use pyo3::types::PyDict;
/// use pyo3::exceptions::Exception; /// 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>( pub fn new_utf8<'p>(
py: Python<'p>, py: Python<'p>,
input: &[u8], input: &[u8],

View File

@ -83,6 +83,8 @@ impl<'p> Drop for PyIterator<'p> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use indoc::indoc;
use crate::conversion::{PyTryFrom, ToPyObject}; use crate::conversion::{PyTryFrom, ToPyObject};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::objectprotocol::ObjectProtocol;

View File

@ -2,8 +2,6 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use std;
use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject}; use crate::conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use crate::err::{self, PyResult}; use crate::err::{self, PyResult};
use crate::ffi::{self, Py_ssize_t}; use crate::ffi::{self, Py_ssize_t};

View File

@ -171,18 +171,18 @@ impl PyModule {
/// Adds a function or a (sub)module to a module, using the functions __name__ as name. /// 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 /// Use this together with the`#[pyfunction]` and [wrap_pyfunction!] or `#[pymodule]` and
/// [wrap_module!]. /// [wrap_pymodule!].
/// ///
/// ```rust,ignore /// ```rust,ignore
/// m.add_wrapped(wrap_function!(double)); /// m.add_wrapped(wrap_pyfunction!(double));
/// m.add_wrapped(wrap_module!(utils)); /// m.add_wrapped(wrap_pymodule!(utils));
/// ``` /// ```
/// ///
/// You can also add a function with a custom name using [add](PyModule::add): /// You can also add a function with a custom name using [add](PyModule::add):
/// ///
/// ```rust,ignore /// ```rust,ignore
/// m.add("also_double", wrap_function!(double)(py)); /// m.add("also_double", wrap_pyfunction!(double)(py));
/// ``` /// ```
pub fn add_wrapped(&self, wrapper: &Fn(Python) -> PyObject) -> PyResult<()> { pub fn add_wrapped(&self, wrapper: &Fn(Python) -> PyObject) -> PyResult<()> {
let function = wrapper(self.py()); let function = wrapper(self.py());

View File

@ -2,18 +2,15 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // 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 super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN};
use conversion::{FromPyObject, IntoPyObject, ToPyObject}; use conversion::{FromPyObject, IntoPyObject, ToPyObject};
use err::{PyErr, PyResult}; use err::{PyErr, PyResult};
use ffi; use ffi;
use instance::{Py, PyObjectWithGIL}; use instance::{Py, PyObjectWithGIL};
use num_traits::cast::cast;
use object::PyObject; use object::PyObject;
use python::{IntoPyPointer, Python, ToPyPointer}; use python::{IntoPyPointer, Python, ToPyPointer};
use std::os::raw::{c_long, c_uchar};
use types::{exceptions, PyObjectRef}; use types::{exceptions, PyObjectRef};
/// Represents a Python `int` object. /// Represents a Python `int` object.

View File

@ -2,9 +2,6 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // 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 super::num_common::{err_if_invalid_value, IS_LITTLE_ENDIAN};
use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject}; use crate::conversion::{FromPyObject, IntoPyObject, ToPyObject};
use crate::err::{PyErr, PyResult}; use crate::err::{PyErr, PyResult};
@ -13,6 +10,7 @@ use crate::instance::PyObjectWithGIL;
use crate::object::PyObject; use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::python::{Python, ToPyPointer};
use crate::types::{exceptions, PyObjectRef}; use crate::types::{exceptions, PyObjectRef};
use num_traits::cast::cast;
use std::i64; use std::i64;
use std::os::raw::{c_long, c_uchar}; use std::os::raw::{c_long, c_uchar};

View File

@ -105,8 +105,6 @@ pub(super) const IS_LITTLE_ENDIAN: c_int = 0;
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std;
use crate::conversion::ToPyObject; use crate::conversion::ToPyObject;
use crate::python::Python; use crate::python::Python;

View File

@ -1,10 +1,5 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // 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::err::{PyErr, PyResult};
use crate::ffi; use crate::ffi;
use crate::instance::{Py, PyObjectWithGIL}; use crate::instance::{Py, PyObjectWithGIL};
@ -12,6 +7,9 @@ use crate::object::PyObject;
use crate::python::{Python, ToPyPointer}; use crate::python::{Python, ToPyPointer};
use crate::types::exceptions; use crate::types::exceptions;
use crate::types::PyObjectRef; use crate::types::PyObjectRef;
use std::borrow::Cow;
use std::os::raw::c_char;
use std::{mem, str};
/// Represents a Python `string`. /// Represents a Python `string`.
#[repr(transparent)] #[repr(transparent)]

View File

@ -2,11 +2,6 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // 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 err::{PyErr, PyResult};
use ffi; use ffi;
use instance::{Py, PyObjectWithGIL}; use instance::{Py, PyObjectWithGIL};
@ -14,6 +9,9 @@ use object::PyObject;
use objectprotocol::ObjectProtocol; use objectprotocol::ObjectProtocol;
use python::IntoPyPointer; use python::IntoPyPointer;
use python::{Python, ToPyPointer}; use python::{Python, ToPyPointer};
use std::borrow::Cow;
use std::os::raw::c_char;
use std::str;
use types::exceptions; use types::exceptions;
use super::PyObjectRef; use super::PyObjectRef;

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::class::*; use pyo3::class::*;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyObjectRef; use pyo3::types::PyObjectRef;

View File

@ -1,15 +1,12 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use std::os::raw::{c_int, c_void};
use std::ptr;
use pyo3::class::PyBufferProtocol; use pyo3::class::PyBufferProtocol;
use pyo3::exceptions::BufferError; use pyo3::exceptions::BufferError;
use pyo3::ffi; use pyo3::ffi;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;
use std::os::raw::{c_int, c_void};
use std::ptr;
#[pyclass] #[pyclass]
struct TestClass { struct TestClass {

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
#[macro_use] #[macro_use]

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::PyRawObject; use pyo3::PyRawObject;

View File

@ -1,7 +1,5 @@
#![feature(concat_idents)] #![feature(concat_idents)]
extern crate pyo3;
use pyo3::ffi::*; use pyo3::ffi::*;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::{PyDate, PyDateTime, PyDict, PyObjectRef, PyTime}; use pyo3::types::{PyDate, PyDateTime, PyDict, PyObjectRef, PyTime};

View File

@ -1,6 +1,5 @@
extern crate pyo3; use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use pyo3::{prelude::*, types::IntoPyDict};
#[test] #[test]
fn iter_dict_nosegv() { fn iter_dict_nosegv() {

View File

@ -1,4 +1,4 @@
extern crate docmatic; use docmatic;
use std::default::Default; use std::default::Default;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use std::{isize, iter}; use std::{isize, iter};
use pyo3::class::{ use pyo3::class::{

View File

@ -1,11 +1,5 @@
#![feature(specialization)] #![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::PyGCProtocol;
use pyo3::class::PyTraverseError; use pyo3::class::PyTraverseError;
use pyo3::class::PyVisit; use pyo3::class::PyVisit;
@ -15,6 +9,9 @@ use pyo3::python::ToPyPointer;
use pyo3::types::PyObjectRef; use pyo3::types::PyObjectRef;
use pyo3::types::PyTuple; use pyo3::types::PyTuple;
use pyo3::PyRawObject; use pyo3::PyRawObject;
use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
#[macro_use] #[macro_use]
mod common; mod common;

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use std::isize; use std::isize;

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;
use std::isize; use std::isize;

View File

@ -1,7 +1,5 @@
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::{PyDict, PyString, PyTuple, PyType}; use pyo3::types::{PyDict, PyString, PyTuple, PyType};
use pyo3::PyRawObject; use pyo3::PyRawObject;

View File

@ -1,9 +1,7 @@
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::{wrap_pyfunction, wrap_pymodule};
#[cfg(Py_3)] #[cfg(Py_3)]
use pyo3::types::PyDict; use pyo3::types::PyDict;
@ -47,8 +45,8 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
m.add("foo", "bar").unwrap(); m.add("foo", "bar").unwrap();
m.add_wrapped(wrap_function!(double)).unwrap(); m.add_wrapped(wrap_pyfunction!(double)).unwrap();
m.add("also_double", wrap_function!(double)(py)).unwrap(); m.add("also_double", wrap_pyfunction!(double)(py)).unwrap();
Ok(()) Ok(())
} }
@ -62,7 +60,7 @@ fn test_module_with_functions() {
let d = PyDict::new(py); let d = PyDict::new(py);
d.set_item( d.set_item(
"module_with_functions", "module_with_functions",
wrap_module!(module_with_functions)(py), wrap_pymodule!(module_with_functions)(py),
) )
.unwrap(); .unwrap();
@ -141,7 +139,7 @@ fn r#move() -> usize {
#[pymodule] #[pymodule]
#[cfg(Py_3)] #[cfg(Py_3)]
fn raw_ident_module(_py: Python, module: &PyModule) -> PyResult<()> { fn raw_ident_module(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_function!(r#move)) module.add_wrapped(wrap_pyfunction!(r#move))
} }
#[test] #[test]
@ -150,7 +148,7 @@ fn test_raw_idents() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); 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"); py_assert!(py, module, "module.move() == 42");
} }
@ -164,7 +162,7 @@ fn subfunction() -> String {
#[cfg(Py_3)] #[cfg(Py_3)]
#[pymodule] #[pymodule]
fn submodule(_py: Python, module: &PyModule) -> PyResult<()> { fn submodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_function!(subfunction))?; module.add_wrapped(wrap_pyfunction!(subfunction))?;
Ok(()) Ok(())
} }
@ -177,8 +175,8 @@ fn superfunction() -> String {
#[cfg(Py_3)] #[cfg(Py_3)]
#[pymodule] #[pymodule]
fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> { fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_function!(superfunction))?; module.add_wrapped(wrap_pyfunction!(superfunction))?;
module.add_wrapped(wrap_module!(submodule))?; module.add_wrapped(wrap_pymodule!(submodule))?;
Ok(()) Ok(())
} }
@ -187,7 +185,7 @@ fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> {
fn test_module_nesting() { fn test_module_nesting() {
let gil = GILGuard::acquire(); let gil = GILGuard::acquire();
let py = gil.python(); let py = gil.python();
let supermodule = wrap_module!(supermodule)(py); let supermodule = wrap_pymodule!(supermodule)(py);
py_assert!( py_assert!(
py, py,

View File

@ -1,8 +1,5 @@
#![feature(custom_attribute)]
#![feature(specialization)] #![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::{PyDict, PyTuple}; use pyo3::types::{PyDict, PyTuple};

View File

@ -1,10 +1,8 @@
#![feature(specialization)] #![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyDict; use pyo3::types::PyDict;
use pyo3::wrap_pyfunction;
use std::isize; use std::isize;
#[macro_use] #[macro_use]
@ -63,6 +61,6 @@ fn return_custom_class() {
assert_eq!(get_zero().unwrap().value, 0); assert_eq!(get_zero().unwrap().value, 0);
// Using from python // 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"); py_assert!(py, get_zero, "get_zero().value == 0");
} }