Merge pull request #1426 from davidhewitt/0.14-deprecations

0.14: deprecations
This commit is contained in:
David Hewitt 2021-02-14 08:29:06 +00:00 committed by GitHub
commit 83821bd961
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 293 deletions

View file

@ -5,13 +5,19 @@ PyO3 versions, please see the [migration guide](https://pyo3.rs/master/migration
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
## [Unreleased]
### Added
- Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)
### Changed
- Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)
- Deprecate FFI definitions `PyModule_GetFilename`, `PyMethodDef_INIT`. [#1425](https://github.com/PyO3/pyo3/pull/1425)
- Deprecate FFI definitions `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425)
### Removed
- Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426)
- Remove deprecated ffi definitions `PyGetSetDef_INIT`, `PyGetSetDef_DICT`, `PyCoro_Check`, `PyCoroWrapper_Check`, and `PyAsyncGen_Check`. [#1426](https://github.com/PyO3/pyo3/pull/1426)
- Remove deprecated redundant methods `Python::is_instance`, `Python::is_subclass`, `Python::release`, `Python::xdecref`, and `Py::from_owned_ptr_or_panic`. [#1426](https://github.com/PyO3/pyo3/pull/1426)
- Remove ffi definition ``PyMethodDef_INIT`. [#1426](https://github.com/PyO3/pyo3/pull/1426)
### Fixed
- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)

View file

@ -207,176 +207,89 @@ macro_rules! create_exception_type_object {
}
macro_rules! impl_native_exception (
($name:ident, $legacy_name:ident, $exc_name:ident, $layout:path) => (
($name:ident, $exc_name:ident, $layout:path) => (
pub struct $name($crate::PyAny);
#[deprecated(note = "Exceptions now have a `Py` prefix, e.g. `PyException`, `PyTypeError`")]
pub type $legacy_name = $crate::Py<$name>;
$crate::impl_exception_boilerplate!($name);
$crate::pyobject_native_type_core!($name, $layout, *(ffi::$exc_name as *mut ffi::PyTypeObject), Some("builtins"));
);
($name:ident, $legacy_name:ident, $exc_name:ident) => (
impl_native_exception!($name, $legacy_name, $exc_name, ffi::PyBaseExceptionObject);
($name:ident, $exc_name:ident) => (
impl_native_exception!($name, $exc_name, ffi::PyBaseExceptionObject);
)
);
impl PySizedLayout<PyBaseException> for ffi::PyBaseExceptionObject {}
impl_native_exception!(PyBaseException, BaseException, PyExc_BaseException);
impl_native_exception!(PyException, Exception, PyExc_Exception);
impl_native_exception!(
PyStopAsyncIteration,
StopAsyncIteration,
PyExc_StopAsyncIteration
);
impl_native_exception!(PyBaseException, PyExc_BaseException);
impl_native_exception!(PyException, PyExc_Exception);
impl_native_exception!(PyStopAsyncIteration, PyExc_StopAsyncIteration);
impl_native_exception!(
PyStopIteration,
StopIteration,
PyExc_StopIteration,
ffi::PyStopIterationObject
);
impl_native_exception!(PyGeneratorExit, GeneratorExit, PyExc_GeneratorExit);
impl_native_exception!(PyArithmeticError, ArithmeticError, PyExc_ArithmeticError);
impl_native_exception!(PyLookupError, LookupError, PyExc_LookupError);
impl_native_exception!(PyGeneratorExit, PyExc_GeneratorExit);
impl_native_exception!(PyArithmeticError, PyExc_ArithmeticError);
impl_native_exception!(PyLookupError, PyExc_LookupError);
impl_native_exception!(PyAssertionError, AssertionError, PyExc_AssertionError);
impl_native_exception!(PyAttributeError, AttributeError, PyExc_AttributeError);
impl_native_exception!(PyBufferError, BufferError, PyExc_BufferError);
impl_native_exception!(PyEOFError, EOFError, PyExc_EOFError);
impl_native_exception!(
PyFloatingPointError,
FloatingPointError,
PyExc_FloatingPointError
);
impl_native_exception!(PyOSError, OSError, PyExc_OSError, ffi::PyOSErrorObject);
impl_native_exception!(PyImportError, ImportError, PyExc_ImportError);
impl_native_exception!(PyAssertionError, PyExc_AssertionError);
impl_native_exception!(PyAttributeError, PyExc_AttributeError);
impl_native_exception!(PyBufferError, PyExc_BufferError);
impl_native_exception!(PyEOFError, PyExc_EOFError);
impl_native_exception!(PyFloatingPointError, PyExc_FloatingPointError);
impl_native_exception!(PyOSError, PyExc_OSError, ffi::PyOSErrorObject);
impl_native_exception!(PyImportError, PyExc_ImportError);
impl_native_exception!(
PyModuleNotFoundError,
ModuleNotFoundError,
PyExc_ModuleNotFoundError
);
impl_native_exception!(PyModuleNotFoundError, PyExc_ModuleNotFoundError);
impl_native_exception!(PyIndexError, IndexError, PyExc_IndexError);
impl_native_exception!(PyKeyError, KeyError, PyExc_KeyError);
impl_native_exception!(
PyKeyboardInterrupt,
KeyboardInterrupt,
PyExc_KeyboardInterrupt
);
impl_native_exception!(PyMemoryError, MemoryError, PyExc_MemoryError);
impl_native_exception!(PyNameError, NameError, PyExc_NameError);
impl_native_exception!(PyOverflowError, OverflowError, PyExc_OverflowError);
impl_native_exception!(PyRuntimeError, RuntimeError, PyExc_RuntimeError);
impl_native_exception!(PyRecursionError, RecursionError, PyExc_RecursionError);
impl_native_exception!(
PyNotImplementedError,
NotImplementedError,
PyExc_NotImplementedError
);
impl_native_exception!(
PySyntaxError,
SyntaxError,
PyExc_SyntaxError,
ffi::PySyntaxErrorObject
);
impl_native_exception!(PyReferenceError, ReferenceError, PyExc_ReferenceError);
impl_native_exception!(PySystemError, SystemError, PyExc_SystemError);
impl_native_exception!(
PySystemExit,
SystemExit,
PyExc_SystemExit,
ffi::PySystemExitObject
);
impl_native_exception!(PyTypeError, TypeError, PyExc_TypeError);
impl_native_exception!(
PyUnboundLocalError,
UnboundLocalError,
PyExc_UnboundLocalError
);
impl_native_exception!(PyIndexError, PyExc_IndexError);
impl_native_exception!(PyKeyError, PyExc_KeyError);
impl_native_exception!(PyKeyboardInterrupt, PyExc_KeyboardInterrupt);
impl_native_exception!(PyMemoryError, PyExc_MemoryError);
impl_native_exception!(PyNameError, PyExc_NameError);
impl_native_exception!(PyOverflowError, PyExc_OverflowError);
impl_native_exception!(PyRuntimeError, PyExc_RuntimeError);
impl_native_exception!(PyRecursionError, PyExc_RecursionError);
impl_native_exception!(PyNotImplementedError, PyExc_NotImplementedError);
impl_native_exception!(PySyntaxError, PyExc_SyntaxError, ffi::PySyntaxErrorObject);
impl_native_exception!(PyReferenceError, PyExc_ReferenceError);
impl_native_exception!(PySystemError, PyExc_SystemError);
impl_native_exception!(PySystemExit, PyExc_SystemExit, ffi::PySystemExitObject);
impl_native_exception!(PyTypeError, PyExc_TypeError);
impl_native_exception!(PyUnboundLocalError, PyExc_UnboundLocalError);
impl_native_exception!(
PyUnicodeError,
UnicodeError,
PyExc_UnicodeError,
ffi::PyUnicodeErrorObject
);
impl_native_exception!(
PyUnicodeDecodeError,
UnicodeDecodeError,
PyExc_UnicodeDecodeError
);
impl_native_exception!(
PyUnicodeEncodeError,
UnicodeEncodeError,
PyExc_UnicodeEncodeError
);
impl_native_exception!(
PyUnicodeTranslateError,
UnicodeTranslateError,
PyExc_UnicodeTranslateError
);
impl_native_exception!(PyValueError, ValueError, PyExc_ValueError);
impl_native_exception!(
PyZeroDivisionError,
ZeroDivisionError,
PyExc_ZeroDivisionError
);
impl_native_exception!(PyUnicodeDecodeError, PyExc_UnicodeDecodeError);
impl_native_exception!(PyUnicodeEncodeError, PyExc_UnicodeEncodeError);
impl_native_exception!(PyUnicodeTranslateError, PyExc_UnicodeTranslateError);
impl_native_exception!(PyValueError, PyExc_ValueError);
impl_native_exception!(PyZeroDivisionError, PyExc_ZeroDivisionError);
impl_native_exception!(PyBlockingIOError, BlockingIOError, PyExc_BlockingIOError);
impl_native_exception!(PyBrokenPipeError, BrokenPipeError, PyExc_BrokenPipeError);
impl_native_exception!(
PyChildProcessError,
ChildProcessError,
PyExc_ChildProcessError
);
impl_native_exception!(PyConnectionError, ConnectionError, PyExc_ConnectionError);
impl_native_exception!(
PyConnectionAbortedError,
ConnectionAbortedError,
PyExc_ConnectionAbortedError
);
impl_native_exception!(
PyConnectionRefusedError,
ConnectionRefusedError,
PyExc_ConnectionRefusedError
);
impl_native_exception!(
PyConnectionResetError,
ConnectionResetError,
PyExc_ConnectionResetError
);
impl_native_exception!(PyFileExistsError, FileExistsError, PyExc_FileExistsError);
impl_native_exception!(
PyFileNotFoundError,
FileNotFoundError,
PyExc_FileNotFoundError
);
impl_native_exception!(PyInterruptedError, InterruptedError, PyExc_InterruptedError);
impl_native_exception!(
PyIsADirectoryError,
IsADirectoryError,
PyExc_IsADirectoryError
);
impl_native_exception!(
PyNotADirectoryError,
NotADirectoryError,
PyExc_NotADirectoryError
);
impl_native_exception!(PyPermissionError, PermissionError, PyExc_PermissionError);
impl_native_exception!(
PyProcessLookupError,
ProcessLookupError,
PyExc_ProcessLookupError
);
impl_native_exception!(PyTimeoutError, TimeoutError, PyExc_TimeoutError);
impl_native_exception!(PyBlockingIOError, PyExc_BlockingIOError);
impl_native_exception!(PyBrokenPipeError, PyExc_BrokenPipeError);
impl_native_exception!(PyChildProcessError, PyExc_ChildProcessError);
impl_native_exception!(PyConnectionError, PyExc_ConnectionError);
impl_native_exception!(PyConnectionAbortedError, PyExc_ConnectionAbortedError);
impl_native_exception!(PyConnectionRefusedError, PyExc_ConnectionRefusedError);
impl_native_exception!(PyConnectionResetError, PyExc_ConnectionResetError);
impl_native_exception!(PyFileExistsError, PyExc_FileExistsError);
impl_native_exception!(PyFileNotFoundError, PyExc_FileNotFoundError);
impl_native_exception!(PyInterruptedError, PyExc_InterruptedError);
impl_native_exception!(PyIsADirectoryError, PyExc_IsADirectoryError);
impl_native_exception!(PyNotADirectoryError, PyExc_NotADirectoryError);
impl_native_exception!(PyPermissionError, PyExc_PermissionError);
impl_native_exception!(PyProcessLookupError, PyExc_ProcessLookupError);
impl_native_exception!(PyTimeoutError, PyExc_TimeoutError);
#[cfg(not(all(windows, PyPy)))]
impl_native_exception!(PyEnvironmentError, EnvironmentError, PyExc_EnvironmentError);
impl_native_exception!(PyEnvironmentError, PyExc_EnvironmentError);
#[cfg(not(all(windows, PyPy)))]
impl_native_exception!(PyIOError, IOError, PyExc_IOError);
impl_native_exception!(PyIOError, PyExc_IOError);
#[cfg(all(windows, not(PyPy)))]
impl_native_exception!(PyWindowsError, WindowsError, PyExc_WindowsError);
impl_native_exception!(PyWindowsError, PyExc_WindowsError);
impl PyUnicodeDecodeError {
pub fn new<'p>(

View file

@ -1,10 +1,7 @@
use crate::ffi::methodobject::PyMethodDef;
use crate::ffi::object::{PyObject, PyTypeObject};
#[cfg(all(not(PyPy), not(Py_LIMITED_API)))]
use crate::ffi::object::{PyObject_GenericGetDict, PyObject_GenericSetDict};
use crate::ffi::structmember::PyMemberDef;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
pub type getter = unsafe extern "C" fn(slf: *mut PyObject, closure: *mut c_void) -> *mut PyObject;
pub type setter =
@ -67,35 +64,3 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyProperty_Type")]
pub static mut PyProperty_Type: PyTypeObject;
}
/// Helper initial value of [`PyGetSetDef`] for a Python class.
///
/// Not present in `cpython/Include/descrobject`.
#[deprecated(note = "not present in Python headers; to be removed")]
pub const PyGetSetDef_INIT: PyGetSetDef = PyGetSetDef {
name: ptr::null_mut(),
get: None,
set: None,
doc: ptr::null_mut(),
closure: ptr::null_mut(),
};
#[cfg(any(PyPy, Py_LIMITED_API))]
#[deprecated(note = "not present in Python headers; to be removed")]
#[allow(deprecated)]
pub const PyGetSetDef_DICT: PyGetSetDef = PyGetSetDef_INIT;
/// Helper initial value of [`PyGetSetDef`] for a dict-like Python class.
///
/// Not present in `cpython/Include/descrobject.h`.
// PyPy doesn't export neither PyObject_GenericGetDict/PyObject_GenericSetDict
// Py_LIMITED_API exposes PyObject_GenericSetDict but not Get.
#[cfg(all(not(PyPy), not(Py_LIMITED_API)))]
#[deprecated(note = "not present in Python headers; to be removed")]
pub const PyGetSetDef_DICT: PyGetSetDef = PyGetSetDef {
name: "__dict__\0".as_ptr() as *mut c_char,
get: Some(PyObject_GenericGetDict),
set: Some(PyObject_GenericSetDict),
doc: ptr::null_mut(),
closure: ptr::null_mut(),
};

View file

@ -54,23 +54,11 @@ extern "C" {
pub static mut _PyCoroWrapper_Type: PyTypeObject;
}
#[deprecated(since = "0.14.0", note = "use PyCoro_CheckExact instead")]
#[inline]
pub unsafe fn PyCoro_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut PyCoro_Type)
}
#[inline]
pub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut PyCoro_Type)
}
#[deprecated(since = "0.14.0", note = "not in Python API")]
#[inline]
pub unsafe fn PyCoroWrapper_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut _PyCoroWrapper_Type)
}
// skipped _PyCoro_GetAwaitableIter
// skipped PyCoro_New
@ -86,12 +74,6 @@ extern "C" {
// skipped PyAsyncGen_New
#[deprecated(since = "0.14.0", note = "use PyCoro_CheckExact instead")]
#[inline]
pub unsafe fn PyAsyncGen_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut PyAsyncGen_Type)
}
#[inline]
pub unsafe fn PyAsyncGen_CheckExact(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut PyAsyncGen_Type)

