Skip to content

Commit

Permalink
Merge pull request #1425 from nw0/ffi-5
Browse files Browse the repository at this point in the history
ffi cleanup: methodobject to moduleobject
  • Loading branch information
davidhewitt authored Feb 14, 2021
2 parents 0b30904 + 2d7d482 commit 28aff42
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 9 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/)
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. [#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)

### Fixed
- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)

## [0.13.2] - 2021-02-12
### Packaging
- Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421)
Expand Down
1 change: 1 addition & 0 deletions src/derive_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ impl ModuleDef {
/// # Safety
/// `name` must be a null-terminated string.
pub const unsafe fn new(name: &'static str) -> Self {
#[allow(deprecated)]
let mut init = ffi::PyModuleDef_INIT;
init.m_name = name.as_ptr() as *const _;
ModuleDef(UnsafeCell::new(init))
Expand Down
34 changes: 31 additions & 3 deletions src/ffi/methodobject.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::ffi::object::{PyObject, PyTypeObject, Py_TYPE};
#[cfg(Py_3_9)]
use crate::ffi::PyObject_TypeCheck;
use std::mem;
use std::os::raw::{c_char, c_int};

Expand All @@ -8,6 +10,19 @@ extern "C" {
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
}

#[cfg(Py_3_9)]
#[inline]
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, &mut PyCFunction_Type)
}

#[cfg(not(Py_3_9))]
#[inline]
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == &mut PyCFunction_Type) as c_int
Expand Down Expand Up @@ -38,11 +53,14 @@ pub type _PyCFunctionFastWithKeywords = unsafe extern "C" fn(
kwnames: *mut PyObject,
) -> *mut PyObject;

// skipped PyCMethod (since 3.9)

extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCFunction_GetFunction")]
pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option<PyCFunction>;
pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject;
pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int;
#[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))]
pub fn PyCFunction_Call(
f: *mut PyObject,
args: *mut PyObject,
Expand All @@ -59,6 +77,10 @@ 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,
Expand All @@ -73,17 +95,19 @@ impl Default for PyMethodDef {
}

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")]
pub fn PyCFunction_NewEx(
ml: *mut PyMethodDef,
slf: *mut PyObject,
module: *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 */
pub const METH_VARARGS: c_int = 0x0001;
pub const METH_KEYWORDS: c_int = 0x0002;
Expand All @@ -109,6 +133,10 @@ be specified alone or with METH_KEYWORDS. */
#[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
pub const METH_FASTCALL: c_int = 0x0080;

// skipped METH_STACKLESS
// skipped METH_METHOD

extern "C" {
#[cfg(not(Py_3_9))]
pub fn PyCFunction_ClearFreeList() -> c_int;
}
7 changes: 4 additions & 3 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ mod listobject;
mod longobject;
pub(crate) mod marshal;
mod memoryobject;
mod methodobject; // TODO: incomplete
mod modsupport; // TODO: incomplete
mod moduleobject; // TODO: incomplete

// skipped namespaceobject.h
// skipped odictobject.h
// skipped opcode.h
Expand Down Expand Up @@ -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 tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 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 classobject; TODO excluded by PEP-384
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
Expand All @@ -191,7 +193,6 @@ mod pystate; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and

#[cfg(Py_LIMITED_API)]
mod pyarena {}
mod modsupport; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))]
mod pyarena; // TODO: incomplete
mod pythonrun; // TODO some functions need to be moved to pylifecycle
Expand Down
29 changes: 27 additions & 2 deletions src/ffi/modsupport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,32 @@ extern "C" {
) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPy_BuildValue")]
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, ...)
// -> *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)
// -> *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")]
pub fn PyModule_AddObject(
arg1: *mut PyObject,
Expand All @@ -49,6 +69,9 @@ extern "C" {
arg2: *const c_char,
arg3: *const c_char,
) -> 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_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int;
pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int;
Expand Down Expand Up @@ -122,3 +145,5 @@ pub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject
},
)
}

// skipped non-limited _Py_PackageContext
10 changes: 10 additions & 0 deletions src/ffi/moduleobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyModule_GetName")]
pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char;
#[cfg(not(all(windows, PyPy)))]
#[deprecated(note = "Python 3.2")]
pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char;
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")]
pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef;
#[cfg_attr(PyPy, link_name = "PyPyModule_GetState")]
Expand Down Expand Up @@ -71,6 +75,8 @@ pub struct PyModuleDef_Slot {
pub const Py_mod_create: c_int = 1;
pub const Py_mod_exec: c_int = 2;

// skipped non-limited _Py_mod_LAST_SLOT

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyModuleDef {
Expand All @@ -85,6 +91,10 @@ pub struct PyModuleDef {
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 {
m_base: PyModuleDef_HEAD_INIT,
m_name: std::ptr::null(),
Expand Down
1 change: 1 addition & 0 deletions src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ fn py_class_method_defs<T: PyMethods>() -> (
}

if !defs.is_empty() {
#[allow(deprecated)]
defs.push(ffi::PyMethodDef_INIT);
}

Expand Down
7 changes: 6 additions & 1 deletion src/types/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ impl PyModule {
/// May fail if the module does not have a `__file__` attribute.
#[cfg(not(all(windows, PyPy)))]
pub fn filename(&self) -> PyResult<&str> {
unsafe { self.str_from_ptr(ffi::PyModule_GetFilename(self.as_ptr())) }
use crate::types::PyString;
unsafe {
self.py()
.from_owned_ptr_or_err::<PyString>(ffi::PyModule_GetFilenameObject(self.as_ptr()))?
.to_str()
}
}

/// Calls a function in the module.
Expand Down

0 comments on commit 28aff42

Please sign in to comment.