wrap_x: change macros back to `macro_rules!`
This commit is contained in:
parent
a8b74a7f33
commit
7a9e70e2c7
|
@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- The deprecated `pyproto` feature is now disabled by default. [#2322](https://github.com/PyO3/pyo3/pull/2322)
|
- The deprecated `pyproto` feature is now disabled by default. [#2322](https://github.com/PyO3/pyo3/pull/2322)
|
||||||
- Deprecate `ToBorrowedObject` trait (it is only used as a wrapper for `ToPyObject`). [#2333](https://github.com/PyO3/pyo3/pull/2333)
|
- Deprecate `ToBorrowedObject` trait (it is only used as a wrapper for `ToPyObject`). [#2333](https://github.com/PyO3/pyo3/pull/2333)
|
||||||
- `impl<T, const N: usize> IntoPy<PyObject> for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326)
|
- `impl<T, const N: usize> IntoPy<PyObject> for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326)
|
||||||
|
- Correct `wrap_pymodule` to match normal namespacing rules: it no longer "sees through" glob imports of `use submodule::*` when `submodule::submodule` is a `#[pymodule]`. [#2363](https://github.com/PyO3/pyo3/pull/2363)
|
||||||
- Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364)
|
- Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -3,7 +3,6 @@ use pyo3::types::PyDict;
|
||||||
use pyo3::wrap_pymodule;
|
use pyo3::wrap_pymodule;
|
||||||
|
|
||||||
mod submodule;
|
mod submodule;
|
||||||
use submodule::*;
|
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
struct ExampleClass {
|
struct ExampleClass {
|
||||||
|
@ -23,7 +22,7 @@ impl ExampleClass {
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn maturin_starter(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
fn maturin_starter(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<ExampleClass>()?;
|
m.add_class::<ExampleClass>()?;
|
||||||
m.add_wrapped(wrap_pymodule!(submodule))?;
|
m.add_wrapped(wrap_pymodule!(submodule::submodule))?;
|
||||||
|
|
||||||
// Inserting to sys.modules allows importing submodules nicely from Python
|
// Inserting to sys.modules allows importing submodules nicely from Python
|
||||||
// e.g. from maturin_starter.submodule import SubmoduleClass
|
// e.g. from maturin_starter.submodule import SubmoduleClass
|
||||||
|
|
|
@ -3,7 +3,6 @@ use pyo3::types::PyDict;
|
||||||
use pyo3::wrap_pymodule;
|
use pyo3::wrap_pymodule;
|
||||||
|
|
||||||
mod submodule;
|
mod submodule;
|
||||||
use submodule::*;
|
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
struct ExampleClass {
|
struct ExampleClass {
|
||||||
|
@ -23,7 +22,7 @@ impl ExampleClass {
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn _setuptools_rust_starter(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
fn _setuptools_rust_starter(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<ExampleClass>()?;
|
m.add_class::<ExampleClass>()?;
|
||||||
m.add_wrapped(wrap_pymodule!(submodule))?;
|
m.add_wrapped(wrap_pymodule!(submodule::submodule))?;
|
||||||
|
|
||||||
// Inserting to sys.modules allows importing submodules nicely from Python
|
// Inserting to sys.modules allows importing submodules nicely from Python
|
||||||
// e.g. from setuptools_rust_starter.submodule import SubmoduleClass
|
// e.g. from setuptools_rust_starter.submodule import SubmoduleClass
|
||||||
|
|
|
@ -26,7 +26,6 @@ mod pyimpl;
|
||||||
mod pymethod;
|
mod pymethod;
|
||||||
#[cfg(feature = "pyproto")]
|
#[cfg(feature = "pyproto")]
|
||||||
mod pyproto;
|
mod pyproto;
|
||||||
mod wrap;
|
|
||||||
|
|
||||||
pub use frompyobject::build_derive_from_pyobject;
|
pub use frompyobject::build_derive_from_pyobject;
|
||||||
pub use module::{process_functions_in_module, pymodule_impl, PyModuleOptions};
|
pub use module::{process_functions_in_module, pymodule_impl, PyModuleOptions};
|
||||||
|
@ -36,4 +35,3 @@ pub use pyimpl::{build_py_methods, PyClassMethodsType};
|
||||||
#[cfg(feature = "pyproto")]
|
#[cfg(feature = "pyproto")]
|
||||||
pub use pyproto::build_py_proto;
|
pub use pyproto::build_py_proto;
|
||||||
pub use utils::get_doc;
|
pub use utils::get_doc;
|
||||||
pub use wrap::{wrap_pyfunction_impl, wrap_pymodule_impl, WrapPyFunctionArgs};
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},
|
pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},
|
||||||
utils::{get_pyo3_crate, PythonDoc},
|
utils::{get_pyo3_crate, PythonDoc},
|
||||||
wrap::module_def_ident,
|
|
||||||
};
|
};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
ext::IdentExt,
|
ext::IdentExt,
|
||||||
|
@ -70,29 +69,49 @@ pub fn pymodule_impl(
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let name = options.name.unwrap_or_else(|| fnname.unraw());
|
let name = options.name.unwrap_or_else(|| fnname.unraw());
|
||||||
let krate = get_pyo3_crate(&options.krate);
|
let krate = get_pyo3_crate(&options.krate);
|
||||||
let cb_name = Ident::new(&format!("PyInit_{}", name), Span::call_site());
|
let pyinit_symbol = format!("PyInit_{}", name);
|
||||||
|
|
||||||
let module_def_name = module_def_ident(fnname);
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[no_mangle]
|
// Create a module with the same name as the `#[pymodule]` - this way `use <the module>`
|
||||||
#[allow(non_snake_case)]
|
// will actually bring both the module and the function into scope.
|
||||||
/// This autogenerated function is called by the python interpreter when importing
|
#[doc(hidden)]
|
||||||
/// the module.
|
#visibility mod #fnname {
|
||||||
pub unsafe extern "C" fn #cb_name() -> *mut #krate::ffi::PyObject {
|
pub(crate) struct MakeDef;
|
||||||
unsafe { #module_def_name.module_init() }
|
pub static DEF: #krate::impl_::pymodule::ModuleDef = MakeDef::make_def();
|
||||||
|
|
||||||
|
/// This autogenerated function is called by the python interpreter when importing
|
||||||
|
/// the module.
|
||||||
|
#[export_name = #pyinit_symbol]
|
||||||
|
pub unsafe extern "C" fn init() -> *mut #krate::ffi::PyObject {
|
||||||
|
DEF.module_init()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
// Generate the definition inside an anonymous function in the same scope as the original function -
|
||||||
#visibility static #module_def_name: #krate::impl_::pymodule::ModuleDef = unsafe {
|
// this avoids complications around the fact that the generated module has a different scope
|
||||||
#krate::impl_::pymodule::ModuleDef::new(concat!(stringify!(#name), "\0"), #doc, #krate::impl_::pymodule::ModuleInitializer(#fnname))
|
// (and `super` doesn't always refer to the outer scope, e.g. if the `#[pymodule] is
|
||||||
|
// inside a function body)
|
||||||
|
const _: () = {
|
||||||
|
use #krate::impl_::pymodule as impl_;
|
||||||
|
impl #fnname::MakeDef {
|
||||||
|
const fn make_def() -> impl_::ModuleDef {
|
||||||
|
const INITIALIZER: impl_::ModuleInitializer = impl_::ModuleInitializer(#fnname);
|
||||||
|
unsafe {
|
||||||
|
impl_::ModuleDef::new(concat!(stringify!(#name), "\0"), #doc, INITIALIZER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds and takes care of the #[pyfn(...)] in `#[pymodule]`
|
/// Finds and takes care of the #[pyfn(...)] in `#[pymodule]`
|
||||||
pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> {
|
pub fn process_functions_in_module(
|
||||||
|
options: &PyModuleOptions,
|
||||||
|
func: &mut syn::ItemFn,
|
||||||
|
) -> syn::Result<()> {
|
||||||
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
||||||
|
let krate = get_pyo3_crate(&options.krate);
|
||||||
|
|
||||||
for mut stmt in func.block.stmts.drain(..) {
|
for mut stmt in func.block.stmts.drain(..) {
|
||||||
if let syn::Stmt::Item(syn::Item::Fn(func)) = &mut stmt {
|
if let syn::Stmt::Item(syn::Item::Fn(func)) = &mut stmt {
|
||||||
|
@ -102,7 +121,7 @@ pub fn process_functions_in_module(func: &mut syn::ItemFn) -> syn::Result<()> {
|
||||||
let name = &func.sig.ident;
|
let name = &func.sig.ident;
|
||||||
let statements: Vec<syn::Stmt> = syn::parse_quote! {
|
let statements: Vec<syn::Stmt> = syn::parse_quote! {
|
||||||
#wrapped_function
|
#wrapped_function
|
||||||
#module_name.add_function(#name::wrap(#name::DEF, #module_name)?)?;
|
#module_name.add_function(#krate::impl_::pyfunction::wrap_pyfunction(&#name::DEF, #module_name)?)?;
|
||||||
};
|
};
|
||||||
stmts.extend(statements);
|
stmts.extend(statements);
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,12 +446,8 @@ pub fn impl_wrap_pyfunction(
|
||||||
// will actually bring both the module and the function into scope.
|
// will actually bring both the module and the function into scope.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#vis mod #name {
|
#vis mod #name {
|
||||||
use #krate as _pyo3;
|
pub(crate) struct MakeDef;
|
||||||
pub(crate) struct PyO3Def;
|
pub const DEF: #krate::impl_::pyfunction::PyMethodDef = MakeDef::DEF;
|
||||||
|
|
||||||
// Exported for `wrap_pyfunction!`
|
|
||||||
pub use _pyo3::impl_::pyfunction::wrap_pyfunction as wrap;
|
|
||||||
pub const DEF: _pyo3::PyMethodDef = <PyO3Def as _pyo3::impl_::pyfunction::PyFunctionDef>::DEF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the definition inside an anonymous function in the same scope as the original function -
|
// Generate the definition inside an anonymous function in the same scope as the original function -
|
||||||
|
@ -460,8 +456,8 @@ pub fn impl_wrap_pyfunction(
|
||||||
// inside a function body)
|
// inside a function body)
|
||||||
const _: () = {
|
const _: () = {
|
||||||
use #krate as _pyo3;
|
use #krate as _pyo3;
|
||||||
impl _pyo3::impl_::pyfunction::PyFunctionDef for #name::PyO3Def {
|
impl #name::MakeDef {
|
||||||
const DEF: _pyo3::PyMethodDef = #methoddef;
|
const DEF: #krate::impl_::pyfunction::PyMethodDef = #methoddef;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use syn::{parse::Parse, spanned::Spanned, Ident, Token};
|
|
||||||
|
|
||||||
pub struct WrapPyFunctionArgs {
|
|
||||||
function: syn::Path,
|
|
||||||
comma_and_arg: Option<(Token![,], syn::Expr)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for WrapPyFunctionArgs {
|
|
||||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
|
||||||
let function = input.parse()?;
|
|
||||||
let comma_and_arg = if !input.is_empty() {
|
|
||||||
Some((input.parse()?, input.parse()?))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Ok(Self {
|
|
||||||
function,
|
|
||||||
comma_and_arg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_pyfunction_impl(args: WrapPyFunctionArgs) -> TokenStream {
|
|
||||||
let WrapPyFunctionArgs {
|
|
||||||
function,
|
|
||||||
comma_and_arg,
|
|
||||||
} = args;
|
|
||||||
if let Some((_, arg)) = comma_and_arg {
|
|
||||||
quote! { #function::wrap(#function::DEF, #arg) }
|
|
||||||
} else {
|
|
||||||
quote! { &|arg| #function::wrap(#function::DEF, arg) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_pymodule_impl(mut module_path: syn::Path) -> syn::Result<TokenStream> {
|
|
||||||
let span = module_path.span();
|
|
||||||
let last_segment = module_path
|
|
||||||
.segments
|
|
||||||
.last_mut()
|
|
||||||
.ok_or_else(|| err_spanned!(span => "expected non-empty path"))?;
|
|
||||||
|
|
||||||
last_segment.ident = module_def_ident(&last_segment.ident);
|
|
||||||
|
|
||||||
Ok(quote! {
|
|
||||||
|
|
||||||
&|py| unsafe { #module_path.make_module(py).expect("failed to wrap pymodule") }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn module_def_ident(name: &Ident) -> Ident {
|
|
||||||
format_ident!("__PYO3_PYMODULE_DEF_{}", name.to_string().to_uppercase())
|
|
||||||
}
|
|
|
@ -9,8 +9,8 @@ use proc_macro::TokenStream;
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use pyo3_macros_backend::{
|
use pyo3_macros_backend::{
|
||||||
build_derive_from_pyobject, build_py_class, build_py_enum, build_py_function, build_py_methods,
|
build_derive_from_pyobject, build_py_class, build_py_enum, build_py_function, build_py_methods,
|
||||||
get_doc, process_functions_in_module, pymodule_impl, wrap_pyfunction_impl, wrap_pymodule_impl,
|
get_doc, process_functions_in_module, pymodule_impl, PyClassArgs, PyClassMethodsType,
|
||||||
PyClassArgs, PyClassMethodsType, PyFunctionOptions, PyModuleOptions, WrapPyFunctionArgs,
|
PyFunctionOptions, PyModuleOptions,
|
||||||
};
|
};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse::Nothing, parse_macro_input};
|
use syn::{parse::Nothing, parse_macro_input};
|
||||||
|
@ -41,7 +41,7 @@ pub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
Err(e) => return e.into_compile_error().into(),
|
Err(e) => return e.into_compile_error().into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = process_functions_in_module(&mut ast) {
|
if let Err(err) = process_functions_in_module(&options, &mut ast) {
|
||||||
return err.into_compile_error().into();
|
return err.into_compile_error().into();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,25 +194,6 @@ pub fn derive_from_py_object(item: TokenStream) -> TokenStream {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a Rust function annotated with [`#[pyfunction]`](macro@crate::pyfunction).
|
|
||||||
///
|
|
||||||
/// This can be used with `PyModule::add_function` to add free functions to a `PyModule` - see its
|
|
||||||
/// documentation for more information.
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn wrap_pyfunction(input: TokenStream) -> TokenStream {
|
|
||||||
let args = parse_macro_input!(input as WrapPyFunctionArgs);
|
|
||||||
wrap_pyfunction_impl(args).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a function that takes a `Python` instance and returns a Python module.
|
|
||||||
///
|
|
||||||
/// Use this together with [`#[pymodule]`](macro@crate::pymodule) and `PyModule::add_wrapped`.
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn wrap_pymodule(input: TokenStream) -> TokenStream {
|
|
||||||
let path = parse_macro_input!(input as syn::Path);
|
|
||||||
wrap_pymodule_impl(path).unwrap_or_compile_error().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pyclass_impl(
|
fn pyclass_impl(
|
||||||
attrs: TokenStream,
|
attrs: TokenStream,
|
||||||
mut ast: syn::ItemStruct,
|
mut ast: syn::ItemStruct,
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
use crate::{
|
use crate::{derive_utils::PyFunctionArguments, types::PyCFunction, PyResult};
|
||||||
derive_utils::PyFunctionArguments, impl_::pymethods::PyMethodDef, types::PyCFunction, PyResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait PyFunctionDef {
|
pub use crate::impl_::pymethods::PyMethodDef;
|
||||||
const DEF: crate::PyMethodDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_pyfunction<'a>(
|
pub fn wrap_pyfunction<'a>(
|
||||||
method_def: PyMethodDef,
|
method_def: &PyMethodDef,
|
||||||
args: impl Into<PyFunctionArguments<'a>>,
|
py_or_module: impl Into<PyFunctionArguments<'a>>,
|
||||||
) -> PyResult<&'a PyCFunction> {
|
) -> PyResult<&'a PyCFunction> {
|
||||||
PyCFunction::internal_new(method_def, args.into())
|
PyCFunction::internal_new(method_def, py_or_module.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,9 +405,7 @@ pub mod proc_macro {
|
||||||
#[cfg(all(feature = "macros", feature = "pyproto"))]
|
#[cfg(all(feature = "macros", feature = "pyproto"))]
|
||||||
pub use pyo3_macros::pyproto;
|
pub use pyo3_macros::pyproto;
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
pub use pyo3_macros::{
|
pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject};
|
||||||
pyclass, pyfunction, pymethods, pymodule, wrap_pyfunction, wrap_pymodule, FromPyObject,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -115,3 +115,38 @@ macro_rules! py_run_impl {
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wraps a Rust function annotated with [`#[pyfunction]`](macro@crate::pyfunction).
|
||||||
|
///
|
||||||
|
/// This can be used with [`PyModule::add_function`](crate::types::PyModule::add_function) to add free
|
||||||
|
/// functions to a [`PyModule`](crate::types::PyModule) - see its documentation for more information.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! wrap_pyfunction {
|
||||||
|
($function:path) => {
|
||||||
|
&|py_or_module| {
|
||||||
|
use $function as wrapped_pyfunction;
|
||||||
|
$crate::impl_::pyfunction::wrap_pyfunction(&wrapped_pyfunction::DEF, py_or_module)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($function:path, $py_or_module:expr) => {{
|
||||||
|
use $function as wrapped_pyfunction;
|
||||||
|
$crate::impl_::pyfunction::wrap_pyfunction(&wrapped_pyfunction::DEF, $py_or_module)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a function that takes a [`Python`](crate::Python) instance and returns a
|
||||||
|
/// Python module.
|
||||||
|
///
|
||||||
|
/// Use this together with [`#[pymodule]`](crate::pymodule) and
|
||||||
|
/// [`PyModule::add_wrapped`](crate::types::PyModule::add_wrapped).
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! wrap_pymodule {
|
||||||
|
($module:path) => {
|
||||||
|
&|py| {
|
||||||
|
use $module as wrapped_pymodule;
|
||||||
|
wrapped_pymodule::DEF
|
||||||
|
.make_module(py)
|
||||||
|
.expect("failed to wrap pymodule")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -140,6 +140,9 @@ impl<T> GILOnceCell<T> {
|
||||||
/// }
|
/// }
|
||||||
/// #
|
/// #
|
||||||
/// # Python::with_gil(|py| {
|
/// # Python::with_gil(|py| {
|
||||||
|
/// # let fun_slow = wrap_pyfunction!(create_dict, py).unwrap();
|
||||||
|
/// # let dict = fun_slow.call0().unwrap();
|
||||||
|
/// # assert!(dict.contains("foo").unwrap());
|
||||||
/// # let fun = wrap_pyfunction!(create_dict_faster, py).unwrap();
|
/// # let fun = wrap_pyfunction!(create_dict_faster, py).unwrap();
|
||||||
/// # let dict = fun.call0().unwrap();
|
/// # let dict = fun.call0().unwrap();
|
||||||
/// # assert!(dict.contains("foo").unwrap());
|
/// # assert!(dict.contains("foo").unwrap());
|
||||||
|
|
|
@ -22,7 +22,10 @@ pub use crate::pyclass_init::PyClassInitializer;
|
||||||
pub use crate::types::{PyAny, PyModule};
|
pub use crate::types::{PyAny, PyModule};
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, wrap_pyfunction, FromPyObject};
|
pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject};
|
||||||
|
|
||||||
#[cfg(all(feature = "macros", feature = "pyproto"))]
|
#[cfg(all(feature = "macros", feature = "pyproto"))]
|
||||||
pub use pyo3_macros::pyproto;
|
pub use pyo3_macros::pyproto;
|
||||||
|
|
||||||
|
#[cfg(feature = "macros")]
|
||||||
|
pub use crate::wrap_pyfunction;
|
||||||
|
|
|
@ -166,10 +166,11 @@ impl PyByteArray {
|
||||||
///
|
///
|
||||||
/// The following `bug` function is unsound ⚠️
|
/// The following `bug` function is unsound ⚠️
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// # use pyo3::prelude::*;
|
/// # use pyo3::prelude::*;
|
||||||
/// # use pyo3::types::PyByteArray;
|
/// # use pyo3::types::PyByteArray;
|
||||||
///
|
///
|
||||||
|
/// # #[allow(dead_code)]
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn bug(py: Python<'_>, bytes: &PyByteArray) {
|
/// fn bug(py: Python<'_>, bytes: &PyByteArray) {
|
||||||
/// let slice = unsafe { bytes.as_bytes() };
|
/// let slice = unsafe { bytes.as_bytes() };
|
||||||
|
@ -186,6 +187,7 @@ impl PyByteArray {
|
||||||
/// // remaining valid. As such this is also undefined behavior.
|
/// // remaining valid. As such this is also undefined behavior.
|
||||||
/// println!("{:?}", slice[0]);
|
/// println!("{:?}", slice[0]);
|
||||||
/// }
|
/// }
|
||||||
|
/// ```
|
||||||
pub unsafe fn as_bytes(&self) -> &[u8] {
|
pub unsafe fn as_bytes(&self) -> &[u8] {
|
||||||
slice::from_raw_parts(self.data(), self.len())
|
slice::from_raw_parts(self.data(), self.len())
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl PyCFunction {
|
||||||
py_or_module: PyFunctionArguments<'a>,
|
py_or_module: PyFunctionArguments<'a>,
|
||||||
) -> PyResult<&'a Self> {
|
) -> PyResult<&'a Self> {
|
||||||
Self::internal_new(
|
Self::internal_new(
|
||||||
PyMethodDef::cfunction_with_keywords(
|
&PyMethodDef::cfunction_with_keywords(
|
||||||
name,
|
name,
|
||||||
pymethods::PyCFunctionWithKeywords(fun),
|
pymethods::PyCFunctionWithKeywords(fun),
|
||||||
doc,
|
doc,
|
||||||
|
@ -82,7 +82,7 @@ impl PyCFunction {
|
||||||
py_or_module: PyFunctionArguments<'a>,
|
py_or_module: PyFunctionArguments<'a>,
|
||||||
) -> PyResult<&'a Self> {
|
) -> PyResult<&'a Self> {
|
||||||
Self::internal_new(
|
Self::internal_new(
|
||||||
PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
|
&PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
|
||||||
py_or_module,
|
py_or_module,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -125,16 +125,16 @@ impl PyCFunction {
|
||||||
pymethods::PyCFunctionWithKeywords(run_closure::<F, R>),
|
pymethods::PyCFunctionWithKeywords(run_closure::<F, R>),
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
Self::internal_new_from_pointers(method_def, py, capsule.as_ptr(), std::ptr::null_mut())
|
Self::internal_new_from_pointers(&method_def, py, capsule.as_ptr(), std::ptr::null_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn internal_new_from_pointers(
|
fn internal_new_from_pointers<'py>(
|
||||||
method_def: PyMethodDef,
|
method_def: &PyMethodDef,
|
||||||
py: Python<'_>,
|
py: Python<'py>,
|
||||||
mod_ptr: *mut ffi::PyObject,
|
mod_ptr: *mut ffi::PyObject,
|
||||||
module_name: *mut ffi::PyObject,
|
module_name: *mut ffi::PyObject,
|
||||||
) -> PyResult<&Self> {
|
) -> PyResult<&'py Self> {
|
||||||
let def = method_def
|
let def = method_def
|
||||||
.as_method_def()
|
.as_method_def()
|
||||||
.map_err(|err| PyValueError::new_err(err.0))?;
|
.map_err(|err| PyValueError::new_err(err.0))?;
|
||||||
|
@ -148,10 +148,10 @@ impl PyCFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn internal_new(
|
pub fn internal_new<'py>(
|
||||||
method_def: PyMethodDef,
|
method_def: &PyMethodDef,
|
||||||
py_or_module: PyFunctionArguments<'_>,
|
py_or_module: PyFunctionArguments<'py>,
|
||||||
) -> PyResult<&Self> {
|
) -> PyResult<&'py Self> {
|
||||||
let (py, module) = py_or_module.into_py_and_maybe_module();
|
let (py, module) = py_or_module.into_py_and_maybe_module();
|
||||||
let (mod_ptr, module_name) = if let Some(m) = module {
|
let (mod_ptr, module_name) = if let Some(m) = module {
|
||||||
let mod_ptr = m.as_ptr();
|
let mod_ptr = m.as_ptr();
|
||||||
|
|
Loading…
Reference in New Issue