View file

@ -77,17 +77,6 @@ pub struct PyMethodDef {
pub ml_doc: *const c_char,
}
/// Helper initial value of [`PyMethodDef`] for a Python class.
///
/// Not present in the Python C API.
#[deprecated(note = "not present in Python headers; to be removed")]
pub const PyMethodDef_INIT: PyMethodDef = PyMethodDef {
ml_name: std::ptr::null(),
ml_meth: None,
ml_flags: 0,
ml_doc: std::ptr::null(),
};
impl Default for PyMethodDef {
fn default() -> PyMethodDef {
unsafe { mem::zeroed() }

View file

@ -358,19 +358,6 @@ impl<T> Py<T> {
}
}
/// Deprecated alias for [`from_owned_ptr`](#method.from_owned_ptr).
///
/// # Safety
/// `ptr` must be a pointer to a Python object of type T.
///
/// Callers must own the object referred to by `ptr`, as this function
/// implicitly takes ownership of that object.
#[inline]
#[deprecated = "this is a deprecated alias for Py::from_owned_ptr"]
pub unsafe fn from_owned_ptr_or_panic(py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
Py::from_owned_ptr(py, ptr)
}
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
///
/// If `ptr` is null then the current Python exception is fetched as a `PyErr`.

View file

@ -350,8 +350,7 @@ fn py_class_method_defs<T: PyMethods>() -> (
}
if !defs.is_empty() {
#[allow(deprecated)]
defs.push(ffi::PyMethodDef_INIT);
defs.push(unsafe { std::mem::zeroed() });
}
(new, call, defs)
@ -399,6 +398,14 @@ fn py_class_members<T: PyClass>() -> Vec<ffi::structmember::PyMemberDef> {
vec![]
}
const PY_GET_SET_DEF_INIT: ffi::PyGetSetDef = ffi::PyGetSetDef {
name: ptr::null_mut(),
get: None,
set: None,
doc: ptr::null_mut(),
closure: ptr::null_mut(),
};
#[allow(clippy::clippy::collapsible_if)] // for if cfg!
fn py_class_properties<T: PyClass>() -> Vec<ffi::PyGetSetDef> {
let mut defs = std::collections::HashMap::new();
@ -408,7 +415,7 @@ fn py_class_properties<T: PyClass>() -> Vec<ffi::PyGetSetDef> {
PyMethodDefType::Getter(getter) => {
if !defs.contains_key(getter.name) {
#[allow(deprecated)]
let _ = defs.insert(getter.name.to_owned(), ffi::PyGetSetDef_INIT);
let _ = defs.insert(getter.name.to_owned(), PY_GET_SET_DEF_INIT);
}
let def = defs.get_mut(getter.name).expect("Failed to call get_mut");
getter.copy_to(def);
@ -416,7 +423,7 @@ fn py_class_properties<T: PyClass>() -> Vec<ffi::PyGetSetDef> {
PyMethodDefType::Setter(setter) => {
if !defs.contains_key(setter.name) {
#[allow(deprecated)]
let _ = defs.insert(setter.name.to_owned(), ffi::PyGetSetDef_INIT);
let _ = defs.insert(setter.name.to_owned(), PY_GET_SET_DEF_INIT);
}
let def = defs.get_mut(setter.name).expect("Failed to call get_mut");
setter.copy_to(def);

View file

@ -551,51 +551,6 @@ impl<'p> Python<'p> {
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.
#[inline]
#[deprecated(since = "0.13.0", note = "Please just drop ob instead")]
pub fn release<T>(self, ob: T)
where
T: IntoPyPointer,
{
unsafe {
let ptr = ob.into_ptr();
if !ptr.is_null() {
ffi::Py_DECREF(ptr);
}
}
}
/// Releases a `ffi::PyObject` pointer.
#[inline]
#[deprecated(since = "0.13.0", note = "Please just drop obj instead")]
pub fn xdecref<T: IntoPyPointer>(self, ptr: T) {
unsafe { ffi::Py_XDECREF(ptr.into_ptr()) };
}
/// Lets the Python interpreter check for pending signals and invoke the
/// corresponding signal handlers. This can run arbitrary Python code.
///
@ -691,7 +646,7 @@ impl<'p> Python<'p> {
#[cfg(test)]
mod test {
use super::*;
use crate::types::{IntoPyDict, PyAny, PyBool, PyInt, PyList};
use crate::types::{IntoPyDict, PyList};
#[test]
fn test_eval() {
@ -734,28 +689,6 @@ mod test {
assert_eq!(v, 2);
}
#[test]
#[allow(deprecated)]
fn test_is_instance() {
let gil = Python::acquire_gil();
let py = gil.python();
assert!(py
.is_instance::<PyBool, PyAny>(PyBool::new(py, true).into())
.unwrap());
let list = PyList::new(py, &[1, 2, 3, 4]);
assert!(!py.is_instance::<PyBool, _>(list.as_ref()).unwrap());
assert!(py.is_instance::<PyList, _>(list.as_ref()).unwrap());
}
#[test]
#[allow(deprecated)]
fn test_is_subclass() {
let gil = Python::acquire_gil();
let py = gil.python();
assert!(py.is_subclass::<PyBool, PyInt>().unwrap());
assert!(!py.is_subclass::<PyBool, PyList>().unwrap());
}
#[test]
fn test_allow_threads_panics_safely() {
// TODO replace with #[cfg(panic = "unwind")] once stable