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:
parent
104328ce14
commit
aef0a05719
|
@ -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 || {
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
deprecate implicit default for trailing optional arguments
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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<'_>,
|
||||||
|
|
|
@ -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>>,
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue