ffi cleanup: methodobject to moduleobject

This commit is contained in:
Nicholas Sim 2021-02-13 15:35:56 +08:00
parent 0b30904eab
commit d84d0de604
8 changed files with 82 additions and 9 deletions

View File

@ -5,6 +5,17 @@ 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/) 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). and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later.
### Changed
- Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and later.
- Deprecate FFI definitions `PyModule_GetFilename`, `PyMethodDef_INIT`.
### Removed
- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later.
## [0.13.2] - 2021-02-12 ## [0.13.2] - 2021-02-12
### Packaging ### Packaging
- Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421) - Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421)

View File

@ -136,6 +136,7 @@ impl ModuleDef {
/// # Safety /// # Safety
/// `name` must be a null-terminated string. /// `name` must be a null-terminated string.
pub const unsafe fn new(name: &'static str) -> Self { pub const unsafe fn new(name: &'static str) -> Self {
#[allow(deprecated)]
let mut init = ffi::PyModuleDef_INIT; let mut init = ffi::PyModuleDef_INIT;
init.m_name = name.as_ptr() as *const _; init.m_name = name.as_ptr() as *const _;
ModuleDef(UnsafeCell::new(init)) ModuleDef(UnsafeCell::new(init))

View File

@ -8,6 +8,12 @@ extern "C" {
pub static mut PyCFunction_Type: PyTypeObject; pub static mut PyCFunction_Type: PyTypeObject;
} }
#[cfg(Py_3_9)]
#[inline]
pub unsafe fn PyCFunction_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == &mut PyCFunction_Type) as c_int
}
#[inline] #[inline]
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == &mut PyCFunction_Type) as c_int (Py_TYPE(op) == &mut PyCFunction_Type) as c_int
@ -38,11 +44,14 @@ pub type _PyCFunctionFastWithKeywords = unsafe extern "C" fn(
kwnames: *mut PyObject, kwnames: *mut PyObject,
) -> *mut PyObject; ) -> *mut PyObject;
// skipped PyCMethod (since 3.9)
extern "C" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCFunction_GetFunction")] #[cfg_attr(PyPy, link_name = "PyPyCFunction_GetFunction")]
pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option<PyCFunction>; pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option<PyCFunction>;
pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject; pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject;
pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int; pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int;
#[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))]
pub fn PyCFunction_Call( pub fn PyCFunction_Call(
f: *mut PyObject, f: *mut PyObject,
args: *mut PyObject, args: *mut PyObject,
@ -59,6 +68,10 @@ pub struct PyMethodDef {
pub ml_doc: *const c_char, 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 { pub const PyMethodDef_INIT: PyMethodDef = PyMethodDef {
ml_name: std::ptr::null(), ml_name: std::ptr::null(),
ml_meth: None, ml_meth: None,
@ -73,17 +86,19 @@ impl Default for PyMethodDef {
} }
extern "C" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCFunction_New")]
pub fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyCFunction_NewEx")] #[cfg_attr(PyPy, link_name = "PyPyCFunction_NewEx")]
pub fn PyCFunction_NewEx( pub fn PyCFunction_NewEx(
ml: *mut PyMethodDef, ml: *mut PyMethodDef,
slf: *mut PyObject, slf: *mut PyObject,
module: *mut PyObject, module: *mut PyObject,
) -> *mut PyObject; ) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyCFunction_New")]
pub fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject;
} }
// skipped non-limited / 3.9 PyCMethod_New
/* Flag passed to newmethodobject */ /* Flag passed to newmethodobject */
pub const METH_VARARGS: c_int = 0x0001; pub const METH_VARARGS: c_int = 0x0001;
pub const METH_KEYWORDS: c_int = 0x0002; pub const METH_KEYWORDS: c_int = 0x0002;
@ -109,6 +124,10 @@ be specified alone or with METH_KEYWORDS. */
#[cfg(all(Py_3_7, not(Py_LIMITED_API)))] #[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
pub const METH_FASTCALL: c_int = 0x0080; pub const METH_FASTCALL: c_int = 0x0080;
// skipped METH_STACKLESS
// skipped METH_METHOD
extern "C" { extern "C" {
#[cfg(not(Py_3_9))]
pub fn PyCFunction_ClearFreeList() -> c_int; pub fn PyCFunction_ClearFreeList() -> c_int;
} }

View File

@ -127,6 +127,10 @@ mod listobject;
mod longobject; mod longobject;
pub(crate) mod marshal; pub(crate) mod marshal;
mod memoryobject; mod memoryobject;
mod methodobject; // TODO: incomplete
mod modsupport; // TODO: incomplete
mod moduleobject; // TODO: incomplete
// skipped namespaceobject.h // skipped namespaceobject.h
// skipped odictobject.h // skipped odictobject.h
// skipped opcode.h // skipped opcode.h
@ -174,8 +178,6 @@ mod unicodeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.
mod rangeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod rangeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod odictobject; TODO new in 3.5 // mod odictobject; TODO new in 3.5
mod methodobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod moduleobject;
mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod classobject; TODO excluded by PEP-384 // mod classobject; TODO excluded by PEP-384
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
@ -191,7 +193,6 @@ mod pystate; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and
#[cfg(Py_LIMITED_API)] #[cfg(Py_LIMITED_API)]
mod pyarena {} mod pyarena {}
mod modsupport; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
mod pyarena; // TODO: incomplete mod pyarena; // TODO: incomplete
mod pythonrun; // TODO some functions need to be moved to pylifecycle mod pythonrun; // TODO some functions need to be moved to pylifecycle

View File

@ -28,12 +28,32 @@ extern "C" {
) -> c_int; ) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPy_BuildValue")] #[cfg_attr(PyPy, link_name = "PyPy_BuildValue")]
pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject; pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "_PyPy_BuildValue_SizeT")] // #[cfg_attr(PyPy, link_name = "_PyPy_BuildValue_SizeT")]
//pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...) //pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...)
// -> *mut PyObject; // -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPy_VaBuildValue")] // #[cfg_attr(PyPy, link_name = "PyPy_VaBuildValue")]
// skipped non-limited _PyArg_UnpackStack
// skipped non-limited _PyArg_NoKeywords
// skipped non-limited _PyArg_NoKwnames
// skipped non-limited _PyArg_NoPositional
// skipped non-limited _PyArg_BadArgument
// skipped non-limited _PyArg_CheckPositional
//pub fn Py_VaBuildValue(arg1: *const c_char, arg2: va_list) //pub fn Py_VaBuildValue(arg1: *const c_char, arg2: va_list)
// -> *mut PyObject; // -> *mut PyObject;
// skipped non-limited _Py_VaBuildStack
// skipped non-limited _PyArg_Parser
// skipped non-limited _PyArg_ParseTupleAndKeywordsFast
// skipped non-limited _PyArg_ParseStack
// skipped non-limited _PyArg_ParseStackAndKeywords
// skipped non-limited _PyArg_VaParseTupleAndKeywordsFast
// skipped non-limited _PyArg_UnpackKeywords
// skipped non-limited _PyArg_Fini
// skipped PyModule_AddObjectRef
#[cfg_attr(PyPy, link_name = "PyPyModule_AddObject")] #[cfg_attr(PyPy, link_name = "PyPyModule_AddObject")]
pub fn PyModule_AddObject( pub fn PyModule_AddObject(
arg1: *mut PyObject, arg1: *mut PyObject,
@ -49,6 +69,9 @@ extern "C" {
arg2: *const c_char, arg2: *const c_char,
arg3: *const c_char, arg3: *const c_char,
) -> c_int; ) -> c_int;
// skipped non-limited / 3.9 PyModule_AddType
// skipped PyModule_AddIntMacro
// skipped PyModule_AddStringMacro
pub fn PyModule_SetDocString(arg1: *mut PyObject, arg2: *const c_char) -> c_int; pub fn PyModule_SetDocString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;
pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int; pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int;
pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int; pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int;
@ -122,3 +145,5 @@ pub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject
}, },
) )
} }
// skipped non-limited _Py_PackageContext

