pyfn: deprecate name argument
This commit is contained in:
parent
51ba541a18
commit
a109640850
|
@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- `PyAsyncProtocol::__aenter__` and `PyAsyncProtocol::__aexit__`
|
||||
- Deprecate `#[name = "..."]` attributes in favor of `#[pyo3(name = "...")]`. [#1567](https://github.com/PyO3/pyo3/pull/1567)
|
||||
- Improve compilation times for projects using PyO3 [#1604](https://github.com/PyO3/pyo3/pull/1604)
|
||||
- Deprecate string-literal second argument to `#[pyfn(m, "name")]`.
|
||||
|
||||
### Removed
|
||||
- Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426)
|
||||
|
|
|
@ -242,8 +242,6 @@ 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
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::PyTraverseError;
|
||||
use pyo3::gc::{PyGCProtocol, PyVisit};
|
||||
|
|
|
@ -1,29 +1,8 @@
|
|||
# Python Functions
|
||||
|
||||
PyO3 supports two ways to define a free function in Python. Both require registering
|
||||
the function to a [module](./module.md).
|
||||
PyO3 supports two ways to define a free function in Python. Both require registering the function to a [module](./module.md).
|
||||
|
||||
One way is defining the function in the module definition, annotated with `#[pyfn]`.
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pymodule]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
fn sum_as_string_py(_py: Python, a:i64, b:i64) -> PyResult<String> {
|
||||
Ok(format!("{}", a + b))
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
The other is annotating a function with `#[pyfunction]` and then adding it
|
||||
to the module using the `wrap_pyfunction!` macro.
|
||||
One way is annotating a function with `#[pyfunction]` and then adding it to the module using the `wrap_pyfunction!` macro.
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
@ -36,7 +15,25 @@ fn double(x: usize) -> usize {
|
|||
|
||||
#[pymodule]
|
||||
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(double, m)?).unwrap();
|
||||
m.add_function(wrap_pyfunction!(double, m)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
Alternatively there is a shorthand; the function can be placed inside the module definition and annotated with `#[pyfn]`, as below:
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pymodule]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m)]
|
||||
fn sum_as_string(_py: Python, a:i64, b:i64) -> PyResult<String> {
|
||||
Ok(format!("{}", a + b))
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -44,16 +41,61 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
|||
# fn main() {}
|
||||
```
|
||||
|
||||
## Argument parsing
|
||||
|
||||
Both the `#[pyfunction]` and `#[pyfn]` attributes support specifying details of
|
||||
argument parsing. The details are given in the section "Method arguments" in
|
||||
the [Classes](class.md) chapter. Here is an example for a function that accepts
|
||||
arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number
|
||||
that was passed:
|
||||
`#[pyfn(m)]` is just syntax sugar for `#[pyfunction]`, and takes all the same options documented in the rest of this chapter. The code above is expanded to the following:
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pymodule]
|
||||
fn rust2py(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfunction]
|
||||
fn sum_as_string(_py: Python, a:i64, b:i64) -> PyResult<String> {
|
||||
Ok(format!("{}", a + b))
|
||||
}
|
||||
|
||||
m.add_function(pyo3::wrap_pyfunction!(sum_as_string, m)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
## Function options
|
||||
|
||||
The `#[pyo3]` attribute can be used to modify properties of the generated Python function. It can take any combination of the following options:
|
||||
|
||||
- `#[pyo3(name = "...")]`
|
||||
|
||||
Overrides the name generated in Python:
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "no_args")]
|
||||
fn no_args_py() -> usize { 42 }
|
||||
|
||||
#[pymodule]
|
||||
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(no_args_py, m)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
# Python::with_gil(|py| {
|
||||
# let m = pyo3::wrap_pymodule!(module_with_functions)(py);
|
||||
# assert!(m.getattr(py, "no_args").is_ok());
|
||||
# assert!(m.getattr(py, "no_args_py").is_err());
|
||||
# });
|
||||
```
|
||||
|
||||
## Argument parsing
|
||||
|
||||
The `#[pyfunction]` attribute supports specifying details of argument parsing. The details are given in the section ["Method arguments" of the Classes chapter](class.md#method-arguments). Here is an example for a function that accepts arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number that was passed:
|
||||
|
||||
```rust
|
||||
# extern crate pyo3;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::wrap_pyfunction;
|
||||
use pyo3::types::PyDict;
|
||||
|
@ -213,8 +255,7 @@ in Python code.
|
|||
|
||||
### Accessing the module of a function
|
||||
|
||||
It is possible to access the module of a `#[pyfunction]` and `#[pyfn]` in the
|
||||
function body by passing the `pass_module` argument to the attribute:
|
||||
It is possible to access the module of a `#[pyfunction]` in the function body by passing the `pass_module` argument to the attribute:
|
||||
|
||||
```rust
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
@ -236,25 +277,6 @@ fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
|||
If `pass_module` is set, the first argument **must** be the `&PyModule`. It is then possible to use the module
|
||||
in the function body.
|
||||
|
||||
The same works for `#[pyfn]`:
|
||||
|
||||
```rust
|
||||
use pyo3::wrap_pyfunction;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pymodule]
|
||||
fn module_with_fn(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
|
||||
#[pyfn(m, "module_name", pass_module)]
|
||||
fn module_name(module: &PyModule) -> PyResult<&str> {
|
||||
module.name()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
## Accessing the FFI functions
|
||||
|
||||
In order to make Rust functions callable from Python, PyO3 generates a
|
||||
|
|
|
@ -15,7 +15,8 @@ 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.
|
||||
// The `_py` argument represents that we're holding the GIL.
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
#[pyfn(m)]
|
||||
#[pyo3(name = "sum_as_string")]
|
||||
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> PyResult<String> {
|
||||
let out = sum_as_string(a, b);
|
||||
Ok(out)
|
||||
|
@ -32,7 +33,7 @@ fn sum_as_string(a: i64, b: i64) -> String {
|
|||
# fn main() {}
|
||||
```
|
||||
|
||||
The `#[pymodule]` procedural macro attribute takes care of exporting the initialization function of your
|
||||
The `#[pymodule]` procedural macro attribute takes care of exporting the initialization function of your
|
||||
module to Python. It can take as an argument the name of your module, which must be the name of the `.so`
|
||||
or `.pyd` file; the default is the Rust function's name.
|
||||
|
||||
|
@ -41,7 +42,7 @@ If the name of the module (the default being the function name) does not match t
|
|||
`ImportError: dynamic module does not define module export function (PyInit_name_of_your_module)`
|
||||
|
||||
To import the module, either copy the shared library as described in [the README](https://github.com/PyO3/pyo3)
|
||||
or use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or
|
||||
or use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or
|
||||
`python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust).
|
||||
|
||||
## Documentation
|
||||
|
@ -95,4 +96,4 @@ fn supermodule(py: Python, module: &PyModule) -> PyResult<()> {
|
|||
|
||||
This way, you can create a module hierarchy within a single extension module.
|
||||
|
||||
It is not necessary to add `#[pymodule]` on nested modules, this is only required on the top-level module.
|
||||
It is not necessary to add `#[pymodule]` on nested modules, this is only required on the top-level module.
|
||||
|
|
|
@ -6,6 +6,8 @@ use syn::{
|
|||
Attribute, ExprPath, Ident, LitStr, Result, Token,
|
||||
};
|
||||
|
||||
use crate::deprecations::{Deprecation, Deprecations};
|
||||
|
||||
pub mod kw {
|
||||
syn::custom_keyword!(annotation);
|
||||
syn::custom_keyword!(attribute);
|
||||
|
@ -81,17 +83,18 @@ pub fn take_attributes(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_deprecated_name_attribute(attr: &syn::Attribute) -> syn::Result<Option<NameAttribute>> {
|
||||
pub fn get_deprecated_name_attribute(
|
||||
attr: &syn::Attribute,
|
||||
deprecations: &mut Deprecations,
|
||||
) -> syn::Result<Option<NameAttribute>> {
|
||||
match attr.parse_meta() {
|
||||
Ok(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(s),
|
||||
..
|
||||
})) if path.is_ident("name") => {
|
||||
let mut ident: syn::Ident = s.parse()?;
|
||||
// This span is the whole attribute span, which is nicer for reporting errors.
|
||||
ident.set_span(attr.span());
|
||||
Ok(Some(NameAttribute(ident)))
|
||||
deprecations.push(Deprecation::NameAttribute, attr.span());
|
||||
Ok(Some(NameAttribute(s.parse()?)))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote_spanned, ToTokens};
|
||||
|
||||
pub enum Deprecation {
|
||||
NameAttribute,
|
||||
PyfnNameArgument,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
fn ident(&self, span: Span) -> syn::Ident {
|
||||
let string = match self {
|
||||
Deprecation::NameAttribute => "NAME_ATTRIBUTE",
|
||||
Deprecation::PyfnNameArgument => "PYFN_NAME_ARGUMENT",
|
||||
};
|
||||
syn::Ident::new(string, span)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Deprecations(Vec<(Deprecation, Span)>);
|
||||
|
||||
impl Deprecations {
|
||||
pub fn new() -> Self {
|
||||
Deprecations(Vec::new())
|
||||
}
|
||||
|
||||
pub fn push(&mut self, deprecation: Deprecation, span: Span) {
|
||||
self.0.push((deprecation, span))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Deprecations {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
for (deprecation, span) in &self.0 {
|
||||
let ident = deprecation.ident(*span);
|
||||
quote_spanned!(
|
||||
*span =>
|
||||
let _ = pyo3::impl_::deprecations::#ident;
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
use crate::attributes::{
|
||||
self, get_deprecated_name_attribute, get_pyo3_attributes, is_attribute_ident, take_attributes,
|
||||
NameAttribute,
|
||||
use crate::{
|
||||
attributes::{
|
||||
self, get_deprecated_name_attribute, get_pyo3_attributes, is_attribute_ident,
|
||||
take_attributes, NameAttribute,
|
||||
},
|
||||
deprecations::Deprecations,
|
||||
};
|
||||
use crate::utils;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
|
@ -19,12 +21,10 @@ pub struct ConstSpec {
|
|||
|
||||
impl ConstSpec {
|
||||
/// Null-terminated Python name
|
||||
pub fn python_name_with_deprecation(&self) -> TokenStream {
|
||||
pub fn null_terminated_python_name(&self) -> TokenStream {
|
||||
if let Some(name) = &self.attributes.name {
|
||||
let deprecation =
|
||||
utils::name_deprecation_token(name.0.span(), self.attributes.name_is_deprecated);
|
||||
let name = format!("{}\0", name.0);
|
||||
quote!({#deprecation #name})
|
||||
quote!({#name})
|
||||
} else {
|
||||
let name = format!("{}\0", self.rust_ident.unraw().to_string());
|
||||
quote!(#name)
|
||||
|
@ -35,7 +35,7 @@ impl ConstSpec {
|
|||
pub struct ConstAttributes {
|
||||
pub is_class_attr: bool,
|
||||
pub name: Option<NameAttribute>,
|
||||
pub name_is_deprecated: bool,
|
||||
pub deprecations: Deprecations,
|
||||
}
|
||||
|
||||
pub enum PyO3ConstAttribute {
|
||||
|
@ -58,7 +58,7 @@ impl ConstAttributes {
|
|||
let mut attributes = ConstAttributes {
|
||||
is_class_attr: false,
|
||||
name: None,
|
||||
name_is_deprecated: false,
|
||||
deprecations: Deprecations::new(),
|
||||
};
|
||||
|
||||
take_attributes(attrs, |attr| {
|
||||
|
@ -76,9 +76,10 @@ impl ConstAttributes {
|
|||
}
|
||||
}
|
||||
Ok(true)
|
||||
} else if let Some(name) = get_deprecated_name_attribute(attr)? {
|
||||
} else if let Some(name) =
|
||||
get_deprecated_name_attribute(attr, &mut attributes.deprecations)?
|
||||
{
|
||||
attributes.set_name(name)?;
|
||||
attributes.name_is_deprecated = true;
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
|
|
@ -10,6 +10,7 @@ mod utils;
|
|||
|
||||
mod attributes;
|
||||
mod defs;
|
||||
mod deprecations;
|
||||
mod from_pyobject;
|
||||
mod konst;
|
||||
mod method;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use crate::pyfunction::Argument;
|
||||
use crate::pyfunction::PyFunctionOptions;
|
||||
use crate::pyfunction::{PyFunctionArgPyO3Attributes, PyFunctionSignature};
|
||||
use crate::utils;
|
||||
use crate::{deprecations::Deprecations, pyfunction::Argument};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use quote::{quote, quote_spanned};
|
||||
|
@ -122,7 +122,6 @@ impl SelfType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FnSpec<'a> {
|
||||
pub tp: FnType,
|
||||
// Rust function name
|
||||
|
@ -134,7 +133,7 @@ pub struct FnSpec<'a> {
|
|||
pub args: Vec<FnArg<'a>>,
|
||||
pub output: syn::Type,
|
||||
pub doc: syn::LitStr,
|
||||
pub name_is_deprecated: bool,
|
||||
pub deprecations: Deprecations,
|
||||
}
|
||||
|
||||
pub fn get_return_info(output: &syn::ReturnType) -> syn::Type {
|
||||
|
@ -217,15 +216,13 @@ impl<'a> FnSpec<'a> {
|
|||
args: arguments,
|
||||
output: ty,
|
||||
doc,
|
||||
name_is_deprecated: options.name_is_deprecated,
|
||||
deprecations: options.deprecations,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn python_name_with_deprecation(&self) -> TokenStream {
|
||||
let deprecation =
|
||||
utils::name_deprecation_token(self.python_name.span(), self.name_is_deprecated);
|
||||
pub fn null_terminated_python_name(&self) -> TokenStream {
|
||||
let name = format!("{}\0", self.python_name);
|
||||
quote!({#deprecation #name})
|
||||
quote!({#name})
|
||||
}
|
||||
|
||||
fn parse_text_signature(
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
//! Code generation for the function that initializes a python module and adds classes and function.
|
||||
|
||||
use crate::attributes::{is_attribute_ident, take_attributes, NameAttribute};
|
||||
use crate::pyfunction::{impl_wrap_pyfunction, PyFunctionOptions};
|
||||
use crate::{
|
||||
attributes::{is_attribute_ident, take_attributes, NameAttribute},
|
||||
deprecations::Deprecation,
|
||||
};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{parse::Parse, spanned::Spanned, token::Comma, Ident, Path};
|
||||
|
@ -59,18 +62,35 @@ pub struct PyFnArgs {
|
|||
|
||||
impl Parse for PyFnArgs {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let modname = input.parse()?;
|
||||
let _: Comma = input.parse()?;
|
||||
let fnname_literal: syn::LitStr = input.parse()?;
|
||||
let fnname = fnname_literal.parse()?;
|
||||
let modname = input.parse().map_err(
|
||||
|e| err_spanned!(e.span() => "expected module as first argument to #[pyfn()]"),
|
||||
)?;
|
||||
|
||||
if input.is_empty() {
|
||||
let mut options = PyFunctionOptions::default();
|
||||
options.set_name(NameAttribute(fnname))?;
|
||||
return Ok(Self { modname, options });
|
||||
return Ok(Self {
|
||||
modname,
|
||||
options: Default::default(),
|
||||
});
|
||||
}
|
||||
|
||||
let _: Comma = input.parse()?;
|
||||
|
||||
let mut deprecated_name_argument = None;
|
||||
if let Ok(lit_str) = input.parse::<syn::LitStr>() {
|
||||
deprecated_name_argument = Some(lit_str);
|
||||
if !input.is_empty() {
|
||||
let _: Comma = input.parse()?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut options: PyFunctionOptions = input.parse()?;
|
||||
options.set_name(NameAttribute(fnname))?;
|
||||
if let Some(lit_str) = deprecated_name_argument {
|
||||
options.set_name(NameAttribute(lit_str.parse()?))?;
|
||||
options
|
||||
.deprecations
|
||||
.push(Deprecation::PyfnNameArgument, lit_str.span());
|
||||
}
|
||||
|
||||
Ok(Self { modname, options })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,10 +508,10 @@ fn impl_descriptors(
|
|||
);
|
||||
match desc {
|
||||
FnType::Getter(self_ty) => {
|
||||
impl_py_getter_def(cls, property_type, self_ty, &doc)
|
||||
impl_py_getter_def(cls, property_type, self_ty, &doc, &Default::default())
|
||||
}
|
||||
FnType::Setter(self_ty) => {
|
||||
impl_py_setter_def(cls, property_type, self_ty, &doc)
|
||||
impl_py_setter_def(cls, property_type, self_ty, &doc, &Default::default())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
|||
self, get_deprecated_name_attribute, get_pyo3_attributes, take_attributes,
|
||||
FromPyWithAttribute, NameAttribute,
|
||||
},
|
||||
deprecations::Deprecations,
|
||||
method::{self, FnArg, FnSpec},
|
||||
pymethod::{check_generic, get_arg_names, impl_arg_params},
|
||||
utils,
|
||||
|
@ -209,8 +210,8 @@ impl PyFunctionSignature {
|
|||
pub struct PyFunctionOptions {
|
||||
pub pass_module: bool,
|
||||
pub name: Option<NameAttribute>,
|
||||
pub name_is_deprecated: bool,
|
||||
pub signature: Option<PyFunctionSignature>,
|
||||
pub deprecations: Deprecations,
|
||||
}
|
||||
|
||||
impl Parse for PyFunctionOptions {
|
||||
|
@ -218,8 +219,8 @@ impl Parse for PyFunctionOptions {
|
|||
let mut options = PyFunctionOptions {
|
||||
pass_module: false,
|
||||
name: None,
|
||||
name_is_deprecated: false,
|
||||
signature: None,
|
||||
deprecations: Deprecations::new(),
|
||||
};
|
||||
|
||||
while !input.is_empty() {
|
||||
|
@ -278,9 +279,9 @@ impl PyFunctionOptions {
|
|||
if let Some(pyo3_attributes) = get_pyo3_attributes(attr)? {
|
||||
self.add_attributes(pyo3_attributes)?;
|
||||
Ok(true)
|
||||
} else if let Some(name) = get_deprecated_name_attribute(attr)? {
|
||||
} else if let Some(name) = get_deprecated_name_attribute(attr, &mut self.deprecations)?
|
||||
{
|
||||
self.set_name(name)?;
|
||||
self.name_is_deprecated = true;
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
@ -390,11 +391,11 @@ pub fn impl_wrap_pyfunction(
|
|||
args: arguments,
|
||||
output: ty,
|
||||
doc,
|
||||
name_is_deprecated: options.name_is_deprecated,
|
||||
deprecations: options.deprecations,
|
||||
};
|
||||
|
||||
let doc = &spec.doc;
|
||||
let python_name = spec.python_name_with_deprecation();
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
|
||||
let name = &func.sig.ident;
|
||||
let wrapper_ident = format_ident!("__pyo3_raw_{}", name);
|
||||
|
@ -453,12 +454,14 @@ fn function_c_wrapper(
|
|||
)
|
||||
};
|
||||
let py = syn::Ident::new("_py", Span::call_site());
|
||||
let deprecations = &spec.deprecations;
|
||||
if spec.args.is_empty() {
|
||||
Ok(quote! {
|
||||
unsafe extern "C" fn #wrapper_ident(
|
||||
_slf: *mut pyo3::ffi::PyObject,
|
||||
_unused: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
#slf_module
|
||||
#cb
|
||||
|
@ -473,6 +476,7 @@ fn function_c_wrapper(
|
|||
_args: *mut pyo3::ffi::PyObject,
|
||||
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
#slf_module
|
||||
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
use crate::utils;
|
||||
use crate::{attributes::FromPyWithAttribute, konst::ConstSpec};
|
||||
use crate::{deprecations::Deprecations, utils};
|
||||
use crate::{
|
||||
method::{FnArg, FnSpec, FnType, SelfType},
|
||||
pyfunction::PyFunctionOptions,
|
||||
|
@ -48,12 +48,14 @@ pub fn gen_py_method(
|
|||
PropertyType::Function(&spec),
|
||||
self_ty,
|
||||
&spec.doc,
|
||||
&spec.deprecations,
|
||||
)?),
|
||||
FnType::Setter(self_ty) => GeneratedPyMethod::Method(impl_py_setter_def(
|
||||
cls,
|
||||
PropertyType::Function(&spec),
|
||||
self_ty,
|
||||
&spec.doc,
|
||||
&spec.deprecations,
|
||||
)?),
|
||||
})
|
||||
}
|
||||
|
@ -72,8 +74,10 @@ pub(crate) fn check_generic(sig: &syn::Signature) -> syn::Result<()> {
|
|||
|
||||
pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec) -> TokenStream {
|
||||
let member = &spec.rust_ident;
|
||||
let deprecations = &spec.attributes.deprecations;
|
||||
let wrapper = quote! {{
|
||||
fn __wrap(py: pyo3::Python<'_>) -> pyo3::PyObject {
|
||||
#deprecations
|
||||
pyo3::IntoPy::into_py(#cls::#member, py)
|
||||
}
|
||||
__wrap
|
||||
|
@ -91,12 +95,14 @@ pub fn impl_wrap_cfunction_with_keywords(
|
|||
let slf = self_ty.receiver(cls);
|
||||
let py = syn::Ident::new("_py", Span::call_site());
|
||||
let body = impl_arg_params(&spec, Some(cls), body, &py)?;
|
||||
let deprecations = &spec.deprecations;
|
||||
Ok(quote! {{
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut pyo3::ffi::PyObject,
|
||||
_args: *mut pyo3::ffi::PyObject,
|
||||
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
#slf
|
||||
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
|
||||
|
@ -113,6 +119,7 @@ pub fn impl_wrap_cfunction_with_keywords(
|
|||
pub fn impl_wrap_noargs(cls: &syn::Type, spec: &FnSpec<'_>, self_ty: &SelfType) -> TokenStream {
|
||||
let body = impl_call(cls, &spec);
|
||||
let slf = self_ty.receiver(cls);
|
||||
let deprecations = &spec.deprecations;
|
||||
assert!(spec.args.is_empty());
|
||||
quote! {{
|
||||
unsafe extern "C" fn __wrap(
|
||||
|
@ -120,6 +127,7 @@ pub fn impl_wrap_noargs(cls: &syn::Type, spec: &FnSpec<'_>, self_ty: &SelfType)
|
|||
_args: *mut pyo3::ffi::PyObject,
|
||||
) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|_py| {
|
||||
#slf
|
||||
#body
|
||||
|
@ -136,7 +144,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStream>
|
|||
let cb = quote! { #cls::#name(#(#names),*) };
|
||||
let py = syn::Ident::new("_py", Span::call_site());
|
||||
let body = impl_arg_params(spec, Some(cls), cb, &py)?;
|
||||
|
||||
let deprecations = &spec.deprecations;
|
||||
Ok(quote! {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn __wrap(
|
||||
|
@ -144,8 +152,8 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStream>
|
|||
_args: *mut pyo3::ffi::PyObject,
|
||||
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
use pyo3::callback::IntoPyCallbackOutput;
|
||||
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
|
||||
let _kwargs: Option<&pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
|
||||
|
@ -166,7 +174,7 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStream
|
|||
let cb = quote! { pyo3::callback::convert(_py, #cls::#name(&_cls, #(#names),*)) };
|
||||
let py = syn::Ident::new("_py", Span::call_site());
|
||||
let body = impl_arg_params(spec, Some(cls), cb, &py)?;
|
||||
|
||||
let deprecations = &spec.deprecations;
|
||||
Ok(quote! {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn __wrap(
|
||||
|
@ -174,6 +182,7 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStream
|
|||
_args: *mut pyo3::ffi::PyObject,
|
||||
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
let _cls = pyo3::types::PyType::from_type_ptr(#py, _cls as *mut pyo3::ffi::PyTypeObject);
|
||||
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
|
||||
|
@ -193,7 +202,7 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStrea
|
|||
let cb = quote! { pyo3::callback::convert(_py, #cls::#name(#(#names),*)) };
|
||||
let py = syn::Ident::new("_py", Span::call_site());
|
||||
let body = impl_arg_params(spec, Some(cls), cb, &py)?;
|
||||
|
||||
let deprecations = &spec.deprecations;
|
||||
Ok(quote! {{
|
||||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn __wrap(
|
||||
|
@ -201,6 +210,7 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStrea
|
|||
_args: *mut pyo3::ffi::PyObject,
|
||||
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
|
||||
{
|
||||
#deprecations
|
||||
pyo3::callback::handle_panic(|#py| {
|
||||
let _args = #py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
|
||||
let _kwargs: Option<&pyo3::types::PyDict> = #py.from_borrowed_ptr_or_opt(_kwargs);
|
||||
|
@ -218,9 +228,10 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> Result<TokenStrea
|
|||
pub fn impl_wrap_class_attribute(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
||||
let name = &spec.name;
|
||||
let cb = quote! { #cls::#name() };
|
||||
|
||||
let deprecations = &spec.deprecations;
|
||||
quote! {{
|
||||
fn __wrap(py: pyo3::Python<'_>) -> pyo3::PyObject {
|
||||
#deprecations
|
||||
pyo3::IntoPy::into_py(#cb, py)
|
||||
}
|
||||
__wrap
|
||||
|
@ -578,7 +589,7 @@ pub fn impl_py_method_def(
|
|||
flags: Option<TokenStream>,
|
||||
) -> Result<TokenStream> {
|
||||
let add_flags = flags.map(|flags| quote!(.flags(#flags)));
|
||||
let python_name = spec.python_name_with_deprecation();
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
let doc = &spec.doc;
|
||||
if spec.args.is_empty() {
|
||||
let wrapper = impl_wrap_noargs(cls, spec, self_ty);
|
||||
|
@ -621,7 +632,7 @@ pub fn impl_py_method_def_new(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStr
|
|||
|
||||
pub fn impl_py_method_def_class(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream> {
|
||||
let wrapper = impl_wrap_class(cls, &spec)?;
|
||||
let python_name = spec.python_name_with_deprecation();
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
let doc = &spec.doc;
|
||||
Ok(quote! {
|
||||
pyo3::class::PyMethodDefType::Class({
|
||||
|
@ -636,7 +647,7 @@ pub fn impl_py_method_def_class(cls: &syn::Type, spec: &FnSpec) -> Result<TokenS
|
|||
|
||||
pub fn impl_py_method_def_static(cls: &syn::Type, spec: &FnSpec) -> Result<TokenStream> {
|
||||
let wrapper = impl_wrap_static(cls, &spec)?;
|
||||
let python_name = spec.python_name_with_deprecation();
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
let doc = &spec.doc;
|
||||
Ok(quote! {
|
||||
pyo3::class::PyMethodDefType::Static({
|
||||
|
@ -651,7 +662,7 @@ pub fn impl_py_method_def_static(cls: &syn::Type, spec: &FnSpec) -> Result<Token
|
|||
|
||||
pub fn impl_py_method_class_attribute(cls: &syn::Type, spec: &FnSpec) -> TokenStream {
|
||||
let wrapper = impl_wrap_class_attribute(cls, &spec);
|
||||
let python_name = spec.python_name_with_deprecation();
|
||||
let python_name = spec.null_terminated_python_name();
|
||||
quote! {
|
||||
pyo3::class::PyMethodDefType::ClassAttribute({
|
||||
pyo3::class::PyClassAttributeDef::new(
|
||||
|
@ -663,7 +674,7 @@ pub fn impl_py_method_class_attribute(cls: &syn::Type, spec: &FnSpec) -> TokenSt
|
|||
}
|
||||
|
||||
pub fn impl_py_const_class_attribute(spec: &ConstSpec, wrapper: &TokenStream) -> TokenStream {
|
||||
let python_name = &spec.python_name_with_deprecation();
|
||||
let python_name = &spec.null_terminated_python_name();
|
||||
quote! {
|
||||
{
|
||||
pyo3::class::PyMethodDefType::ClassAttribute({
|
||||
|
@ -696,17 +707,19 @@ pub(crate) fn impl_py_setter_def(
|
|||
property_type: PropertyType,
|
||||
self_ty: &SelfType,
|
||||
doc: &syn::LitStr,
|
||||
deprecations: &Deprecations,
|
||||
) -> Result<TokenStream> {
|
||||
let python_name = match property_type {
|
||||
PropertyType::Descriptor(ident) => {
|
||||
let formatted_name = format!("{}\0", ident.unraw());
|
||||
quote!(#formatted_name)
|
||||
}
|
||||
PropertyType::Function(spec) => spec.python_name_with_deprecation(),
|
||||
PropertyType::Function(spec) => spec.null_terminated_python_name(),
|
||||
};
|
||||
let wrapper = impl_wrap_setter(cls, property_type, self_ty)?;
|
||||
Ok(quote! {
|
||||
pyo3::class::PyMethodDefType::Setter({
|
||||
#deprecations
|
||||
pyo3::class::PySetterDef::new(
|
||||
#python_name,
|
||||
pyo3::class::methods::PySetter(#wrapper),
|
||||
|
@ -721,17 +734,19 @@ pub(crate) fn impl_py_getter_def(
|
|||
property_type: PropertyType,
|
||||
self_ty: &SelfType,
|
||||
doc: &syn::LitStr,
|
||||
deprecations: &Deprecations,
|
||||
) -> Result<TokenStream> {
|
||||
let python_name = match property_type {
|
||||
PropertyType::Descriptor(ident) => {
|
||||
let formatted_name = format!("{}\0", ident.unraw());
|
||||
quote!(#formatted_name)
|
||||
}
|
||||
PropertyType::Function(spec) => spec.python_name_with_deprecation(),
|
||||
PropertyType::Function(spec) => spec.null_terminated_python_name(),
|
||||
};
|
||||
let wrapper = impl_wrap_getter(cls, property_type, self_ty)?;
|
||||
Ok(quote! {
|
||||
pyo3::class::PyMethodDefType::Getter({
|
||||
#deprecations
|
||||
pyo3::class::PyGetterDef::new(
|
||||
#python_name,
|
||||
pyo3::class::methods::PyGetter(#wrapper),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote_spanned;
|
||||
use proc_macro2::Span;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Macro inspired by `anyhow::anyhow!` to create a compiler error with the given span.
|
||||
|
@ -165,14 +164,3 @@ pub fn get_doc(
|
|||
|
||||
Ok(syn::LitStr::new(&doc, span))
|
||||
}
|
||||
|
||||
pub fn name_deprecation_token(span: Span, name_is_deprecated: bool) -> Option<TokenStream> {
|
||||
if name_is_deprecated {
|
||||
Some(quote_spanned!(
|
||||
span =>
|
||||
let _ = pyo3::impl_::deprecations::NAME_ATTRIBUTE;
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,4 @@
|
|||
//! any of these APIs in downstream code is implicitly acknowledging that these APIs may change at
|
||||
//! any time without documentation in the CHANGELOG and without breaking semver guarantees.
|
||||
|
||||
/// Symbols to represent deprecated uses of PyO3's macros.
|
||||
pub mod deprecations {
|
||||
#[doc(hidden)]
|
||||
#[deprecated(
|
||||
since = "0.14.0",
|
||||
note = "use `#[pyo3(name = \"...\")]` instead of `#[name = \"...\"]`"
|
||||
)]
|
||||
pub const NAME_ATTRIBUTE: () = ();
|
||||
}
|
||||
pub mod deprecations;
|
|
@ -0,0 +1,13 @@
|
|||
//! Symbols used to denote deprecated usages of PyO3's proc macros.
|
||||
|
||||
#[deprecated(
|
||||
since = "0.14.0",
|
||||
note = "use `#[pyo3(name = \"...\")]` instead of `#[name = \"...\"]`"
|
||||
)]
|
||||
pub const NAME_ATTRIBUTE: () = ();
|
||||
|
||||
#[deprecated(
|
||||
since = "0.14.0",
|
||||
note = "use `#[pyfn(m)] #[pyo3(name = \"...\")]` instead of `#[pyfn(m, \"...\")]`"
|
||||
)]
|
||||
pub const PYFN_NAME_ARGUMENT: () = ();
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
|
||||
use pyo3::py_run;
|
||||
use pyo3::types::{IntoPyDict, PyDict, PyTuple};
|
||||
use pyo3::{py_run, wrap_pyfunction};
|
||||
mod common;
|
||||
|
||||
#[pyclass]
|
||||
|
@ -36,24 +36,24 @@ fn double(x: usize) -> usize {
|
|||
/// This module is implemented in Rust.
|
||||
#[pymodule]
|
||||
fn module_with_functions(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
#![allow(deprecated)]
|
||||
#[pyfn(m, "sum_as_string")]
|
||||
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> String {
|
||||
fn function_with_deprecated_name(_py: Python, a: i64, b: i64) -> String {
|
||||
sum_as_string(a, b)
|
||||
}
|
||||
|
||||
#[pyfn(m, "no_parameters")]
|
||||
fn no_parameters() -> usize {
|
||||
#[pyfn(m)]
|
||||
#[pyo3(name = "no_parameters")]
|
||||
fn function_with_name() -> usize {
|
||||
42
|
||||
}
|
||||
|
||||
#[pyfn(m, "with_module", pass_module)]
|
||||
#[pyfn(m, pass_module)]
|
||||
fn with_module(module: &PyModule) -> PyResult<&str> {
|
||||
module.name()
|
||||
}
|
||||
|
||||
#[pyfn(m, "double_value")]
|
||||
#[pyfn(m)]
|
||||
fn double_value(v: &ValueClass) -> usize {
|
||||
v.value * 2
|
||||
}
|
||||
|
@ -174,8 +174,6 @@ fn r#move() -> usize {
|
|||
|
||||
#[pymodule]
|
||||
fn raw_ident_module(_py: Python, module: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
module.add_function(wrap_pyfunction!(r#move, module)?)
|
||||
}
|
||||
|
||||
|
@ -199,8 +197,6 @@ fn custom_named_fn() -> usize {
|
|||
|
||||
#[pymodule]
|
||||
fn foobar_module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?;
|
||||
m.dict().set_item("yay", "me")?;
|
||||
Ok(())
|
||||
|
@ -241,16 +237,12 @@ fn subfunction() -> String {
|
|||
}
|
||||
|
||||
fn submodule(module: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
module.add_function(wrap_pyfunction!(subfunction, module)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymodule]
|
||||
fn submodule_with_init_fn(_py: Python, module: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
module.add_function(wrap_pyfunction!(subfunction, module)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -262,8 +254,6 @@ fn superfunction() -> String {
|
|||
|
||||
#[pymodule]
|
||||
fn supermodule(py: Python, module: &PyModule) -> PyResult<()> {
|
||||
use pyo3::wrap_pyfunction;
|
||||
|
||||
module.add_function(wrap_pyfunction!(superfunction, module)?)?;
|
||||
let module_to_add = PyModule::new(py, "submodule")?;
|
||||
submodule(module_to_add)?;
|
||||
|
@ -308,13 +298,12 @@ fn ext_vararg_fn(py: Python, a: i32, vararg: &PyTuple) -> PyObject {
|
|||
|
||||
#[pymodule]
|
||||
fn vararg_module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "int_vararg_fn", a = 5, vararg = "*")]
|
||||
#[pyfn(m, a = 5, vararg = "*")]
|
||||
fn int_vararg_fn(py: Python, a: i32, vararg: &PyTuple) -> PyObject {
|
||||
ext_vararg_fn(py, a, vararg)
|
||||
}
|
||||
|
||||
m.add_function(pyo3::wrap_pyfunction!(ext_vararg_fn, m)?)
|
||||
.unwrap();
|
||||
m.add_function(wrap_pyfunction!(ext_vararg_fn, m)?).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -390,17 +379,11 @@ fn pyfunction_with_module_and_args_kwargs<'a>(
|
|||
|
||||
#[pymodule]
|
||||
fn module_with_functions_with_module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(pyo3::wrap_pyfunction!(pyfunction_with_module, m)?)?;
|
||||
m.add_function(pyo3::wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?;
|
||||
m.add_function(pyo3::wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?;
|
||||
m.add_function(pyo3::wrap_pyfunction!(
|
||||
pyfunction_with_module_and_default_arg,
|
||||
m
|
||||
)?)?;
|
||||
m.add_function(pyo3::wrap_pyfunction!(
|
||||
pyfunction_with_module_and_args_kwargs,
|
||||
m
|
||||
)?)
|
||||
m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_default_arg, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_args_kwargs, m)?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -119,7 +119,7 @@ fn test_function() {
|
|||
fn test_pyfn() {
|
||||
#[pymodule]
|
||||
fn my_module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "my_function", a, b = "None", "*", c = 42)]
|
||||
#[pyfn(m, a, b = "None", "*", c = 42)]
|
||||
#[text_signature = "(a, b=None, *, c=42)"]
|
||||
fn my_function(a: i32, b: Option<i32>, c: i32) {
|
||||
let _ = (a, b, c);
|
||||
|
|
|
@ -25,6 +25,14 @@ impl TestClass {
|
|||
#[name = "foo"]
|
||||
fn deprecated_name_pyfunction() { }
|
||||
|
||||
#[pymodule]
|
||||
fn my_module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "some_name")]
|
||||
fn deprecated_name_pyfn() { }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
|
|
|
@ -27,3 +27,9 @@ error: use of deprecated constant `pyo3::impl_::deprecations::NAME_ATTRIBUTE`: u
|
|||
|
|
||||
25 | #[name = "foo"]
|
||||
| ^
|
||||
|
||||
error: use of deprecated constant `pyo3::impl_::deprecations::PYFN_NAME_ARGUMENT`: use `#[pyfn(m)] #[pyo3(name = "...")]` instead of `#[pyfn(m, "...")]`
|
||||
--> $DIR/deprecations.rs:30:15
|
||||
|
|
||||
30 | #[pyfn(m, "some_name")]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
|
@ -2,11 +2,11 @@ use pyo3::prelude::*;
|
|||
|
||||
#[pymodule]
|
||||
fn module(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
#[pyfn(m, "with_module", pass_module)]
|
||||
#[pyfn(m, pass_module)]
|
||||
fn fail(string: &str, module: &PyModule) -> PyResult<&str> {
|
||||
module.name()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main(){}
|
||||
fn main(){}
|
||||
|
|
Loading…
Reference in New Issue