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/
venv*
guide/book/
examples/*/py
examples/*/py*
*.so
*.out

View File

@ -8,13 +8,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
* Added a `wrap_module!` macro similar to the existing `wrap_function!` macro. Only available on python 3
* Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3
* Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details.
### Changed
* Renamed `add_function` to `add_wrapped` as it now also supports modules.
* Renamed `#[pymodinit]` to `#[pymodule]`.
* Renamed `py_exception` to `create_exception` and refactored the error macros.
* Renamed `wrap_function!` to `wrap_pyfunction!`
* Migrated to the 2018 edition
### Removed

View File

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

View File

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

View File

@ -1,9 +1,9 @@
#![feature(test)]
extern crate pyo3;
extern crate test;
use test::Bencher;
use pyo3::{prelude::*, types::IntoPyDict};
extern crate test;
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use test::Bencher;
#[bench]
fn iter_dict(b: &mut Bencher) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,6 @@ To define python custom class, rust struct needs to be annotated with `#[pyclass
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
#[pyclass]
@ -45,7 +44,6 @@ attribute. Only the python `__new__` method can be specified, `__init__` is not
```rust
# #![feature(specialization)]
#
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::PyRawObject;
@ -89,7 +87,6 @@ with value of custom class struct. Subclass must call parent's `__new__` method.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::PyRawObject;
#[pyclass]
@ -140,7 +137,6 @@ attributes. i.e.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -166,7 +162,6 @@ rust's special keywords like `type`.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -196,7 +191,6 @@ If parameter is specified, it is used and property name. i.e.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -225,7 +219,6 @@ For simple cases you can also define getters and setters in your Rust struct fie
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
#[pyclass]
struct MyClass {
@ -245,7 +238,6 @@ class method static methods, etc.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -274,7 +266,6 @@ get injected by method wrapper. i.e
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -299,7 +290,6 @@ with`#[classmethod]` attribute.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -332,7 +322,6 @@ for some `T` that implements `IntoPyObject`.
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -356,7 +345,6 @@ with `#[call]` attribute. Arguments of the method are specified same as for inst
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# #[pyclass]
# struct MyClass {
@ -400,7 +388,6 @@ Each parameter could one of following type:
Example:
```rust
# #![feature(specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
#
# #[pyclass]
@ -429,7 +416,7 @@ with `#[pyproto]` attribute.
### Basic object customization
[`PyObjectProtocol`](https://docs.rs/pyo3/0.5.2/class/basic/trait.PyObjectProtocol.html) trait provide several basic customizations.
[`PyObjectProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/basic/trait.PyObjectProtocol.html) trait provide several basic customizations.
#### Attribute access
@ -493,7 +480,7 @@ Each methods corresponds to python's `self.attr`, `self.attr = value` and `del s
If your type owns references to other python objects, you will need to
integrate with Python's garbage collector so that the GC is aware of
those references.
To do this, implement [`PyGCProtocol`](https://docs.rs/pyo3/0.5.2/class/gc/trait.PyGCProtocol.html) trait for your struct.
To do this, implement [`PyGCProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/gc/trait.PyGCProtocol.html) trait for your struct.
It includes two methods `__traverse__` and `__clear__`.
These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API.
`__traverse__` must call `visit.call()` for each reference to another python object.
@ -503,7 +490,6 @@ as every cycle must contain at least one mutable reference.
Example:
```rust
#![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*;
@ -540,7 +526,7 @@ collector, and it is possible to track them with `gc` module methods.
### Iterator Types
Iterators can be defined using the
[`PyIterProtocol`](https://docs.rs/pyo3/0.5.2/class/iter/trait.PyIterProtocol.html) trait.
[`PyIterProtocol`](https://docs.rs/pyo3/0.6.0-alpha.2/class/iter/trait.PyIterProtocol.html) trait.
It includes two methods `__iter__` and `__next__`:
* `fn __iter__(&mut self) -> PyResult<impl IntoPyObject>`
* `fn __next__(&mut self) -> PyResult<Option<impl IntoPyObject>>`
@ -552,8 +538,6 @@ Example:
```rust
#![feature(specialization)]
extern crate pyo3;
use pyo3::prelude::*;
#[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]
```rust
extern crate pyo3;
use pyo3::{Python, IntoPyTuple};
fn main() {
@ -43,16 +42,15 @@ Both methods accept `args` and `kwargs` arguments. `args` argument is generate o
rust tuple with up to 10 elements. Or `NoArgs` object which represents empty tuple object.
```rust
extern crate pyo3;
use pyo3::prelude::*;
# struct SomeObject;
# impl SomeObject {
# fn new(py: Python) -> PyObject {
# pyo3::PyDict::new(py).to_object(py)
# }
# }
#
struct SomeObject;
impl SomeObject {
fn new(py: Python) -> PyObject {
pyo3::PyDict::new(py).to_object(py)
}
}
fn main() {
# let arg1 = "arg1";
# let arg2 = "arg2";
@ -80,22 +78,23 @@ fn main() {
[`IntoPyDict`][IntoPyDict] trait to convert other dict-like containers, e.g. `HashMap`, `BTreeMap` as well as tuples with up to 10 elements and `Vec`s where each element is a two element tuple.
```rust
extern crate pyo3;
use std::collections::HashMap;
use pyo3::prelude::*;
use pyo3::types::{IntoPyDict, PyDict};
use std::collections::HashMap;
struct SomeObject;
impl SomeObject {
fn new(py: Python) -> PyObject {
PyDict::new(py).to_object(py)
}
}
# struct SomeObject;
# impl SomeObject {
# fn new(py: Python) -> PyObject {
# pyo3::PyDict::new(py).to_object(py)
# }
# }
fn main() {
# let key1 = "key1";
# let val1 = 1;
# let key2 = "key2";
# let val2 = 2;
let key1 = "key1";
let val1 = 1;
let key2 = "key2";
let val2 = 2;
let gil = Python::acquire_gil();
let py = gil.python();
@ -105,26 +104,25 @@ fn main() {
// call object with PyDict
let kwargs = PyDict::new(py);
kwargs.set_item(key1, val1);
obj.call(py, NoArgs, kwargs);
obj.call(py, NoArgs, Some(kwargs));
// pass arguments as rust tuple
let kwargs = ((key1, val1), (key2, val2));
obj.call(py, NoArgs, kwargs);
// pass arguments as Vec
let kwargs = vec![(key1, val1), (key2, val2)];
obj.call(py, NoArgs, Some(kwargs.into_py_dict(py)));
// pass arguments as HashMap
let mut kwargs = HashMap::<&str, i32>::new();
kwargs.insert(key1, 1);
obj.call(py, NoArgs, kwargs);
obj.call(py, NoArgs, Some(kwargs.into_py_dict(py)));
}
```
TODO
[`ToPyObject`]: https://docs.rs/pyo3/0.5.2/trait.ToPyObject.html
[IntoPyObject]: https://docs.rs/pyo3/0.5.2/trait.IntoPyObject.html
[PyObject]: https://docs.rs/pyo3/0.5.2/struct.PyObject.html
[IntoPyTuple]: https://docs.rs/pyo3/0.5.2/trait.IntoPyTuple.html
[PyTuple]: https://docs.rs/pyo3/0.5.2/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.5.2/trait.ObjectProtocol.html
[IntoPyDict]: https://docs.rs/pyo3/0.5.2/trait.IntoPyDict.html
[`ToPyObject`]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ToPyObject.html
[IntoPyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyObject.html
[PyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyObject.html
[IntoPyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyTuple.html
[PyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ObjectProtocol.html
[IntoPyDict]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyDict.html

View File

@ -5,7 +5,7 @@
You can use the `create_exception!` macro to define a new exception type:
```rust
#[macro_use] extern crate pyo3;
use pyo3::import_exception;
create_exception!(module, MyError, pyo3::exceptions::Exception);
```
@ -16,9 +16,8 @@ create_exception!(module, MyError, pyo3::exceptions::Exception);
For example:
```rust
#[macro_use] extern crate pyo3;
use pyo3::Python;
use pyo3::prelude::*;
use pyo3::create_exception;
use pyo3::types::PyDict;
use pyo3::exceptions::Exception;
@ -41,8 +40,6 @@ fn main() {
To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html), then call [`PyErr::restore()`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state.
```rust
extern crate pyo3;
use pyo3::{Python, PyErr, exc};
fn main() {
@ -66,7 +63,6 @@ has corresponding rust type, exceptions defined by `create_exception!` and `impo
have rust type as well.
```rust
# extern crate pyo3;
# use pyo3::prelude::*;
# fn check_for_error() -> bool {false}
fn my_func(arg: PyObject) -> PyResult<()> {
@ -84,8 +80,6 @@ Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#is
in `PyO3` there is a [`Python::is_instance()`](https://docs.rs/pyo3/0.2.7/struct.Python.html#method.is_instance) method which does the same thing.
```rust
extern crate pyo3;
use pyo3::{Python, PyBool, PyList};
fn main() {
@ -103,7 +97,6 @@ fn main() {
To check the type of an exception, you can simply do:
```rust
# extern crate pyo3;
# use pyo3::prelude::*;
# fn main() {
# let gil = Python::acquire_gil();
@ -134,7 +127,6 @@ until `Python` object is available.
```rust,ignore
#![feature(specialization)]
extern crate pyo3;
use std::net::TcpListener;
use pyo3::{PyErr, PyResult, exc};
@ -157,7 +149,6 @@ The code snippet above will raise `OSError` in Python if `TcpListener::bind()` r
types so `try!` macro or `?` operator can be used.
```rust
# extern crate pyo3;
use pyo3::prelude::*;
fn parse_int(s: String) -> PyResult<usize> {
@ -175,8 +166,8 @@ It is possible to use exception defined in python code as native rust types.
for that exception.
```rust
#[macro_use] extern crate pyo3;
use pyo3::prelude::*;
use pyo3::import_exception;
import_exception!(io, UnsupportedOperation);

View File

@ -6,12 +6,8 @@ the function to a [module](./module.md)
One way is defining the function in the module definition.
```rust
#![feature(proc_macro)]
extern crate pyo3;
use pyo3::prelude::*;
#[pymodule]
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
@ -36,9 +32,8 @@ as third.
```rust
#![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn double(x: usize) -> usize {
@ -47,7 +42,7 @@ fn double(x: usize) -> usize {
#[pymodule]
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_function!(double)).unwrap();
m.add_wrapped(wrap_pyfunction!(double)).unwrap();
Ok(())
}
@ -95,5 +90,5 @@ You can use `ObjectProtocol::is_callable` to check if you got a callable, which
### Calling rust `Fn`s in python
If you have a static function, you can expose it with `#[pyfunction]` and use `wrap_function!` to get the corresponding `PyObject`. For dynamic functions, e.g. lambda and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a box. (Long-Term a special container similar to wasm-bindgen's `Closure` should take care of that). You can than use a `#[pyclass]` struct with that container as field as a way to pass the function over the ffi-barrier. You can even make that class callable with `__call__` so it looks like a function in python code.
If you have a static function, you can expose it with `#[pyfunction]` and use `wrap_pyfunction!` to get the corresponding `PyObject`. For dynamic functions, e.g. lambda and functions that were passed as arguments, you must put them in some kind of owned container, e.g. a box. (Long-Term a special container similar to wasm-bindgen's `Closure` should take care of that). You can than use a `#[pyclass]` struct with that container as field as a way to pass the function over the ffi-barrier. You can even make that class callable with `__call__` so it looks like a function in python code.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use crate::utils::print_err;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn;
use utils::print_err;
// TODO:
// Add lifetime support for args with Rptr
@ -87,7 +88,7 @@ pub fn impl_method_proto(
let p: syn::Path = syn::parse_str(proto).unwrap();
let (ty, succ) = get_res_success(ty);
let tmp: syn::ItemFn = parse_quote! {
let tmp: syn::ItemFn = syn::parse_quote! {
fn test(&self) -> <#cls as #p<'p>>::Result {}
};
sig.decl.output = tmp.decl.output;
@ -124,11 +125,11 @@ pub fn impl_method_proto(
let arg_ty = get_arg_ty(sig, 1);
let (ty, succ) = get_res_success(ty);
let tmp = extract_decl(parse_quote! {
let tmp = extract_decl(syn::parse_quote! {
fn test(&self,arg: <#cls as #p<'p>>::#arg_name)-> <#cls as #p<'p>>::Result {}
});
let tmp2 = extract_decl(parse_quote! {
let tmp2 = extract_decl(syn::parse_quote! {
fn test( &self, arg: Option<<#cls as #p<'p>>::#arg_name>) -> <#cls as #p<'p>>::Result {}
});
@ -171,11 +172,11 @@ pub fn impl_method_proto(
let (ty, succ) = get_res_success(ty);
// rewrite ty
let tmp = extract_decl(parse_quote! {fn test(
let tmp = extract_decl(syn::parse_quote! {fn test(
arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name)
-> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test(
let tmp2 = extract_decl(syn::parse_quote! {fn test(
arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>)
-> <#cls as #p<'p>>::Result {}});
@ -220,12 +221,12 @@ pub fn impl_method_proto(
let (ty, succ) = get_res_success(ty);
// rewrite ty
let tmp = extract_decl(parse_quote! {fn test(
let tmp = extract_decl(syn::parse_quote! {fn test(
&self,
arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name)
-> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test(
let tmp2 = extract_decl(syn::parse_quote! {fn test(
&self,
arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>)
@ -275,12 +276,12 @@ pub fn impl_method_proto(
let (ty, succ) = get_res_success(ty);
// rewrite ty
let tmp = extract_decl(parse_quote! {fn test(
let tmp = extract_decl(syn::parse_quote! {fn test(
arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name,
arg3: <#cls as #p<'p>>::#arg3_name)
-> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test(
let tmp2 = extract_decl(syn::parse_quote! {fn test(
arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>,
arg3: Option<<#cls as #p<'p>>::#arg3_name>)
@ -331,13 +332,13 @@ pub fn impl_method_proto(
let (ty, succ) = get_res_success(ty);
// rewrite ty
let tmp = extract_decl(parse_quote! {fn test(
let tmp = extract_decl(syn::parse_quote! {fn test(
&self,
arg1: <#cls as #p<'p>>::#arg1_name,
arg2: <#cls as #p<'p>>::#arg2_name,
arg3: <#cls as #p<'p>>::#arg3_name)
-> <#cls as #p<'p>>::Result {}});
let tmp2 = extract_decl(parse_quote! {fn test(
let tmp2 = extract_decl(syn::parse_quote! {fn test(
&self,
arg1: Option<<#cls as #p<'p>>::#arg1_name>,
arg2: Option<<#cls as #p<'p>>::#arg2_name>,
@ -395,7 +396,7 @@ fn get_arg_ty(sig: &syn::MethodSig, idx: usize) -> syn::Type {
// Add a lifetime if there is none
if let syn::Type::Reference(ref mut r) = ty {
r.lifetime.get_or_insert(parse_quote! {'p});
r.lifetime.get_or_insert(syn::parse_quote! {'p});
}
ty
@ -492,7 +493,7 @@ fn modify_arg_ty(sig: &mut syn::MethodSig, idx: usize, decl1: &syn::FnDecl, decl
fn modify_self_ty(sig: &mut syn::MethodSig) {
if let syn::FnArg::SelfRef(ref mut r) = sig.decl.inputs[0] {
r.lifetime = Some(parse_quote! {'p});
r.lifetime = Some(syn::parse_quote! {'p});
} else {
panic!("not supported")
}

View File

@ -3,13 +3,6 @@
#![recursion_limit = "1024"]
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate proc_macro;
extern crate proc_macro2;
pub mod args;
pub mod defs;
pub mod func;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use method::{FnArg, FnSpec, FnType};
use crate::method::{FnArg, FnSpec, FnType};
use crate::utils;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use quote::ToTokens;
use syn;
use proc_macro2::{Span, TokenStream};
use utils;
pub fn gen_py_method<'a>(
cls: &syn::Type,
name: &syn::Ident,
@ -42,7 +42,7 @@ fn check_generic(name: &syn::Ident, sig: &syn::MethodSig) {
}
}
pub fn body_to_result(body: &TokenStream, spec: &FnSpec) -> TokenStream {
pub fn body_to_result(body: &TokenStream, spec: &FnSpec<'_>) -> TokenStream {
let output = &spec.output;
quote! {
let _result: ::pyo3::PyResult<<#output as ::pyo3::ReturnTypeIntoPyResult>::Inner> = {
@ -52,7 +52,12 @@ pub fn body_to_result(body: &TokenStream, spec: &FnSpec) -> TokenStream {
}
/// Generate function wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec, noargs: bool) -> TokenStream {
pub fn impl_wrap(
cls: &syn::Type,
name: &syn::Ident,
spec: &FnSpec<'_>,
noargs: bool,
) -> TokenStream {
let body = impl_call(cls, name, &spec);
if spec.args.is_empty() && noargs {
@ -100,7 +105,7 @@ pub fn impl_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec, noargs: bool
}
/// Generate function wrapper for protocol method (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let cb = impl_call(cls, name, &spec);
let body = impl_arg_params(&spec, cb);
@ -128,7 +133,7 @@ pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok
}
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let names: Vec<syn::Ident> = spec
.args
.iter()
@ -185,11 +190,11 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Token
}
/// Generate function wrapper for ffi::initproc
fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let cb = impl_call(cls, name, &spec);
let output = &spec.output;
let result_empty: syn::Type = parse_quote!(PyResult<()>);
let empty: syn::Type = parse_quote!(());
let result_empty: syn::Type = syn::parse_quote!(PyResult<()>);
let empty: syn::Type = syn::parse_quote!(());
if output != &result_empty || output != &empty {
panic!("Constructor must return PyResult<()> or a ()");
}
@ -202,7 +207,7 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStr
unsafe extern "C" fn __wrap(
_slf: *mut ::pyo3::ffi::PyObject,
_args: *mut ::pyo3::ffi::PyObject,
_kwargs: *mut ::pyo3::ffi::PyObject) -> ::pyo3::libc::c_int
_kwargs: *mut ::pyo3::ffi::PyObject) -> libc::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = ::pyo3::GILPool::new();
@ -224,7 +229,7 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStr
}
/// Generate class method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let names: Vec<syn::Ident> = spec
.args
.iter()
@ -266,7 +271,7 @@ pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> Tok
}
/// Generate static method wrapper (PyCFunction, PyCFunctionWithKeywords)
pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let names: Vec<syn::Ident> = spec
.args
.iter()
@ -332,7 +337,11 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident) -> TokenStrea
}
/// Generate functiona wrapper (PyCFunction, PyCFunctionWithKeywords)
pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec) -> TokenStream {
pub(crate) fn impl_wrap_setter(
cls: &syn::Type,
name: &syn::Ident,
spec: &FnSpec<'_>,
) -> TokenStream {
if spec.args.len() < 1 {
println!(
"Not enough arguments for setter {}::{}",
@ -346,7 +355,7 @@ pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec
#[allow(unused_mut)]
unsafe extern "C" fn __wrap(
_slf: *mut ::pyo3::ffi::PyObject,
_value: *mut ::pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> ::pyo3::libc::c_int
_value: *mut ::pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> libc::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = ::pyo3::GILPool::new();
@ -369,7 +378,7 @@ pub(crate) fn impl_wrap_setter(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec
}
}
fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec) -> TokenStream {
fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec<'_>) -> TokenStream {
let names: Vec<syn::Ident> = spec
.args
.iter()
@ -387,8 +396,8 @@ fn impl_call(_cls: &syn::Type, fname: &syn::Ident, spec: &FnSpec) -> TokenStream
}
}
pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream {
let args: Vec<FnArg> = spec
pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
let args: Vec<FnArg<'_>> = spec
.args
.iter()
.filter(|item| !item.py)
@ -474,7 +483,12 @@ pub fn impl_arg_params(spec: &FnSpec, body: TokenStream) -> TokenStream {
}
}
fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &TokenStream, idx: usize) -> TokenStream {
fn impl_arg_param(
arg: &FnArg<'_>,
spec: &FnSpec<'_>,
body: &TokenStream,
idx: usize,
) -> TokenStream {
if arg.py {
return body.clone();
}
@ -562,7 +576,7 @@ fn impl_arg_param(arg: &FnArg, spec: &FnSpec, body: &TokenStream, idx: usize) ->
pub fn impl_py_method_def(
name: &syn::Ident,
doc: syn::Lit,
spec: &FnSpec,
spec: &FnSpec<'_>,
wrapper: &TokenStream,
) -> TokenStream {
if spec.args.is_empty() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,10 @@
//! Rust bindings to the Python interpreter.
//!
//! Look at [the guide](https://pyo3.rs/) for a detailed introduction.
//!
//! # Ownership and Lifetimes
//!
//! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//!
@ -28,10 +31,77 @@
//!
//! # Example
//!
//! ## Using rust from python
//!
//! Pyo3 can be used to generate a native python module.
//!
//! **`Cargo.toml`**
//!
//! ```toml
//! [package]
//! name = "string-sum"
//! version = "0.1.0"
//! edition = "2018"
//!
//! [lib]
//! name = "string_sum"
//! crate-type = ["cdylib"]
//!
//! [dependencies.pyo3]
//! version = "0.6.0-alpha.2"
//! features = ["extension-module"]
//! ```
//!
//! **`src/lib.rs`**
//!
//! ```rust
//! #![feature(specialization)]
//!
//! extern crate pyo3;
//! use pyo3::prelude::*;
//! use pyo3::wrap_pyfunction;
//!
//! #[pyfunction]
//! /// Formats the sum of two numbers as string
//! fn sum_as_string(a: usize, b: usize) -> PyResult<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::types::PyDict;
@ -51,91 +121,6 @@
//! Ok(())
//! }
//! ```
//!
//! # Python extension
//!
//! To allow Python to load the rust code as a Python extension
//! module, you need an initialization function with `Fn(Python, &PyModule) -> PyResult<()>`
//! that is annotates with `#[pymodule]`. By default the function name will become the module name,
//! but you can override that with `#[pymodule(name)]`.
//!
//! To creates a Python callable object that invokes a Rust function, specify rust
//! function and decorate it with `#[pyfn()]` attribute. `pyfn()` accepts three parameters.
//!
//! 1. `m`: The module name.
//! 2. name of function visible to Python code.
//! 3. comma separated arguments, i.e. param="None", "*", param3="55"
//!
//!
//! # Example
//!
//! ```rust
//! #![feature(specialization)]
//!
//! extern crate pyo3;
//! use pyo3::prelude::*;
//!
//! // Add bindings to the generated python module
//! // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
//! /// This module is implemented in Rust.
//! #[pymodule]
//! fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
//!
//! #[pyfn(m, "sum_as_string")]
//! // ``#[pyfn()]` converts the arguments from Python objects to Rust values
//! // and the Rust return value back into a Python object.
//! fn sum_as_string_py(a:i64, b:i64) -> PyResult<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::conversion::{
@ -152,6 +137,13 @@ pub use crate::pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GIL
pub use crate::typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub use crate::types::exceptions;
// We need those types in the macro exports
#[doc(hidden)]
pub use libc;
// We need that reexport for wrap_function
#[doc(hidden)]
pub use mashup;
/// Rust FFI declarations for Python
pub mod ffi;
@ -203,7 +195,7 @@ pub mod proc_macro {
///
/// Use this together with `#[pyfunction]` and [types::PyModule::add_wrapped].
#[macro_export]
macro_rules! wrap_function {
macro_rules! wrap_pyfunction {
($function_name:ident) => {{
// Get the mashup macro and its helpers into scope
use $crate::mashup::*;
@ -224,7 +216,7 @@ macro_rules! wrap_function {
/// Use this together with `#[pymodule]` and [types::PyModule::add_wrapped].
#[cfg(Py_3)]
#[macro_export]
macro_rules! wrap_module {
macro_rules! wrap_pymodule {
($module_name:ident) => {{
use $crate::mashup::*;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -44,6 +44,7 @@ macro_rules! impl_exception_boilerplate {
/// Defines rust type for exception defined in Python code.
///
/// # Syntax
///
/// `import_exception!(module, MyError)`
///
/// * `module` is the name of the containing module.
@ -51,14 +52,13 @@ macro_rules! impl_exception_boilerplate {
///
/// # Example
/// ```
///extern crate pyo3;
/// use pyo3::import_exception;
/// use pyo3::types::PyDict;
/// use pyo3::Python;
///
///use pyo3::import_exception;
///use pyo3::types::PyDict;
///use pyo3::Python;
///import_exception!(socket, gaierror);
/// import_exception!(socket, gaierror);
///
///fn main() {
/// fn main() {
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// let ctx = PyDict::new(py);
@ -70,7 +70,7 @@ macro_rules! impl_exception_boilerplate {
/// Some(ctx),
/// )
/// .unwrap();
///}
/// }
///
/// ```
#[macro_export]
@ -142,10 +142,8 @@ macro_rules! import_exception_type_object {
///
/// # Example
/// ```
/// #[macro_use]
/// extern crate pyo3;
///
/// use pyo3::prelude::*;
/// use pyo3::create_exception;
/// use pyo3::types::PyDict;
/// use pyo3::exceptions::Exception;
///
@ -360,6 +358,7 @@ impl UnicodeDecodeError {
}
}
#[allow(clippy::range_plus_one)] // False positive, ..= returns the wrong type
pub fn new_utf8<'p>(
py: Python<'p>,
input: &[u8],

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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