View File

@ -30,8 +30,12 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyModule_GetName")] #[cfg_attr(PyPy, link_name = "PyPyModule_GetName")]
pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char; pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char;
#[cfg(not(all(windows, PyPy)))] #[cfg(not(all(windows, PyPy)))]
#[deprecated(note = "Python 3.2")]
pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char; pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char;
pub fn PyModule_GetFilenameObject(arg1: *mut PyObject) -> *mut PyObject; pub fn PyModule_GetFilenameObject(arg1: *mut PyObject) -> *mut PyObject;
// skipped non-limited _PyModule_Clear
// skipped non-limited _PyModule_ClearDict
// skipped non-limited _PyModuleSpec_IsInitializing
#[cfg_attr(PyPy, link_name = "PyPyModule_GetDef")] #[cfg_attr(PyPy, link_name = "PyPyModule_GetDef")]
pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef; pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef;
#[cfg_attr(PyPy, link_name = "PyPyModule_GetState")] #[cfg_attr(PyPy, link_name = "PyPyModule_GetState")]
@ -71,6 +75,8 @@ pub struct PyModuleDef_Slot {
pub const Py_mod_create: c_int = 1; pub const Py_mod_create: c_int = 1;
pub const Py_mod_exec: c_int = 2; pub const Py_mod_exec: c_int = 2;
// skipped non-limited _Py_mod_LAST_SLOT
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct PyModuleDef { pub struct PyModuleDef {
@ -85,6 +91,10 @@ pub struct PyModuleDef {
pub m_free: Option<freefunc>, pub m_free: Option<freefunc>,
} }
/// Helper initial value of [`PyModuleDef`] for a Python class.
///
/// Not present in the Python C API.
#[deprecated(note = "not present in Python headers; to be removed")]
pub const PyModuleDef_INIT: PyModuleDef = PyModuleDef { pub const PyModuleDef_INIT: PyModuleDef = PyModuleDef {
m_base: PyModuleDef_HEAD_INIT, m_base: PyModuleDef_HEAD_INIT,
m_name: std::ptr::null(), m_name: std::ptr::null(),

View File

@ -350,6 +350,7 @@ fn py_class_method_defs<T: PyMethods>() -> (
} }
if !defs.is_empty() { if !defs.is_empty() {
#[allow(deprecated)]
defs.push(ffi::PyMethodDef_INIT); defs.push(ffi::PyMethodDef_INIT);
} }

View File

@ -121,7 +121,12 @@ impl PyModule {
/// May fail if the module does not have a `__file__` attribute. /// May fail if the module does not have a `__file__` attribute.
#[cfg(not(all(windows, PyPy)))] #[cfg(not(all(windows, PyPy)))]
pub fn filename(&self) -> PyResult<&str> { pub fn filename(&self) -> PyResult<&str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.as_ptr())) } unsafe {
self.str_from_ptr(
#[allow(deprecated)]
ffi::PyModule_GetFilename(self.as_ptr()),
)
}
} }
/// Calls a function in the module. /// Calls a function in the module.