From 1196cbd39618b40602a238d0df6b692eb736635c Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 13 Feb 2021 09:12:26 +0000 Subject: [PATCH] 0.14: deprecations --- CHANGELOG.md | 10 +- src/exceptions.rs | 197 +++++++++++----------------------------- src/ffi/descrobject.rs | 35 ------- src/ffi/genobject.rs | 18 ---- src/ffi/methodobject.rs | 11 --- src/instance.rs | 13 --- src/pyclass.rs | 15 ++- src/python.rs | 69 +------------- 8 files changed, 75 insertions(+), 293 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f941c75a..8d2c360d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/src/exceptions.rs b/src/exceptions.rs index 694c66ec..aab9057a 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -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 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>( diff --git a/src/ffi/descrobject.rs b/src/ffi/descrobject.rs index 41eec1cb..6b6b0b2d 100644 --- a/src/ffi/descrobject.rs +++ b/src/ffi/descrobject.rs @@ -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(), -}; diff --git a/src/ffi/genobject.rs b/src/ffi/genobject.rs index aa6b6607..340d28b0 100644 --- a/src/ffi/genobject.rs +++ b/src/ffi/genobject.rs @@ -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) diff --git a/src/ffi/methodobject.rs b/src/ffi/methodobject.rs index ecfbc81c..e58bb8dc 100644 --- a/src/ffi/methodobject.rs +++ b/src/ffi/methodobject.rs @@ -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() } diff --git a/src/instance.rs b/src/instance.rs index 9c3ab110..e37ef2a7 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -358,19 +358,6 @@ impl Py { } } - /// 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 { - Py::from_owned_ptr(py, ptr) - } - /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// If `ptr` is null then the current Python exception is fetched as a `PyErr`. diff --git a/src/pyclass.rs b/src/pyclass.rs index 066ea238..e31b5b86 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -350,8 +350,7 @@ fn py_class_method_defs() -> ( } 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() -> Vec { 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() -> Vec { let mut defs = std::collections::HashMap::new(); @@ -408,7 +415,7 @@ fn py_class_properties() -> Vec { 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() -> Vec { 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); diff --git a/src/python.rs b/src/python.rs index 9dc4c55d..b350423c 100644 --- a/src/python.rs +++ b/src/python.rs @@ -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::() instead")] - pub fn is_instance(self, obj: &V) -> PyResult { - 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::() instead" - )] - pub fn is_subclass(self) -> PyResult - where - T: PyTypeObject, - U: PyTypeObject, - { - T::type_object(self).is_subclass::() - } - - /// Releases a PyObject reference. - #[inline] - #[deprecated(since = "0.13.0", note = "Please just drop ob instead")] - pub fn release(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(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::new(py, true).into()) - .unwrap()); - let list = PyList::new(py, &[1, 2, 3, 4]); - assert!(!py.is_instance::(list.as_ref()).unwrap()); - assert!(py.is_instance::(list.as_ref()).unwrap()); - } - - #[test] - #[allow(deprecated)] - fn test_is_subclass() { - let gil = Python::acquire_gil(); - let py = gil.python(); - assert!(py.is_subclass::().unwrap()); - assert!(!py.is_subclass::().unwrap()); - } - #[test] fn test_allow_threads_panics_safely() { // TODO replace with #[cfg(panic = "unwind")] once stable