deprecate implicit default for trailing optional arguments (#4078)

* deprecate "trailing optional arguments" implicit default behaviour

* add newsfragment

* generate individual deprecation messages per function

* add migration guide entry
This commit is contained in:
Icxolu 2024-05-10 12:34:58 +02:00 committed by GitHub
parent 104328ce14
commit aef0a05719
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 211 additions and 26 deletions

View File

@ -12,6 +12,7 @@ use futures::channel::oneshot;
use pyo3::prelude::*; use pyo3::prelude::*;
#[pyfunction] #[pyfunction]
#[pyo3(signature=(seconds, result=None))]
async fn sleep(seconds: f64, result: Option<PyObject>) -> Option<PyObject> { async fn sleep(seconds: f64, result: Option<PyObject>) -> Option<PyObject> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
thread::spawn(move || { thread::spawn(move || {

View File

@ -121,9 +121,22 @@ num=-1
## Trailing optional arguments ## Trailing optional arguments
<div class="warning">
⚠️ Warning: This behaviour is being phased out 🛠️
The special casing of trailing optional arguments is deprecated. In a future `pyo3` version, arguments of type `Option<..>` will share the same behaviour as other arguments, they are required unless a default is set using `#[pyo3(signature = (...))]`.
This is done to better align the Python and Rust definition of such functions and make it more intuitive to rewrite them from Python in Rust. Specifically `def some_fn(a: int, b: Optional[int]): ...` will not automatically default `b` to `none`, but requires an explicit default if desired, where as in current `pyo3` it is handled the other way around.
During the migration window a `#[pyo3(signature = (...))]` will be required to silence the deprecation warning. After support for trailing optional arguments is fully removed, the signature attribute can be removed if all arguments should be required.
</div>
As a convenience, functions without a `#[pyo3(signature = (...))]` option will treat trailing `Option<T>` arguments as having a default of `None`. In the example below, PyO3 will create `increment` with a signature of `increment(x, amount=None)`. As a convenience, functions without a `#[pyo3(signature = (...))]` option will treat trailing `Option<T>` arguments as having a default of `None`. In the example below, PyO3 will create `increment` with a signature of `increment(x, amount=None)`.
```rust ```rust
#![allow(deprecated)]
use pyo3::prelude::*; use pyo3::prelude::*;
/// Returns a copy of `x` increased by `amount`. /// Returns a copy of `x` increased by `amount`.

View File

@ -3,6 +3,41 @@
This guide can help you upgrade code through breaking changes from one PyO3 version to the next. This guide can help you upgrade code through breaking changes from one PyO3 version to the next.
For a detailed list of all changes, see the [CHANGELOG](changelog.md). For a detailed list of all changes, see the [CHANGELOG](changelog.md).
## from 0.21.* to 0.22
### Deprecation of implicit default for trailing optional arguments
<details open>
<summary><small>Click to expand</small></summary>
With `pyo3` 0.22 the implicit `None` default for trailing `Option<T>` type argument is deprecated. To migrate, place a `#[pyo3(signature = (...))]` attribute on affected functions or methods and specify the desired behavior.
The migration warning specifies the corresponding signature to keep the current behavior. With 0.23 the signature will be required for any function containing `Option<T>` type parameters to prevent accidental
and unnoticed changes in behavior. With 0.24 this restriction will be lifted again and `Option<T>` type arguments will be treated as any other argument _without_ special handling.
Before:
```rust
# #![allow(deprecated, dead_code)]
# use pyo3::prelude::*;
#[pyfunction]
fn increment(x: u64, amount: Option<u64>) -> u64 {
x + amount.unwrap_or(1)
}
```
After:
```rust
# #![allow(dead_code)]
# use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (x, amount=None))]
fn increment(x: u64, amount: Option<u64>) -> u64 {
x + amount.unwrap_or(1)
}
```
</details>
## from 0.20.* to 0.21 ## from 0.20.* to 0.21
<details open> <details open>
<summary><small>Click to expand</small></summary> <summary><small>Click to expand</small></summary>

View File

@ -0,0 +1 @@
deprecate implicit default for trailing optional arguments

View File

@ -1,4 +1,7 @@
use crate::utils::Ctx; use crate::{
method::{FnArg, FnSpec},
utils::Ctx,
};
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{quote_spanned, ToTokens}; use quote::{quote_spanned, ToTokens};
@ -45,3 +48,51 @@ impl<'ctx> ToTokens for Deprecations<'ctx> {
} }
} }
} }
pub(crate) fn deprecate_trailing_option_default(spec: &FnSpec<'_>) -> TokenStream {
if spec.signature.attribute.is_none()
&& spec.signature.arguments.iter().any(|arg| {
if let FnArg::Regular(arg) = arg {
arg.option_wrapped_type.is_some()
} else {
false
}
})
{
use std::fmt::Write;
let mut deprecation_msg = String::from(
"This function has implicit defaults for the trailing `Option<T>` arguments. \
These implicit defaults are being phased out. Add `#[pyo3(signature = (",
);
spec.signature.arguments.iter().for_each(|arg| {
match arg {
FnArg::Regular(arg) => {
if arg.option_wrapped_type.is_some() {
write!(deprecation_msg, "{}=None, ", arg.name)
} else {
write!(deprecation_msg, "{}, ", arg.name)
}
}
FnArg::VarArgs(arg) => write!(deprecation_msg, "{}, ", arg.name),
FnArg::KwArgs(arg) => write!(deprecation_msg, "{}, ", arg.name),
FnArg::Py(_) | FnArg::CancelHandle(_) => Ok(()),
}
.expect("writing to `String` should not fail");
});
//remove trailing space and comma
deprecation_msg.pop();
deprecation_msg.pop();
deprecation_msg
.push_str(")]` to this function to silence this warning and keep the current behavior");
quote_spanned! { spec.name.span() =>
#[deprecated(note = #deprecation_msg)]
#[allow(dead_code)]
const SIGNATURE: () = ();
const _: () = SIGNATURE;
}
} else {
TokenStream::new()
}
}

View File

@ -5,6 +5,7 @@ use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens}; use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::{ext::IdentExt, spanned::Spanned, Ident, Result}; use syn::{ext::IdentExt, spanned::Spanned, Ident, Result};
use crate::deprecations::deprecate_trailing_option_default;
use crate::utils::Ctx; use crate::utils::Ctx;
use crate::{ use crate::{
attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue}, attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue},
@ -708,6 +709,8 @@ impl<'a> FnSpec<'a> {
quote!(#func_name) quote!(#func_name)
}; };
let deprecation = deprecate_trailing_option_default(self);
Ok(match self.convention { Ok(match self.convention {
CallingConvention::Noargs => { CallingConvention::Noargs => {
let mut holders = Holders::new(); let mut holders = Holders::new();
@ -730,6 +733,7 @@ impl<'a> FnSpec<'a> {
py: #pyo3_path::Python<'py>, py: #pyo3_path::Python<'py>,
_slf: *mut #pyo3_path::ffi::PyObject, _slf: *mut #pyo3_path::ffi::PyObject,
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
#deprecation
let _slf_ref = &_slf; let _slf_ref = &_slf;
let function = #rust_name; // Shadow the function name to avoid #3017 let function = #rust_name; // Shadow the function name to avoid #3017
#init_holders #init_holders
@ -754,6 +758,7 @@ impl<'a> FnSpec<'a> {
_nargs: #pyo3_path::ffi::Py_ssize_t, _nargs: #pyo3_path::ffi::Py_ssize_t,
_kwnames: *mut #pyo3_path::ffi::PyObject _kwnames: *mut #pyo3_path::ffi::PyObject
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
#deprecation
let _slf_ref = &_slf; let _slf_ref = &_slf;
let function = #rust_name; // Shadow the function name to avoid #3017 let function = #rust_name; // Shadow the function name to avoid #3017
#arg_convert #arg_convert
@ -778,6 +783,7 @@ impl<'a> FnSpec<'a> {
_args: *mut #pyo3_path::ffi::PyObject, _args: *mut #pyo3_path::ffi::PyObject,
_kwargs: *mut #pyo3_path::ffi::PyObject _kwargs: *mut #pyo3_path::ffi::PyObject
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
#deprecation
let _slf_ref = &_slf; let _slf_ref = &_slf;
let function = #rust_name; // Shadow the function name to avoid #3017 let function = #rust_name; // Shadow the function name to avoid #3017
#arg_convert #arg_convert
@ -805,6 +811,7 @@ impl<'a> FnSpec<'a> {
_kwargs: *mut #pyo3_path::ffi::PyObject _kwargs: *mut #pyo3_path::ffi::PyObject
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
use #pyo3_path::callback::IntoPyCallbackOutput; use #pyo3_path::callback::IntoPyCallbackOutput;
#deprecation
let _slf_ref = &_slf; let _slf_ref = &_slf;
let function = #rust_name; // Shadow the function name to avoid #3017 let function = #rust_name; // Shadow the function name to avoid #3017
#arg_convert #arg_convert

View File

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use crate::attributes::{NameAttribute, RenamingRule}; use crate::attributes::{NameAttribute, RenamingRule};
use crate::deprecations::deprecate_trailing_option_default;
use crate::method::{CallingConvention, ExtractErrorMode, PyArg}; use crate::method::{CallingConvention, ExtractErrorMode, PyArg};
use crate::params::{check_arg_for_gil_refs, impl_regular_arg_param, Holders}; use crate::params::{check_arg_for_gil_refs, impl_regular_arg_param, Holders};
use crate::utils::Ctx; use crate::utils::Ctx;
@ -637,7 +638,10 @@ pub fn impl_py_setter_def(
); );
let extract = let extract =
check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx); check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx);
let deprecation = deprecate_trailing_option_default(spec);
quote! { quote! {
#deprecation
#from_py_with #from_py_with
let _val = #extract; let _val = #extract;
} }

View File

@ -25,6 +25,7 @@ fn date_from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult<Bound<'_, PyD
} }
#[pyfunction] #[pyfunction]
#[pyo3(signature=(hour, minute, second, microsecond, tzinfo=None))]
fn make_time<'py>( fn make_time<'py>(
py: Python<'py>, py: Python<'py>,
hour: u8, hour: u8,
@ -101,6 +102,7 @@ fn get_delta_tuple<'py>(delta: &Bound<'py, PyDelta>) -> Bound<'py, PyTuple> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[pyfunction] #[pyfunction]
#[pyo3(signature=(year, month, day, hour, minute, second, microsecond, tzinfo=None))]
fn make_datetime<'py>( fn make_datetime<'py>(
py: Python<'py>, py: Python<'py>,
year: i32, year: i32,
@ -159,6 +161,7 @@ fn get_datetime_tuple_fold<'py>(dt: &Bound<'py, PyDateTime>) -> Bound<'py, PyTup
} }
#[pyfunction] #[pyfunction]
#[pyo3(signature=(ts, tz=None))]
fn datetime_from_timestamp<'py>( fn datetime_from_timestamp<'py>(
py: Python<'py>, py: Python<'py>,
ts: f64, ts: f64,

View File

@ -309,6 +309,7 @@ impl Dummy {
0 0
} }
#[pyo3(signature=(ndigits=::std::option::Option::None))]
fn __round__(&self, ndigits: ::std::option::Option<u32>) -> u32 { fn __round__(&self, ndigits: ::std::option::Option<u32>) -> u32 {
0 0
} }

View File

@ -35,6 +35,7 @@ impl UnaryArithmetic {
Self::new(self.inner.abs()) Self::new(self.inner.abs())
} }
#[pyo3(signature=(_ndigits=None))]
fn __round__(&self, _ndigits: Option<u32>) -> Self { fn __round__(&self, _ndigits: Option<u32>) -> Self {
Self::new(self.inner.round()) Self::new(self.inner.round())
} }

View File

@ -21,6 +21,7 @@ struct Mapping {
#[pymethods] #[pymethods]
impl Mapping { impl Mapping {
#[new] #[new]
#[pyo3(signature=(elements=None))]
fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> { fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> {
if let Some(pylist) = elements { if let Some(pylist) = elements {
let mut elems = HashMap::with_capacity(pylist.len()); let mut elems = HashMap::with_capacity(pylist.len());
@ -59,6 +60,7 @@ impl Mapping {
} }
} }
#[pyo3(signature=(key, default=None))]
fn get(&self, py: Python<'_>, key: &str, default: Option<PyObject>) -> Option<PyObject> { fn get(&self, py: Python<'_>, key: &str, default: Option<PyObject>) -> Option<PyObject> {
self.index self.index
.get(key) .get(key)

View File

@ -187,6 +187,7 @@ impl MethSignature {
fn get_optional2(&self, test: Option<i32>) -> Option<i32> { fn get_optional2(&self, test: Option<i32>) -> Option<i32> {
test test
} }
#[pyo3(signature=(_t1 = None, t2 = None, _t3 = None))]
fn get_optional_positional( fn get_optional_positional(
&self, &self,
_t1: Option<i32>, _t1: Option<i32>,
@ -745,11 +746,13 @@ impl MethodWithPyClassArg {
fn inplace_add_pyref(&self, mut other: PyRefMut<'_, MethodWithPyClassArg>) { fn inplace_add_pyref(&self, mut other: PyRefMut<'_, MethodWithPyClassArg>) {
other.value += self.value; other.value += self.value;
} }
#[pyo3(signature=(other = None))]
fn optional_add(&self, other: Option<&MethodWithPyClassArg>) -> MethodWithPyClassArg { fn optional_add(&self, other: Option<&MethodWithPyClassArg>) -> MethodWithPyClassArg {
MethodWithPyClassArg { MethodWithPyClassArg {
value: self.value + other.map(|o| o.value).unwrap_or(10), value: self.value + other.map(|o| o.value).unwrap_or(10),
} }
} }
#[pyo3(signature=(other = None))]
fn optional_inplace_add(&self, other: Option<&mut MethodWithPyClassArg>) { fn optional_inplace_add(&self, other: Option<&mut MethodWithPyClassArg>) {
if let Some(other) = other { if let Some(other) = other {
other.value += self.value; other.value += self.value;
@ -851,6 +854,7 @@ struct FromSequence {
#[pymethods] #[pymethods]
impl FromSequence { impl FromSequence {
#[new] #[new]
#[pyo3(signature=(seq = None))]
fn new(seq: Option<&Bound<'_, PySequence>>) -> PyResult<Self> { fn new(seq: Option<&Bound<'_, PySequence>>) -> PyResult<Self> {
if let Some(seq) = seq { if let Some(seq) = seq {
Ok(FromSequence { Ok(FromSequence {
@ -1026,6 +1030,7 @@ macro_rules! issue_1506 {
issue_1506!( issue_1506!(
#[pymethods] #[pymethods]
impl Issue1506 { impl Issue1506 {
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506( fn issue_1506(
&self, &self,
_py: Python<'_>, _py: Python<'_>,
@ -1035,6 +1040,7 @@ issue_1506!(
) { ) {
} }
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_mut( fn issue_1506_mut(
&mut self, &mut self,
_py: Python<'_>, _py: Python<'_>,
@ -1044,6 +1050,7 @@ issue_1506!(
) { ) {
} }
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_custom_receiver( fn issue_1506_custom_receiver(
_slf: Py<Self>, _slf: Py<Self>,
_py: Python<'_>, _py: Python<'_>,
@ -1053,6 +1060,7 @@ issue_1506!(
) { ) {
} }
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_custom_receiver_explicit( fn issue_1506_custom_receiver_explicit(
_slf: Py<Issue1506>, _slf: Py<Issue1506>,
_py: Python<'_>, _py: Python<'_>,
@ -1063,6 +1071,7 @@ issue_1506!(
} }
#[new] #[new]
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_new( fn issue_1506_new(
_py: Python<'_>, _py: Python<'_>,
_arg: &Bound<'_, PyAny>, _arg: &Bound<'_, PyAny>,
@ -1081,6 +1090,7 @@ issue_1506!(
fn issue_1506_setter(&self, _py: Python<'_>, _value: i32) {} fn issue_1506_setter(&self, _py: Python<'_>, _value: i32) {}
#[staticmethod] #[staticmethod]
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_static( fn issue_1506_static(
_py: Python<'_>, _py: Python<'_>,
_arg: &Bound<'_, PyAny>, _arg: &Bound<'_, PyAny>,
@ -1090,6 +1100,7 @@ issue_1506!(
} }
#[classmethod] #[classmethod]
#[pyo3(signature = (_arg, _args, _kwargs=None))]
fn issue_1506_class( fn issue_1506_class(
_cls: &Bound<'_, PyType>, _cls: &Bound<'_, PyType>,
_py: Python<'_>, _py: Python<'_>,

View File

@ -182,6 +182,7 @@ fn test_from_py_with_defaults() {
// issue 2280 combination of from_py_with and Option<T> did not compile // issue 2280 combination of from_py_with and Option<T> did not compile
#[pyfunction] #[pyfunction]
#[pyo3(signature = (int=None))]
fn from_py_with_option(#[pyo3(from_py_with = "optional_int")] int: Option<i32>) -> i32 { fn from_py_with_option(#[pyo3(from_py_with = "optional_int")] int: Option<i32>) -> i32 {
int.unwrap_or(0) int.unwrap_or(0)
} }
@ -216,6 +217,7 @@ struct ValueClass {
} }
#[pyfunction] #[pyfunction]
#[pyo3(signature=(str_arg, int_arg, tuple_arg, option_arg = None, struct_arg = None))]
fn conversion_error( fn conversion_error(
str_arg: &str, str_arg: &str,
int_arg: i64, int_arg: i64,
@ -542,6 +544,7 @@ fn test_some_wrap_arguments() {
#[test] #[test]
fn test_reference_to_bound_arguments() { fn test_reference_to_bound_arguments() {
#[pyfunction] #[pyfunction]
#[pyo3(signature = (x, y = None))]
fn reference_args<'py>( fn reference_args<'py>(
x: &Bound<'py, PyAny>, x: &Bound<'py, PyAny>,
y: Option<&Bound<'py, PyAny>>, y: Option<&Bound<'py, PyAny>>,

View File

@ -17,6 +17,7 @@ struct ByteSequence {
#[pymethods] #[pymethods]
impl ByteSequence { impl ByteSequence {
#[new] #[new]
#[pyo3(signature=(elements = None))]
fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> { fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> {
if let Some(pylist) = elements { if let Some(pylist) = elements {
let mut elems = Vec::with_capacity(pylist.len()); let mut elems = Vec::with_capacity(pylist.len());

View File

@ -142,6 +142,7 @@ fn test_auto_test_signature_function() {
} }
#[pyfunction] #[pyfunction]
#[pyo3(signature=(a, b=None, c=None))]
fn my_function_6(a: i32, b: Option<i32>, c: Option<i32>) { fn my_function_6(a: i32, b: Option<i32>, c: Option<i32>) {
let _ = (a, b, c); let _ = (a, b, c);
} }

View File

@ -39,6 +39,9 @@ impl MyClass {
#[setter] #[setter]
fn set_bar_bound(&self, _value: &Bound<'_, PyAny>) {} fn set_bar_bound(&self, _value: &Bound<'_, PyAny>) {}
#[setter]
fn set_option(&self, _value: Option<i32>) {}
fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool { fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool {
true true
} }
@ -103,6 +106,10 @@ fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<i32> {
obj.extract() obj.extract()
} }
fn extract_options(obj: &Bound<'_, PyAny>) -> PyResult<Option<i32>> {
obj.extract()
}
#[pyfunction] #[pyfunction]
fn pyfunction_from_py_with( fn pyfunction_from_py_with(
#[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32, #[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32,
@ -114,8 +121,27 @@ fn pyfunction_from_py_with(
fn pyfunction_gil_ref(_any: &PyAny) {} fn pyfunction_gil_ref(_any: &PyAny) {}
#[pyfunction] #[pyfunction]
#[pyo3(signature = (_any))]
fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {} fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {}
#[pyfunction]
#[pyo3(signature = (_i, _any=None))]
fn pyfunction_option_1(_i: u32, _any: Option<i32>) {}
#[pyfunction]
fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
#[pyfunction]
fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {}
#[pyfunction]
fn pyfunction_option_4(
_i: u32,
#[pyo3(from_py_with = "extract_options")] _any: Option<i32>,
_foo: Option<String>,
) {
}
#[derive(Debug, FromPyObject)] #[derive(Debug, FromPyObject)]
pub struct Zap { pub struct Zap {
#[pyo3(item)] #[pyo3(item)]

View File

@ -10,10 +10,34 @@ note: the lint level is defined here
1 | #![deny(deprecated)] 1 | #![deny(deprecated)]
| ^^^^^^^^^^ | ^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated constant `MyClass::__pymethod_set_set_option__::SIGNATURE`: This function has implicit defaults for the trailing `Option<T>` arguments. These implicit defaults are being phased out. Add `#[pyo3(signature = (_value=None)]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:42:44 --> tests/ui/deprecations.rs:43:8
| |
42 | fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool { 43 | fn set_option(&self, _value: Option<i32>) {}
| ^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_2::SIGNATURE`: This function has implicit defaults for the trailing `Option<T>` arguments. These implicit defaults are being phased out. Add `#[pyo3(signature = (_i, _any=None)]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:132:4
|
132 | fn pyfunction_option_2(_i: u32, _any: Option<i32>) {}
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_3::SIGNATURE`: This function has implicit defaults for the trailing `Option<T>` arguments. These implicit defaults are being phased out. Add `#[pyo3(signature = (_i, _any=None, _foo=None)]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:135:4
|
135 | fn pyfunction_option_3(_i: u32, _any: Option<i32>, _foo: Option<String>) {}
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated constant `__pyfunction_pyfunction_option_4::SIGNATURE`: This function has implicit defaults for the trailing `Option<T>` arguments. These implicit defaults are being phased out. Add `#[pyo3(signature = (_i, _any=None, _foo=None)]` to this function to silence this warning and keep the current behavior
--> tests/ui/deprecations.rs:138:4
|
138 | fn pyfunction_option_4(
| ^^^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:45:44
|
45 | fn __eq__(&self, #[pyo3(from_py_with = "extract_gil_ref")] _other: i32) -> bool {
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
@ -47,69 +71,69 @@ error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`
| ^ | ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:61:44 --> tests/ui/deprecations.rs:64:44
| |
61 | fn pyfunction_with_module_gil_ref(_module: &PyModule) -> PyResult<&str> { 64 | fn pyfunction_with_module_gil_ref(_module: &PyModule) -> PyResult<&str> {
| ^ | ^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:71:19 --> tests/ui/deprecations.rs:74:19
| |
71 | fn module_gil_ref(_m: &PyModule) -> PyResult<()> { 74 | fn module_gil_ref(_m: &PyModule) -> PyResult<()> {
| ^^ | ^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:76:57 --> tests/ui/deprecations.rs:79:57
| |
76 | fn module_gil_ref_with_explicit_py_arg(_py: Python<'_>, _m: &PyModule) -> PyResult<()> { 79 | fn module_gil_ref_with_explicit_py_arg(_py: Python<'_>, _m: &PyModule) -> PyResult<()> {
| ^^ | ^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:108:27 --> tests/ui/deprecations.rs:115:27
| |
108 | #[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32, 115 | #[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32,
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
--> tests/ui/deprecations.rs:114:29 --> tests/ui/deprecations.rs:121:29
| |
114 | fn pyfunction_gil_ref(_any: &PyAny) {} 121 | fn pyfunction_gil_ref(_any: &PyAny) {}
| ^ | ^
error: use of deprecated method `pyo3::deprecations::OptionGilRefs::<std::option::Option<T>>::function_arg`: use `Option<&Bound<'_, T>>` instead for this function argument error: use of deprecated method `pyo3::deprecations::OptionGilRefs::<std::option::Option<T>>::function_arg`: use `Option<&Bound<'_, T>>` instead for this function argument
--> tests/ui/deprecations.rs:117:36 --> tests/ui/deprecations.rs:125:36
| |
117 | fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {} 125 | fn pyfunction_option_gil_ref(_any: Option<&PyAny>) {}
| ^^^^^^ | ^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:124:27 --> tests/ui/deprecations.rs:150:27
| |
124 | #[pyo3(from_py_with = "PyAny::len", item("my_object"))] 150 | #[pyo3(from_py_with = "PyAny::len", item("my_object"))]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:134:27 --> tests/ui/deprecations.rs:160:27
| |
134 | #[pyo3(from_py_with = "PyAny::len")] usize, 160 | #[pyo3(from_py_with = "PyAny::len")] usize,
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:140:31 --> tests/ui/deprecations.rs:166:31
| |
140 | Zip(#[pyo3(from_py_with = "extract_gil_ref")] i32), 166 | Zip(#[pyo3(from_py_with = "extract_gil_ref")] i32),
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
--> tests/ui/deprecations.rs:147:27 --> tests/ui/deprecations.rs:173:27
| |
147 | #[pyo3(from_py_with = "extract_gil_ref")] 173 | #[pyo3(from_py_with = "extract_gil_ref")]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: use of deprecated method `pyo3::deprecations::GilRefs::<pyo3::Python<'_>>::is_python`: use `wrap_pyfunction_bound!` instead error: use of deprecated method `pyo3::deprecations::GilRefs::<pyo3::Python<'_>>::is_python`: use `wrap_pyfunction_bound!` instead
--> tests/ui/deprecations.rs:160:13 --> tests/ui/deprecations.rs:186:13
| |
160 | let _ = wrap_pyfunction!(double, py); 186 | let _ = wrap_pyfunction!(double, py);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `wrap_pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `wrap_pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)