feature gate `PyCell` (#4177)
* feature gate `PyCell` * feature gate `HasPyGilRef` completely * bump version
This commit is contained in:
parent
57500d9b09
commit
10152a7078
10
Cargo.toml
10
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
description = "Bindings to Python interpreter"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
readme = "README.md"
|
||||
|
@ -20,10 +20,10 @@ libc = "0.2.62"
|
|||
memoffset = "0.9"
|
||||
|
||||
# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
|
||||
pyo3-ffi = { path = "pyo3-ffi", version = "=0.21.2" }
|
||||
pyo3-ffi = { path = "pyo3-ffi", version = "=0.22.0-dev" }
|
||||
|
||||
# support crates for macros feature
|
||||
pyo3-macros = { path = "pyo3-macros", version = "=0.21.2", optional = true }
|
||||
pyo3-macros = { path = "pyo3-macros", version = "=0.22.0-dev", optional = true }
|
||||
indoc = { version = "2.0.1", optional = true }
|
||||
unindent = { version = "0.2.1", optional = true }
|
||||
|
||||
|
@ -62,7 +62,7 @@ rayon = "1.6.1"
|
|||
futures = "0.3.28"
|
||||
|
||||
[build-dependencies]
|
||||
pyo3-build-config = { path = "pyo3-build-config", version = "=0.21.2", features = ["resolve-config"] }
|
||||
pyo3-build-config = { path = "pyo3-build-config", version = "=0.22.0-dev", features = ["resolve-config"] }
|
||||
|
||||
[features]
|
||||
default = ["macros"]
|
||||
|
@ -106,7 +106,7 @@ generate-import-lib = ["pyo3-ffi/generate-import-lib"]
|
|||
auto-initialize = []
|
||||
|
||||
# Allows use of the deprecated "GIL Refs" APIs.
|
||||
gil-refs = []
|
||||
gil-refs = ["pyo3-macros/gil-refs"]
|
||||
|
||||
# Enables `Clone`ing references to Python objects `Py<T>` which panics if the GIL is not held.
|
||||
py-clone = []
|
||||
|
|
|
@ -1307,6 +1307,7 @@ struct MyClass {
|
|||
impl pyo3::types::DerefToPyAny for MyClass {}
|
||||
|
||||
# #[allow(deprecated)]
|
||||
# #[cfg(feature = "gil-refs")]
|
||||
unsafe impl pyo3::type_object::HasPyGilRef for MyClass {
|
||||
type AsRefTarget = pyo3::PyCell<Self>;
|
||||
}
|
||||
|
|
|
@ -1609,7 +1609,7 @@ For more, see [the constructor section](class.md#constructor) of this guide.
|
|||
<details>
|
||||
<summary><small>Click to expand</small></summary>
|
||||
|
||||
PyO3 0.9 introduces [`PyCell`], which is a [`RefCell`]-like object wrapper
|
||||
PyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper
|
||||
for ensuring Rust's rules regarding aliasing of references are upheld.
|
||||
For more detail, see the
|
||||
[Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references)
|
||||
|
@ -1788,7 +1788,6 @@ impl PySequenceProtocol for ByteSequence {
|
|||
|
||||
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html
|
||||
[`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html
|
||||
[`PyCell`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html
|
||||
[`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html
|
||||
[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
|
||||
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3-build-config"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
description = "Build configuration for the PyO3 ecosystem"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
keywords = ["pyo3", "python", "cpython", "ffi"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3-ffi"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
description = "Python-API bindings for the PyO3 ecosystem"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
keywords = ["pyo3", "python", "cpython", "ffi"]
|
||||
|
@ -38,7 +38,7 @@ abi3-py312 = ["abi3", "pyo3-build-config/abi3-py312"]
|
|||
generate-import-lib = ["pyo3-build-config/python3-dll-a"]
|
||||
|
||||
[build-dependencies]
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.21.2", features = ["resolve-config"] }
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.22.0-dev", features = ["resolve-config"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3-macros-backend"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
description = "Code generation for PyO3 package"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
keywords = ["pyo3", "python", "cpython", "ffi"]
|
||||
|
@ -16,7 +16,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
heck = "0.5"
|
||||
proc-macro2 = { version = "1", default-features = false }
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.21.2", features = ["resolve-config"] }
|
||||
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.22.0-dev", features = ["resolve-config"] }
|
||||
quote = { version = "1", default-features = false }
|
||||
|
||||
[dependencies.syn]
|
||||
|
@ -29,3 +29,4 @@ workspace = true
|
|||
|
||||
[features]
|
||||
experimental-async = []
|
||||
gil-refs = []
|
||||
|
|
|
@ -384,6 +384,11 @@ fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn
|
|||
let Ctx { pyo3_path } = ctx;
|
||||
let mut stmts: Vec<syn::Stmt> = Vec::new();
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
let imports = quote!(use #pyo3_path::{PyNativeType, types::PyModuleMethods};);
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
let imports = quote!(use #pyo3_path::types::PyModuleMethods;);
|
||||
|
||||
for mut stmt in func.block.stmts.drain(..) {
|
||||
if let syn::Stmt::Item(Item::Fn(func)) = &mut stmt {
|
||||
if let Some(pyfn_args) = get_pyfn_attr(&mut func.attrs)? {
|
||||
|
@ -394,7 +399,7 @@ fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn
|
|||
#wrapped_function
|
||||
{
|
||||
#[allow(unknown_lints, unused_imports, redundant_imports)]
|
||||
use #pyo3_path::{PyNativeType, types::PyModuleMethods};
|
||||
#imports
|
||||
#module_name.as_borrowed().add_function(#pyo3_path::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1307,11 +1307,19 @@ fn impl_pytypeinfo(
|
|||
quote! { ::core::option::Option::None }
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[cfg(feature = "gil-refs")]
|
||||
let has_py_gil_ref = quote! {
|
||||
#[allow(deprecated)]
|
||||
unsafe impl #pyo3_path::type_object::HasPyGilRef for #cls {
|
||||
type AsRefTarget = #pyo3_path::PyCell<Self>;
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
let has_py_gil_ref = TokenStream::new();
|
||||
|
||||
quote! {
|
||||
#has_py_gil_ref
|
||||
|
||||
unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls {
|
||||
const NAME: &'static str = #cls_name;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pyo3-macros"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
description = "Proc macros for PyO3 package"
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
|
||||
keywords = ["pyo3", "python", "cpython", "ffi"]
|
||||
|
@ -17,12 +17,13 @@ proc-macro = true
|
|||
multiple-pymethods = []
|
||||
experimental-async = ["pyo3-macros-backend/experimental-async"]
|
||||
experimental-declarative-modules = []
|
||||
gil-refs = ["pyo3-macros-backend/gil-refs"]
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { version = "1", default-features = false }
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full", "extra-traits"] }
|
||||
pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.21.2" }
|
||||
pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.22.0-dev" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[tool.towncrier]
|
||||
filename = "CHANGELOG.md"
|
||||
version = "0.21.2"
|
||||
version = "0.22.0-dev"
|
||||
start_string = "<!-- towncrier release notes start -->\n"
|
||||
template = ".towncrier.template.md"
|
||||
title_format = "## [{version}] - {project_date}"
|
||||
|
|
|
@ -5,14 +5,12 @@ use crate::inspect::types::TypeInfo;
|
|||
use crate::pyclass::boolean_struct::False;
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::types::PyTuple;
|
||||
use crate::{
|
||||
ffi, Borrowed, Bound, Py, PyAny, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
||||
};
|
||||
use crate::{ffi, Borrowed, Bound, Py, PyAny, PyClass, PyObject, PyRef, PyRefMut, Python};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use {
|
||||
crate::{
|
||||
err::{self, PyDowncastError},
|
||||
gil,
|
||||
gil, PyNativeType,
|
||||
},
|
||||
std::ptr::NonNull,
|
||||
};
|
||||
|
@ -221,6 +219,7 @@ pub trait FromPyObject<'py>: Sized {
|
|||
///
|
||||
/// Implementors are encouraged to implement `extract_bound` and leave this method as the
|
||||
/// default implementation, which will forward calls to `extract_bound`.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
fn extract(ob: &'py PyAny) -> PyResult<Self> {
|
||||
Self::extract_bound(&ob.as_borrowed())
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ use crate::panic::PanicException;
|
|||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::types::{string::PyStringMethods, typeobject::PyTypeMethods, PyTraceback, PyType};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use crate::PyNativeType;
|
||||
use crate::{
|
||||
exceptions::{self, PyBaseException},
|
||||
ffi,
|
||||
};
|
||||
use crate::{Borrowed, IntoPy, Py, PyAny, PyNativeType, PyObject, Python, ToPyObject};
|
||||
use crate::{Borrowed, IntoPy, Py, PyAny, PyObject, Python, ToPyObject};
|
||||
use std::borrow::Cow;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::ffi::CString;
|
||||
|
@ -47,11 +49,13 @@ pub type PyResult<T> = Result<T, PyErr>;
|
|||
|
||||
/// Error that indicates a failure to convert a PyAny to a more specific Python type.
|
||||
#[derive(Debug)]
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub struct PyDowncastError<'a> {
|
||||
from: &'a PyAny,
|
||||
to: Cow<'static, str>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<'a> PyDowncastError<'a> {
|
||||
/// Create a new `PyDowncastError` representing a failure to convert the object
|
||||
/// `from` into the type named in `to`.
|
||||
|
@ -64,7 +68,6 @@ impl<'a> PyDowncastError<'a> {
|
|||
|
||||
/// Compatibility API to convert the Bound variant `DowncastError` into the
|
||||
/// gil-ref variant
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self {
|
||||
#[allow(deprecated)]
|
||||
let from = unsafe { from.py().from_borrowed_ptr(from.as_ptr()) };
|
||||
|
@ -1012,8 +1015,10 @@ impl<'a> std::convert::From<PyDowncastError<'a>> for PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<'a> std::error::Error for PyDowncastError<'a> {}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<'a> std::fmt::Display for PyDowncastError<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
display_downcast_error(f, &self.from.as_borrowed(), &self.to)
|
||||
|
|
|
@ -146,6 +146,7 @@ macro_rules! import_exception_bound {
|
|||
|
||||
// FIXME remove this: was necessary while `PyTypeInfo` requires `HasPyGilRef`,
|
||||
// should change in 0.22.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
unsafe impl $crate::type_object::HasPyGilRef for $name {
|
||||
type AsRefTarget = $crate::PyAny;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ pub struct NotAGilRef<T>(std::marker::PhantomData<T>);
|
|||
|
||||
pub trait IsGilRef {}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<T: crate::PyNativeType> IsGilRef for &'_ T {}
|
||||
|
||||
impl<T> GilRefs<T> {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#[cfg(feature = "gil-refs")]
|
||||
use crate::PyNativeType;
|
||||
use crate::{
|
||||
exceptions::{PyAttributeError, PyNotImplementedError, PyRuntimeError, PyValueError},
|
||||
ffi,
|
||||
|
@ -7,8 +9,7 @@ use crate::{
|
|||
pyclass_init::PyObjectInit,
|
||||
types::any::PyAnyMethods,
|
||||
types::PyBool,
|
||||
Borrowed, Py, PyAny, PyClass, PyErr, PyMethodDefType, PyNativeType, PyResult, PyTypeInfo,
|
||||
Python,
|
||||
Borrowed, Py, PyAny, PyClass, PyErr, PyMethodDefType, PyResult, PyTypeInfo, Python,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
@ -168,7 +169,12 @@ pub trait PyClassImpl: Sized + 'static {
|
|||
|
||||
/// The closest native ancestor. This is `PyAny` by default, and when you declare
|
||||
/// `#[pyclass(extends=PyDict)]`, it's `PyDict`.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
type BaseNativeType: PyTypeInfo + PyNativeType;
|
||||
/// The closest native ancestor. This is `PyAny` by default, and when you declare
|
||||
/// `#[pyclass(extends=PyDict)]`, it's `PyDict`.
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
type BaseNativeType: PyTypeInfo;
|
||||
|
||||
/// This handles following two situations:
|
||||
/// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing.
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::err::{self, PyErr, PyResult};
|
|||
use crate::impl_::pycell::PyClassObject;
|
||||
use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
||||
use crate::pyclass::boolean_struct::{False, True};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use crate::type_object::HasPyGilRef;
|
||||
use crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods};
|
||||
use crate::types::{DerefToPyAny, PyDict, PyString, PyTuple};
|
||||
|
@ -24,6 +25,7 @@ use std::ptr::NonNull;
|
|||
/// # Safety
|
||||
///
|
||||
/// This trait must only be implemented for types which cannot be accessed without the GIL.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub unsafe trait PyNativeType: Sized {
|
||||
/// The form of this which is stored inside a `Py<T>` smart pointer.
|
||||
type AsRefSource: HasPyGilRef<AsRefTarget = Self>;
|
||||
|
@ -666,11 +668,11 @@ impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<'py, T> Borrowed<'py, 'py, T>
|
||||
where
|
||||
T: HasPyGilRef,
|
||||
{
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub(crate) fn into_gil_ref(self) -> &'py T::AsRefTarget {
|
||||
// Safety: self is a borrow over `'py`.
|
||||
#[allow(deprecated)]
|
||||
|
@ -953,6 +955,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<T> Py<T>
|
||||
where
|
||||
T: HasPyGilRef,
|
||||
|
@ -1000,7 +1003,6 @@ where
|
|||
/// assert!(my_class_cell.try_borrow().is_ok());
|
||||
/// });
|
||||
/// ```
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "use `obj.bind(py)` instead of `obj.as_ref(py)`"
|
||||
|
@ -1053,7 +1055,6 @@ where
|
|||
/// obj.into_ref(py)
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "use `obj.into_bound(py)` instead of `obj.into_ref(py)`"
|
||||
|
@ -1118,8 +1119,7 @@ where
|
|||
///
|
||||
/// For frozen classes, the simpler [`get`][Self::get] is available.
|
||||
///
|
||||
/// Equivalent to `self.as_ref(py).borrow()` -
|
||||
/// see [`PyCell::borrow`](crate::pycell::PyCell::borrow).
|
||||
/// Equivalent to `self.bind(py).borrow()` - see [`Bound::borrow`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1157,8 +1157,7 @@ where
|
|||
///
|
||||
/// This borrow lasts while the returned [`PyRefMut`] exists.
|
||||
///
|
||||
/// Equivalent to `self.as_ref(py).borrow_mut()` -
|
||||
/// see [`PyCell::borrow_mut`](crate::pycell::PyCell::borrow_mut).
|
||||
/// Equivalent to `self.bind(py).borrow_mut()` - see [`Bound::borrow_mut`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1202,8 +1201,7 @@ where
|
|||
///
|
||||
/// For frozen classes, the simpler [`get`][Self::get] is available.
|
||||
///
|
||||
/// Equivalent to `self.as_ref(py).borrow_mut()` -
|
||||
/// see [`PyCell::try_borrow`](crate::pycell::PyCell::try_borrow).
|
||||
/// Equivalent to `self.bind(py).try_borrow()` - see [`Bound::try_borrow`].
|
||||
#[inline]
|
||||
pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result<PyRef<'py, T>, PyBorrowError> {
|
||||
self.bind(py).try_borrow()
|
||||
|
@ -1215,8 +1213,7 @@ where
|
|||
///
|
||||
/// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
|
||||
///
|
||||
/// Equivalent to `self.as_ref(py).try_borrow_mut()` -
|
||||
/// see [`PyCell::try_borrow_mut`](crate::pycell::PyCell::try_borrow_mut).
|
||||
/// Equivalent to `self.bind(py).try_borrow_mut()` - see [`Bound::try_borrow_mut`].
|
||||
#[inline]
|
||||
pub fn try_borrow_mut<'py>(
|
||||
&'py self,
|
||||
|
@ -1742,6 +1739,7 @@ unsafe impl<T> crate::AsPyPointer for Py<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<T> std::convert::From<&'_ T> for PyObject
|
||||
where
|
||||
T: PyNativeType,
|
||||
|
@ -1866,6 +1864,7 @@ where
|
|||
///
|
||||
/// However for GIL lifetime reasons, cause() cannot be implemented for `Py<T>`.
|
||||
/// Use .as_ref() to get the GIL-scoped error if you need to inspect the cause.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<T> std::error::Error for Py<T>
|
||||
where
|
||||
T: std::error::Error + PyTypeInfo,
|
||||
|
@ -1876,7 +1875,6 @@ where
|
|||
impl<T> std::fmt::Display for Py<T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T::AsRefTarget: std::fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Python::with_gil(|py| std::fmt::Display::fmt(self.bind(py), f))
|
||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -320,15 +320,18 @@ pub use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, ToPyObject};
|
|||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::conversion::{FromPyPointer, PyTryFrom, PyTryInto};
|
||||
pub use crate::err::{
|
||||
DowncastError, DowncastIntoError, PyDowncastError, PyErr, PyErrArguments, PyResult, ToPyErr,
|
||||
};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub use crate::err::PyDowncastError;
|
||||
pub use crate::err::{DowncastError, DowncastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr};
|
||||
#[allow(deprecated)]
|
||||
pub use crate::gil::GILPool;
|
||||
#[cfg(not(any(PyPy, GraalPy)))]
|
||||
pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter};
|
||||
pub use crate::instance::{Borrowed, Bound, Py, PyNativeType, PyObject};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub use crate::instance::PyNativeType;
|
||||
pub use crate::instance::{Borrowed, Bound, Py, PyObject};
|
||||
pub use crate::marker::Python;
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::pycell::PyCell;
|
||||
pub use crate::pycell::{PyRef, PyRefMut};
|
||||
|
@ -443,6 +446,7 @@ mod conversions;
|
|||
pub mod coroutine;
|
||||
#[macro_use]
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub mod derive_utils;
|
||||
mod err;
|
||||
pub mod exceptions;
|
||||
|
|
|
@ -105,6 +105,7 @@ macro_rules! py_run_impl {
|
|||
($py:expr, *$dict:expr, $code:expr) => {{
|
||||
use ::std::option::Option::*;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use $crate::PyNativeType;
|
||||
if let ::std::result::Result::Err(e) = $py.run_bound($code, None, Some(&$dict.as_borrowed())) {
|
||||
e.print($py);
|
||||
|
|
|
@ -15,11 +15,13 @@ pub use crate::conversion::{PyTryFrom, PyTryInto};
|
|||
pub use crate::err::{PyErr, PyResult};
|
||||
pub use crate::instance::{Borrowed, Bound, Py, PyObject};
|
||||
pub use crate::marker::Python;
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::pycell::PyCell;
|
||||
pub use crate::pycell::{PyRef, PyRefMut};
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::types::{PyAny, PyModule};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub use crate::PyNativeType;
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
//! - However, methods and functions in Rust usually *do* need `&mut` references. While PyO3 can
|
||||
//! use the [`Python<'py>`](crate::Python) token to guarantee thread-safe access to them, it cannot
|
||||
//! statically guarantee uniqueness of `&mut` references. As such those references have to be tracked
|
||||
//! dynamically at runtime, using [`PyCell`] and the other types defined in this module. This works
|
||||
//! dynamically at runtime, using `PyCell` and the other types defined in this module. This works
|
||||
//! similar to std's [`RefCell`](std::cell::RefCell) type.
|
||||
//!
|
||||
//! # When *not* to use PyCell
|
||||
//!
|
||||
//! Usually you can use `&mut` references as method and function receivers and arguments, and you
|
||||
//! won't need to use [`PyCell`] directly:
|
||||
//! won't need to use `PyCell` directly:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use pyo3::prelude::*;
|
||||
|
@ -39,7 +39,7 @@
|
|||
//! ```
|
||||
//!
|
||||
//! The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper function (and more),
|
||||
//! using [`PyCell`] under the hood:
|
||||
//! using `PyCell` under the hood:
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! # use pyo3::prelude::*;
|
||||
|
@ -76,7 +76,7 @@
|
|||
//! # When to use PyCell
|
||||
//! ## Using pyclasses from Rust
|
||||
//!
|
||||
//! However, we *do* need [`PyCell`] if we want to call its methods from Rust:
|
||||
//! However, we *do* need `PyCell` if we want to call its methods from Rust:
|
||||
//! ```rust
|
||||
//! # use pyo3::prelude::*;
|
||||
//! #
|
||||
|
@ -115,7 +115,7 @@
|
|||
//! ```
|
||||
//! ## Dealing with possibly overlapping mutable references
|
||||
//!
|
||||
//! It is also necessary to use [`PyCell`] if you can receive mutable arguments that may overlap.
|
||||
//! It is also necessary to use `PyCell` if you can receive mutable arguments that may overlap.
|
||||
//! Suppose the following function that swaps the values of two `Number`s:
|
||||
//! ```
|
||||
//! # use pyo3::prelude::*;
|
||||
|
@ -193,28 +193,30 @@
|
|||
//! [guide]: https://pyo3.rs/latest/class.html#pycell-and-interior-mutability "PyCell and interior mutability"
|
||||
//! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html "RefCell<T> and the Interior Mutability Pattern - The Rust Programming Language"
|
||||
|
||||
use crate::conversion::{AsPyPointer, ToPyObject};
|
||||
use crate::conversion::AsPyPointer;
|
||||
use crate::exceptions::PyRuntimeError;
|
||||
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||
use crate::impl_::pyclass::PyClassImpl;
|
||||
use crate::pyclass::{
|
||||
boolean_struct::{False, True},
|
||||
PyClass,
|
||||
};
|
||||
use crate::type_object::{PyLayout, PySizedLayout};
|
||||
use crate::pyclass::{boolean_struct::False, PyClass};
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, Bound, IntoPy, PyErr, PyNativeType, PyObject, PyTypeCheck, Python};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use crate::{pyclass_init::PyClassInitializer, PyResult};
|
||||
use crate::{
|
||||
conversion::ToPyObject,
|
||||
impl_::pyclass::PyClassImpl,
|
||||
pyclass::boolean_struct::True,
|
||||
pyclass_init::PyClassInitializer,
|
||||
type_object::{PyLayout, PySizedLayout},
|
||||
types::PyAny,
|
||||
PyNativeType, PyResult, PyTypeCheck,
|
||||
};
|
||||
use crate::{ffi, Bound, IntoPy, PyErr, PyObject, Python};
|
||||
use std::fmt;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
pub(crate) mod impl_;
|
||||
use impl_::PyClassBorrowChecker;
|
||||
|
||||
use self::impl_::{PyClassObject, PyClassObjectLayout};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use self::impl_::PyClassObject;
|
||||
use impl_::{PyClassBorrowChecker, PyClassObjectLayout};
|
||||
|
||||
/// A container type for (mutably) accessing [`PyClass`] values
|
||||
///
|
||||
|
@ -223,7 +225,7 @@ use self::impl_::{PyClassObject, PyClassObjectLayout};
|
|||
/// # Examples
|
||||
///
|
||||
/// This example demonstrates getting a mutable reference of the contained `PyClass`.
|
||||
/// ```rust,ignore
|
||||
/// ```rust
|
||||
/// use pyo3::prelude::*;
|
||||
///
|
||||
/// #[pyclass]
|
||||
|
@ -252,28 +254,27 @@ use self::impl_::{PyClassObject, PyClassObjectLayout};
|
|||
/// ```
|
||||
/// For more information on how, when and why (not) to use `PyCell` please see the
|
||||
/// [module-level documentation](self).
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyCell` was merged into `Bound`, use that instead; see the migration guide for more info"
|
||||
)
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyCell` was merged into `Bound`, use that instead; see the migration guide for more info"
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyCell<T: PyClassImpl>(PyClassObject<T>);
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClass> PyNativeType for PyCell<T> {
|
||||
type AsRefSource = T;
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> PyCell<T> {
|
||||
/// Makes a new `PyCell` on the Python heap and return the reference to it.
|
||||
///
|
||||
/// In cases where the value in the cell does not need to be accessed immediately after
|
||||
/// creation, consider [`Py::new`](crate::Py::new) as a more efficient alternative.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "use `Bound::new(py, value)` or `Py::new(py, value)` instead of `PyCell::new(py, value)`"
|
||||
|
@ -316,7 +317,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// #[pyclass]
|
||||
/// struct Class {}
|
||||
|
@ -346,7 +347,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// #[pyclass]
|
||||
/// struct Class {}
|
||||
|
@ -379,7 +380,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// #[pyclass]
|
||||
/// struct Class {}
|
||||
|
@ -416,7 +417,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// ```
|
||||
/// use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
/// # use pyo3::prelude::*;
|
||||
///
|
||||
|
@ -487,11 +488,14 @@ impl<T: PyClass> PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClassImpl> PyLayout<T> for PyCell<T> {}
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> PySizedLayout<T> for PyCell<T> {}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<T> PyTypeCheck for PyCell<T>
|
||||
where
|
||||
|
@ -503,7 +507,7 @@ where
|
|||
<T as PyTypeCheck>::type_check(object)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClass> AsPyPointer for PyCell<T> {
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
|
@ -511,6 +515,7 @@ unsafe impl<T: PyClass> AsPyPointer for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> ToPyObject for &PyCell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
|
@ -542,6 +547,7 @@ impl<T: PyClass> Deref for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -768,6 +774,7 @@ impl<T: PyClass> IntoPy<PyObject> for &'_ PyRef<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: PyClass> std::convert::TryFrom<&'a PyCell<T>> for crate::PyRef<'a, T> {
|
||||
type Error = PyBorrowError;
|
||||
|
@ -788,7 +795,7 @@ impl<T: PyClass + fmt::Debug> fmt::Debug for PyRef<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A wrapper type for a mutably borrowed value from a[`PyCell`]`<T>`.
|
||||
/// A wrapper type for a mutably borrowed value from a [`Bound<'py, T>`].
|
||||
///
|
||||
/// See the [module-level documentation](self) for more information.
|
||||
pub struct PyRefMut<'p, T: PyClass<Frozen = False>> {
|
||||
|
@ -928,6 +935,7 @@ unsafe impl<'a, T: PyClass<Frozen = False>> AsPyPointer for PyRefMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: PyClass<Frozen = False>> std::convert::TryFrom<&'a PyCell<T>>
|
||||
for crate::PyRefMut<'a, T>
|
||||
|
@ -944,7 +952,7 @@ impl<T: PyClass<Frozen = False> + fmt::Debug> fmt::Debug for PyRefMut<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error type returned by [`PyCell::try_borrow`].
|
||||
/// An error type returned by [`Bound::try_borrow`].
|
||||
///
|
||||
/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.
|
||||
pub struct PyBorrowError {
|
||||
|
@ -969,7 +977,7 @@ impl From<PyBorrowError> for PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error type returned by [`PyCell::try_borrow_mut`].
|
||||
/// An error type returned by [`Bound::try_borrow_mut`].
|
||||
///
|
||||
/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.
|
||||
pub struct PyBorrowMutError {
|
||||
|
|
|
@ -74,6 +74,7 @@ pub trait PyClassBorrowChecker {
|
|||
/// Increments immutable borrow count, if possible
|
||||
fn try_borrow(&self) -> Result<(), PyBorrowError>;
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError>;
|
||||
|
||||
/// Decrements immutable borrow count
|
||||
|
@ -96,6 +97,7 @@ impl PyClassBorrowChecker for EmptySlot {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "gil-refs")]
|
||||
fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -130,6 +132,7 @@ impl PyClassBorrowChecker for BorrowChecker {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError> {
|
||||
let flag = self.0.get();
|
||||
if flag != BorrowFlag::HAS_MUTABLE_BORROW {
|
||||
|
|
|
@ -16,6 +16,7 @@ pub use self::gc::{PyTraverseError, PyVisit};
|
|||
/// The `#[pyclass]` attribute implements this trait for your Rust struct -
|
||||
/// you shouldn't implement this trait directly.
|
||||
#[allow(deprecated)]
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub trait PyClass: PyTypeInfo<AsRefTarget = crate::PyCell<Self>> + PyClassImpl {
|
||||
/// Whether the pyclass is frozen.
|
||||
///
|
||||
|
@ -23,6 +24,18 @@ pub trait PyClass: PyTypeInfo<AsRefTarget = crate::PyCell<Self>> + PyClassImpl {
|
|||
type Frozen: Frozen;
|
||||
}
|
||||
|
||||
/// Types that can be used as Python classes.
|
||||
///
|
||||
/// The `#[pyclass]` attribute implements this trait for your Rust struct -
|
||||
/// you shouldn't implement this trait directly.
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
pub trait PyClass: PyTypeInfo + PyClassImpl {
|
||||
/// Whether the pyclass is frozen.
|
||||
///
|
||||
/// This can be enabled via `#[pyclass(frozen)]`.
|
||||
type Frozen: Frozen;
|
||||
}
|
||||
|
||||
/// Operators for the `__richcmp__` method
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum CompareOp {
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::types::{PyAny, PyType};
|
||||
use crate::{ffi, Bound, PyNativeType, Python};
|
||||
#[cfg(feature = "gil-refs")]
|
||||
use crate::PyNativeType;
|
||||
use crate::{ffi, Bound, Python};
|
||||
|
||||
/// `T: PyLayout<U>` represents that `T` is a concrete representation of `U` in the Python heap.
|
||||
/// E.g., `PyClassObject` is a concrete representation of all `pyclass`es, and `ffi::PyObject`
|
||||
|
@ -29,11 +31,13 @@ pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
|
|||
///
|
||||
/// - `Py<Self>::as_ref` will hand out references to `Self::AsRefTarget`.
|
||||
/// - `Self::AsRefTarget` must have the same layout as `UnsafeCell<ffi::PyAny>`.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub unsafe trait HasPyGilRef {
|
||||
/// Utility type to make Py::as_ref work.
|
||||
type AsRefTarget: PyNativeType;
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
unsafe impl<T> HasPyGilRef for T
|
||||
where
|
||||
T: PyNativeType,
|
||||
|
@ -54,6 +58,7 @@ where
|
|||
///
|
||||
/// Implementations must provide an implementation for `type_object_raw` which infallibly produces a
|
||||
/// non-null pointer to the corresponding Python type object.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub unsafe trait PyTypeInfo: Sized + HasPyGilRef {
|
||||
/// Class name.
|
||||
const NAME: &'static str;
|
||||
|
@ -132,7 +137,62 @@ pub unsafe trait PyTypeInfo: Sized + HasPyGilRef {
|
|||
}
|
||||
}
|
||||
|
||||
/// Python type information.
|
||||
/// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait.
|
||||
///
|
||||
/// This trait is marked unsafe because:
|
||||
/// - specifying the incorrect layout can lead to memory errors
|
||||
/// - the return value of type_object must always point to the same PyTypeObject instance
|
||||
///
|
||||
/// It is safely implemented by the `pyclass` macro.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Implementations must provide an implementation for `type_object_raw` which infallibly produces a
|
||||
/// non-null pointer to the corresponding Python type object.
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
pub unsafe trait PyTypeInfo: Sized {
|
||||
/// Class name.
|
||||
const NAME: &'static str;
|
||||
|
||||
/// Module name, if any.
|
||||
const MODULE: Option<&'static str>;
|
||||
|
||||
/// Returns the PyTypeObject instance for this type.
|
||||
fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;
|
||||
|
||||
/// Returns the safe abstraction over the type object.
|
||||
#[inline]
|
||||
fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType> {
|
||||
// Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme
|
||||
// edge case, but arbitrary Python code _could_ change the __class__ of an object and cause
|
||||
// the type object to be freed.
|
||||
//
|
||||
// By making `Bound` we assume ownership which is then safe against races.
|
||||
unsafe {
|
||||
Self::type_object_raw(py)
|
||||
.cast::<ffi::PyObject>()
|
||||
.assume_borrowed_unchecked(py)
|
||||
.to_owned()
|
||||
.downcast_into_unchecked()
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `object` is an instance of this type or a subclass of this type.
|
||||
#[inline]
|
||||
fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
|
||||
unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }
|
||||
}
|
||||
|
||||
/// Checks if `object` is an instance of this type.
|
||||
#[inline]
|
||||
fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
|
||||
unsafe { ffi::Py_TYPE(object.as_ptr()) == Self::type_object_raw(object.py()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Implemented by types which can be used as a concrete Python type inside `Py<T>` smart pointers.
|
||||
#[cfg(feature = "gil-refs")]
|
||||
pub trait PyTypeCheck: HasPyGilRef {
|
||||
/// Name of self. This is used in error messages, for example.
|
||||
const NAME: &'static str;
|
||||
|
@ -143,6 +203,18 @@ pub trait PyTypeCheck: HasPyGilRef {
|
|||
fn type_check(object: &Bound<'_, PyAny>) -> bool;
|
||||
}
|
||||
|
||||
/// Implemented by types which can be used as a concrete Python type inside `Py<T>` smart pointers.
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
pub trait PyTypeCheck {
|
||||
/// Name of self. This is used in error messages, for example.
|
||||
const NAME: &'static str;
|
||||
|
||||
/// Checks if `object` is an instance of `Self`, which may include a subtype.
|
||||
///
|
||||
/// This should be equivalent to the Python expression `isinstance(object, Self)`.
|
||||
fn type_check(object: &Bound<'_, PyAny>) -> bool;
|
||||
}
|
||||
|
||||
impl<T> PyTypeCheck for T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
|
|
|
@ -1646,7 +1646,7 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
|
|||
/// Extracts some type from the Python object.
|
||||
///
|
||||
/// This is a wrapper function around
|
||||
/// [`FromPyObject::extract()`](crate::FromPyObject::extract).
|
||||
/// [`FromPyObject::extract_bound()`](crate::FromPyObject::extract_bound).
|
||||
fn extract<'a, T>(&'a self) -> PyResult<T>
|
||||
where
|
||||
T: FromPyObjectBound<'a, 'py>;
|
||||
|
|
|
@ -122,10 +122,12 @@ pub trait DerefToPyAny {
|
|||
#[macro_export]
|
||||
macro_rules! pyobject_native_type_base(
|
||||
($name:ty $(;$generics:ident)* ) => {
|
||||
#[cfg(feature = "gil-refs")]
|
||||
unsafe impl<$($generics,)*> $crate::PyNativeType for $name {
|
||||
type AsRefSource = Self;
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<$($generics,)*> ::std::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>)
|
||||
-> ::std::result::Result<(), ::std::fmt::Error>
|
||||
|
@ -136,6 +138,7 @@ macro_rules! pyobject_native_type_base(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gil-refs")]
|
||||
impl<$($generics,)*> ::std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>)
|
||||
-> ::std::result::Result<(), ::std::fmt::Error>
|
||||
|
|
|
@ -14,7 +14,7 @@ fn test_compile_errors() {
|
|||
#[cfg(any(not(Py_LIMITED_API), Py_3_11))]
|
||||
t.compile_fail("tests/ui/invalid_pymethods_buffer.rs");
|
||||
// The output is not stable across abi3 / not abi3 and features
|
||||
#[cfg(all(not(Py_LIMITED_API), feature = "full"))]
|
||||
#[cfg(all(not(Py_LIMITED_API), feature = "full", not(feature = "gil-refs")))]
|
||||
t.compile_fail("tests/ui/invalid_pymethods_duplicates.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_enum.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_names.rs");
|
||||
|
@ -27,12 +27,14 @@ fn test_compile_errors() {
|
|||
t.compile_fail("tests/ui/invalid_argument_attributes.rs");
|
||||
t.compile_fail("tests/ui/invalid_frompy_derive.rs");
|
||||
t.compile_fail("tests/ui/static_ref.rs");
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
t.compile_fail("tests/ui/wrong_aspyref_lifetimes.rs");
|
||||
t.compile_fail("tests/ui/invalid_pyfunctions.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethods.rs");
|
||||
// output changes with async feature
|
||||
#[cfg(all(Py_LIMITED_API, feature = "experimental-async"))]
|
||||
t.compile_fail("tests/ui/abi3_nativetype_inheritance.rs");
|
||||
#[cfg(not(feature = "gil-refs"))]
|
||||
t.compile_fail("tests/ui/invalid_intern_arg.rs");
|
||||
t.compile_fail("tests/ui/invalid_frozen_pyclass_borrow.rs");
|
||||
t.compile_fail("tests/ui/invalid_pymethod_receiver.rs");
|
||||
|
|
|
@ -34,6 +34,12 @@ error: use of deprecated constant `__pyfunction_pyfunction_option_4::SIGNATURE`:
|
|||
138 | fn pyfunction_option_4(
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of deprecated struct `pyo3::PyCell`: `PyCell` was merged into `Bound`, use that instead; see the migration guide for more info
|
||||
--> tests/ui/deprecations.rs:23:30
|
||||
|
|
||||
23 | fn method_gil_ref(_slf: &PyCell<Self>) {}
|
||||
| ^^^^^^
|
||||
|
||||
error: use of deprecated method `pyo3::deprecations::GilRefs::<T>::from_py_with_arg`: use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor
|
||||
--> tests/ui/deprecations.rs:45:44
|
||||
|
|
||||
|
|
|
@ -13,5 +13,5 @@ error: lifetime may not live long enough
|
|||
5 | Python::with_gil(|py| py.import_bound(pyo3::intern!(py, _foo)).unwrap());
|
||||
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||
| | |
|
||||
| | return type of closure is pyo3::Bound<'2, pyo3::prelude::PyModule>
|
||||
| has type `pyo3::Python<'1>`
|
||||
| | return type of closure is pyo3::Bound<'2, PyModule>
|
||||
| has type `Python<'1>`
|
||||
|
|
|
@ -26,23 +26,6 @@ error[E0277]: the trait bound `TwoNew: PyTypeInfo` is not satisfied
|
|||
PyDate
|
||||
and $N others
|
||||
|
||||
error[E0277]: the trait bound `TwoNew: HasPyGilRef` is not satisfied
|
||||
--> tests/ui/invalid_pymethods_duplicates.rs:9:6
|
||||
|
|
||||
9 | impl TwoNew {
|
||||
| ^^^^^^ the trait `PyNativeType` is not implemented for `TwoNew`, which is required by `TwoNew: HasPyGilRef`
|
||||
|
|
||||
= help: the trait `HasPyGilRef` is implemented for `pyo3::coroutine::Coroutine`
|
||||
= note: required for `TwoNew` to implement `HasPyGilRef`
|
||||
note: required by a bound in `pyo3::PyTypeInfo::NAME`
|
||||
--> src/type_object.rs
|
||||
|
|
||||
| pub unsafe trait PyTypeInfo: Sized + HasPyGilRef {
|
||||
| ^^^^^^^^^^^ required by this bound in `PyTypeInfo::NAME`
|
||||
| /// Class name.
|
||||
| const NAME: &'static str;
|
||||
| ---- required by a bound in this associated constant
|
||||
|
||||
error[E0592]: duplicate definitions with name `__pymethod___new____`
|
||||
--> tests/ui/invalid_pymethods_duplicates.rs:8:1
|
||||
|
|
||||
|
|
|
@ -5,4 +5,4 @@ error: lifetime may not live long enough
|
|||
| --- ^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||
| | |
|
||||
| | return type of closure is &'2 pyo3::Bound<'_, PyDict>
|
||||
| has type `pyo3::Python<'1>`
|
||||
| has type `Python<'1>`
|
||||
|
|
Loading…
Reference in New Issue