Upgrade from proc_macro to use_extern_macros

This commit is contained in:
konstin 2018-07-18 13:08:05 +02:00
parent dbd74401eb
commit d59bebcc38
27 changed files with 78 additions and 107 deletions

View File

@ -4,7 +4,8 @@
* Upgraded to syn 0.14 which means much better error messages :tada:
* 128 bit integer support by [kngwyu](https://github.com/kngwyu) ([#137](https://github.com/PyO3/pyo3/pull/173))
* Added `py` prefixes to the proc macros and moved them into the root module. You should just use the plain proc macros, i.e. `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]`. This is important because `proc_macro_path_invoc` isn't going to be stabilized soon.
* `proc_macro` has been stabilized on nightly ([rust-lang/rust#52081](https://github.com/rust-lang/rust/pull/52081)). This means that we can remove the `proc_macro` feature, but now we need the `use_extern_macros` from the 2018 edition instead.
* All proc macro are now prefixed with `py` and live in the prelude. This means you can use `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]` directly, at least after a `use pyo3::prelude::*`. They were also moved into a module called `proc_macro`. You shouldn't use `#[pyo3::proc_macro::pyclass]` or other longer paths in attributes because `proc_macro_path_invoc` isn't going to be stabilized soon.
* Renamed the `base` option in the `pyclass` macro to `extends`.
* `#[pymodinit]` uses the function name as module name, unless the name is overrriden with `#[pymodinit(name)]`
* The guide is now properly versioned.

View File

@ -25,7 +25,7 @@ pyo3 = "0.2"
Example program displaying the value of `sys.version`:
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
@ -69,12 +69,12 @@ features = ["extension-module"]
**`src/lib.rs`**
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pymodinit;
// Add bindings to the generated python module
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file

View File

@ -9,8 +9,9 @@ use std::process::Command;
use version_check::{is_min_date, is_min_version, supports_features};
// Specifies the minimum nightly version needed to compile pyo3.
const MIN_DATE: &'static str = "2018-05-01";
const MIN_VERSION: &'static str = "1.27.0-nightly";
// This requirement is due to https://github.com/rust-lang/rust/pull/52081
const MIN_DATE: &'static str = "2018-07-16";
const MIN_VERSION: &'static str = "1.29.0-nightly";
#[derive(Debug)]
struct PythonVersion {

View File

@ -1,12 +1,11 @@
// Source adopted from
// https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
extern crate rayon;
use pyo3::prelude::*;
use pyo3::{pyclass, pymethods, pymodinit};
use rayon::prelude::*;
use std::fs::File;
use std::io::prelude::*;

View File

@ -1,6 +1,6 @@
// Source adopted from
// https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
extern crate rayon;
@ -10,8 +10,6 @@ use std::io::prelude::*;
use pyo3::prelude::*;
use rayon::prelude::*;
use pyo3::pymodinit;
fn matches(word: &str, search: &str) -> bool {
let mut search = search.chars();
for ch in word.chars().skip_while(|ch| !ch.is_alphabetic()) {

View File

@ -5,10 +5,10 @@
To define python custom class, rust struct needs to be annotated with `#[pyclass]` attribute.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
use pyo3::pyclass;
#[pyclass]
struct MyClass {
@ -45,11 +45,11 @@ To declare a constructor, you need to define a class method and annotate it with
attribute. Only the python `__new__` method can be specified, `__init__` is not available.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
#
# extern crate pyo3;
# use pyo3::prelude::*;
use pyo3::{pyclass, pymethods};
#[pyclass]
struct MyClass {
@ -92,10 +92,9 @@ By default `PyObject` is used as default base class. To override default base cl
with value of custom class struct. Subclass must call parent's `__new__` method.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
#
#[pyclass]
struct BaseClass {
@ -146,10 +145,9 @@ Descriptor methods can be defined in
attributes. i.e.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -174,10 +172,9 @@ Descriptor name becomes function name with prefix removed. This is useful in cas
rust's special keywords like `type`.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -206,10 +203,9 @@ Also both `#[getter]` and `#[setter]` attributes accepts one parameter.
If parameter is specified, it is used and property name. i.e.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -237,10 +233,9 @@ In this case property `number` is defined. And it is available from python code
For simple cases you can also define getters and setters in your Rust struct field definition, for example:
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
#[pyclass]
struct MyClass {
#[prop(get, set)]
@ -258,10 +253,9 @@ wrappers for all functions in this block with some variations, like descriptors,
class method static methods, etc.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -289,10 +283,9 @@ The return type must be `PyResult<T>` for some `T` that implements `IntoPyObject
get injected by method wrapper. i.e
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -316,10 +309,9 @@ To specify class method for custom class, method needs to be annotated
with`#[classmethod]` attribute.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -351,10 +343,9 @@ with `#[staticmethod]` attribute. The return type must be `PyResult<T>`
for some `T` that implements `IntoPyObject`.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -377,10 +368,9 @@ To specify custom `__call__` method for custom class, call method needs to be an
with `#[call]` attribute. Arguments of the method are specified same as for instance method.
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
# #[pyclass]
# struct MyClass {
# num: i32,
@ -423,10 +413,10 @@ Each parameter could one of following type:
Example:
```rust
# #![feature(proc_macro, specialization)]
# #![feature(use_extern_macros, specialization)]
# extern crate pyo3;
# use pyo3::prelude::*;
# use pyo3::{pyclass, pymethods};
#
# #[pyclass]
# struct MyClass {
# num: i32,
@ -527,11 +517,11 @@ These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API.
as every cycle must contain at least one mutable reference.
Example:
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyclass, pyproto};
#[pyclass]
struct ClassWithGCSupport {
@ -576,11 +566,11 @@ It includes two methods `__iter__` and `__next__`:
Example:
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyclass, pyproto};
#[pyclass]
struct MyIterator {

View File

@ -131,7 +131,7 @@ trait can be implemented. In that case actual exception arguments creation get d
until `Python` object is available.
```rust,ignore
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use std::net::TcpListener;

View File

@ -10,7 +10,7 @@ One way is defining the function in the module definition.
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pymodinit;
#[pymodinit]
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
@ -34,13 +34,13 @@ as first parameter, the function name as second and an instance of `Python`
as third.
```rust
#![feature(proc_macro, concat_idents)]
#![feature(use_extern_macros, concat_idents)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyfunction, pymodinit};
#[pyfunction]
fn double(x: usize) -> usize {

View File

@ -8,7 +8,7 @@ As shown in the Getting Started chapter, you can create a module as follows:
extern crate pyo3;
use pyo3::{PyResult, Python, PyModule};
use pyo3::pymodinit;
// add bindings to the generated python module
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file

View File

@ -59,12 +59,12 @@ features = ["extension-module"]
**`src/lib.rs`**
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pymodinit;
// Add bindings to the generated python module
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file

View File

@ -25,12 +25,12 @@ py_class!(class MyClass |py| {
**pyo3**
```rust
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyclass, pymethods};
#[pyclass]
struct MyClass {

View File

@ -17,7 +17,6 @@ pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS
quote! {
#[no_mangle]
#[allow(non_snake_case)]
#[doc(hidden)]
/// This autogenerated function is called by the python interpreter when importing
/// the module.
pub unsafe extern "C" fn #cb_name() -> *mut ::pyo3::ffi::PyObject {

View File

@ -1,9 +1,8 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! This crate declares only the proc macro attributes, as a crate defining proc macro attributes
//! must not contain any other public items
//! must not contain any other public items.
#![recursion_limit = "1024"]
#![feature(proc_macro)]
extern crate proc_macro;
extern crate proc_macro2;

View File

@ -1,4 +1,4 @@
#![feature(specialization, proc_macro)]
#![feature(specialization, use_extern_macros)]
//! Rust bindings to the Python interpreter.
//!
@ -29,7 +29,7 @@
//! # Example
//!
//! ```rust
//! #![feature(proc_macro, specialization)]
//! #![feature(use_extern_macros, specialization)]
//!
//! extern crate pyo3;
//!
@ -68,13 +68,11 @@
//! # Example
//!
//! ```rust
//! #![feature(proc_macro, specialization)]
//! #![feature(use_extern_macros, specialization)]
//!
//! extern crate pyo3;
//! use pyo3::prelude::*;
//!
//! use pyo3::pymodinit;
//!
//! // Add bindings to the generated python module
//! // N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
//! /// This module is implemented in Rust.
@ -157,13 +155,16 @@ pub use conversion::{FromPyObject, PyTryFrom, PyTryInto,
pub mod class;
pub use class::*;
pub use pyo3cls::{pyproto, pyclass, pymethods, pyfunction};
/// The proc macro attributes
pub mod proc_macro {
pub use pyo3cls::{pyproto, pyclass, pymethods, pyfunction};
#[cfg(Py_3)]
pub use pyo3cls::mod3init as pymodinit;
#[cfg(Py_3)]
pub use pyo3cls::mod3init as pymodinit;
#[cfg(not(Py_3))]
pub use pyo3cls::mod2init as pymodinit;
#[cfg(not(Py_3))]
pub use pyo3cls::mod2init as pymodinit;
}
/// Constructs a `&'static CStr` literal.
macro_rules! cstr {

View File

@ -1,6 +1,6 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! The `PyO3` Prelude
//! A collection of items you most likely want to have in scope when working with pyo3
//!
//! The purpose of this module is to alleviate imports of many common pyo3 traits
//! by adding a glob import to the top of pyo3 heavy modules:
@ -22,3 +22,11 @@ pub use typeob::PyRawObject;
pub use instance::{PyToken, PyObjectWithToken, AsPyRef, Py, PyNativeType};
pub use conversion::{FromPyObject, PyTryFrom, PyTryInto,
ToPyObject, ToBorrowedObject, IntoPyObject, IntoPyTuple};
pub use pyo3cls::{pyproto, pyclass, pymethods, pyfunction};
#[cfg(Py_3)]
pub use pyo3cls::mod3init as pymodinit;
#[cfg(not(Py_3))]
pub use pyo3cls::mod2init as pymodinit;

View File

@ -103,7 +103,7 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
///
/// Example of custom class implementation with `__new__` method:
/// ```rust,ignore
/// use pyo3::{pyclass, pymethods};
/// use pyo3::prelude::*;
///
/// #[pyclass]
/// struct MyClass {

View File

@ -1,9 +1,8 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyclass, pyproto};
#[macro_use]
mod common;

View File

@ -1,4 +1,4 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
@ -8,9 +8,6 @@ use std::ptr;
use pyo3::ffi;
use pyo3::prelude::*;
use pyo3::pyclass;
use pyo3::pyproto;
#[pyclass]
struct TestClass {
vec: Vec<u8>,

View File

@ -1,11 +1,9 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pyclass;
#[macro_use]
mod common;

View File

@ -1,12 +1,9 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pyclass;
use pyo3::pymethods;
#[pyclass]
struct EmptyClassWithNew {
token: PyToken,

View File

@ -1,4 +1,4 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
@ -6,10 +6,6 @@ use pyo3::ffi;
use pyo3::prelude::*;
use std::{isize, iter};
use pyo3::pyclass;
use pyo3::pymethods;
use pyo3::pyproto;
#[macro_use]
mod common;

View File

@ -1,4 +1,4 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
@ -8,10 +8,6 @@ use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use pyo3::pyclass;
use pyo3::pymethods;
use pyo3::pyproto;
#[macro_use]
mod common;

View File

@ -1,13 +1,10 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use std::isize;
use pyo3::pyclass;
use pyo3::pymethods;
#[macro_use]
mod common;

View File

@ -1,12 +1,10 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use std::isize;
use pyo3::{pyclass, pymethods};
#[macro_use]
mod common;

View File

@ -1,12 +1,9 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::pyclass;
use pyo3::pymethods;
#[macro_use]
mod common;

View File

@ -1,10 +1,9 @@
#![feature(proc_macro, specialization, concat_idents)]
#![feature(use_extern_macros, specialization, concat_idents)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{pyclass, pyfunction, pymodinit};
#[pyclass]
struct EmptyClass {}
@ -80,7 +79,11 @@ fn test_module_renaming() {
PyObject::from_owned_ptr(py, PyInit_other_name())
}).unwrap();
py.run("assert different_name.__name__ == 'other_name'", None, Some(d)).unwrap();
py.run(
"assert different_name.__name__ == 'other_name'",
None,
Some(d),
).unwrap();
}
#[test]

View File

@ -1,13 +1,10 @@
#![feature(proc_macro, specialization)]
#![feature(use_extern_macros, specialization)]
extern crate pyo3;
use pyo3::prelude::*;
use std::isize;
use pyo3::pyclass;
use pyo3::pymethods;
#[macro_use]
mod common;