Merge pull request #1292 from davidhewitt/python-deprecations
python: deprecate some redundant methods
This commit is contained in:
commit
6465766ebc
|
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
- Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275)
|
- Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275)
|
||||||
- Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275)
|
- Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275)
|
||||||
- Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278)
|
- Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278)
|
||||||
|
- Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217)
|
- Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217)
|
||||||
|
|
189
src/python.rs
189
src/python.rs
|
@ -72,21 +72,6 @@ impl Python<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Python<'p> {
|
impl<'p> Python<'p> {
|
||||||
/// Retrieves a Python instance under the assumption that the GIL is already
|
|
||||||
/// acquired at this point, and stays acquired for the lifetime `'p`.
|
|
||||||
///
|
|
||||||
/// Because the output lifetime `'p` is not connected to any input parameter,
|
|
||||||
/// care must be taken that the compiler infers an appropriate lifetime for `'p`
|
|
||||||
/// when calling this function.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// The lifetime `'p` must be shorter than the period you *assume* that you have GIL.
|
|
||||||
/// I.e., `Python<'static>` is always *really* unsafe.
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn assume_gil_acquired() -> Python<'p> {
|
|
||||||
Python(PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Acquires the global interpreter lock, which allows access to the Python runtime.
|
/// Acquires the global interpreter lock, which allows access to the Python runtime.
|
||||||
///
|
///
|
||||||
/// If the Python runtime is not already initialized, this function will initialize it.
|
/// If the Python runtime is not already initialized, this function will initialize it.
|
||||||
|
@ -303,24 +288,6 @@ impl<'p> Python<'p> {
|
||||||
PyModule::import(self, name)
|
PyModule::import(self, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether `obj` is an instance of type `T`.
|
|
||||||
///
|
|
||||||
/// This is equivalent to the Python `isinstance` function.
|
|
||||||
pub fn is_instance<T: PyTypeObject, V: AsPyPointer>(self, obj: &V) -> PyResult<bool> {
|
|
||||||
T::type_object(self).is_instance(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether type `T` is subclass of type `U`.
|
|
||||||
///
|
|
||||||
/// This is equivalent to the Python `issubclass` function.
|
|
||||||
pub fn is_subclass<T, U>(self) -> PyResult<bool>
|
|
||||||
where
|
|
||||||
T: PyTypeObject,
|
|
||||||
U: PyTypeObject,
|
|
||||||
{
|
|
||||||
T::type_object(self).is_subclass::<U>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the Python builtin value `None`.
|
/// Gets the Python builtin value `None`.
|
||||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -335,64 +302,6 @@ impl<'p> Python<'p> {
|
||||||
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_NotImplemented()) }
|
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_NotImplemented()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new pool for managing PyO3's owned references.
|
|
||||||
///
|
|
||||||
/// When this `GILPool` is dropped, all PyO3 owned references created after this `GILPool` will
|
|
||||||
/// all have their Python reference counts decremented, potentially allowing Python to drop
|
|
||||||
/// the corresponding Python objects.
|
|
||||||
///
|
|
||||||
/// Typical usage of PyO3 will not need this API, as `Python::acquire_gil` automatically
|
|
||||||
/// creates a `GILPool` where appropriate.
|
|
||||||
///
|
|
||||||
/// Advanced uses of PyO3 which perform long-running tasks which never free the GIL may need
|
|
||||||
/// to use this API to clear memory, as PyO3 usually does not clear memory until the GIL is
|
|
||||||
/// released.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```rust
|
|
||||||
/// # use pyo3::prelude::*;
|
|
||||||
/// let gil = Python::acquire_gil();
|
|
||||||
/// let py = gil.python();
|
|
||||||
///
|
|
||||||
/// // Some long-running process like a webserver, which never releases the GIL.
|
|
||||||
/// loop {
|
|
||||||
/// // Create a new pool, so that PyO3 can clear memory at the end of the loop.
|
|
||||||
/// let pool = unsafe { py.new_pool() };
|
|
||||||
///
|
|
||||||
/// // It is recommended to *always* immediately set py to the pool's Python, to help
|
|
||||||
/// // avoid creating references with invalid lifetimes.
|
|
||||||
/// let py = unsafe { pool.python() };
|
|
||||||
///
|
|
||||||
/// // do stuff...
|
|
||||||
/// # break; // Exit the loop so that doctest terminates!
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// Extreme care must be taken when using this API, as misuse can lead to accessing invalid
|
|
||||||
/// memory. In addition, the caller is responsible for guaranteeing that the GIL remains held
|
|
||||||
/// for the entire lifetime of the returned `GILPool`.
|
|
||||||
///
|
|
||||||
/// Two best practices are required when using this API:
|
|
||||||
/// - From the moment `new_pool()` is called, only the `Python` token from the returned
|
|
||||||
/// `GILPool` (accessible using `.python()`) should be used in PyO3 APIs. All other older
|
|
||||||
/// `Python` tokens with longer lifetimes are unsafe to use until the `GILPool` is dropped,
|
|
||||||
/// because they can be used to create PyO3 owned references which have lifetimes which
|
|
||||||
/// outlive the `GILPool`.
|
|
||||||
/// - Similarly, methods on existing owned references will implicitly refer back to the
|
|
||||||
/// `Python` token which that reference was originally created with. If the returned values
|
|
||||||
/// from these methods are owned references they will inherit the same lifetime. As a result,
|
|
||||||
/// Rust's lifetime rules may allow them to outlive the `GILPool`, even though this is not
|
|
||||||
/// safe for reasons discussed above. Care must be taken to never access these return values
|
|
||||||
/// after the `GILPool` is dropped, unless they are converted to `Py<T>` *before* the pool
|
|
||||||
/// is dropped.
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn new_pool(self) -> GILPool {
|
|
||||||
GILPool::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'p> Python<'p> {
|
|
||||||
/// Registers the object in the release pool, and tries to downcast to specific type.
|
/// Registers the object in the release pool, and tries to downcast to specific type.
|
||||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError<'p>>
|
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError<'p>>
|
||||||
where
|
where
|
||||||
|
@ -479,8 +388,32 @@ impl<'p> Python<'p> {
|
||||||
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether `obj` is an instance of type `T`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python `isinstance` function.
|
||||||
|
#[deprecated(since = "0.13.0", note = "Please use obj.is_instance::<T>() instead")]
|
||||||
|
pub fn is_instance<T: PyTypeObject, V: AsPyPointer>(self, obj: &V) -> PyResult<bool> {
|
||||||
|
T::type_object(self).is_instance(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks whether type `T` is subclass of type `U`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python `issubclass` function.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.13.0",
|
||||||
|
note = "Please use T::type_object(py).is_subclass::<U>() instead"
|
||||||
|
)]
|
||||||
|
pub fn is_subclass<T, U>(self) -> PyResult<bool>
|
||||||
|
where
|
||||||
|
T: PyTypeObject,
|
||||||
|
U: PyTypeObject,
|
||||||
|
{
|
||||||
|
T::type_object(self).is_subclass::<U>()
|
||||||
|
}
|
||||||
|
|
||||||
/// Releases a PyObject reference.
|
/// Releases a PyObject reference.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[deprecated(since = "0.13.0", note = "Please just drop ob instead")]
|
||||||
pub fn release<T>(self, ob: T)
|
pub fn release<T>(self, ob: T)
|
||||||
where
|
where
|
||||||
T: IntoPyPointer,
|
T: IntoPyPointer,
|
||||||
|
@ -495,6 +428,7 @@ impl<'p> Python<'p> {
|
||||||
|
|
||||||
/// Releases a `ffi::PyObject` pointer.
|
/// Releases a `ffi::PyObject` pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[deprecated(since = "0.13.0", note = "Please just drop obj instead")]
|
||||||
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
|
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
|
||||||
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };
|
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };
|
||||||
}
|
}
|
||||||
|
@ -518,6 +452,77 @@ impl<'p> Python<'p> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves a Python instance under the assumption that the GIL is already
|
||||||
|
/// acquired at this point, and stays acquired for the lifetime `'p`.
|
||||||
|
///
|
||||||
|
/// Because the output lifetime `'p` is not connected to any input parameter,
|
||||||
|
/// care must be taken that the compiler infers an appropriate lifetime for `'p`
|
||||||
|
/// when calling this function.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// The lifetime `'p` must be shorter than the period you *assume* that you have GIL.
|
||||||
|
/// I.e., `Python<'static>` is always *really* unsafe.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn assume_gil_acquired() -> Python<'p> {
|
||||||
|
Python(PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new pool for managing PyO3's owned references.
|
||||||
|
///
|
||||||
|
/// When this `GILPool` is dropped, all PyO3 owned references created after this `GILPool` will
|
||||||
|
/// all have their Python reference counts decremented, potentially allowing Python to drop
|
||||||
|
/// the corresponding Python objects.
|
||||||
|
///
|
||||||
|
/// Typical usage of PyO3 will not need this API, as `Python::acquire_gil` automatically
|
||||||
|
/// creates a `GILPool` where appropriate.
|
||||||
|
///
|
||||||
|
/// Advanced uses of PyO3 which perform long-running tasks which never free the GIL may need
|
||||||
|
/// to use this API to clear memory, as PyO3 usually does not clear memory until the GIL is
|
||||||
|
/// released.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// # use pyo3::prelude::*;
|
||||||
|
/// let gil = Python::acquire_gil();
|
||||||
|
/// let py = gil.python();
|
||||||
|
///
|
||||||
|
/// // Some long-running process like a webserver, which never releases the GIL.
|
||||||
|
/// loop {
|
||||||
|
/// // Create a new pool, so that PyO3 can clear memory at the end of the loop.
|
||||||
|
/// let pool = unsafe { py.new_pool() };
|
||||||
|
///
|
||||||
|
/// // It is recommended to *always* immediately set py to the pool's Python, to help
|
||||||
|
/// // avoid creating references with invalid lifetimes.
|
||||||
|
/// let py = unsafe { pool.python() };
|
||||||
|
///
|
||||||
|
/// // do stuff...
|
||||||
|
/// # break; // Exit the loop so that doctest terminates!
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Extreme care must be taken when using this API, as misuse can lead to accessing invalid
|
||||||
|
/// memory. In addition, the caller is responsible for guaranteeing that the GIL remains held
|
||||||
|
/// for the entire lifetime of the returned `GILPool`.
|
||||||
|
///
|
||||||
|
/// Two best practices are required when using this API:
|
||||||
|
/// - From the moment `new_pool()` is called, only the `Python` token from the returned
|
||||||
|
/// `GILPool` (accessible using `.python()`) should be used in PyO3 APIs. All other older
|
||||||
|
/// `Python` tokens with longer lifetimes are unsafe to use until the `GILPool` is dropped,
|
||||||
|
/// because they can be used to create PyO3 owned references which have lifetimes which
|
||||||
|
/// outlive the `GILPool`.
|
||||||
|
/// - Similarly, methods on existing owned references will implicitly refer back to the
|
||||||
|
/// `Python` token which that reference was originally created with. If the returned values
|
||||||
|
/// from these methods are owned references they will inherit the same lifetime. As a result,
|
||||||
|
/// Rust's lifetime rules may allow them to outlive the `GILPool`, even though this is not
|
||||||
|
/// safe for reasons discussed above. Care must be taken to never access these return values
|
||||||
|
/// after the `GILPool` is dropped, unless they are converted to `Py<T>` *before* the pool
|
||||||
|
/// is dropped.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn new_pool(self) -> GILPool {
|
||||||
|
GILPool::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -567,6 +572,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_is_instance() {
|
fn test_is_instance() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
@ -579,6 +585,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_is_subclass() {
|
fn test_is_subclass() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
Loading…
Reference in New Issue