Migrate to rust 2018
This commit is contained in:
parent
423b5d1099
commit
936f0153e8
|
@ -14,7 +14,7 @@ dist/
|
|||
.eggs/
|
||||
venv*
|
||||
guide/book/
|
||||
examples/*/py
|
||||
examples/*/py*
|
||||
|
||||
*.so
|
||||
*.out
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
20
README.md
20
README.md
|
@ -31,19 +31,20 @@ sudo apt install python3-dev python-dev
|
|||
|
||||
Pyo3 can be used to generate a native python module.
|
||||
|
||||
**`Cargo.toml`:**
|
||||
**`Cargo.toml`**
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "string-sum"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "string_sum"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies.pyo3]
|
||||
version = "0.6.0-alpha.1"
|
||||
version = "0.6.0-alpha.2"
|
||||
features = ["extension-module"]
|
||||
```
|
||||
|
||||
|
@ -52,10 +53,8 @@ features = ["extension-module"]
|
|||
```rust
|
||||
#![feature(specialization)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
#[pyfunction]
|
||||
/// Formats the sum of two numbers as string
|
||||
|
@ -66,7 +65,7 @@ fn sum_as_string(a: usize, b: usize) -> PyResult<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(())
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
3
build.rs
3
build.rs
|
@ -1,6 +1,3 @@
|
|||
extern crate regex;
|
||||
extern crate version_check;
|
||||
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::AsRef;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pyo3;
|
||||
|
||||
pub mod datetime;
|
||||
pub mod dict_iter;
|
||||
pub mod othermod;
|
||||
|
|
|
@ -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())?;
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
authors = ["Messense Lv <messense@icloud.com>"]
|
||||
name = "word-count"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rayon = "1.0.2"
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -27,8 +27,6 @@ py_class!(class MyClass |py| {
|
|||
```rust
|
||||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::PyRawObject;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
nightly-2019-01-12
|
||||
nightly
|
|
@ -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;
|
||||
|
|
|
@ -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>,
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
168
src/lib.rs
168
src/lib.rs
|
@ -2,7 +2,10 @@
|
|||
|
||||
//! Rust bindings to the Python interpreter.
|
||||
//!
|
||||
//! Look at [the guide](https://pyo3.rs/) for a detailed introduction.
|
||||
//!
|
||||
//! # Ownership and Lifetimes
|
||||
//!
|
||||
//! In Python, all objects are implicitly reference counted.
|
||||
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
|
||||
//!
|
||||
|
@ -28,10 +31,77 @@
|
|||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ## Using rust from python
|
||||
//!
|
||||
//! Pyo3 can be used to generate a native python module.
|
||||
//!
|
||||
//! **`Cargo.toml`**
|
||||
//!
|
||||
//! ```toml
|
||||
//! [package]
|
||||
//! name = "string-sum"
|
||||
//! version = "0.1.0"
|
||||
//! edition = "2018"
|
||||
//!
|
||||
//! [lib]
|
||||
//! name = "string_sum"
|
||||
//! crate-type = ["cdylib"]
|
||||
//!
|
||||
//! [dependencies.pyo3]
|
||||
//! version = "0.6.0-alpha.2"
|
||||
//! features = ["extension-module"]
|
||||
//! ```
|
||||
//!
|
||||
//! **`src/lib.rs`**
|
||||
//!
|
||||
//! ```rust
|
||||
//! #![feature(specialization)]
|
||||
//!
|
||||
//! extern crate pyo3;
|
||||
//! use pyo3::prelude::*;
|
||||
//! use pyo3::wrap_pyfunction;
|
||||
//!
|
||||
//! #[pyfunction]
|
||||
//! /// Formats the sum of two numbers as string
|
||||
//! fn sum_as_string(a: usize, b: usize) -> PyResult<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::*;
|
||||
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -44,6 +44,7 @@ macro_rules! impl_exception_boilerplate {
|
|||
/// Defines rust type for exception defined in Python code.
|
||||
///
|
||||
/// # Syntax
|
||||
///
|
||||
/// `import_exception!(module, MyError)`
|
||||
///
|
||||
/// * `module` is the name of the containing module.
|
||||
|
@ -51,26 +52,25 @@ macro_rules! impl_exception_boilerplate {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
///extern crate pyo3;
|
||||
/// use pyo3::import_exception;
|
||||
/// use pyo3::types::PyDict;
|
||||
/// use pyo3::Python;
|
||||
///
|
||||
///use pyo3::import_exception;
|
||||
///use pyo3::types::PyDict;
|
||||
///use pyo3::Python;
|
||||
///import_exception!(socket, gaierror);
|
||||
/// import_exception!(socket, gaierror);
|
||||
///
|
||||
///fn main() {
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let ctx = PyDict::new(py);
|
||||
/// fn main() {
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let ctx = PyDict::new(py);
|
||||
///
|
||||
/// ctx.set_item("gaierror", py.get_type::<gaierror>()).unwrap();
|
||||
/// py.run(
|
||||
/// "import socket; assert gaierror is socket.gaierror",
|
||||
/// None,
|
||||
/// Some(ctx),
|
||||
/// )
|
||||
/// .unwrap();
|
||||
///}
|
||||
/// ctx.set_item("gaierror", py.get_type::<gaierror>()).unwrap();
|
||||
/// py.run(
|
||||
/// "import socket; assert gaierror is socket.gaierror",
|
||||
/// None,
|
||||
/// Some(ctx),
|
||||
/// )
|
||||
/// .unwrap();
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
#[macro_export]
|
||||
|
@ -142,10 +142,8 @@ macro_rules! import_exception_type_object {
|
|||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #[macro_use]
|
||||
/// extern crate pyo3;
|
||||
///
|
||||
/// use pyo3::prelude::*;
|
||||
/// use pyo3::create_exception;
|
||||
/// use pyo3::types::PyDict;
|
||||
/// use pyo3::exceptions::Exception;
|
||||
///
|
||||
|
@ -360,6 +358,7 @@ impl UnicodeDecodeError {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::range_plus_one)] // False positive, ..= returns the wrong type
|
||||
pub fn new_utf8<'p>(
|
||||
py: Python<'p>,
|
||||
input: &[u8],
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::class::*;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::PyObjectRef;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::PyRawObject;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(concat_idents)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::ffi::*;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDate, PyDateTime, PyDict, PyObjectRef, PyTime};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
extern crate pyo3;
|
||||
|
||||
use pyo3::{prelude::*, types::IntoPyDict};
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
|
||||
#[test]
|
||||
fn iter_dict_nosegv() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extern crate docmatic;
|
||||
use docmatic;
|
||||
|
||||
use std::default::Default;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use std::{isize, iter};
|
||||
|
||||
use pyo3::class::{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use std::isize;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::PyDict;
|
||||
use std::isize;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDict, PyString, PyTuple, PyType};
|
||||
use pyo3::PyRawObject;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#![feature(custom_attribute)]
|
||||
#![feature(specialization)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyDict, PyTuple};
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue