deprecate GIL refs in function argument (#3847)
* deprecate GIL Refs in function arguments * fix deprecated gil refs in function arguments * add notes on deprecations limitations to migration guide * Apply suggestions from code review Co-authored-by: Icxolu <10486322+Icxolu@users.noreply.github.com> * review: Icxolu * fix proto method extract failure for option * fix gil refs in examples --------- Co-authored-by: Icxolu <10486322+Icxolu@users.noreply.github.com>
This commit is contained in:
parent
cedac43dbb
commit
870a4bb20d
|
@ -7,7 +7,7 @@ use std::os::raw::c_long;
|
||||||
#[derive(FromPyObject)]
|
#[derive(FromPyObject)]
|
||||||
enum IntOrSlice<'py> {
|
enum IntOrSlice<'py> {
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Slice(&'py PySlice),
|
Slice(Bound<'py, PySlice>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
@ -23,7 +23,7 @@ impl ExampleContainer {
|
||||||
ExampleContainer { max_length: 100 }
|
ExampleContainer { max_length: 100 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __getitem__(&self, key: &PyAny) -> PyResult<i32> {
|
fn __getitem__(&self, key: &Bound<'_, PyAny>) -> PyResult<i32> {
|
||||||
if let Ok(position) = key.extract::<i32>() {
|
if let Ok(position) = key.extract::<i32>() {
|
||||||
return Ok(position);
|
return Ok(position);
|
||||||
} else if let Ok(slice) = key.downcast::<PySlice>() {
|
} else if let Ok(slice) = key.downcast::<PySlice>() {
|
||||||
|
@ -63,7 +63,10 @@ impl ExampleContainer {
|
||||||
match idx {
|
match idx {
|
||||||
IntOrSlice::Slice(slice) => {
|
IntOrSlice::Slice(slice) => {
|
||||||
let index = slice.indices(self.max_length as c_long).unwrap();
|
let index = slice.indices(self.max_length as c_long).unwrap();
|
||||||
println!("Got a slice! {}-{}, step: {}, value: {}", index.start, index.stop, index.step, value);
|
println!(
|
||||||
|
"Got a slice! {}-{}, step: {}, value: {}",
|
||||||
|
index.start, index.stop, index.step, value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
IntOrSlice::Int(index) => {
|
IntOrSlice::Int(index) => {
|
||||||
println!("Got an index! {} : value: {}", index, value);
|
println!("Got an index! {} : value: {}", index, value);
|
||||||
|
|
|
@ -4,6 +4,8 @@ This guide can help you upgrade code through breaking changes from one PyO3 vers
|
||||||
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.20.* to 0.21
|
## from 0.20.* to 0.21
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see https://github.com/PyO3/pyo3/issues/3382.
|
PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see https://github.com/PyO3/pyo3/issues/3382.
|
||||||
|
|
||||||
|
@ -17,8 +19,11 @@ The recommended steps to update to PyO3 0.21 is as follows:
|
||||||
3. Disable the `gil-refs` feature and migrate off the deprecated APIs
|
3. Disable the `gil-refs` feature and migrate off the deprecated APIs
|
||||||
|
|
||||||
The following sections are laid out in this order.
|
The following sections are laid out in this order.
|
||||||
|
</details>
|
||||||
|
|
||||||
### Enable the `gil-refs` feature
|
### Enable the `gil-refs` feature
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound<T>` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound<PyTuple>` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature.
|
To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound<T>` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound<PyTuple>` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature.
|
||||||
|
|
||||||
|
@ -41,8 +46,11 @@ After:
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pyo3 = { version = "0.21", features = ["gil-refs"] }
|
pyo3 = { version = "0.21", features = ["gil-refs"] }
|
||||||
```
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
### `PyTypeInfo` and `PyTryFrom` have been adjusted
|
### `PyTypeInfo` and `PyTryFrom` have been adjusted
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
The `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`.
|
The `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`.
|
||||||
|
|
||||||
|
@ -81,8 +89,11 @@ Python::with_gil(|py| {
|
||||||
})
|
})
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
### `Iter(A)NextOutput` are deprecated
|
### `Iter(A)NextOutput` are deprecated
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option<T>` and `Result<Option<T>, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration.
|
The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option<T>` and `Result<Option<T>, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration.
|
||||||
|
|
||||||
|
@ -200,20 +211,29 @@ impl PyClassAsyncIter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
### `PyType::name` has been renamed to `PyType::qualname`
|
### `PyType::name` has been renamed to `PyType::qualname`
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
`PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
|
`PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
|
||||||
|
</details>
|
||||||
|
|
||||||
### `PyCell` has been deprecated
|
### `PyCell` has been deprecated
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
Interactions with Python objects implemented in Rust no longer need to go though `PyCell<T>`. Instead iteractions with Python object now consistently go through `Bound<T>` or `Py<T>` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust. Use `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.
|
Interactions with Python objects implemented in Rust no longer need to go though `PyCell<T>`. Instead iteractions with Python object now consistently go through `Bound<T>` or `Py<T>` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust. Use `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.
|
||||||
|
</details>
|
||||||
|
|
||||||
### Migrating from the GIL-Refs API to `Bound<T>`
|
### Migrating from the GIL Refs API to `Bound<T>`
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
To minimise breakage of code using the GIL-Refs API, the `Bound<T>` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones.
|
To minimise breakage of code using the GIL Refs API, the `Bound<T>` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones.
|
||||||
|
|
||||||
To identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on all uses of APIs accepting and producing GIL Refs. Over one or more PRs it should be possible to follow the deprecation hints to update code. Depending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first.
|
To identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on [almost](#cases-where-pyo3-cannot-emit-gil-ref-deprecation-warnings) all uses of APIs accepting and producing GIL Refs . Over one or more PRs it should be possible to follow the deprecation hints to update code. Depending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first.
|
||||||
|
|
||||||
For example, the following APIs have gained updated variants:
|
For example, the following APIs have gained updated variants:
|
||||||
- `PyList::new`, `PyTyple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc.
|
- `PyList::new`, `PyTyple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc.
|
||||||
|
@ -276,7 +296,19 @@ impl<'py> FromPyObject<'py> for MyType {
|
||||||
|
|
||||||
The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed.
|
The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed.
|
||||||
|
|
||||||
|
#### Cases where PyO3 cannot emit GIL Ref deprecation warnings
|
||||||
|
|
||||||
|
Despite a large amount of deprecations warnings produced by PyO3 to aid with the transition from GIL Refs to the Bound API, there are a few cases where PyO3 cannot automatically warn on uses of GIL Refs. It is worth checking for these cases manually after the deprecation warnings have all been addressed:
|
||||||
|
|
||||||
|
- Individual implementations of the `FromPyObject` trait cannot be deprecated, so PyO3 cannot warn about uses of code patterns like `.extract<&PyAny>()` which produce a GIL Ref.
|
||||||
|
- GIL Refs in `#[pyfunction]` arguments emit a warning, but if the GIL Ref is wrapped inside another container such as `Option<&PyAny>` or `Vec<&PyAny>` then PyO3 cannot warn against this.
|
||||||
|
- The `wrap_pyfunction!(function)(py)` deferred argument form of the `wrap_pyfunction` macro taking `py: Python<'py>` produces a GIL Ref, and due to limitations in type inference PyO3 cannot warn against this specific case.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
### Deactivating the `gil-refs` feature
|
### Deactivating the `gil-refs` feature
|
||||||
|
<details open>
|
||||||
|
<summary><small>Click to expand</small></summary>
|
||||||
|
|
||||||
As a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22.
|
As a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22.
|
||||||
|
|
||||||
|
@ -284,9 +316,10 @@ At this point code which needed to manage GIL Ref memory can safely remove uses
|
||||||
|
|
||||||
There is one notable API removed when this feature is disabled. `FromPyObject` trait implementations for types which borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the migration is ongoing). These types are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`.
|
There is one notable API removed when this feature is disabled. `FromPyObject` trait implementations for types which borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the migration is ongoing). These types are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`.
|
||||||
|
|
||||||
To ease pain during migration, these types instead implement a new temporary trait `FromPyObjectBound` which is the expected future form of `FromPyObject`. The new temporary trait ensures is that `obj.extract::<&str>()` continues to work (with the new constraint that the extracted value now depends on the input `obj` lifetime), as well for these types in `#[pyfunction]` arguments.
|
To ease pain during migration, these types instead implement a new temporary trait `FromPyObjectBound` which is the expected future form of `FromPyObject`. The new temporary trait ensures is that `obj.extract::<&str>()` continues to work, as well for these types in `#[pyfunction]` arguments.
|
||||||
|
|
||||||
An unfortunate final point here is that PyO3 cannot offer this new implementation for `&str` on `abi3` builds for Python older than 3.10. On code which needs `abi3` builds for these older Python versions, many cases of `.extract::<&str>()` may need to be replaced with `.extract::<PyBackedStr>()`, which is string data which borrows from the Python `str` object. Alternatively, use `.extract::<Cow<str>>()`, `.extract::<String>()` to copy the data into Rust for these versions.
|
An unfortunate final point here is that PyO3 cannot offer this new implementation for `&str` on `abi3` builds for Python older than 3.10. On code which needs `abi3` builds for these older Python versions, many cases of `.extract::<&str>()` may need to be replaced with `.extract::<PyBackedStr>()`, which is string data which borrows from the Python `str` object. Alternatively, use `.extract::<Cow<str>>()` ro `.extract::<String>()` to copy the data into Rust for these versions.
|
||||||
|
</details>
|
||||||
|
|
||||||
## from 0.19.* to 0.20
|
## from 0.19.* to 0.20
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::utils::Ctx;
|
||||||
use crate::{
|
use crate::{
|
||||||
attributes::{TextSignatureAttribute, TextSignatureAttributeValue},
|
attributes::{TextSignatureAttribute, TextSignatureAttributeValue},
|
||||||
deprecations::{Deprecation, Deprecations},
|
deprecations::{Deprecation, Deprecations},
|
||||||
params::impl_arg_params,
|
params::{impl_arg_params, Holders},
|
||||||
pyfunction::{
|
pyfunction::{
|
||||||
FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute,
|
FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute,
|
||||||
},
|
},
|
||||||
|
@ -108,7 +108,7 @@ impl FnType {
|
||||||
&self,
|
&self,
|
||||||
cls: Option<&syn::Type>,
|
cls: Option<&syn::Type>,
|
||||||
error_mode: ExtractErrorMode,
|
error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
@ -186,7 +186,7 @@ impl SelfType {
|
||||||
&self,
|
&self,
|
||||||
cls: &syn::Type,
|
cls: &syn::Type,
|
||||||
error_mode: ExtractErrorMode,
|
error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
// Due to use of quote_spanned in this function, need to bind these idents to the
|
// Due to use of quote_spanned in this function, need to bind these idents to the
|
||||||
|
@ -201,17 +201,12 @@ impl SelfType {
|
||||||
} else {
|
} else {
|
||||||
syn::Ident::new("extract_pyclass_ref", *span)
|
syn::Ident::new("extract_pyclass_ref", *span)
|
||||||
};
|
};
|
||||||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), *span);
|
let holder = holders.push_holder(*span);
|
||||||
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
let pyo3_path = pyo3_path.to_tokens_spanned(*span);
|
||||||
holders.push(quote_spanned! { *span =>
|
|
||||||
#[allow(clippy::let_unit_value)]
|
|
||||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
|
||||||
let mut #slf = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf);
|
|
||||||
});
|
|
||||||
error_mode.handle_error(
|
error_mode.handle_error(
|
||||||
quote_spanned! { *span =>
|
quote_spanned! { *span =>
|
||||||
#pyo3_path::impl_::extract_argument::#method::<#cls>(
|
#pyo3_path::impl_::extract_argument::#method::<#cls>(
|
||||||
&#slf,
|
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).0,
|
||||||
&mut #holder,
|
&mut #holder,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -519,10 +514,8 @@ impl<'a> FnSpec<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rust_call = |args: Vec<TokenStream>,
|
let rust_call = |args: Vec<TokenStream>, holders: &mut Holders| {
|
||||||
self_e: &syn::Ident,
|
let mut self_arg = || self.tp.self_arg(cls, ExtractErrorMode::Raise, holders, ctx);
|
||||||
holders: &mut Vec<TokenStream>| {
|
|
||||||
let self_arg = self.tp.self_arg(cls, ExtractErrorMode::Raise, holders, ctx);
|
|
||||||
|
|
||||||
let call = if self.asyncness.is_some() {
|
let call = if self.asyncness.is_some() {
|
||||||
let throw_callback = if cancel_handle.is_some() {
|
let throw_callback = if cancel_handle.is_some() {
|
||||||
|
@ -537,35 +530,30 @@ impl<'a> FnSpec<'a> {
|
||||||
};
|
};
|
||||||
let future = match self.tp {
|
let future = match self.tp {
|
||||||
FnType::Fn(SelfType::Receiver { mutable: false, .. }) => {
|
FnType::Fn(SelfType::Receiver { mutable: false, .. }) => {
|
||||||
holders.pop().unwrap(); // does not actually use holder created by `self_arg`
|
|
||||||
|
|
||||||
quote! {{
|
quote! {{
|
||||||
#self_e = #pyo3_path::impl_::deprecations::GilRefs::<()>::new();
|
|
||||||
let __guard = #pyo3_path::impl_::coroutine::RefGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
let __guard = #pyo3_path::impl_::coroutine::RefGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||||
async move { function(&__guard, #(#args),*).await }
|
async move { function(&__guard, #(#args),*).await }
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
FnType::Fn(SelfType::Receiver { mutable: true, .. }) => {
|
FnType::Fn(SelfType::Receiver { mutable: true, .. }) => {
|
||||||
holders.pop().unwrap(); // does not actually use holder created by `self_arg`
|
|
||||||
|
|
||||||
quote! {{
|
quote! {{
|
||||||
#self_e = #pyo3_path::impl_::deprecations::GilRefs::<()>::new();
|
|
||||||
let mut __guard = #pyo3_path::impl_::coroutine::RefMutGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
let mut __guard = #pyo3_path::impl_::coroutine::RefMutGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?;
|
||||||
async move { function(&mut __guard, #(#args),*).await }
|
async move { function(&mut __guard, #(#args),*).await }
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
let self_arg = self_arg();
|
||||||
if self_arg.is_empty() {
|
if self_arg.is_empty() {
|
||||||
quote! {{
|
quote! { function(#(#args),*) }
|
||||||
#self_e = #pyo3_path::impl_::deprecations::GilRefs::<()>::new();
|
|
||||||
function(#(#args),*)
|
|
||||||
}}
|
|
||||||
} else {
|
} else {
|
||||||
quote! { function({
|
let self_checker = holders.push_gil_refs_checker(self_arg.span());
|
||||||
let (self_arg, e) = #pyo3_path::impl_::deprecations::inspect_type(#self_arg);
|
quote! {
|
||||||
#self_e = e;
|
function(
|
||||||
self_arg
|
// NB #self_arg includes a comma, so none inserted here
|
||||||
}, #(#args),*) }
|
#pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
|
||||||
|
#(#args),*
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -586,24 +574,22 @@ impl<'a> FnSpec<'a> {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
call
|
call
|
||||||
} else if self_arg.is_empty() {
|
|
||||||
quote! {{
|
|
||||||
#self_e = #pyo3_path::impl_::deprecations::GilRefs::<()>::new();
|
|
||||||
function(#(#args),*)
|
|
||||||
}}
|
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
let self_arg = self_arg();
|
||||||
function({
|
if self_arg.is_empty() {
|
||||||
let (self_arg, e) = #pyo3_path::impl_::deprecations::inspect_type(#self_arg);
|
quote! { function(#(#args),*) }
|
||||||
#self_e = e;
|
} else {
|
||||||
self_arg
|
let self_checker = holders.push_gil_refs_checker(self_arg.span());
|
||||||
}, #(#args),*)
|
quote! {
|
||||||
|
function(
|
||||||
|
// NB #self_arg includes a comma, so none inserted here
|
||||||
|
#pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker),
|
||||||
|
#(#args),*
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(
|
quotes::map_result_into_ptr(quotes::ok_wrap(call, ctx), ctx)
|
||||||
quotes::map_result_into_ptr(quotes::ok_wrap(call, ctx), ctx),
|
|
||||||
self_arg.span(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let func_name = &self.name;
|
let func_name = &self.name;
|
||||||
|
@ -613,10 +599,9 @@ impl<'a> FnSpec<'a> {
|
||||||
quote!(#func_name)
|
quote!(#func_name)
|
||||||
};
|
};
|
||||||
|
|
||||||
let self_e = syn::Ident::new("self_e", Span::call_site());
|
|
||||||
Ok(match self.convention {
|
Ok(match self.convention {
|
||||||
CallingConvention::Noargs => {
|
CallingConvention::Noargs => {
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let args = self
|
let args = self
|
||||||
.signature
|
.signature
|
||||||
.arguments
|
.arguments
|
||||||
|
@ -631,8 +616,9 @@ impl<'a> FnSpec<'a> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let (call, self_arg_span) = rust_call(args, &self_e, &mut holders);
|
let call = rust_call(args, &mut holders);
|
||||||
let function_arg = quote_spanned! { self_arg_span => #self_e.function_arg(); };
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
unsafe fn #ident<'py>(
|
unsafe fn #ident<'py>(
|
||||||
|
@ -641,19 +627,19 @@ impl<'a> FnSpec<'a> {
|
||||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||||
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
|
||||||
let #self_e;
|
#init_holders
|
||||||
#( #holders )*
|
|
||||||
let result = #call;
|
let result = #call;
|
||||||
#function_arg
|
#check_gil_refs
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallingConvention::Fastcall => {
|
CallingConvention::Fastcall => {
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx)?;
|
let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx)?;
|
||||||
let (call, self_arg_span) = rust_call(args, &self_e, &mut holders);
|
let call = rust_call(args, &mut holders);
|
||||||
let function_arg = quote_spanned! { self_arg_span => #self_e.function_arg(); };
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
unsafe fn #ident<'py>(
|
unsafe fn #ident<'py>(
|
||||||
|
@ -665,20 +651,20 @@ impl<'a> FnSpec<'a> {
|
||||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||||
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
|
||||||
let #self_e;
|
|
||||||
#arg_convert
|
#arg_convert
|
||||||
#( #holders )*
|
#init_holders
|
||||||
let result = #call;
|
let result = #call;
|
||||||
#function_arg
|
#check_gil_refs
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallingConvention::Varargs => {
|
CallingConvention::Varargs => {
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
||||||
let (call, self_arg_span) = rust_call(args, &self_e, &mut holders);
|
let call = rust_call(args, &mut holders);
|
||||||
let function_arg = quote_spanned! { self_arg_span => #self_e.function_arg(); };
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
unsafe fn #ident<'py>(
|
unsafe fn #ident<'py>(
|
||||||
|
@ -689,22 +675,23 @@ impl<'a> FnSpec<'a> {
|
||||||
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {
|
||||||
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
|
||||||
let #self_e;
|
|
||||||
#arg_convert
|
#arg_convert
|
||||||
#( #holders )*
|
#init_holders
|
||||||
let result = #call;
|
let result = #call;
|
||||||
#function_arg
|
#check_gil_refs
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallingConvention::TpNew => {
|
CallingConvention::TpNew => {
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx)?;
|
||||||
let self_arg = self
|
let self_arg = self
|
||||||
.tp
|
.tp
|
||||||
.self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx);
|
.self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx);
|
||||||
let call = quote! { #rust_name(#self_arg #(#args),*) };
|
let call = quote! { #rust_name(#self_arg #(#args),*) };
|
||||||
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
quote! {
|
quote! {
|
||||||
unsafe fn #ident(
|
unsafe fn #ident(
|
||||||
py: #pyo3_path::Python<'_>,
|
py: #pyo3_path::Python<'_>,
|
||||||
|
@ -716,9 +703,10 @@ impl<'a> FnSpec<'a> {
|
||||||
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
|
||||||
#( #holders )*
|
#init_holders
|
||||||
let result = #call;
|
let result = #call;
|
||||||
let initializer: #pyo3_path::PyClassInitializer::<#cls> = result.convert(py)?;
|
let initializer: #pyo3_path::PyClassInitializer::<#cls> = result.convert(py)?;
|
||||||
|
#check_gil_refs
|
||||||
#pyo3_path::impl_::pymethods::tp_new_impl(py, initializer, _slf)
|
#pyo3_path::impl_::pymethods::tp_new_impl(py, initializer, _slf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,10 +305,11 @@ pub fn pymodule_function_impl(mut function: syn::ItemFn) -> Result<TokenStream>
|
||||||
.filter_map(|param| {
|
.filter_map(|param| {
|
||||||
if let syn::FnArg::Typed(pat_type) = param {
|
if let syn::FnArg::Typed(pat_type) = param {
|
||||||
if let syn::Pat::Ident(pat_ident) = &*pat_type.pat {
|
if let syn::Pat::Ident(pat_ident) = &*pat_type.pat {
|
||||||
let ident = &pat_ident.ident;
|
let ident: &syn::Ident = &pat_ident.ident;
|
||||||
return Some([
|
return Some([
|
||||||
parse_quote! { let (#ident, e) = #pyo3_path::impl_::deprecations::inspect_type(#ident); },
|
parse_quote!{ let check_gil_refs = #pyo3_path::impl_::deprecations::GilRefs::new(); },
|
||||||
parse_quote_spanned! { pat_type.span() => e.function_arg(); },
|
parse_quote! { let #ident = #pyo3_path::impl_::deprecations::inspect_type(#ident, &check_gil_refs); },
|
||||||
|
parse_quote_spanned! { pat_type.span() => check_gil_refs.function_arg(); },
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,53 @@ use quote::{quote, quote_spanned};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::Result;
|
use syn::Result;
|
||||||
|
|
||||||
|
pub struct Holders {
|
||||||
|
holders: Vec<syn::Ident>,
|
||||||
|
gil_refs_checkers: Vec<syn::Ident>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Holders {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Holders {
|
||||||
|
holders: Vec::new(),
|
||||||
|
gil_refs_checkers: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_holder(&mut self, span: Span) -> syn::Ident {
|
||||||
|
let holder = syn::Ident::new(&format!("holder_{}", self.holders.len()), span);
|
||||||
|
self.holders.push(holder.clone());
|
||||||
|
holder
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_gil_refs_checker(&mut self, span: Span) -> syn::Ident {
|
||||||
|
let gil_refs_checker = syn::Ident::new(
|
||||||
|
&format!("gil_refs_checker_{}", self.gil_refs_checkers.len()),
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
self.gil_refs_checkers.push(gil_refs_checker.clone());
|
||||||
|
gil_refs_checker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_holders(&self, ctx: &Ctx) -> TokenStream {
|
||||||
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
let holders = &self.holders;
|
||||||
|
let gil_refs_checkers = &self.gil_refs_checkers;
|
||||||
|
quote! {
|
||||||
|
#[allow(clippy::let_unit_value)]
|
||||||
|
#(let mut #holders = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;)*
|
||||||
|
#(let #gil_refs_checkers = #pyo3_path::impl_::deprecations::GilRefs::new();)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_gil_refs(&self) -> TokenStream {
|
||||||
|
self.gil_refs_checkers
|
||||||
|
.iter()
|
||||||
|
.map(|e| quote_spanned! { e.span() => #e.function_arg(); })
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if the argument list is simply (*args, **kwds).
|
/// Return true if the argument list is simply (*args, **kwds).
|
||||||
pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {
|
pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
|
@ -26,11 +73,22 @@ pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_arg_for_gil_refs(
|
||||||
|
tokens: TokenStream,
|
||||||
|
gil_refs_checker: syn::Ident,
|
||||||
|
ctx: &Ctx,
|
||||||
|
) -> TokenStream {
|
||||||
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
quote! {
|
||||||
|
#pyo3_path::impl_::deprecations::inspect_type(#tokens, &#gil_refs_checker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn impl_arg_params(
|
pub fn impl_arg_params(
|
||||||
spec: &FnSpec<'_>,
|
spec: &FnSpec<'_>,
|
||||||
self_: Option<&syn::Type>,
|
self_: Option<&syn::Type>,
|
||||||
fastcall: bool,
|
fastcall: bool,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> Result<(TokenStream, Vec<TokenStream>)> {
|
) -> Result<(TokenStream, Vec<TokenStream>)> {
|
||||||
let args_array = syn::Ident::new("output", Span::call_site());
|
let args_array = syn::Ident::new("output", Span::call_site());
|
||||||
|
@ -61,7 +119,15 @@ pub fn impl_arg_params(
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, arg)| impl_arg_param(arg, i, &mut 0, &args_array, holders, ctx))
|
.map(|(i, arg)| {
|
||||||
|
impl_arg_param(arg, i, &mut 0, &args_array, holders, ctx).map(|tokens| {
|
||||||
|
check_arg_for_gil_refs(
|
||||||
|
tokens,
|
||||||
|
holders.push_gil_refs_checker(arg.ty.span()),
|
||||||
|
ctx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect::<Result<_>>()?;
|
.collect::<Result<_>>()?;
|
||||||
return Ok((
|
return Ok((
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -101,7 +167,11 @@ pub fn impl_arg_params(
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, arg)| impl_arg_param(arg, i, &mut option_pos, &args_array, holders, ctx))
|
.map(|(i, arg)| {
|
||||||
|
impl_arg_param(arg, i, &mut option_pos, &args_array, holders, ctx).map(|tokens| {
|
||||||
|
check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx)
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect::<Result<_>>()?;
|
.collect::<Result<_>>()?;
|
||||||
|
|
||||||
let args_handler = if spec.signature.python_signature.varargs.is_some() {
|
let args_handler = if spec.signature.python_signature.varargs.is_some() {
|
||||||
|
@ -169,7 +239,7 @@ fn impl_arg_param(
|
||||||
pos: usize,
|
pos: usize,
|
||||||
option_pos: &mut usize,
|
option_pos: &mut usize,
|
||||||
args_array: &syn::Ident,
|
args_array: &syn::Ident,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
@ -192,21 +262,12 @@ fn impl_arg_param(
|
||||||
let name = arg.name;
|
let name = arg.name;
|
||||||
let name_str = name.to_string();
|
let name_str = name.to_string();
|
||||||
|
|
||||||
let mut push_holder = || {
|
|
||||||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), arg.ty.span());
|
|
||||||
holders.push(quote_arg_span! {
|
|
||||||
#[allow(clippy::let_unit_value)]
|
|
||||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
|
||||||
});
|
|
||||||
holder
|
|
||||||
};
|
|
||||||
|
|
||||||
if arg.is_varargs {
|
if arg.is_varargs {
|
||||||
ensure_spanned!(
|
ensure_spanned!(
|
||||||
arg.optional.is_none(),
|
arg.optional.is_none(),
|
||||||
arg.name.span() => "args cannot be optional"
|
arg.name.span() => "args cannot be optional"
|
||||||
);
|
);
|
||||||
let holder = push_holder();
|
let holder = holders.push_holder(arg.ty.span());
|
||||||
return Ok(quote_arg_span! {
|
return Ok(quote_arg_span! {
|
||||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||||
&_args,
|
&_args,
|
||||||
|
@ -219,7 +280,7 @@ fn impl_arg_param(
|
||||||
arg.optional.is_some(),
|
arg.optional.is_some(),
|
||||||
arg.name.span() => "kwargs must be Option<_>"
|
arg.name.span() => "kwargs must be Option<_>"
|
||||||
);
|
);
|
||||||
let holder = push_holder();
|
let holder = holders.push_holder(arg.name.span());
|
||||||
return Ok(quote_arg_span! {
|
return Ok(quote_arg_span! {
|
||||||
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
||||||
_kwargs.as_deref(),
|
_kwargs.as_deref(),
|
||||||
|
@ -254,12 +315,14 @@ fn impl_arg_param(
|
||||||
let from_py_with = syn::Ident::new(&format!("from_py_with_{}", pos), Span::call_site());
|
let from_py_with = syn::Ident::new(&format!("from_py_with_{}", pos), Span::call_site());
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
quote_arg_span! {
|
quote_arg_span! {
|
||||||
#[allow(clippy::redundant_closure)]
|
|
||||||
#pyo3_path::impl_::extract_argument::from_py_with_with_default(
|
#pyo3_path::impl_::extract_argument::from_py_with_with_default(
|
||||||
#arg_value.as_deref(),
|
#arg_value.as_deref(),
|
||||||
#name_str,
|
#name_str,
|
||||||
#from_py_with as fn(_) -> _,
|
#from_py_with as fn(_) -> _,
|
||||||
|| #default
|
#[allow(clippy::redundant_closure)]
|
||||||
|
{
|
||||||
|
|| #default
|
||||||
|
}
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -272,29 +335,33 @@ fn impl_arg_param(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if arg.optional.is_some() {
|
} else if arg.optional.is_some() {
|
||||||
let holder = push_holder();
|
let holder = holders.push_holder(arg.name.span());
|
||||||
quote_arg_span! {
|
quote_arg_span! {
|
||||||
#[allow(clippy::redundant_closure)]
|
|
||||||
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
#pyo3_path::impl_::extract_argument::extract_optional_argument(
|
||||||
#arg_value.as_deref(),
|
#arg_value.as_deref(),
|
||||||
&mut #holder,
|
&mut #holder,
|
||||||
#name_str,
|
#name_str,
|
||||||
|| #default
|
#[allow(clippy::redundant_closure)]
|
||||||
|
{
|
||||||
|
|| #default
|
||||||
|
}
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
} else if let Some(default) = default {
|
} else if let Some(default) = default {
|
||||||
let holder = push_holder();
|
let holder = holders.push_holder(arg.name.span());
|
||||||
quote_arg_span! {
|
quote_arg_span! {
|
||||||
#[allow(clippy::redundant_closure)]
|
|
||||||
#pyo3_path::impl_::extract_argument::extract_argument_with_default(
|
#pyo3_path::impl_::extract_argument::extract_argument_with_default(
|
||||||
#arg_value.as_deref(),
|
#arg_value.as_deref(),
|
||||||
&mut #holder,
|
&mut #holder,
|
||||||
#name_str,
|
#name_str,
|
||||||
|| #default
|
#[allow(clippy::redundant_closure)]
|
||||||
|
{
|
||||||
|
|| #default
|
||||||
|
}
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let holder = push_holder();
|
let holder = holders.push_holder(arg.name.span());
|
||||||
quote_arg_span! {
|
quote_arg_span! {
|
||||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||||
&#pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
&#pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value),
|
||||||
|
@ -303,5 +370,6 @@ fn impl_arg_param(
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,10 +736,11 @@ fn impl_simple_enum(
|
||||||
fn __pyo3__richcmp__(
|
fn __pyo3__richcmp__(
|
||||||
&self,
|
&self,
|
||||||
py: #pyo3_path::Python,
|
py: #pyo3_path::Python,
|
||||||
other: &#pyo3_path::PyAny,
|
other: &#pyo3_path::Bound<'_, #pyo3_path::PyAny>,
|
||||||
op: #pyo3_path::basic::CompareOp
|
op: #pyo3_path::basic::CompareOp
|
||||||
) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
|
) -> #pyo3_path::PyResult<#pyo3_path::PyObject> {
|
||||||
use #pyo3_path::conversion::ToPyObject;
|
use #pyo3_path::conversion::ToPyObject;
|
||||||
|
use #pyo3_path::types::PyAnyMethods;
|
||||||
use ::core::result::Result::*;
|
use ::core::result::Result::*;
|
||||||
match op {
|
match op {
|
||||||
#pyo3_path::basic::CompareOp::Eq => {
|
#pyo3_path::basic::CompareOp::Eq => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::attributes::{NameAttribute, RenamingRule};
|
use crate::attributes::{NameAttribute, RenamingRule};
|
||||||
use crate::method::{CallingConvention, ExtractErrorMode};
|
use crate::method::{CallingConvention, ExtractErrorMode};
|
||||||
|
use crate::params::Holders;
|
||||||
use crate::utils::Ctx;
|
use crate::utils::Ctx;
|
||||||
use crate::utils::PythonDoc;
|
use crate::utils::PythonDoc;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -510,7 +511,7 @@ fn impl_call_setter(
|
||||||
cls: &syn::Type,
|
cls: &syn::Type,
|
||||||
spec: &FnSpec<'_>,
|
spec: &FnSpec<'_>,
|
||||||
self_type: &SelfType,
|
self_type: &SelfType,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> syn::Result<TokenStream> {
|
) -> syn::Result<TokenStream> {
|
||||||
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
||||||
|
@ -544,7 +545,7 @@ pub fn impl_py_setter_def(
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
let python_name = property_type.null_terminated_python_name()?;
|
let python_name = property_type.null_terminated_python_name()?;
|
||||||
let doc = property_type.doc();
|
let doc = property_type.doc();
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let setter_impl = match property_type {
|
let setter_impl = match property_type {
|
||||||
PropertyType::Descriptor {
|
PropertyType::Descriptor {
|
||||||
field_index, field, ..
|
field_index, field, ..
|
||||||
|
@ -596,6 +597,8 @@ pub fn impl_py_setter_def(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
let associated_method = quote! {
|
let associated_method = quote! {
|
||||||
#cfg_attrs
|
#cfg_attrs
|
||||||
unsafe fn #wrapper_ident(
|
unsafe fn #wrapper_ident(
|
||||||
|
@ -609,8 +612,10 @@ pub fn impl_py_setter_def(
|
||||||
#pyo3_path::exceptions::PyAttributeError::new_err("can't delete attribute")
|
#pyo3_path::exceptions::PyAttributeError::new_err("can't delete attribute")
|
||||||
})?;
|
})?;
|
||||||
let _val = #pyo3_path::FromPyObject::extract_bound(_value.into())?;
|
let _val = #pyo3_path::FromPyObject::extract_bound(_value.into())?;
|
||||||
#( #holders )*
|
#init_holders
|
||||||
#pyo3_path::callback::convert(py, #setter_impl)
|
let result = #setter_impl;
|
||||||
|
#check_gil_refs
|
||||||
|
#pyo3_path::callback::convert(py, result)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,7 +640,7 @@ fn impl_call_getter(
|
||||||
cls: &syn::Type,
|
cls: &syn::Type,
|
||||||
spec: &FnSpec<'_>,
|
spec: &FnSpec<'_>,
|
||||||
self_type: &SelfType,
|
self_type: &SelfType,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> syn::Result<TokenStream> {
|
) -> syn::Result<TokenStream> {
|
||||||
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);
|
||||||
|
@ -665,7 +670,7 @@ pub fn impl_py_getter_def(
|
||||||
let python_name = property_type.null_terminated_python_name()?;
|
let python_name = property_type.null_terminated_python_name()?;
|
||||||
let doc = property_type.doc();
|
let doc = property_type.doc();
|
||||||
|
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let body = match property_type {
|
let body = match property_type {
|
||||||
PropertyType::Descriptor {
|
PropertyType::Descriptor {
|
||||||
field_index, field, ..
|
field_index, field, ..
|
||||||
|
@ -731,14 +736,17 @@ pub fn impl_py_getter_def(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let init_holders = holders.init_holders(ctx);
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
let associated_method = quote! {
|
let associated_method = quote! {
|
||||||
#cfg_attrs
|
#cfg_attrs
|
||||||
unsafe fn #wrapper_ident(
|
unsafe fn #wrapper_ident(
|
||||||
py: #pyo3_path::Python<'_>,
|
py: #pyo3_path::Python<'_>,
|
||||||
_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> {
|
||||||
#( #holders )*
|
#init_holders
|
||||||
let result = #body;
|
let result = #body;
|
||||||
|
#check_gil_refs
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -966,7 +974,7 @@ impl Ty {
|
||||||
ident: &syn::Ident,
|
ident: &syn::Ident,
|
||||||
arg: &FnArg<'_>,
|
arg: &FnArg<'_>,
|
||||||
extract_error_mode: ExtractErrorMode,
|
extract_error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
@ -976,7 +984,9 @@ impl Ty {
|
||||||
extract_error_mode,
|
extract_error_mode,
|
||||||
holders,
|
holders,
|
||||||
&name_str,
|
&name_str,
|
||||||
quote! { #ident },ctx
|
quote! { #ident },
|
||||||
|
arg.ty.span(),
|
||||||
|
ctx
|
||||||
),
|
),
|
||||||
Ty::MaybeNullObject => extract_object(
|
Ty::MaybeNullObject => extract_object(
|
||||||
extract_error_mode,
|
extract_error_mode,
|
||||||
|
@ -988,32 +998,40 @@ impl Ty {
|
||||||
} else {
|
} else {
|
||||||
#ident
|
#ident
|
||||||
}
|
}
|
||||||
},ctx
|
},
|
||||||
|
arg.ty.span(),
|
||||||
|
ctx
|
||||||
),
|
),
|
||||||
Ty::NonNullObject => extract_object(
|
Ty::NonNullObject => extract_object(
|
||||||
extract_error_mode,
|
extract_error_mode,
|
||||||
holders,
|
holders,
|
||||||
&name_str,
|
&name_str,
|
||||||
quote! { #ident.as_ptr() },ctx
|
quote! { #ident.as_ptr() },
|
||||||
|
arg.ty.span(),
|
||||||
|
ctx
|
||||||
),
|
),
|
||||||
Ty::IPowModulo => extract_object(
|
Ty::IPowModulo => extract_object(
|
||||||
extract_error_mode,
|
extract_error_mode,
|
||||||
holders,
|
holders,
|
||||||
&name_str,
|
&name_str,
|
||||||
quote! { #ident.as_ptr() },ctx
|
quote! { #ident.as_ptr() },
|
||||||
|
arg.ty.span(),
|
||||||
|
ctx
|
||||||
),
|
),
|
||||||
Ty::CompareOp => extract_error_mode.handle_error(
|
Ty::CompareOp => extract_error_mode.handle_error(
|
||||||
quote! {
|
quote! {
|
||||||
#pyo3_path::class::basic::CompareOp::from_raw(#ident)
|
#pyo3_path::class::basic::CompareOp::from_raw(#ident)
|
||||||
.ok_or_else(|| #pyo3_path::exceptions::PyValueError::new_err("invalid comparison operator"))
|
.ok_or_else(|| #pyo3_path::exceptions::PyValueError::new_err("invalid comparison operator"))
|
||||||
},ctx
|
},
|
||||||
|
ctx
|
||||||
),
|
),
|
||||||
Ty::PySsizeT => {
|
Ty::PySsizeT => {
|
||||||
let ty = arg.ty;
|
let ty = arg.ty;
|
||||||
extract_error_mode.handle_error(
|
extract_error_mode.handle_error(
|
||||||
quote! {
|
quote! {
|
||||||
::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| #pyo3_path::exceptions::PyValueError::new_err(e.to_string()))
|
::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| #pyo3_path::exceptions::PyValueError::new_err(e.to_string()))
|
||||||
},ctx
|
},
|
||||||
|
ctx
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Just pass other types through unmodified
|
// Just pass other types through unmodified
|
||||||
|
@ -1024,27 +1042,28 @@ impl Ty {
|
||||||
|
|
||||||
fn extract_object(
|
fn extract_object(
|
||||||
extract_error_mode: ExtractErrorMode,
|
extract_error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
name: &str,
|
name: &str,
|
||||||
source_ptr: TokenStream,
|
source_ptr: TokenStream,
|
||||||
|
span: Span,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
let holder = syn::Ident::new(&format!("holder_{}", holders.len()), Span::call_site());
|
let holder = holders.push_holder(Span::call_site());
|
||||||
holders.push(quote! {
|
let gil_refs_checker = holders.push_gil_refs_checker(span);
|
||||||
#[allow(clippy::let_unit_value)]
|
let extracted = extract_error_mode.handle_error(
|
||||||
let mut #holder = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;
|
|
||||||
});
|
|
||||||
extract_error_mode.handle_error(
|
|
||||||
quote! {
|
quote! {
|
||||||
#pyo3_path::impl_::extract_argument::extract_argument(
|
#pyo3_path::impl_::extract_argument::extract_argument(
|
||||||
&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr),
|
#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0,
|
||||||
&mut #holder,
|
&mut #holder,
|
||||||
#name
|
#name
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
ctx,
|
ctx,
|
||||||
)
|
);
|
||||||
|
quote! {
|
||||||
|
#pyo3_path::impl_::deprecations::inspect_type(#extracted, &#gil_refs_checker)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ReturnMode {
|
enum ReturnMode {
|
||||||
|
@ -1054,13 +1073,15 @@ enum ReturnMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReturnMode {
|
impl ReturnMode {
|
||||||
fn return_call_output(&self, call: TokenStream, ctx: &Ctx) -> TokenStream {
|
fn return_call_output(&self, call: TokenStream, ctx: &Ctx, holders: &Holders) -> TokenStream {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
match self {
|
match self {
|
||||||
ReturnMode::Conversion(conversion) => {
|
ReturnMode::Conversion(conversion) => {
|
||||||
let conversion = TokenGeneratorCtx(*conversion, ctx);
|
let conversion = TokenGeneratorCtx(*conversion, ctx);
|
||||||
quote! {
|
quote! {
|
||||||
let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::callback::convert(py, #call);
|
let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::callback::convert(py, #call);
|
||||||
|
#check_gil_refs
|
||||||
#pyo3_path::callback::convert(py, _result)
|
#pyo3_path::callback::convert(py, _result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1070,12 +1091,14 @@ impl ReturnMode {
|
||||||
quote! {
|
quote! {
|
||||||
let _result = #call;
|
let _result = #call;
|
||||||
use #pyo3_path::impl_::pymethods::{#traits};
|
use #pyo3_path::impl_::pymethods::{#traits};
|
||||||
|
#check_gil_refs
|
||||||
(&_result).#tag().convert(py, _result)
|
(&_result).#tag().convert(py, _result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReturnMode::ReturnSelf => quote! {
|
ReturnMode::ReturnSelf => quote! {
|
||||||
let _result: #pyo3_path::PyResult<()> = #pyo3_path::callback::convert(py, #call);
|
let _result: #pyo3_path::PyResult<()> = #pyo3_path::callback::convert(py, #call);
|
||||||
_result?;
|
_result?;
|
||||||
|
#check_gil_refs
|
||||||
#pyo3_path::ffi::Py_XINCREF(_raw_slf);
|
#pyo3_path::ffi::Py_XINCREF(_raw_slf);
|
||||||
::std::result::Result::Ok(_raw_slf)
|
::std::result::Result::Ok(_raw_slf)
|
||||||
},
|
},
|
||||||
|
@ -1176,7 +1199,7 @@ impl SlotDef {
|
||||||
.collect();
|
.collect();
|
||||||
let wrapper_ident = format_ident!("__pymethod_{}__", method_name);
|
let wrapper_ident = format_ident!("__pymethod_{}__", method_name);
|
||||||
let ret_ty = ret_ty.ffi_type(ctx);
|
let ret_ty = ret_ty.ffi_type(ctx);
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let body = generate_method_body(
|
let body = generate_method_body(
|
||||||
cls,
|
cls,
|
||||||
spec,
|
spec,
|
||||||
|
@ -1187,6 +1210,7 @@ impl SlotDef {
|
||||||
ctx,
|
ctx,
|
||||||
)?;
|
)?;
|
||||||
let name = spec.name;
|
let name = spec.name;
|
||||||
|
let holders = holders.init_holders(ctx);
|
||||||
let associated_method = quote! {
|
let associated_method = quote! {
|
||||||
unsafe fn #wrapper_ident(
|
unsafe fn #wrapper_ident(
|
||||||
py: #pyo3_path::Python<'_>,
|
py: #pyo3_path::Python<'_>,
|
||||||
|
@ -1195,7 +1219,7 @@ impl SlotDef {
|
||||||
) -> #pyo3_path::PyResult<#ret_ty> {
|
) -> #pyo3_path::PyResult<#ret_ty> {
|
||||||
let function = #cls::#name; // Shadow the method name to avoid #3017
|
let function = #cls::#name; // Shadow the method name to avoid #3017
|
||||||
let _slf = _raw_slf;
|
let _slf = _raw_slf;
|
||||||
#( #holders )*
|
#holders
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1229,7 +1253,7 @@ fn generate_method_body(
|
||||||
spec: &FnSpec<'_>,
|
spec: &FnSpec<'_>,
|
||||||
arguments: &[Ty],
|
arguments: &[Ty],
|
||||||
extract_error_mode: ExtractErrorMode,
|
extract_error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
return_mode: Option<&ReturnMode>,
|
return_mode: Option<&ReturnMode>,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
|
@ -1241,9 +1265,14 @@ fn generate_method_body(
|
||||||
let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?;
|
let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?;
|
||||||
let call = quote! { #cls::#rust_name(#self_arg #(#args),*) };
|
let call = quote! { #cls::#rust_name(#self_arg #(#args),*) };
|
||||||
Ok(if let Some(return_mode) = return_mode {
|
Ok(if let Some(return_mode) = return_mode {
|
||||||
return_mode.return_call_output(call, ctx)
|
return_mode.return_call_output(call, ctx, holders)
|
||||||
} else {
|
} else {
|
||||||
quote! { #pyo3_path::callback::convert(py, #call) }
|
let check_gil_refs = holders.check_gil_refs();
|
||||||
|
quote! {
|
||||||
|
let result = #call;
|
||||||
|
#check_gil_refs;
|
||||||
|
#pyo3_path::callback::convert(py, result)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1294,7 +1323,7 @@ impl SlotFragmentDef {
|
||||||
let arg_idents: &Vec<_> = &(0..arguments.len())
|
let arg_idents: &Vec<_> = &(0..arguments.len())
|
||||||
.map(|i| format_ident!("arg{}", i))
|
.map(|i| format_ident!("arg{}", i))
|
||||||
.collect();
|
.collect();
|
||||||
let mut holders = Vec::new();
|
let mut holders = Holders::new();
|
||||||
let body = generate_method_body(
|
let body = generate_method_body(
|
||||||
cls,
|
cls,
|
||||||
spec,
|
spec,
|
||||||
|
@ -1305,6 +1334,7 @@ impl SlotFragmentDef {
|
||||||
ctx,
|
ctx,
|
||||||
)?;
|
)?;
|
||||||
let ret_ty = ret_ty.ffi_type(ctx);
|
let ret_ty = ret_ty.ffi_type(ctx);
|
||||||
|
let holders = holders.init_holders(ctx);
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
impl #cls {
|
impl #cls {
|
||||||
unsafe fn #wrapper_ident(
|
unsafe fn #wrapper_ident(
|
||||||
|
@ -1313,7 +1343,7 @@ impl SlotFragmentDef {
|
||||||
#(#arg_idents: #arg_types),*
|
#(#arg_idents: #arg_types),*
|
||||||
) -> #pyo3_path::PyResult<#ret_ty> {
|
) -> #pyo3_path::PyResult<#ret_ty> {
|
||||||
let _slf = _raw_slf;
|
let _slf = _raw_slf;
|
||||||
#( #holders )*
|
#holders
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1412,7 +1442,7 @@ fn extract_proto_arguments(
|
||||||
spec: &FnSpec<'_>,
|
spec: &FnSpec<'_>,
|
||||||
proto_args: &[Ty],
|
proto_args: &[Ty],
|
||||||
extract_error_mode: ExtractErrorMode,
|
extract_error_mode: ExtractErrorMode,
|
||||||
holders: &mut Vec<TokenStream>,
|
holders: &mut Holders,
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
) -> Result<Vec<TokenStream>> {
|
) -> Result<Vec<TokenStream>> {
|
||||||
let mut args = Vec::with_capacity(spec.signature.arguments.len());
|
let mut args = Vec::with_capacity(spec.signature.arguments.len());
|
||||||
|
|
|
@ -19,7 +19,5 @@ pub(crate) fn ok_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||||
|
|
||||||
pub(crate) fn map_result_into_ptr(result: TokenStream, ctx: &Ctx) -> TokenStream {
|
pub(crate) fn map_result_into_ptr(result: TokenStream, ctx: &Ctx) -> TokenStream {
|
||||||
let Ctx { pyo3_path } = ctx;
|
let Ctx { pyo3_path } = ctx;
|
||||||
quote! {
|
quote! { #pyo3_path::impl_::wrap::map_result_into_ptr(py, #result) }
|
||||||
#pyo3_path::impl_::wrap::map_result_into_ptr(py, #result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,19 @@ impl BytesExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
pub fn from_bytes(bytes: &PyBytes) -> PyResult<usize> {
|
pub fn from_bytes(bytes: &Bound<'_, PyBytes>) -> PyResult<usize> {
|
||||||
let byte_vec: Vec<u8> = bytes.extract()?;
|
let byte_vec: Vec<u8> = bytes.extract()?;
|
||||||
Ok(byte_vec.len())
|
Ok(byte_vec.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
pub fn from_str(string: &PyString) -> PyResult<usize> {
|
pub fn from_str(string: &Bound<'_, PyString>) -> PyResult<usize> {
|
||||||
let rust_string: String = string.extract()?;
|
let rust_string: String = string.extract()?;
|
||||||
Ok(rust_string.len())
|
Ok(rust_string.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
pub fn from_str_lossy(string: &PyString) -> usize {
|
pub fn from_str_lossy(string: &Bound<'_, PyString>) -> usize {
|
||||||
let rust_string_lossy: String = string.to_string_lossy().to_string();
|
let rust_string_lossy: String = string.to_string_lossy().to_string();
|
||||||
rust_string_lossy.len()
|
rust_string_lossy.len()
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,11 @@ fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Bound<'_
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> Bound<'p, PyTuple> {
|
fn get_date_tuple<'py>(d: &Bound<'py, PyDate>) -> Bound<'py, PyTuple> {
|
||||||
PyTuple::new_bound(py, [d.get_year(), d.get_month() as i32, d.get_day() as i32])
|
PyTuple::new_bound(
|
||||||
|
d.py(),
|
||||||
|
[d.get_year(), d.get_month() as i32, d.get_day() as i32],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
|
@ -48,9 +51,9 @@ fn time_with_fold<'py>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> Bound<'p, PyTuple> {
|
fn get_time_tuple<'py>(dt: &Bound<'py, PyTime>) -> Bound<'py, PyTuple> {
|
||||||
PyTuple::new_bound(
|
PyTuple::new_bound(
|
||||||
py,
|
dt.py(),
|
||||||
[
|
[
|
||||||
dt.get_hour() as u32,
|
dt.get_hour() as u32,
|
||||||
dt.get_minute() as u32,
|
dt.get_minute() as u32,
|
||||||
|
@ -61,9 +64,9 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> Bound<'p, PyTuple> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> Bound<'p, PyTuple> {
|
fn get_time_tuple_fold<'py>(dt: &Bound<'py, PyTime>) -> Bound<'py, PyTuple> {
|
||||||
PyTuple::new_bound(
|
PyTuple::new_bound(
|
||||||
py,
|
dt.py(),
|
||||||
[
|
[
|
||||||
dt.get_hour() as u32,
|
dt.get_hour() as u32,
|
||||||
dt.get_minute() as u32,
|
dt.get_minute() as u32,
|
||||||
|
@ -123,9 +126,9 @@ fn make_datetime<'py>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_datetime_tuple<'py>(py: Python<'py>, dt: &Bound<'py, PyDateTime>) -> Bound<'py, PyTuple> {
|
fn get_datetime_tuple<'py>(dt: &Bound<'py, PyDateTime>) -> Bound<'py, PyTuple> {
|
||||||
PyTuple::new_bound(
|
PyTuple::new_bound(
|
||||||
py,
|
dt.py(),
|
||||||
[
|
[
|
||||||
dt.get_year(),
|
dt.get_year(),
|
||||||
dt.get_month() as i32,
|
dt.get_month() as i32,
|
||||||
|
@ -139,12 +142,9 @@ fn get_datetime_tuple<'py>(py: Python<'py>, dt: &Bound<'py, PyDateTime>) -> Boun
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_datetime_tuple_fold<'py>(
|
fn get_datetime_tuple_fold<'py>(dt: &Bound<'py, PyDateTime>) -> Bound<'py, PyTuple> {
|
||||||
py: Python<'py>,
|
|
||||||
dt: &Bound<'py, PyDateTime>,
|
|
||||||
) -> Bound<'py, PyTuple> {
|
|
||||||
PyTuple::new_bound(
|
PyTuple::new_bound(
|
||||||
py,
|
dt.py(),
|
||||||
[
|
[
|
||||||
dt.get_year(),
|
dt.get_year(),
|
||||||
dt.get_month() as i32,
|
dt.get_month() as i32,
|
||||||
|
@ -187,12 +187,8 @@ impl TzClass {
|
||||||
TzClass {}
|
TzClass {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn utcoffset<'py>(
|
fn utcoffset<'py>(&self, dt: &Bound<'py, PyDateTime>) -> PyResult<Bound<'py, PyDelta>> {
|
||||||
&self,
|
PyDelta::new_bound(dt.py(), 0, 3600, 0, true)
|
||||||
py: Python<'py>,
|
|
||||||
_dt: &Bound<'py, PyDateTime>,
|
|
||||||
) -> PyResult<Bound<'py, PyDelta>> {
|
|
||||||
PyDelta::new_bound(py, 0, 3600, 0, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tzname(&self, _dt: &Bound<'_, PyDateTime>) -> String {
|
fn tzname(&self, _dt: &Bound<'_, PyDateTime>) -> String {
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl DictSize {
|
||||||
DictSize { expected }
|
DictSize { expected }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_dict(&mut self, _py: Python<'_>, dict: &PyDict) -> PyResult<u32> {
|
fn iter_dict(&mut self, _py: Python<'_>, dict: &Bound<'_, PyDict>) -> PyResult<u32> {
|
||||||
let mut seen = 0u32;
|
let mut seen = 0u32;
|
||||||
for (sym, values) in dict {
|
for (sym, values) in dict {
|
||||||
seen += 1;
|
seen += 1;
|
||||||
|
|
|
@ -8,8 +8,8 @@ fn issue_219() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_type_full_name(obj: &PyAny) -> PyResult<Cow<'_, str>> {
|
fn get_type_full_name(obj: &Bound<'_, PyAny>) -> PyResult<String> {
|
||||||
obj.get_type().name()
|
obj.get_type().name().map(Cow::into_owned)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl ObjStore {
|
||||||
ObjStore::default()
|
ObjStore::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, py: Python<'_>, obj: &PyAny) {
|
fn push(&mut self, py: Python<'_>, obj: &Bound<'_, PyAny>) {
|
||||||
self.obj.push(obj.to_object(py));
|
self.obj.push(obj.to_object(py));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,22 +57,27 @@ impl AssertingBaseClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass(subclass)]
|
#[allow(deprecated)]
|
||||||
#[derive(Clone, Debug)]
|
mod deprecated {
|
||||||
struct AssertingBaseClassGilRef;
|
use super::*;
|
||||||
|
|
||||||
#[pymethods]
|
#[pyclass(subclass)]
|
||||||
impl AssertingBaseClassGilRef {
|
#[derive(Clone, Debug)]
|
||||||
#[new]
|
pub struct AssertingBaseClassGilRef;
|
||||||
#[classmethod]
|
|
||||||
fn new(cls: &PyType, expected_type: &PyType) -> PyResult<Self> {
|
#[pymethods]
|
||||||
if !cls.is(expected_type) {
|
impl AssertingBaseClassGilRef {
|
||||||
return Err(PyValueError::new_err(format!(
|
#[new]
|
||||||
"{:?} != {:?}",
|
#[classmethod]
|
||||||
cls, expected_type
|
fn new(cls: &PyType, expected_type: &PyType) -> PyResult<Self> {
|
||||||
)));
|
if !cls.is(expected_type) {
|
||||||
|
return Err(PyValueError::new_err(format!(
|
||||||
|
"{:?} != {:?}",
|
||||||
|
cls, expected_type
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
Ok(Self)
|
||||||
}
|
}
|
||||||
Ok(Self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +89,7 @@ pub fn pyclasses(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||||
m.add_class::<EmptyClass>()?;
|
m.add_class::<EmptyClass>()?;
|
||||||
m.add_class::<PyClassIter>()?;
|
m.add_class::<PyClassIter>()?;
|
||||||
m.add_class::<AssertingBaseClass>()?;
|
m.add_class::<AssertingBaseClass>()?;
|
||||||
m.add_class::<AssertingBaseClassGilRef>()?;
|
m.add_class::<deprecated::AssertingBaseClassGilRef>()?;
|
||||||
m.add_class::<ClassWithoutConstructor>()?;
|
m.add_class::<ClassWithoutConstructor>()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration},
|
exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration},
|
||||||
panic::PanicException,
|
panic::PanicException,
|
||||||
types::{string::PyStringMethods, PyIterator, PyString},
|
types::{string::PyStringMethods, PyIterator, PyString},
|
||||||
IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python,
|
Bound, IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod cancel;
|
pub(crate) mod cancel;
|
||||||
|
@ -143,7 +143,7 @@ impl Coroutine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, py: Python<'_>, _value: &PyAny) -> PyResult<PyObject> {
|
fn send(&mut self, py: Python<'_>, _value: &Bound<'_, PyAny>) -> PyResult<PyObject> {
|
||||||
self.poll(py, None)
|
self.poll(py, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl LoopAndFuture {
|
||||||
/// Future can be cancelled by the event loop before being waken.
|
/// Future can be cancelled by the event loop before being waken.
|
||||||
/// See <https://github.com/python/cpython/blob/main/Lib/asyncio/tasks.py#L452C5-L452C5>
|
/// See <https://github.com/python/cpython/blob/main/Lib/asyncio/tasks.py#L452C5-L452C5>
|
||||||
#[pyfunction(crate = "crate")]
|
#[pyfunction(crate = "crate")]
|
||||||
fn release_waiter(future: &PyAny) -> PyResult<()> {
|
fn release_waiter(future: &Bound<'_, PyAny>) -> PyResult<()> {
|
||||||
let done = future.call_method0(intern!(future.py(), "done"))?;
|
let done = future.call_method0(intern!(future.py(), "done"))?;
|
||||||
if !done.extract::<bool>()? {
|
if !done.extract::<bool>()? {
|
||||||
future.call_method1(intern!(future.py(), "set_result"), (future.py().None(),))?;
|
future.call_method1(intern!(future.py(), "set_result"), (future.py().None(),))?;
|
||||||
|
|
|
@ -5,8 +5,8 @@ use crate::{PyResult, Python};
|
||||||
#[deprecated(since = "0.20.0", note = "use `#[new]` instead of `#[__new__]`")]
|
#[deprecated(since = "0.20.0", note = "use `#[new]` instead of `#[__new__]`")]
|
||||||
pub const PYMETHODS_NEW_DEPRECATED_FORM: () = ();
|
pub const PYMETHODS_NEW_DEPRECATED_FORM: () = ();
|
||||||
|
|
||||||
pub fn inspect_type<T>(t: T) -> (T, GilRefs<T>) {
|
pub fn inspect_type<T>(t: T, _: &GilRefs<T>) -> T {
|
||||||
(t, GilRefs::new())
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inspect_fn<A, T>(f: fn(A) -> PyResult<T>, _: &GilRefs<A>) -> fn(A) -> PyResult<T> {
|
pub fn inspect_fn<A, T>(f: fn(A) -> PyResult<T>, _: &GilRefs<A>) -> fn(A) -> PyResult<T> {
|
||||||
|
|
|
@ -41,14 +41,27 @@ impl<'a, 'py, T: 'py> PyFunctionArgument<'a, 'py> for &'a Bound<'py, T>
|
||||||
where
|
where
|
||||||
T: PyTypeCheck,
|
T: PyTypeCheck,
|
||||||
{
|
{
|
||||||
type Holder = Option<&'a Bound<'py, T>>;
|
type Holder = Option<()>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extract(
|
fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut Option<()>) -> PyResult<Self> {
|
||||||
obj: &'a Bound<'py, PyAny>,
|
obj.downcast().map_err(Into::into)
|
||||||
holder: &'a mut Option<&'a Bound<'py, T>>,
|
}
|
||||||
) -> PyResult<Self> {
|
}
|
||||||
Ok(holder.insert(obj.downcast()?))
|
|
||||||
|
impl<'a, 'py, T: 'py> PyFunctionArgument<'a, 'py> for Option<&'a Bound<'py, T>>
|
||||||
|
where
|
||||||
|
T: PyTypeCheck,
|
||||||
|
{
|
||||||
|
type Holder = ();
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut ()) -> PyResult<Self> {
|
||||||
|
if obj.is_none() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(obj.downcast()?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,8 +144,10 @@ macro_rules! wrap_pyfunction {
|
||||||
};
|
};
|
||||||
($function:path, $py_or_module:expr) => {{
|
($function:path, $py_or_module:expr) => {{
|
||||||
use $function as wrapped_pyfunction;
|
use $function as wrapped_pyfunction;
|
||||||
let (py_or_module, e) = $crate::impl_::deprecations::inspect_type($py_or_module);
|
let check_gil_refs = $crate::impl_::deprecations::GilRefs::new();
|
||||||
e.is_python();
|
let py_or_module =
|
||||||
|
$crate::impl_::deprecations::inspect_type($py_or_module, &check_gil_refs);
|
||||||
|
check_gil_refs.is_python();
|
||||||
$crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction(
|
$crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction(
|
||||||
py_or_module,
|
py_or_module,
|
||||||
&wrapped_pyfunction::DEF,
|
&wrapped_pyfunction::DEF,
|
||||||
|
|
|
@ -149,12 +149,12 @@
|
||||||
//!
|
//!
|
||||||
//! It is better to write that function like this:
|
//! It is better to write that function like this:
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
//! # #![allow(deprecated)]
|
||||||
//! # use pyo3::prelude::*;
|
//! # use pyo3::prelude::*;
|
||||||
//! # #[pyclass]
|
//! # #[pyclass]
|
||||||
//! # pub struct Number {
|
//! # pub struct Number {
|
||||||
//! # inner: u32,
|
//! # inner: u32,
|
||||||
//! # }
|
//! # }
|
||||||
//! # #[allow(deprecated)]
|
|
||||||
//! #[pyfunction]
|
//! #[pyfunction]
|
||||||
//! fn swap_numbers(a: &PyCell<Number>, b: &PyCell<Number>) {
|
//! fn swap_numbers(a: &PyCell<Number>, b: &PyCell<Number>) {
|
||||||
//! // Check that the pointers are unequal
|
//! // Check that the pointers are unequal
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl Dummy {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String {
|
fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String {
|
||||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
::std::unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __lt__(&self, other: &Self) -> bool {
|
fn __lt__(&self, other: &Self) -> bool {
|
||||||
|
@ -63,12 +63,12 @@ impl Dummy {
|
||||||
// Customizing attribute access
|
// Customizing attribute access
|
||||||
//////////////////////
|
//////////////////////
|
||||||
|
|
||||||
fn __getattr__(&self, name: ::std::string::String) -> &crate::PyAny {
|
fn __getattr__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> {
|
||||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
::std::unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __getattribute__(&self, name: ::std::string::String) -> &crate::PyAny {
|
fn __getattribute__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> {
|
||||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
::std::unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {}
|
fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {}
|
||||||
|
@ -85,17 +85,27 @@ impl Dummy {
|
||||||
|
|
||||||
fn __get__(
|
fn __get__(
|
||||||
&self,
|
&self,
|
||||||
instance: &crate::PyAny,
|
instance: &crate::Bound<'_, crate::PyAny>,
|
||||||
owner: &crate::PyAny,
|
owner: &crate::Bound<'_, crate::PyAny>,
|
||||||
) -> crate::PyResult<&crate::PyAny> {
|
) -> crate::PyResult<&crate::Bound<'_, crate::PyAny>> {
|
||||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
::std::unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __set__(&self, instance: &crate::PyAny, owner: &crate::PyAny) {}
|
fn __set__(
|
||||||
|
&self,
|
||||||
|
instance: &crate::Bound<'_, crate::PyAny>,
|
||||||
|
owner: &crate::Bound<'_, crate::PyAny>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
fn __delete__(&self, instance: &crate::PyAny) {}
|
fn __delete__(&self, instance: &crate::Bound<'_, crate::PyAny>) {}
|
||||||
|
|
||||||
fn __set_name__(&self, owner: &crate::PyAny, name: &crate::PyAny) {}
|
fn __set_name__(
|
||||||
|
&self,
|
||||||
|
owner: &crate::Bound<'_, crate::PyAny>,
|
||||||
|
name: &crate::Bound<'_, crate::PyAny>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Implementing Descriptors
|
// Implementing Descriptors
|
||||||
|
@ -323,9 +333,9 @@ impl Dummy {
|
||||||
|
|
||||||
fn __exit__(
|
fn __exit__(
|
||||||
&mut self,
|
&mut self,
|
||||||
exc_type: &crate::PyAny,
|
exc_type: &crate::Bound<'_, crate::PyAny>,
|
||||||
exc_value: &crate::PyAny,
|
exc_value: &crate::Bound<'_, crate::PyAny>,
|
||||||
traceback: &crate::PyAny,
|
traceback: &crate::Bound<'_, crate::PyAny>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,9 +371,9 @@ impl Dummy {
|
||||||
|
|
||||||
fn __aexit__(
|
fn __aexit__(
|
||||||
&mut self,
|
&mut self,
|
||||||
exc_type: &crate::PyAny,
|
exc_type: &crate::Bound<'_, crate::PyAny>,
|
||||||
exc_value: &crate::PyAny,
|
exc_value: &crate::Bound<'_, crate::PyAny>,
|
||||||
traceback: &crate::PyAny,
|
traceback: &crate::Bound<'_, crate::PyAny>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,10 +388,10 @@ impl Dummy {
|
||||||
#[pyo3(signature = (*_args, **_kwds))]
|
#[pyo3(signature = (*_args, **_kwds))]
|
||||||
fn __call__(
|
fn __call__(
|
||||||
&self,
|
&self,
|
||||||
_args: &crate::types::PyTuple,
|
_args: &crate::Bound<'_, crate::types::PyTuple>,
|
||||||
_kwds: ::std::option::Option<&crate::types::PyDict>,
|
_kwds: ::std::option::Option<&crate::Bound<'_, crate::types::PyDict>>,
|
||||||
) -> crate::PyResult<i32> {
|
) -> crate::PyResult<i32> {
|
||||||
::std::panic!("unimplemented isn't hygienic before 1.50")
|
::std::unimplemented!()
|
||||||
}
|
}
|
||||||
#[new]
|
#[new]
|
||||||
fn new(a: u8) -> Self {
|
fn new(a: u8) -> Self {
|
||||||
|
|
|
@ -171,7 +171,7 @@ impl PyByteArray {
|
||||||
/// use pyo3::types::PyByteArray;
|
/// use pyo3::types::PyByteArray;
|
||||||
///
|
///
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn a_valid_function(bytes: &PyByteArray) -> PyResult<()> {
|
/// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> {
|
||||||
/// let section = {
|
/// let section = {
|
||||||
/// // SAFETY: We promise to not let the interpreter regain control
|
/// // SAFETY: We promise to not let the interpreter regain control
|
||||||
/// // or invoke any PyO3 APIs while using the slice.
|
/// // or invoke any PyO3 APIs while using the slice.
|
||||||
|
@ -224,7 +224,7 @@ impl PyByteArray {
|
||||||
///
|
///
|
||||||
/// # #[allow(dead_code)]
|
/// # #[allow(dead_code)]
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn bug(py: Python<'_>, bytes: &PyByteArray) {
|
/// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) {
|
||||||
/// let slice = unsafe { bytes.as_bytes() };
|
/// let slice = unsafe { bytes.as_bytes() };
|
||||||
///
|
///
|
||||||
/// // This explicitly yields control back to the Python interpreter...
|
/// // This explicitly yields control back to the Python interpreter...
|
||||||
|
@ -333,7 +333,7 @@ pub trait PyByteArrayMethods<'py>: crate::sealed::Sealed {
|
||||||
/// use pyo3::types::PyByteArray;
|
/// use pyo3::types::PyByteArray;
|
||||||
///
|
///
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn a_valid_function(bytes: &PyByteArray) -> PyResult<()> {
|
/// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> {
|
||||||
/// let section = {
|
/// let section = {
|
||||||
/// // SAFETY: We promise to not let the interpreter regain control
|
/// // SAFETY: We promise to not let the interpreter regain control
|
||||||
/// // or invoke any PyO3 APIs while using the slice.
|
/// // or invoke any PyO3 APIs while using the slice.
|
||||||
|
@ -386,7 +386,7 @@ pub trait PyByteArrayMethods<'py>: crate::sealed::Sealed {
|
||||||
///
|
///
|
||||||
/// # #[allow(dead_code)]
|
/// # #[allow(dead_code)]
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn bug(py: Python<'_>, bytes: &PyByteArray) {
|
/// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) {
|
||||||
/// let slice = unsafe { bytes.as_bytes() };
|
/// let slice = unsafe { bytes.as_bytes() };
|
||||||
///
|
///
|
||||||
/// // This explicitly yields control back to the Python interpreter...
|
/// // This explicitly yields control back to the Python interpreter...
|
||||||
|
|
|
@ -166,43 +166,43 @@ impl BinaryArithmetic {
|
||||||
"BA"
|
"BA"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __add__(&self, rhs: &PyAny) -> String {
|
fn __add__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA + {:?}", rhs)
|
format!("BA + {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __sub__(&self, rhs: &PyAny) -> String {
|
fn __sub__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA - {:?}", rhs)
|
format!("BA - {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __mul__(&self, rhs: &PyAny) -> String {
|
fn __mul__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA * {:?}", rhs)
|
format!("BA * {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __truediv__(&self, rhs: &PyAny) -> String {
|
fn __truediv__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA / {:?}", rhs)
|
format!("BA / {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __lshift__(&self, rhs: &PyAny) -> String {
|
fn __lshift__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA << {:?}", rhs)
|
format!("BA << {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rshift__(&self, rhs: &PyAny) -> String {
|
fn __rshift__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA >> {:?}", rhs)
|
format!("BA >> {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __and__(&self, rhs: &PyAny) -> String {
|
fn __and__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA & {:?}", rhs)
|
format!("BA & {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __xor__(&self, rhs: &PyAny) -> String {
|
fn __xor__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA ^ {:?}", rhs)
|
format!("BA ^ {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __or__(&self, rhs: &PyAny) -> String {
|
fn __or__(&self, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("BA | {:?}", rhs)
|
format!("BA | {:?}", rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __pow__(&self, rhs: &PyAny, mod_: Option<u32>) -> String {
|
fn __pow__(&self, rhs: &Bound<'_, PyAny>, mod_: Option<u32>) -> String {
|
||||||
format!("BA ** {:?} (mod: {:?})", rhs, mod_)
|
format!("BA ** {:?} (mod: {:?})", rhs, mod_)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,39 +257,39 @@ struct RhsArithmetic {}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl RhsArithmetic {
|
impl RhsArithmetic {
|
||||||
fn __radd__(&self, other: &PyAny) -> String {
|
fn __radd__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} + RA", other)
|
format!("{:?} + RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rsub__(&self, other: &PyAny) -> String {
|
fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} - RA", other)
|
format!("{:?} - RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rmul__(&self, other: &PyAny) -> String {
|
fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} * RA", other)
|
format!("{:?} * RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rlshift__(&self, other: &PyAny) -> String {
|
fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} << RA", other)
|
format!("{:?} << RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rrshift__(&self, other: &PyAny) -> String {
|
fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} >> RA", other)
|
format!("{:?} >> RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rand__(&self, other: &PyAny) -> String {
|
fn __rand__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} & RA", other)
|
format!("{:?} & RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rxor__(&self, other: &PyAny) -> String {
|
fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} ^ RA", other)
|
format!("{:?} ^ RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __ror__(&self, other: &PyAny) -> String {
|
fn __ror__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} | RA", other)
|
format!("{:?} | RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rpow__(&self, other: &PyAny, _mod: Option<&PyAny>) -> String {
|
fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&PyAny>) -> String {
|
||||||
format!("{:?} ** RA", other)
|
format!("{:?} ** RA", other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,91 +334,91 @@ impl LhsAndRhs {
|
||||||
// "BA"
|
// "BA"
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn __add__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __add__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} + {:?}", lhs, rhs)
|
format!("{:?} + {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __sub__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __sub__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} - {:?}", lhs, rhs)
|
format!("{:?} - {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __mul__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __mul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} * {:?}", lhs, rhs)
|
format!("{:?} * {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __lshift__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __lshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} << {:?}", lhs, rhs)
|
format!("{:?} << {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rshift__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __rshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} >> {:?}", lhs, rhs)
|
format!("{:?} >> {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __and__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __and__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} & {:?}", lhs, rhs)
|
format!("{:?} & {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __xor__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __xor__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} ^ {:?}", lhs, rhs)
|
format!("{:?} ^ {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __or__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __or__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} | {:?}", lhs, rhs)
|
format!("{:?} | {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __pow__(lhs: PyRef<'_, Self>, rhs: &PyAny, _mod: Option<usize>) -> String {
|
fn __pow__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>, _mod: Option<usize>) -> String {
|
||||||
format!("{:?} ** {:?}", lhs, rhs)
|
format!("{:?} ** {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __matmul__(lhs: PyRef<'_, Self>, rhs: &PyAny) -> String {
|
fn __matmul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} @ {:?}", lhs, rhs)
|
format!("{:?} @ {:?}", lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __radd__(&self, other: &PyAny) -> String {
|
fn __radd__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} + RA", other)
|
format!("{:?} + RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rsub__(&self, other: &PyAny) -> String {
|
fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} - RA", other)
|
format!("{:?} - RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rmul__(&self, other: &PyAny) -> String {
|
fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} * RA", other)
|
format!("{:?} * RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rlshift__(&self, other: &PyAny) -> String {
|
fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} << RA", other)
|
format!("{:?} << RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rrshift__(&self, other: &PyAny) -> String {
|
fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} >> RA", other)
|
format!("{:?} >> RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rand__(&self, other: &PyAny) -> String {
|
fn __rand__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} & RA", other)
|
format!("{:?} & RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rxor__(&self, other: &PyAny) -> String {
|
fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} ^ RA", other)
|
format!("{:?} ^ RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __ror__(&self, other: &PyAny) -> String {
|
fn __ror__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} | RA", other)
|
format!("{:?} | RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rpow__(&self, other: &PyAny, _mod: Option<&PyAny>) -> String {
|
fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&PyAny>) -> String {
|
||||||
format!("{:?} ** RA", other)
|
format!("{:?} ** RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rmatmul__(&self, other: &PyAny) -> String {
|
fn __rmatmul__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} @ RA", other)
|
format!("{:?} @ RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rtruediv__(&self, other: &PyAny) -> String {
|
fn __rtruediv__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} / RA", other)
|
format!("{:?} / RA", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __rfloordiv__(&self, other: &PyAny) -> String {
|
fn __rfloordiv__(&self, other: &Bound<'_, PyAny>) -> String {
|
||||||
format!("{:?} // RA", other)
|
format!("{:?} // RA", other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,7 +461,7 @@ impl RichComparisons {
|
||||||
"RC"
|
"RC"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __richcmp__(&self, other: &PyAny, op: CompareOp) -> String {
|
fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> String {
|
||||||
match op {
|
match op {
|
||||||
CompareOp::Lt => format!("{} < {:?}", self.__repr__(), other),
|
CompareOp::Lt => format!("{} < {:?}", self.__repr__(), other),
|
||||||
CompareOp::Le => format!("{} <= {:?}", self.__repr__(), other),
|
CompareOp::Le => format!("{} <= {:?}", self.__repr__(), other),
|
||||||
|
@ -482,7 +482,7 @@ impl RichComparisons2 {
|
||||||
"RC2"
|
"RC2"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __richcmp__(&self, other: &PyAny, op: CompareOp) -> PyObject {
|
fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyObject {
|
||||||
match op {
|
match op {
|
||||||
CompareOp::Eq => true.into_py(other.py()),
|
CompareOp::Eq => true.into_py(other.py()),
|
||||||
CompareOp::Ne => false.into_py(other.py()),
|
CompareOp::Ne => false.into_py(other.py()),
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl BaseClass {
|
||||||
fn base_method(&self, x: usize) -> usize {
|
fn base_method(&self, x: usize) -> usize {
|
||||||
x * self.val1
|
x * self.val1
|
||||||
}
|
}
|
||||||
fn base_set(&mut self, fn_: &pyo3::PyAny) -> PyResult<()> {
|
fn base_set(&mut self, fn_: &Bound<'_, PyAny>) -> PyResult<()> {
|
||||||
let value: usize = fn_.call0()?.extract()?;
|
let value: usize = fn_.call0()?.extract()?;
|
||||||
self.val1 = value;
|
self.val1 = value;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -264,7 +264,7 @@ mod inheriting_native_type {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl CustomException {
|
impl CustomException {
|
||||||
#[new]
|
#[new]
|
||||||
fn new(_exc_arg: &PyAny) -> Self {
|
fn new(_exc_arg: &Bound<'_, PyAny>) -> Self {
|
||||||
CustomException {
|
CustomException {
|
||||||
context: "Hello :)",
|
context: "Hello :)",
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,12 +112,8 @@ struct ClassMethodWithArgs {}
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl ClassMethodWithArgs {
|
impl ClassMethodWithArgs {
|
||||||
#[classmethod]
|
#[classmethod]
|
||||||
fn method(cls: &Bound<'_, PyType>, input: &PyString) -> PyResult<String> {
|
fn method(cls: &Bound<'_, PyType>, input: &Bound<'_, PyString>) -> PyResult<String> {
|
||||||
Ok(format!(
|
Ok(format!("{}.method({})", cls.qualname()?, input))
|
||||||
"{}.method({})",
|
|
||||||
cls.as_gil_ref().qualname()?,
|
|
||||||
input
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,8 +211,13 @@ impl MethSignature {
|
||||||
test
|
test
|
||||||
}
|
}
|
||||||
#[pyo3(signature = (*args, **kwargs))]
|
#[pyo3(signature = (*args, **kwargs))]
|
||||||
fn get_kwargs(&self, py: Python<'_>, args: &PyTuple, kwargs: Option<&PyDict>) -> PyObject {
|
fn get_kwargs(
|
||||||
[args.into(), kwargs.to_object(py)].to_object(py)
|
&self,
|
||||||
|
py: Python<'_>,
|
||||||
|
args: &Bound<'_, PyTuple>,
|
||||||
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
|
) -> PyObject {
|
||||||
|
[args.to_object(py), kwargs.to_object(py)].to_object(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyo3(signature = (a, *args, **kwargs))]
|
#[pyo3(signature = (a, *args, **kwargs))]
|
||||||
|
@ -224,10 +225,10 @@ impl MethSignature {
|
||||||
&self,
|
&self,
|
||||||
py: Python<'_>,
|
py: Python<'_>,
|
||||||
a: i32,
|
a: i32,
|
||||||
args: &PyTuple,
|
args: &Bound<'_, PyTuple>,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) -> PyObject {
|
) -> PyObject {
|
||||||
[a.to_object(py), args.into(), kwargs.to_object(py)].to_object(py)
|
[a.to_object(py), args.to_object(py), kwargs.to_object(py)].to_object(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyo3(signature = (a, b, /))]
|
#[pyo3(signature = (a, b, /))]
|
||||||
|
@ -270,7 +271,7 @@ impl MethSignature {
|
||||||
&self,
|
&self,
|
||||||
py: Python<'_>,
|
py: Python<'_>,
|
||||||
a: i32,
|
a: i32,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) -> PyObject {
|
) -> PyObject {
|
||||||
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
||||||
}
|
}
|
||||||
|
@ -280,7 +281,7 @@ impl MethSignature {
|
||||||
&self,
|
&self,
|
||||||
py: Python<'_>,
|
py: Python<'_>,
|
||||||
a: i32,
|
a: i32,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) -> PyObject {
|
) -> PyObject {
|
||||||
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
||||||
}
|
}
|
||||||
|
@ -301,7 +302,12 @@ impl MethSignature {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyo3(signature = (*args, a))]
|
#[pyo3(signature = (*args, a))]
|
||||||
fn get_args_and_required_keyword(&self, py: Python<'_>, args: &PyTuple, a: i32) -> PyObject {
|
fn get_args_and_required_keyword(
|
||||||
|
&self,
|
||||||
|
py: Python<'_>,
|
||||||
|
args: &Bound<'_, PyTuple>,
|
||||||
|
a: i32,
|
||||||
|
) -> PyObject {
|
||||||
(args, a).to_object(py)
|
(args, a).to_object(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +322,7 @@ impl MethSignature {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyo3(signature = (a, **kwargs))]
|
#[pyo3(signature = (a, **kwargs))]
|
||||||
fn get_pos_kw(&self, py: Python<'_>, a: i32, kwargs: Option<&PyDict>) -> PyObject {
|
fn get_pos_kw(&self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>) -> PyObject {
|
||||||
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
[a.to_object(py), kwargs.to_object(py)].to_object(py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,7 +703,8 @@ struct MethodWithLifeTime {}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl MethodWithLifeTime {
|
impl MethodWithLifeTime {
|
||||||
fn set_to_list<'py>(&self, py: Python<'py>, set: &'py PySet) -> PyResult<Bound<'py, PyList>> {
|
fn set_to_list<'py>(&self, set: &Bound<'py, PySet>) -> PyResult<Bound<'py, PyList>> {
|
||||||
|
let py = set.py();
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
for _ in 0..set.len() {
|
for _ in 0..set.len() {
|
||||||
items.push(set.pop().unwrap());
|
items.push(set.pop().unwrap());
|
||||||
|
@ -1028,45 +1035,45 @@ issue_1506!(
|
||||||
fn issue_1506(
|
fn issue_1506(
|
||||||
&self,
|
&self,
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn issue_1506_mut(
|
fn issue_1506_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn issue_1506_custom_receiver(
|
fn issue_1506_custom_receiver(
|
||||||
_slf: Py<Self>,
|
_slf: Py<Self>,
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn issue_1506_custom_receiver_explicit(
|
fn issue_1506_custom_receiver_explicit(
|
||||||
_slf: Py<Issue1506>,
|
_slf: Py<Issue1506>,
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[new]
|
#[new]
|
||||||
fn issue_1506_new(
|
fn issue_1506_new(
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Issue1506 {}
|
Issue1506 {}
|
||||||
}
|
}
|
||||||
|
@ -1082,9 +1089,9 @@ issue_1506!(
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
fn issue_1506_static(
|
fn issue_1506_static(
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,9 +1099,9 @@ issue_1506!(
|
||||||
fn issue_1506_class(
|
fn issue_1506_class(
|
||||||
_cls: &Bound<'_, PyType>,
|
_cls: &Bound<'_, PyType>,
|
||||||
_py: Python<'_>,
|
_py: Python<'_>,
|
||||||
_arg: &PyAny,
|
_arg: &Bound<'_, PyAny>,
|
||||||
_args: &PyTuple,
|
_args: &Bound<'_, PyTuple>,
|
||||||
_kwargs: Option<&PyDict>,
|
_kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl BasicClass {
|
||||||
const OKAY: bool = true;
|
const OKAY: bool = true;
|
||||||
|
|
||||||
#[new]
|
#[new]
|
||||||
fn new(arg: &pyo3::PyAny) -> pyo3::PyResult<Self> {
|
fn new(arg: &pyo3::Bound<'_, pyo3::PyAny>) -> pyo3::PyResult<Self> {
|
||||||
if let Ok(v) = arg.extract::<usize>() {
|
if let Ok(v) = arg.extract::<usize>() {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
v,
|
v,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl ExampleClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __setattr__(&mut self, attr: &str, value: &PyAny) -> PyResult<()> {
|
fn __setattr__(&mut self, attr: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
|
||||||
if attr == "special_custom_attr" {
|
if attr == "special_custom_attr" {
|
||||||
self.custom_attr = Some(value.extract()?);
|
self.custom_attr = Some(value.extract()?);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -528,7 +528,7 @@ struct GetItem {}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl GetItem {
|
impl GetItem {
|
||||||
fn __getitem__(&self, idx: &PyAny) -> PyResult<&'static str> {
|
fn __getitem__(&self, idx: &Bound<'_, PyAny>) -> PyResult<&'static str> {
|
||||||
if let Ok(slice) = idx.downcast::<PySlice>() {
|
if let Ok(slice) = idx.downcast::<PySlice>() {
|
||||||
let indices = slice.indices(1000)?;
|
let indices = slice.indices(1000)?;
|
||||||
if indices.start == 100 && indices.stop == 200 && indices.step == 1 {
|
if indices.start == 100 && indices.stop == 200 && indices.step == 1 {
|
||||||
|
@ -767,18 +767,18 @@ impl DescrCounter {
|
||||||
/// Each access will increase the count
|
/// Each access will increase the count
|
||||||
fn __get__<'a>(
|
fn __get__<'a>(
|
||||||
mut slf: PyRefMut<'a, Self>,
|
mut slf: PyRefMut<'a, Self>,
|
||||||
_instance: &PyAny,
|
_instance: &Bound<'_, PyAny>,
|
||||||
_owner: Option<&PyType>,
|
_owner: Option<&Bound<'_, PyType>>,
|
||||||
) -> PyRefMut<'a, Self> {
|
) -> PyRefMut<'a, Self> {
|
||||||
slf.count += 1;
|
slf.count += 1;
|
||||||
slf
|
slf
|
||||||
}
|
}
|
||||||
/// Allow assigning a new counter to the descriptor, copying the count across
|
/// Allow assigning a new counter to the descriptor, copying the count across
|
||||||
fn __set__(&self, _instance: &PyAny, new_value: &mut Self) {
|
fn __set__(&self, _instance: &Bound<'_, PyAny>, new_value: &mut Self) {
|
||||||
new_value.count = self.count;
|
new_value.count = self.count;
|
||||||
}
|
}
|
||||||
/// Delete to reset the counter
|
/// Delete to reset the counter
|
||||||
fn __delete__(&mut self, _instance: &PyAny) {
|
fn __delete__(&mut self, _instance: &Bound<'_, PyAny>) {
|
||||||
self.count = 0;
|
self.count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,12 +77,14 @@ assert a, array.array("i", [2, 4, 6, 8])
|
||||||
|
|
||||||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn function_with_pyfunction_arg(fun: &PyFunction) -> PyResult<&PyAny> {
|
fn function_with_pyfunction_arg<'py>(fun: &Bound<'py, PyFunction>) -> PyResult<Bound<'py, PyAny>> {
|
||||||
fun.call((), None)
|
fun.call((), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn function_with_pycfunction_arg(fun: &PyCFunction) -> PyResult<&PyAny> {
|
fn function_with_pycfunction_arg<'py>(
|
||||||
|
fun: &Bound<'py, PyCFunction>,
|
||||||
|
) -> PyResult<Bound<'py, PyAny>> {
|
||||||
fun.call((), None)
|
fun.call((), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@ impl ByteSequence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __contains__(&self, other: &PyAny) -> bool {
|
fn __contains__(&self, other: &Bound<'_, PyAny>) -> bool {
|
||||||
match u8::extract(other) {
|
match other.extract::<u8>() {
|
||||||
Ok(x) => self.elements.contains(&x),
|
Ok(x) => self.elements.contains(&x),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,10 +128,10 @@ fn test_auto_test_signature_function() {
|
||||||
fn my_function_4(
|
fn my_function_4(
|
||||||
a: i32,
|
a: i32,
|
||||||
b: Option<i32>,
|
b: Option<i32>,
|
||||||
args: &PyTuple,
|
args: &Bound<'_, PyTuple>,
|
||||||
c: i32,
|
c: i32,
|
||||||
d: i32,
|
d: i32,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
let _ = (a, b, args, c, d, kwargs);
|
let _ = (a, b, args, c, d, kwargs);
|
||||||
}
|
}
|
||||||
|
@ -218,10 +218,10 @@ fn test_auto_test_signature_method() {
|
||||||
&self,
|
&self,
|
||||||
a: i32,
|
a: i32,
|
||||||
b: Option<i32>,
|
b: Option<i32>,
|
||||||
args: &PyTuple,
|
args: &Bound<'_, PyTuple>,
|
||||||
c: i32,
|
c: i32,
|
||||||
d: i32,
|
d: i32,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&Bound<'_, PyDict>>,
|
||||||
) {
|
) {
|
||||||
let _ = (a, b, args, c, d, kwargs);
|
let _ = (a, b, args, c, d, kwargs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ struct MyClass {}
|
||||||
impl MyClass {
|
impl MyClass {
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
#[pyo3(signature = (*args))]
|
#[pyo3(signature = (*args))]
|
||||||
fn test_args(args: &PyTuple) -> &PyTuple {
|
fn test_args(args: Bound<'_, PyTuple>) -> Bound<'_, PyTuple> {
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
|
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
#[pyo3(signature = (**kwargs))]
|
#[pyo3(signature = (**kwargs))]
|
||||||
fn test_kwargs(kwargs: Option<&PyDict>) -> Option<&PyDict> {
|
fn test_kwargs(kwargs: Option<Bound<'_, PyDict>>) -> Option<Bound<'_, PyDict>> {
|
||||||
kwargs
|
kwargs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ impl MyClass {
|
||||||
fn method_gil_ref(_slf: &PyCell<Self>) {}
|
fn method_gil_ref(_slf: &PyCell<Self>) {}
|
||||||
|
|
||||||
fn method_bound(_slf: &Bound<'_, Self>) {}
|
fn method_bound(_slf: &Bound<'_, Self>) {}
|
||||||
|
|
||||||
|
#[staticmethod]
|
||||||
|
fn static_method_gil_ref(_any: &PyAny) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -89,6 +92,9 @@ fn pyfunction_from_py_with(
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn pyfunction_gil_ref(_any: &PyAny) {}
|
||||||
|
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
pub struct Zap {
|
pub struct Zap {
|
||||||
#[pyo3(item)]
|
#[pyo3(item)]
|
||||||
|
|
|
@ -29,57 +29,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:38:43
|
--> tests/ui/deprecations.rs:28:36
|
||||||
|
|
|
|
||||||
38 | fn pyfunction_with_module_gil_ref(module: &PyModule) -> PyResult<&str> {
|
28 | fn static_method_gil_ref(_any: &PyAny) {}
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::function_arg`: use `&Bound<'_, T>` instead for this function argument
|
||||||
|
--> tests/ui/deprecations.rs:41:43
|
||||||
|
|
|
||||||
|
41 | 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:48:19
|
--> tests/ui/deprecations.rs:51:19
|
||||||
|
|
|
|
||||||
48 | fn module_gil_ref(m: &PyModule) -> PyResult<()> {
|
51 | 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:54:57
|
--> tests/ui/deprecations.rs:57:57
|
||||||
|
|
|
|
||||||
54 | fn module_gil_ref_with_explicit_py_arg(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
57 | 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:87:27
|
--> tests/ui/deprecations.rs:90:27
|
||||||
|
|
|
|
||||||
87 | #[pyo3(from_py_with = "extract_gil_ref")] _gil_ref: i32,
|
90 | #[pyo3(from_py_with = "extract_gil_ref")] _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>::function_arg`: use `&Bound<'_, T>` instead for this function argument
|
||||||
--> tests/ui/deprecations.rs:97:27
|
--> tests/ui/deprecations.rs:96:29
|
||||||
|
|
|
|
||||||
97 | #[pyo3(from_py_with = "PyAny::len", item("my_object"))]
|
96 | fn pyfunction_gil_ref(_any: &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:107:27
|
--> tests/ui/deprecations.rs:103:27
|
||||||
|
|
|
|
||||||
107 | #[pyo3(from_py_with = "PyAny::len")] usize,
|
103 | #[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:113:31
|
--> tests/ui/deprecations.rs:113:27
|
||||||
|
|
|
|
||||||
113 | Zip(#[pyo3(from_py_with = "extract_gil_ref")] i32),
|
113 | #[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
|
||||||
|
--> tests/ui/deprecations.rs:119:31
|
||||||
|
|
|
||||||
|
119 | 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:120:27
|
--> tests/ui/deprecations.rs:126:27
|
||||||
|
|
|
|
||||||
120 | #[pyo3(from_py_with = "extract_gil_ref")]
|
126 | #[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:133:13
|
--> tests/ui/deprecations.rs:139:13
|
||||||
|
|
|
|
||||||
133 | let _ = wrap_pyfunction!(double, py);
|
139 | 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)
|
||||||
|
|
|
@ -58,6 +58,7 @@ error[E0277]: the trait bound `CancelHandle: Clone` is not satisfied
|
||||||
| ^^^^ the trait `Clone` is not implemented for `CancelHandle`
|
| ^^^^ the trait `Clone` is not implemented for `CancelHandle`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `PyFunctionArgument<'a, 'py>`:
|
= help: the following other types implement trait `PyFunctionArgument<'a, 'py>`:
|
||||||
|
Option<&'a pyo3::Bound<'py, T>>
|
||||||
&'a pyo3::Bound<'py, T>
|
&'a pyo3::Bound<'py, T>
|
||||||
&'a pyo3::coroutine::Coroutine
|
&'a pyo3::coroutine::Coroutine
|
||||||
&'a mut pyo3::coroutine::Coroutine
|
&'a mut pyo3::coroutine::Coroutine
|
||||||
|
|
|
@ -16,6 +16,19 @@ note: required by a bound in `extract_pyclass_ref_mut`
|
||||||
| pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
|
| pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`
|
| ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`
|
||||||
|
|
||||||
|
error[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`
|
||||||
|
--> tests/ui/invalid_frozen_pyclass_borrow.rs:9:1
|
||||||
|
|
|
||||||
|
9 | #[pymethods]
|
||||||
|
| ^^^^^^^^^^^^ expected `False`, found `True`
|
||||||
|
|
|
||||||
|
note: required by a bound in `PyRefMut`
|
||||||
|
--> src/pycell.rs
|
||||||
|
|
|
||||||
|
| pub struct PyRefMut<'p, T: PyClass<Frozen = False>> {
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `PyRefMut`
|
||||||
|
= note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`
|
error[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`
|
||||||
--> tests/ui/invalid_frozen_pyclass_borrow.rs:15:31
|
--> tests/ui/invalid_frozen_pyclass_borrow.rs:15:31
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::types::PyString;
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn generic_function<T>(value: T) {}
|
fn generic_function<T>(value: T) {}
|
||||||
|
@ -19,7 +20,10 @@ fn function_with_required_after_option(_opt: Option<i32>, _x: i32) {}
|
||||||
fn pass_module_but_no_arguments<'py>() {}
|
fn pass_module_but_no_arguments<'py>() {}
|
||||||
|
|
||||||
#[pyfunction(pass_module)]
|
#[pyfunction(pass_module)]
|
||||||
fn first_argument_not_module<'py>(string: &str, module: &'py PyModule) -> PyResult<&'py str> {
|
fn first_argument_not_module<'a, 'py>(
|
||||||
|
string: &str,
|
||||||
|
module: &'a Bound<'_, PyModule>,
|
||||||
|
) -> PyResult<Bound<'py, PyString>> {
|
||||||
module.name()
|
module.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
error: Python functions cannot have generic type parameters
|
error: Python functions cannot have generic type parameters
|
||||||
--> tests/ui/invalid_pyfunctions.rs:4:21
|
--> tests/ui/invalid_pyfunctions.rs:5:21
|
||||||
|
|
|
|
||||||
4 | fn generic_function<T>(value: T) {}
|
5 | fn generic_function<T>(value: T) {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: Python functions cannot have `impl Trait` arguments
|
error: Python functions cannot have `impl Trait` arguments
|
||||||
--> tests/ui/invalid_pyfunctions.rs:7:36
|
--> tests/ui/invalid_pyfunctions.rs:8:36
|
||||||
|
|
|
|
||||||
7 | fn impl_trait_function(impl_trait: impl AsRef<PyAny>) {}
|
8 | fn impl_trait_function(impl_trait: impl AsRef<PyAny>) {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: wildcard argument names are not supported
|
error: wildcard argument names are not supported
|
||||||
--> tests/ui/invalid_pyfunctions.rs:10:22
|
--> tests/ui/invalid_pyfunctions.rs:11:22
|
||||||
|
|
|
|
||||||
10 | fn wildcard_argument(_: i32) {}
|
11 | fn wildcard_argument(_: i32) {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: destructuring in arguments is not supported
|
error: destructuring in arguments is not supported
|
||||||
--> tests/ui/invalid_pyfunctions.rs:13:26
|
--> tests/ui/invalid_pyfunctions.rs:14:26
|
||||||
|
|
|
|
||||||
13 | fn destructured_argument((a, b): (i32, i32)) {}
|
14 | fn destructured_argument((a, b): (i32, i32)) {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: required arguments after an `Option<_>` argument are ambiguous
|
error: required arguments after an `Option<_>` argument are ambiguous
|
||||||
= help: add a `#[pyo3(signature)]` annotation on this function to unambiguously specify the default values for all optional parameters
|
= help: add a `#[pyo3(signature)]` annotation on this function to unambiguously specify the default values for all optional parameters
|
||||||
--> tests/ui/invalid_pyfunctions.rs:16:63
|
--> tests/ui/invalid_pyfunctions.rs:17:63
|
||||||
|
|
|
|
||||||
16 | fn function_with_required_after_option(_opt: Option<i32>, _x: i32) {}
|
17 | fn function_with_required_after_option(_opt: Option<i32>, _x: i32) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: expected `&PyModule` or `Py<PyModule>` as first argument with `pass_module`
|
error: expected `&PyModule` or `Py<PyModule>` as first argument with `pass_module`
|
||||||
--> tests/ui/invalid_pyfunctions.rs:19:37
|
--> tests/ui/invalid_pyfunctions.rs:20:37
|
||||||
|
|
|
|
||||||
19 | fn pass_module_but_no_arguments<'py>() {}
|
20 | fn pass_module_but_no_arguments<'py>() {}
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `&str: From<BoundRef<'_, '_, pyo3::prelude::PyModule>>` is not satisfied
|
error[E0277]: the trait bound `&str: From<BoundRef<'_, '_, pyo3::prelude::PyModule>>` is not satisfied
|
||||||
--> tests/ui/invalid_pyfunctions.rs:22:43
|
--> tests/ui/invalid_pyfunctions.rs:24:13
|
||||||
|
|
|
|
||||||
22 | fn first_argument_not_module<'py>(string: &str, module: &'py PyModule) -> PyResult<&'py str> {
|
24 | string: &str,
|
||||||
| ^ the trait `From<BoundRef<'_, '_, pyo3::prelude::PyModule>>` is not implemented for `&str`
|
| ^ the trait `From<BoundRef<'_, '_, pyo3::prelude::PyModule>>` is not implemented for `&str`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `From<T>`:
|
= help: the following other types implement trait `From<T>`:
|
||||||
<String as From<char>>
|
<String as From<char>>
|
||||||
|
|
|
@ -9,3 +9,16 @@ note: required by a bound in `extract_pyclass_ref_mut`
|
||||||
|
|
|
|
||||||
| pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
|
| pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`
|
| ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`
|
||||||
|
|
||||||
|
error[E0271]: type mismatch resolving `<ComplexEnum as PyClass>::Frozen == False`
|
||||||
|
--> tests/ui/invalid_pymethod_enum.rs:9:1
|
||||||
|
|
|
||||||
|
9 | #[pymethods]
|
||||||
|
| ^^^^^^^^^^^^ expected `False`, found `True`
|
||||||
|
|
|
||||||
|
note: required by a bound in `PyRefMut`
|
||||||
|
--> src/pycell.rs
|
||||||
|
|
|
||||||
|
| pub struct PyRefMut<'p, T: PyClass<Frozen = False>> {
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `PyRefMut`
|
||||||
|
= note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
|
@ -2,7 +2,12 @@ use pyo3::prelude::*;
|
||||||
use pyo3::types::PyList;
|
use pyo3::types::PyList;
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn static_ref(list: &'static PyList) -> usize {
|
fn static_ref(list: &'static Bound<'_, PyList>) -> usize {
|
||||||
|
list.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyfunction]
|
||||||
|
fn static_py(list: &Bound<'static, PyList>) -> usize {
|
||||||
list.len()
|
list.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,3 +8,37 @@ error: lifetime may not live long enough
|
||||||
| cast requires that `'py` must outlive `'static`
|
| cast requires that `'py` must outlive `'static`
|
||||||
|
|
|
|
||||||
= note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0597]: `holder_0` does not live long enough
|
||||||
|
--> tests/ui/static_ref.rs:5:15
|
||||||
|
|
|
||||||
|
4 | #[pyfunction]
|
||||||
|
| -------------
|
||||||
|
| | |
|
||||||
|
| | `holder_0` dropped here while still borrowed
|
||||||
|
| binding `holder_0` declared here
|
||||||
|
| argument requires that `holder_0` is borrowed for `'static`
|
||||||
|
5 | fn static_ref(list: &'static Bound<'_, PyList>) -> usize {
|
||||||
|
| ^^^^^^^ borrowed value does not live long enough
|
||||||
|
|
||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> tests/ui/static_ref.rs:5:21
|
||||||
|
|
|
||||||
|
4 | #[pyfunction]
|
||||||
|
| -------------
|
||||||
|
| | |
|
||||||
|
| | temporary value is freed at the end of this statement
|
||||||
|
| argument requires that borrow lasts for `'static`
|
||||||
|
5 | fn static_ref(list: &'static Bound<'_, PyList>) -> usize {
|
||||||
|
| ^ creates a temporary value which is freed while still in use
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> tests/ui/static_ref.rs:9:1
|
||||||
|
|
|
||||||
|
9 | #[pyfunction]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| lifetime `'py` defined here
|
||||||
|
| cast requires that `'py` must outlive `'static`
|
||||||
|
|
|
||||||
|
= note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
Loading…
Reference in New Issue