#[pymodinit] now uses the function name as default module name
This commit is contained in:
parent
c32dd1c120
commit
fe931a594f
|
@ -5,6 +5,7 @@
|
|||
* 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.
|
||||
* `#[pymodinit]` uses the function name as module name, unless the name is overrriden with `#[pymodinit(name)]`
|
||||
* The guide is now properly versioned.
|
||||
* A few internal macros became part of the public api ([#155](https://github.com/PyO3/pyo3/pull/155), [#186](https://github.com/PyO3/pyo3/pull/186))
|
||||
* Always clone in getters. This allows using the get-annotation on all Clone-Types
|
||||
|
|
|
@ -79,8 +79,8 @@ 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.
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
// ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||
|
|
|
@ -10,5 +10,5 @@ rayon = "0.8"
|
|||
path = "../../"
|
||||
|
||||
[lib]
|
||||
name = "word_count"
|
||||
name = "word_count_cls"
|
||||
crate-type = ["cdylib"]
|
||||
|
|
|
@ -44,7 +44,7 @@ setup(
|
|||
'Operating System :: MacOS :: MacOS X',
|
||||
],
|
||||
packages=['word_count_cls'],
|
||||
rust_extensions=[RustExtension('word_count_cls._word_count', 'Cargo.toml')],
|
||||
rust_extensions=[RustExtension('word_count_cls.word_count_cls', 'Cargo.toml')],
|
||||
install_requires=install_requires,
|
||||
tests_require=tests_require,
|
||||
setup_requires=setup_requires,
|
||||
|
|
|
@ -79,8 +79,8 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
|||
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
||||
}
|
||||
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn word_count(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<WordCounter>()?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from ._word_count import WordCounter
|
||||
from .word_count_cls import WordCounter
|
||||
|
||||
__all__ = ['WordCounter', 'search_py']
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ setup(
|
|||
'Operating System :: MacOS :: MacOS X',
|
||||
],
|
||||
packages=['word_count'],
|
||||
rust_extensions=[RustExtension('word_count._word_count', 'Cargo.toml')],
|
||||
rust_extensions=[RustExtension('word_count.word_count', 'Cargo.toml')],
|
||||
install_requires=install_requires,
|
||||
tests_require=tests_require,
|
||||
setup_requires=setup_requires,
|
||||
|
|
|
@ -50,8 +50,8 @@ fn wc_parallel(lines: &str, search: &str) -> i32 {
|
|||
lines.par_lines().map(|line| wc_line(line, search)).sum()
|
||||
}
|
||||
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn word_count(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "search")]
|
||||
fn search(py: Python, path: String, search: String) -> PyResult<i32> {
|
||||
let mut file = File::open(path)?;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from ._word_count import search, search_sequential
|
||||
from .word_count import search, search_sequential
|
||||
|
||||
__all__ = ['search', 'search_sequential', 'search_py']
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ extern crate pyo3;
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::pymodinit;
|
||||
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
// Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
||||
// Python objects to Rust values; and the Rust return value back into a Python object.
|
||||
|
@ -47,8 +47,8 @@ fn double(x: usize) -> usize {
|
|||
x * 2
|
||||
}
|
||||
|
||||
#[pymodinit(module_with_functions)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_function!(double)).unwrap();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -13,8 +13,8 @@ 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.
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
// pyo3 aware function. All of our python interface could be declared in a separate module.
|
||||
// Note that the `#[pyfn()]` annotation automatically converts the arguments from
|
||||
|
|
|
@ -69,8 +69,8 @@ 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.
|
||||
#[pymodinit(rust2py)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
// ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||
|
|
|
@ -28,8 +28,8 @@ Then in the Python bridge, we have a function `search` exposed to Python runtime
|
|||
`Python::allow_threads` method to enable true parallelism:
|
||||
|
||||
```rust,ignore
|
||||
#[pymodinit(_word_count)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn word_count(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "search")]
|
||||
fn search(py: Python, path: String, search: String) -> PyResult<i32> {
|
||||
|
|
|
@ -92,7 +92,7 @@ pub fn py2_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> TokenS
|
|||
}
|
||||
}
|
||||
|
||||
/// Finds and takes care of the #[pyfn(...)] in #[pymodinit(...)]
|
||||
/// Finds and takes care of the #[pyfn(...)] in #[pymodinit]
|
||||
pub fn process_functions_in_module(func: &mut syn::ItemFn) {
|
||||
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
||||
|
||||
|
|
|
@ -26,8 +26,12 @@ pub fn mod2init(
|
|||
// Parse the token stream into a syntax tree
|
||||
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodinit] must be used on a function");
|
||||
|
||||
// Extract the mod name
|
||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||
let modname: syn::Ident;
|
||||
if attr.is_empty() {
|
||||
modname = ast.ident.clone();
|
||||
} else {
|
||||
modname = syn::parse(attr).expect("could not parse module name");
|
||||
}
|
||||
|
||||
// Process the functions within the module
|
||||
module::process_functions_in_module(&mut ast);
|
||||
|
@ -49,8 +53,12 @@ pub fn mod3init(
|
|||
// Parse the token stream into a syntax tree
|
||||
let mut ast: syn::ItemFn = syn::parse(input).expect("#[pymodinit] must be used on a `fn` block");
|
||||
|
||||
// Extract the mod name
|
||||
let modname: syn::Ident = syn::parse(attr).expect("could not parse module name");
|
||||
let modname: syn::Ident;
|
||||
if attr.is_empty() {
|
||||
modname = ast.ident.clone();
|
||||
} else {
|
||||
modname = syn::parse(attr).expect("could not parse module name");
|
||||
}
|
||||
|
||||
// Process the functions within the module
|
||||
module::process_functions_in_module(&mut ast);
|
||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -53,15 +53,9 @@
|
|||
//! # Python extension
|
||||
//!
|
||||
//! To allow Python to load the rust code as a Python extension
|
||||
//! module, you need provide initialization function and annotate it with `#[pymodinit(name)]`.
|
||||
//! `pymodinit` expands to an `extern "C"` function.
|
||||
//!
|
||||
//! Macro syntax: `#[pymodinit(name)]`
|
||||
//!
|
||||
//! 1. `name`: The module name as a Rust identifier
|
||||
//! 2. Decorate init function `Fn(Python, &PyModule) -> PyResult<()>`.
|
||||
//! This function will be called when the module is imported, and is responsible
|
||||
//! for adding the module's members.
|
||||
//! module, you need an initialization function with `Fn(Python, &PyModule) -> PyResult<()>`
|
||||
//! that is annotates with `#[pymodinit]`. By default the function name will become the module name,
|
||||
//! but you can override that with `#[pymodinit(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.
|
||||
|
@ -84,8 +78,8 @@
|
|||
//! // 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.
|
||||
//! #[pymodinit(rust2py)]
|
||||
//! fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
//! #[pymodinit]
|
||||
//! fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
//!
|
||||
//! #[pyfn(m, "sum_as_string")]
|
||||
//! // ``#[pyfn()]` converts the arguments from Python objects to Rust values
|
||||
|
|
|
@ -27,7 +27,7 @@ static START_PYO3: sync::Once = sync::ONCE_INIT;
|
|||
/// thread (the thread which originally initialized Python) also initializes
|
||||
/// threading.
|
||||
///
|
||||
/// When writing an extension module, the `#[pymodinit(..)]` macro
|
||||
/// When writing an extension module, the `#[pymodinit]` macro
|
||||
/// will ensure that Python threading is initialized.
|
||||
///
|
||||
pub fn prepare_freethreaded_python() {
|
||||
|
|
|
@ -19,8 +19,8 @@ fn double(x: usize) -> usize {
|
|||
}
|
||||
|
||||
/// This module is implemented in Rust.
|
||||
#[pymodinit(module_with_functions)]
|
||||
fn init_mod(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pymodinit]
|
||||
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> PyResult<String> {
|
||||
let out = sum_as_string(a, b);
|
||||
|
@ -64,6 +64,25 @@ fn test_module_with_functions() {
|
|||
run("assert module_with_functions.also_double(3) == 6");
|
||||
}
|
||||
|
||||
#[pymodinit(other_name)]
|
||||
fn some_name(_: Python, _: &PyModule) -> PyResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(Py_3)]
|
||||
fn test_module_renaming() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let d = PyDict::new(py);
|
||||
d.set_item("different_name", unsafe {
|
||||
PyObject::from_owned_ptr(py, PyInit_other_name())
|
||||
}).unwrap();
|
||||
|
||||
py.run("assert different_name.__name__ == 'other_name'", None, Some(d)).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(Py_3)]
|
||||
fn test_module_from_code() {
|
||||
|
|
Loading…
Reference in New Issue