diff --git a/CHANGELOG.md b/CHANGELOG.md index a6f53bf0ae7..89ba065321e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Add support for `#[pyclass(dict)]` and `#[pyclass(weakref)]` with the `abi3` feature on Python 3.9 and up. [#1342](https://github.com/PyO3/pyo3/pull/1342) +### Changed +- Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338) +- Deprecate FFI definitions `PyGetSetDef_DICT` and `PyGetSetDef_INIT` which have never been in the Python API. [#1341](https://github.com/PyO3/pyo3/pull/1341) + +### Removed +- Remove FFI definition `PyFrame_ClearFreeList` when building for Python 3.9. [#1341](https://github.com/PyO3/pyo3/pull/1341) +- Remove FFI definition `_PyDict_Contains` when building for Python 3.10. [#1341](https://github.com/PyO3/pyo3/pull/1341) + ### Fixed - Stop including `Py_TRACE_REFS` config setting automatically if `Py_DEBUG` is set on Python 3.8 and up. [#1334](https://github.com/PyO3/pyo3/pull/1334) - Remove `#[deny(warnings)]` attribute (and instead refuse warnings only in CI). [#1340](https://github.com/PyO3/pyo3/pull/1340) -- Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338) - Fix deprecation warning for missing `__module__` with `#[pyclass]`. [#1343](https://github.com/PyO3/pyo3/pull/1343) ## [0.13.0] - 2020-12-22 diff --git a/src/ffi/context.rs b/src/ffi/context.rs index 20778e744ac..cbb58f39216 100644 --- a/src/ffi/context.rs +++ b/src/ffi/context.rs @@ -3,21 +3,11 @@ use std::os::raw::{c_char, c_int}; extern "C" { pub static mut PyContext_Type: PyTypeObject; + // skipped non-limited opaque PyContext pub static mut PyContextVar_Type: PyTypeObject; + // skipped non-limited opaque PyContextVar pub static mut PyContextToken_Type: PyTypeObject; - pub fn PyContext_New() -> *mut PyObject; - pub fn PyContext_Copy(ctx: *mut PyObject) -> *mut PyObject; - pub fn PyContext_CopyCurrent() -> *mut PyObject; - pub fn PyContext_Enter(ctx: *mut PyObject) -> c_int; - pub fn PyContext_Exit(ctx: *mut PyObject) -> c_int; - pub fn PyContextVar_New(name: *const c_char, def: *mut PyObject) -> *mut PyObject; - pub fn PyContextVar_Get( - var: *mut PyObject, - default_value: *mut PyObject, - value: *mut *mut PyObject, - ) -> c_int; - pub fn PyContextVar_Set(var: *mut PyObject, value: *mut PyObject) -> *mut PyObject; - pub fn PyContextVar_Reset(var: *mut PyObject, token: *mut PyObject) -> c_int; +// skipped non-limited opaque PyContextToken } #[inline] @@ -34,3 +24,22 @@ pub unsafe fn PyContextVar_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyContextToken_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == &mut PyContextToken_Type) as c_int } + +extern "C" { + pub fn PyContext_New() -> *mut PyObject; + pub fn PyContext_Copy(ctx: *mut PyObject) -> *mut PyObject; + pub fn PyContext_CopyCurrent() -> *mut PyObject; + + pub fn PyContext_Enter(ctx: *mut PyObject) -> c_int; + pub fn PyContext_Exit(ctx: *mut PyObject) -> c_int; + + pub fn PyContextVar_New(name: *const c_char, def: *mut PyObject) -> *mut PyObject; + pub fn PyContextVar_Get( + var: *mut PyObject, + default_value: *mut PyObject, + value: *mut *mut PyObject, + ) -> c_int; + pub fn PyContextVar_Set(var: *mut PyObject, value: *mut PyObject) -> *mut PyObject; + pub fn PyContextVar_Reset(var: *mut PyObject, token: *mut PyObject) -> c_int; +// skipped non-limited _PyContext_NewHamtForTests +} diff --git a/src/ffi/cpython/dictobject.rs b/src/ffi/cpython/dictobject.rs new file mode 100644 index 00000000000..3e58e7b90b8 --- /dev/null +++ b/src/ffi/cpython/dictobject.rs @@ -0,0 +1,63 @@ +use crate::ffi::object::*; +use crate::ffi::pyport::Py_ssize_t; +use std::os::raw::c_int; + +opaque_struct!(PyDictKeysObject); + +#[repr(C)] +#[derive(Debug)] +// Not moved because dict.rs uses PyDictObject extensively. +pub struct PyDictObject { + pub ob_base: PyObject, + pub ma_used: Py_ssize_t, + pub ma_version_tag: u64, + pub ma_keys: *mut PyDictKeysObject, + pub ma_values: *mut *mut PyObject, +} + +extern "C" { + // skipped _PyDict_GetItem_KnownHash + // skipped _PyDict_GetItemIdWithError + // skipped _PyDict_GetItemStringWithError + // skipped PyDict_SetDefault + pub fn _PyDict_SetItem_KnownHash( + mp: *mut PyObject, + key: *mut PyObject, + item: *mut PyObject, + hash: crate::ffi::Py_hash_t, + ) -> c_int; + // skipped _PyDict_DelItem_KnownHash + // skipped _PyDict_DelItemIf + // skipped _PyDict_NewKeysForClass + pub fn _PyDict_Next( + mp: *mut PyObject, + pos: *mut Py_ssize_t, + key: *mut *mut PyObject, + value: *mut *mut PyObject, + hash: *mut crate::ffi::Py_hash_t, + ) -> c_int; + // skipped PyDict_GET_SIZE + // skipped _PyDict_Contains_KnownHash + // skipped _PyDict_ContainsId + pub fn _PyDict_NewPresized(minused: Py_ssize_t) -> *mut PyObject; + // skipped _PyDict_MaybeUntrack + // skipped _PyDict_HasOnlyStringKeys + // skipped _PyDict_KeysSize + // skipped _PyDict_SizeOf + // skipped _PyDict_Pop + // skipped _PyDict_Pop_KnownHash + // skipped _PyDict_FromKeys + // skipped _PyDict_HasSplitTable + // skipped _PyDict_MergeEx + // skipped _PyDict_SetItemId + // skipped _PyDict_DelItemId + // skipped _PyDict_DebugMallocStats + // skipped _PyObjectDict_SetItem + // skipped _PyDict_LoadGlobal + // skipped _PyDict_GetItemHint + // skipped _PyDictViewObject + // skipped _PyDictView_New + // skipped _PyDictView_Intersect + #[cfg(not(Py_3_10))] + pub fn _PyDict_Contains(mp: *mut PyObject, key: *mut PyObject, hash: Py_ssize_t) -> c_int; +} diff --git a/src/ffi/frameobject.rs b/src/ffi/cpython/frameobject.rs similarity index 90% rename from src/ffi/frameobject.rs rename to src/ffi/cpython/frameobject.rs index 6178ab87af8..2f7d2b1df90 100644 --- a/src/ffi/frameobject.rs +++ b/src/ffi/cpython/frameobject.rs @@ -3,6 +3,9 @@ use crate::ffi::object::*; use crate::ffi::pystate::PyThreadState; use std::os::raw::{c_char, c_int}; +// skipped _framestate +// skipped PyFrameState + #[repr(C)] #[derive(Copy, Clone)] pub struct PyTryBlock { @@ -11,6 +14,7 @@ pub struct PyTryBlock { pub b_level: c_int, } +/// struct _frame as typedef'ed in pyframe.h #[repr(C)] #[derive(Copy, Clone)] pub struct PyFrameObject { @@ -45,6 +49,10 @@ pub struct PyFrameObject { pub f_localsplus: [*mut PyObject; 1], /* locals+stack, dynamically sized */ } +// skipped _PyFrame_IsRunnable +// skipped _PyFrame_IsExecuting +// skipped _PyFrameHasCompleted + #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyFrame_Type: PyTypeObject; @@ -63,6 +71,7 @@ extern "C" { globals: *mut PyObject, locals: *mut PyObject, ) -> *mut PyFrameObject; + // skipped _PyFrame_New_NoTrack pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int); pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; @@ -71,6 +80,9 @@ extern "C" { pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int; pub fn PyFrame_FastToLocals(f: *mut PyFrameObject); + // skipped _PyFrame_DebugMallocStats + // skipped PyFrame_GetBack + + #[cfg(not(Py_3_9))] pub fn PyFrame_ClearFreeList() -> c_int; - pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int; } diff --git a/src/ffi/cpython/mod.rs b/src/ffi/cpython/mod.rs index 76513bde8f2..2e3ff22ab1b 100644 --- a/src/ffi/cpython/mod.rs +++ b/src/ffi/cpython/mod.rs @@ -1,11 +1,19 @@ pub mod abstract_; +// skipped bytearrayobject.h #[cfg(not(PyPy))] pub mod bytesobject; pub mod ceval; pub mod code; +#[cfg(not(PyPy))] +pub mod dictobject; +// skipped fileobject.h +pub mod frameobject; pub use self::abstract_::*; #[cfg(not(PyPy))] pub use self::bytesobject::*; pub use self::ceval::*; pub use self::code::*; +#[cfg(not(PyPy))] +pub use self::dictobject::*; +pub use self::frameobject::*; diff --git a/src/ffi/datetime.rs b/src/ffi/datetime.rs index 4b17e3efc81..daa8f0e106e 100644 --- a/src/ffi/datetime.rs +++ b/src/ffi/datetime.rs @@ -23,6 +23,338 @@ use { std::ffi::CString, }; +// Type struct wrappers +const _PyDateTime_DATE_DATASIZE: usize = 4; +const _PyDateTime_TIME_DATASIZE: usize = 6; +const _PyDateTime_DATETIME_DATASIZE: usize = 10; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// Structure representing a `datetime.timedelta`. +pub struct PyDateTime_Delta { + pub ob_base: PyObject, + #[cfg(not(PyPy))] + pub hashcode: Py_hash_t, + pub days: c_int, + pub seconds: c_int, + pub microseconds: c_int, +} + +// skipped non-limited PyDateTime_TZInfo +// skipped non-limited _PyDateTime_BaseTZInfo +// skipped non-limited _PyDateTime_BaseTime + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// Structure representing a `datetime.time`. +pub struct PyDateTime_Time { + pub ob_base: PyObject, + #[cfg(not(PyPy))] + pub hashcode: Py_hash_t, + pub hastzinfo: c_char, + #[cfg(not(PyPy))] + pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], + #[cfg(not(PyPy))] + pub fold: c_uchar, + pub tzinfo: *mut PyObject, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// Structure representing a `datetime.date` +pub struct PyDateTime_Date { + pub ob_base: PyObject, + #[cfg(not(PyPy))] + pub hashcode: Py_hash_t, + pub hastzinfo: c_char, + pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], +} + +// skipped non-limited _PyDateTime_BaseDateTime + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// Structure representing a `datetime.datetime` +pub struct PyDateTime_DateTime { + pub ob_base: PyObject, + #[cfg(not(PyPy))] + pub hashcode: Py_hash_t, + pub hastzinfo: c_char, + #[cfg(not(PyPy))] + pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], + #[cfg(not(PyPy))] + pub fold: c_uchar, + pub tzinfo: *mut PyObject, +} + +// skipped non-limited _PyDateTime_HAS_TZINFO + +// Accessor functions for PyDateTime_Date and PyDateTime_DateTime +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`. +/// Returns a signed integer greater than 0. +pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { + // This should work for Date or DateTime + let d = *(o as *mut PyDateTime_Date); + c_int::from(d.data[0]) << 8 | c_int::from(d.data[1]) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`. +/// Returns a signed integer in the range `[1, 12]`. +pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { + let d = *(o as *mut PyDateTime_Date); + c_int::from(d.data[2]) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[1, 31]`. +pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { + let d = *(o as *mut PyDateTime_Date); + c_int::from(d.data[3]) +} + +// Accessor macros for times +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_HOUR { + ($o: expr, $offset:expr) => { + c_int::from((*$o).data[$offset + 0]) + }; +} + +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_MINUTE { + ($o: expr, $offset:expr) => { + c_int::from((*$o).data[$offset + 1]) + }; +} + +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_SECOND { + ($o: expr, $offset:expr) => { + c_int::from((*$o).data[$offset + 2]) + }; +} + +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_MICROSECOND { + ($o: expr, $offset:expr) => { + (c_int::from((*$o).data[$offset + 3]) << 16) + | (c_int::from((*$o).data[$offset + 4]) << 8) + | (c_int::from((*$o).data[$offset + 5])) + }; +} + +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_FOLD { + ($o: expr) => { + (*$o).fold + }; +} + +#[cfg(not(PyPy))] +macro_rules! _PyDateTime_GET_TZINFO { + ($o: expr) => { + (*$o).tzinfo + }; +} + +// Accessor functions for DateTime +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the hour component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 23]` +pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { + _PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the minute component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 59]` +pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { + _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the second component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 59]` +pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { + _PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the microsecond component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 999999]` +pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { + _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the fold component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 1]` +pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { + _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the tzinfo component of a `PyDateTime_DateTime`. +/// Returns a pointer to a `PyObject` that should be either NULL or an instance +/// of a `datetime.tzinfo` subclass. +pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { + _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime) +} + +// Accessor functions for Time +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the hour component of a `PyDateTime_Time`. +/// Returns a signed integer in the interval `[0, 23]` +pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { + _PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the minute component of a `PyDateTime_Time`. +/// Returns a signed integer in the interval `[0, 59]` +pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { + _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the second component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 59]` +pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { + _PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the microsecond component of a `PyDateTime_DateTime`. +/// Returns a signed integer in the interval `[0, 999999]` +pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { + _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0) +} + +#[cfg(not(PyPy))] +#[inline] +/// Retrieve the fold component of a `PyDateTime_Time`. +/// Returns a signed integer in the interval `[0, 1]` +pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar { + _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the tzinfo component of a `PyDateTime_Time`. +/// Returns a pointer to a `PyObject` that should be either NULL or an instance +/// of a `datetime.tzinfo` subclass. +pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { + _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time) +} + +// Accessor functions +#[cfg(not(PyPy))] +macro_rules! _access_field { + ($obj:expr, $type: ident, $field:ident) => { + (*($obj as *mut $type)).$field + }; +} + +// Accessor functions for PyDateTime_Delta +#[cfg(not(PyPy))] +macro_rules! _access_delta_field { + ($obj:expr, $field:ident) => { + _access_field!($obj, PyDateTime_Delta, $field) + }; +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the days component of a `PyDateTime_Delta`. +/// +/// Returns a signed integer in the interval [-999999999, 999999999]. +/// +/// Note: This retrieves a component from the underlying structure, it is *not* +/// a representation of the total duration of the structure. +pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { + _access_delta_field!(o, days) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the seconds component of a `PyDateTime_Delta`. +/// +/// Returns a signed integer in the interval [0, 86399]. +/// +/// Note: This retrieves a component from the underlying structure, it is *not* +/// a representation of the total duration of the structure. +pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { + _access_delta_field!(o, seconds) +} + +#[inline] +#[cfg(not(PyPy))] +/// Retrieve the seconds component of a `PyDateTime_Delta`. +/// +/// Returns a signed integer in the interval [0, 999999]. +/// +/// Note: This retrieves a component from the underlying structure, it is *not* +/// a representation of the total duration of the structure. +pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { + _access_delta_field!(o, microseconds) +} + +#[cfg(PyPy)] +extern "C" { + // skipped _PyDateTime_HAS_TZINFO (not in PyPy) + #[link_name = "PyPyDateTime_GET_YEAR"] + pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_GET_MONTH"] + pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_GET_DAY"] + pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int; + + #[link_name = "PyPyDateTime_DATE_GET_HOUR"] + pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_DATE_GET_MINUTE"] + pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_DATE_GET_SECOND"] + pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_DATE_GET_MICROSECOND"] + pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int; + // skipped PyDateTime_DATE_GET_FOLD (not in PyPy) + // skipped PyDateTime_DATE_GET_TZINFO (not in PyPy) + + #[link_name = "PyPyDateTime_TIME_GET_HOUR"] + pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_TIME_GET_MINUTE"] + pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_TIME_GET_SECOND"] + pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_TIME_GET_MICROSECOND"] + pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int; + // skipped PyDateTime_TIME_GET_FOLD (not in PyPy) + // skipped PyDateTime_TIME_GET_TZINFO (not in PyPy) + + #[link_name = "PyPyDateTime_DELTA_GET_DAYS"] + pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_DELTA_GET_SECONDS"] + pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int; + #[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"] + pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int; +} + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct PyDateTime_CAPI { @@ -84,124 +416,27 @@ pub struct PyDateTime_CAPI { unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject, #[cfg(not(PyPy))] pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn( - year: c_int, - month: c_int, - day: c_int, - hour: c_int, - minute: c_int, - second: c_int, - microsecond: c_int, - tzinfo: *mut PyObject, - fold: c_int, - cls: *mut PyTypeObject, - ) -> *mut PyObject, - #[cfg(not(PyPy))] - pub Time_FromTimeAndFold: unsafe extern "C" fn( - hour: c_int, - minute: c_int, - second: c_int, - microsecond: c_int, - tzinfo: *mut PyObject, - fold: c_int, - cls: *mut PyTypeObject, - ) -> *mut PyObject, -} - -#[cfg(PyPy)] -extern "C" { - #[link_name = "_PyPyDateTime_Import"] - pub fn PyDateTime_Import() -> &'static PyDateTime_CAPI; - #[link_name = "PyPyDateTime_DATE_GET_HOUR"] - pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DATE_GET_MICROSECOND"] - pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DATE_GET_MINUTE"] - pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DATE_GET_SECOND"] - pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DELTA_GET_DAYS"] - pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"] - pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_DELTA_GET_SECONDS"] - pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_GET_DAY"] - pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_GET_MONTH"] - pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_GET_YEAR"] - pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_TIME_GET_HOUR"] - pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_TIME_GET_MICROSECOND"] - pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_TIME_GET_MINUTE"] - pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int; - #[link_name = "PyPyDateTime_TIME_GET_SECOND"] - pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int; - - #[link_name = "PyPyDate_FromTimestamp"] - pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject; - #[link_name = "PyPyDateTime_FromTimestamp"] - pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject; -} - -// Type struct wrappers -const _PyDateTime_DATE_DATASIZE: usize = 4; -const _PyDateTime_TIME_DATASIZE: usize = 6; -const _PyDateTime_DATETIME_DATASIZE: usize = 10; - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -/// Structure representing a `datetime.date` -pub struct PyDateTime_Date { - pub ob_base: PyObject, - #[cfg(not(PyPy))] - pub hashcode: Py_hash_t, - pub hastzinfo: c_char, - pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], -} - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -/// Structure representing a `datetime.time` -pub struct PyDateTime_Time { - pub ob_base: PyObject, - #[cfg(not(PyPy))] - pub hashcode: Py_hash_t, - pub hastzinfo: c_char, - #[cfg(not(PyPy))] - pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], - #[cfg(not(PyPy))] - pub fold: c_uchar, - pub tzinfo: *mut PyObject, -} - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -/// Structure representing a `datetime.datetime` -pub struct PyDateTime_DateTime { - pub ob_base: PyObject, - #[cfg(not(PyPy))] - pub hashcode: Py_hash_t, - pub hastzinfo: c_char, - #[cfg(not(PyPy))] - pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], - #[cfg(not(PyPy))] - pub fold: c_uchar, - pub tzinfo: *mut PyObject, -} - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -/// Structure representing a `datetime.timedelta` -pub struct PyDateTime_Delta { - pub ob_base: PyObject, + year: c_int, + month: c_int, + day: c_int, + hour: c_int, + minute: c_int, + second: c_int, + microsecond: c_int, + tzinfo: *mut PyObject, + fold: c_int, + cls: *mut PyTypeObject, + ) -> *mut PyObject, #[cfg(not(PyPy))] - pub hashcode: Py_hash_t, - pub days: c_int, - pub seconds: c_int, - pub microseconds: c_int, + pub Time_FromTimeAndFold: unsafe extern "C" fn( + hour: c_int, + minute: c_int, + second: c_int, + microsecond: c_int, + tzinfo: *mut PyObject, + fold: c_int, + cls: *mut PyTypeObject, + ) -> *mut PyObject, } // Python already shares this object between threads, so it's no more evil for us to do it too! @@ -256,6 +491,8 @@ pub unsafe fn PyDateTime_IMPORT() -> &'static PyDateTime_CAPI { }) } +// skipped non-limited PyDateTime_TimeZone_UTC + /// Type Check macros /// /// These are bindings around the C API typecheck macros, all of them return @@ -321,228 +558,24 @@ pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == PyDateTimeAPI.TZInfoType) as c_int } -/// Accessor functions -#[cfg(not(PyPy))] -macro_rules! _access_field { - ($obj:expr, $type: ident, $field:ident) => { - (*($obj as *mut $type)).$field - }; -} - -// Accessor functions for PyDateTime_Date and PyDateTime_DateTime -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`. -/// Returns a signed integer greater than 0. -pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { - // This should work for Date or DateTime - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[0]) << 8 | c_int::from(d.data[1]) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`. -/// Returns a signed integer in the range `[1, 12]`. -pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[2]) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[1, 31]`. -pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { - let d = *(o as *mut PyDateTime_Date); - c_int::from(d.data[3]) -} - -// Accessor macros for times -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_HOUR { - ($o: expr, $offset:expr) => { - c_int::from((*$o).data[$offset + 0]) - }; -} - -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_MINUTE { - ($o: expr, $offset:expr) => { - c_int::from((*$o).data[$offset + 1]) - }; -} - -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_SECOND { - ($o: expr, $offset:expr) => { - c_int::from((*$o).data[$offset + 2]) - }; -} - -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_MICROSECOND { - ($o: expr, $offset:expr) => { - (c_int::from((*$o).data[$offset + 3]) << 16) - | (c_int::from((*$o).data[$offset + 4]) << 8) - | (c_int::from((*$o).data[$offset + 5])) - }; -} - -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_FOLD { - ($o: expr) => { - (*$o).fold - }; -} - -#[cfg(not(PyPy))] -macro_rules! _PyDateTime_GET_TZINFO { - ($o: expr) => { - (*$o).tzinfo - }; -} - -// Accessor functions for DateTime -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the hour component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 23]` -pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { - _PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the minute component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 59]` -pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { - _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the second component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 59]` -pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { - _PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the microsecond component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 999999]` -pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { - _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the fold component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 1]` -pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { - _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the tzinfo component of a `PyDateTime_DateTime`. -/// Returns a pointer to a `PyObject` that should be either NULL or an instance -/// of a `datetime.tzinfo` subclass. -pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { - _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime) -} - -// Accessor functions for Time -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the hour component of a `PyDateTime_Time`. -/// Returns a signed integer in the interval `[0, 23]` -pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { - _PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the minute component of a `PyDateTime_Time`. -/// Returns a signed integer in the interval `[0, 59]` -pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { - _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the second component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 59]` -pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { - _PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the microsecond component of a `PyDateTime_DateTime`. -/// Returns a signed integer in the interval `[0, 999999]` -pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { - _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0) -} - -#[cfg(not(PyPy))] -#[inline] -/// Retrieve the fold component of a `PyDateTime_Time`. -/// Returns a signed integer in the interval `[0, 1]` -pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar { - _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time) -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the tzinfo component of a `PyDateTime_Time`. -/// Returns a pointer to a `PyObject` that should be either NULL or an instance -/// of a `datetime.tzinfo` subclass. -pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { - _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time) -} - -// Accessor functions for PyDateTime_Delta -#[cfg(not(PyPy))] -macro_rules! _access_delta_field { - ($obj:expr, $field:ident) => { - _access_field!($obj, PyDateTime_Delta, $field) - }; -} - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the days component of a `PyDateTime_Delta`. -/// -/// Returns a signed integer in the interval [-999999999, 999999999]. -/// -/// Note: This retrieves a component from the underlying structure, it is *not* -/// a representation of the total duration of the structure. -pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { - _access_delta_field!(o, days) -} +// skipped non-limited PyDate_FromDate +// skipped non-limited PyDateTime_FromDateAndTime +// skipped non-limited PyDateTime_FromDateAndTimeAndFold +// skipped non-limited PyTime_FromTime +// skipped non-limited PyTime_FromTimeAndFold +// skipped non-limited PyDelta_FromDSU +// skipped non-limited PyTimeZone_FromOffset +// skipped non-limited PyTimeZone_FromOffsetAndName -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the seconds component of a `PyDateTime_Delta`. -/// -/// Returns a signed integer in the interval [0, 86399]. -/// -/// Note: This retrieves a component from the underlying structure, it is *not* -/// a representation of the total duration of the structure. -pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { - _access_delta_field!(o, seconds) +#[cfg(PyPy)] +extern "C" { + #[link_name = "PyPyDate_FromTimestamp"] + pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject; + #[link_name = "PyPyDateTime_FromTimestamp"] + pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject; } - -#[inline] -#[cfg(not(PyPy))] -/// Retrieve the seconds component of a `PyDateTime_Delta`. -/// -/// Returns a signed integer in the interval [0, 999999]. -/// -/// Note: This retrieves a component from the underlying structure, it is *not* -/// a representation of the total duration of the structure. -pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { - _access_delta_field!(o, microseconds) +#[cfg(PyPy)] +extern "C" { + #[link_name = "_PyPyDateTime_Import"] + pub fn PyDateTime_Import() -> &'static PyDateTime_CAPI; } diff --git a/src/ffi/descrobject.rs b/src/ffi/descrobject.rs index 6cdb91a4626..177387723c0 100644 --- a/src/ffi/descrobject.rs +++ b/src/ffi/descrobject.rs @@ -20,27 +20,19 @@ pub struct PyGetSetDef { pub closure: *mut c_void, } -pub const PyGetSetDef_INIT: PyGetSetDef = PyGetSetDef { - name: ptr::null_mut(), - get: None, - set: None, - doc: ptr::null_mut(), - closure: ptr::null_mut(), -}; +// skipped non-limited wrapperfunc +// skipped non-limited wrapperfunc_kwds +// skipped non-limited struct wrapperbase +// skipped non-limited PyWrapperFlag_KEYWORDS -#[cfg(any(PyPy, Py_LIMITED_API))] -pub const PyGetSetDef_DICT: PyGetSetDef = PyGetSetDef_INIT; - -// 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)))] -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(), -}; +// skipped non-limited PyDescrObject +// skipped non-limited PyDescr_COMMON +// skipped non-limited PyDescr_TYPE +// skipped non-limited PyDescr_NAME +// skipped non-limited PyMethodDescrObject +// skipped non-limited PyMemberDescrObject +// skipped non-limited PyGetSetDescrObject +// skipped non-limited PyWrapperDescrObject #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { @@ -56,6 +48,7 @@ extern "C" { pub static mut PyWrapperDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyDictProxy_Type")] pub static mut PyDictProxy_Type: PyTypeObject; +// skipped non-limited _PyMethodWrapper_Type } extern "C" { @@ -65,6 +58,8 @@ extern "C" { -> *mut PyObject; pub fn PyDescr_NewMember(arg1: *mut PyTypeObject, arg2: *mut PyMemberDef) -> *mut PyObject; pub fn PyDescr_NewGetSet(arg1: *mut PyTypeObject, arg2: *mut PyGetSetDef) -> *mut PyObject; + // skipped non-limited PyDescr_NewWrapper + // skipped non-limited PyDescr_IsData #[cfg_attr(PyPy, link_name = "PyPyDictProxy_New")] pub fn PyDictProxy_New(arg1: *mut PyObject) -> *mut PyObject; pub fn PyWrapper_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; @@ -72,3 +67,35 @@ 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/dictobject.rs b/src/ffi/dictobject.rs index fa37ed1ebdd..cfb579952f5 100644 --- a/src/ffi/dictobject.rs +++ b/src/ffi/dictobject.rs @@ -6,33 +6,6 @@ use std::os::raw::{c_char, c_int}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyDict_Type")] pub static mut PyDict_Type: PyTypeObject; - pub static mut PyDictIterKey_Type: PyTypeObject; - pub static mut PyDictIterValue_Type: PyTypeObject; - pub static mut PyDictIterItem_Type: PyTypeObject; - pub static mut PyDictKeys_Type: PyTypeObject; - pub static mut PyDictItems_Type: PyTypeObject; - pub static mut PyDictValues_Type: PyTypeObject; - #[cfg(Py_3_8)] - pub static mut PyDictRevIterKey_Type: PyTypeObject; - #[cfg(Py_3_8)] - pub static mut PyDictRevIterValue_Type: PyTypeObject; - #[cfg(Py_3_8)] - pub static mut PyDictRevIterItem_Type: PyTypeObject; -} - -#[repr(C)] -pub struct PyDictKeysObject { - _unused: [u8; 0], -} - -#[repr(C)] -#[derive(Debug)] -pub struct PyDictObject { - pub ob_base: PyObject, - pub ma_used: Py_ssize_t, - pub ma_version_tag: u64, - pub ma_keys: *mut PyDictKeysObject, - pub ma_values: *mut *mut PyObject, } #[inline] @@ -45,43 +18,14 @@ pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == &mut PyDict_Type) as c_int } -#[inline] -pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int { - (Py_TYPE(op) == &mut PyDictKeys_Type) as c_int -} - -#[inline] -pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int { - (Py_TYPE(op) == &mut PyDictItems_Type) as c_int -} - -#[inline] -pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int { - (Py_TYPE(op) == &mut PyDictValues_Type) as c_int -} - -#[inline] -pub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int { - (PyDictKeys_Check(op) != 0 || PyDictItems_Check(op) != 0) as c_int -} - extern "C" { #[cfg_attr(PyPy, link_name = "PyPyDict_New")] pub fn PyDict_New() -> *mut PyObject; - #[cfg(not(PyPy))] - pub fn _PyDict_NewPresized(minused: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_GetItem")] pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject; pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_SetItem")] pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject, item: *mut PyObject) -> c_int; - #[cfg(not(PyPy))] - pub fn _PyDict_SetItem_KnownHash( - mp: *mut PyObject, - key: *mut PyObject, - item: *mut PyObject, - hash: crate::ffi::Py_hash_t, - ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_DelItem")] pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Clear")] @@ -93,14 +37,6 @@ extern "C" { key: *mut *mut PyObject, value: *mut *mut PyObject, ) -> c_int; - #[cfg(not(PyPy))] - pub fn _PyDict_Next( - mp: *mut PyObject, - pos: *mut Py_ssize_t, - key: *mut *mut PyObject, - value: *mut *mut PyObject, - hash: *mut crate::ffi::Py_hash_t, - ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Keys")] pub fn PyDict_Keys(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Values")] @@ -113,8 +49,6 @@ extern "C" { pub fn PyDict_Copy(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Contains")] pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject) -> c_int; - #[cfg(not(PyPy))] - pub fn _PyDict_Contains(mp: *mut PyObject, key: *mut PyObject, hash: Py_ssize_t) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Update")] pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Merge")] @@ -130,6 +64,49 @@ extern "C" { ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_DelItemString")] pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char) -> c_int; - #[cfg(not(PyPy))] - pub fn _PyObject_GetDictPtr(obj: *mut PyObject) -> *mut *mut PyObject; +// skipped 3.10 / ex-non-limited PyObject_GenericGetDict +} + +#[cfg_attr(windows, link(name = "pythonXY"))] +extern "C" { + pub static mut PyDictKeys_Type: PyTypeObject; + pub static mut PyDictValues_Type: PyTypeObject; + pub static mut PyDictItems_Type: PyTypeObject; +} + +#[inline] +pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyDictKeys_Type) as c_int +} + +#[inline] +pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyDictValues_Type) as c_int +} + +#[inline] +pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int { + (Py_TYPE(op) == &mut PyDictItems_Type) as c_int } + +#[inline] +pub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int { + (PyDictKeys_Check(op) != 0 || PyDictItems_Check(op) != 0) as c_int +} + +#[cfg_attr(windows, link(name = "pythonXY"))] +extern "C" { + pub static mut PyDictIterKey_Type: PyTypeObject; + pub static mut PyDictIterValue_Type: PyTypeObject; + pub static mut PyDictIterItem_Type: PyTypeObject; + #[cfg(Py_3_8)] + pub static mut PyDictRevIterKey_Type: PyTypeObject; + #[cfg(Py_3_8)] + pub static mut PyDictRevIterValue_Type: PyTypeObject; + #[cfg(Py_3_8)] + pub static mut PyDictRevIterItem_Type: PyTypeObject; +} + +#[cfg(any(PyPy, Py_LIMITED_API))] +// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) +opaque_struct!(PyDictObject); diff --git a/src/ffi/eval.rs b/src/ffi/eval.rs index 347f1390ddb..b554cda3c32 100644 --- a/src/ffi/eval.rs +++ b/src/ffi/eval.rs @@ -21,4 +21,7 @@ extern "C" { kwdefs: *mut PyObject, closure: *mut PyObject, ) -> *mut PyObject; + +// skipped non-limited _PyEval_EvalCodeWithName +// skipped non-limited _PyEval_CallTracing } diff --git a/src/ffi/fileobject.rs b/src/ffi/fileobject.rs index 61307496d88..029304eb6f2 100644 --- a/src/ffi/fileobject.rs +++ b/src/ffi/fileobject.rs @@ -14,14 +14,14 @@ extern "C" { arg7: *const c_char, arg8: c_int, ) -> *mut PyObject; - #[cfg_attr(PyPy, link_name = "PyPyFile_AsFileDescriptor")] - pub fn PyObject_AsFileDescriptor(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyFile_GetLine")] pub fn PyFile_GetLine(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFile_WriteObject")] pub fn PyFile_WriteObject(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyFile_WriteString")] pub fn PyFile_WriteString(arg1: *const c_char, arg2: *mut PyObject) -> c_int; + #[cfg_attr(PyPy, link_name = "PyPyFile_AsFileDescriptor")] + pub fn PyObject_AsFileDescriptor(arg1: *mut PyObject) -> c_int; } #[cfg_attr(windows, link(name = "pythonXY"))] @@ -29,4 +29,7 @@ extern "C" { pub static mut Py_FileSystemDefaultEncoding: *const c_char; pub static mut Py_FileSystemDefaultEncodeErrors: *const c_char; pub static mut Py_HasFileSystemDefaultEncoding: c_int; +// skipped Python 3.7 / ex-non-limited Py_UTF8Mode } + +// skipped _PyIsSelectable_fd diff --git a/src/ffi/floatobject.rs b/src/ffi/floatobject.rs index a5928d28493..d33feb9aa9b 100644 --- a/src/ffi/floatobject.rs +++ b/src/ffi/floatobject.rs @@ -1,6 +1,11 @@ use crate::ffi::object::*; use std::os::raw::{c_double, c_int}; +#[cfg(Py_LIMITED_API)] +// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) +opaque_struct!(PyFloatObject); + +#[cfg(not(Py_LIMITED_API))] #[repr(C)] pub struct PyFloatObject { pub ob_base: PyObject, @@ -23,11 +28,8 @@ pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == &mut PyFloat_Type) as c_int } -#[cfg(not(Py_LIMITED_API))] -#[inline] -pub unsafe fn PyFloat_AS_DOUBLE(op: *mut PyObject) -> c_double { - (*(op as *mut PyFloatObject)).ob_fval -} +// skipped Py_RETURN_NAN +// skipped Py_RETURN_INF extern "C" { pub fn PyFloat_GetMax() -> c_double; @@ -40,3 +42,18 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyFloat_AsDouble")] pub fn PyFloat_AsDouble(arg1: *mut PyObject) -> c_double; } + +#[cfg(not(Py_LIMITED_API))] +#[inline] +pub unsafe fn PyFloat_AS_DOUBLE(op: *mut PyObject) -> c_double { + (*(op as *mut PyFloatObject)).ob_fval +} + +// skipped non-limited _PyFloat_Pack2 +// skipped non-limited _PyFloat_Pack4 +// skipped non-limited _PyFloat_Pack8 +// skipped non-limited _PyFloat_Unpack2 +// skipped non-limited _PyFloat_Unpack4 +// skipped non-limited _PyFloat_Unpack8 +// skipped non-limited _PyFloat_DebugMallocStats +// skipped non-limited _PyFloat_FormatAdvancedWriter diff --git a/src/ffi/genobject.rs b/src/ffi/genobject.rs index af7a936bde0..88e9f25fb1c 100644 --- a/src/ffi/genobject.rs +++ b/src/ffi/genobject.rs @@ -1,6 +1,6 @@ -use crate::ffi::frameobject::PyFrameObject; use crate::ffi::object::*; use crate::ffi::pyport::Py_ssize_t; +use crate::ffi::PyFrameObject; use std::os::raw::c_int; #[repr(C)] diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 4f9b394b695..a72c25e184b 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -30,7 +30,6 @@ pub use self::enumobject::*; pub use self::eval::*; pub use self::fileobject::*; pub use self::floatobject::*; -pub use self::frameobject::PyFrameObject; pub use self::funcobject::*; pub use self::genobject::*; pub use self::import::*; @@ -53,6 +52,7 @@ pub use self::pyarena::*; pub use self::pycapsule::*; pub use self::pydebug::*; pub use self::pyerrors::*; +pub use self::pyframe::*; pub use self::pyhash::*; pub use self::pylifecycle::*; pub use self::pymem::*; @@ -79,22 +79,37 @@ pub use self::cpython::*; // skipped asdl.h // skipped ast.h mod bltinmodule; -mod boolobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 +mod boolobject; // TODO supports PEP-384 only mod bytearrayobject; mod bytesobject; // skipped cellobject.h -mod ceval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 +mod ceval; // TODO supports PEP-384 only // skipped classobject.h mod code; -mod codecs; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 +mod codecs; // TODO supports PEP-384 only mod compile; // TODO: incomplete -mod complexobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 - +mod complexobject; // TODO supports PEP-384 only +#[cfg(all(Py_3_8, not(Py_LIMITED_API)))] +mod context; // It's actually 3.7.1, but no cfg for patches. +#[cfg(not(all(Py_3_8, not(Py_LIMITED_API))))] +mod context {} +#[cfg(not(Py_LIMITED_API))] +pub(crate) mod datetime; +mod descrobject; // TODO supports PEP-384 only +mod dictobject; // skipped dynamic_annotations.h +mod enumobject; // skipped errcode.h +mod eval; // TODO supports PEP-384 only + // skipped exports.h +mod fileobject; // TODO: incomplete + // skipped fileutils.h +mod floatobject; // TODO supports PEP-384 only + +// skipped empty frameobject.h // skipped genericaliasobject.h // skipped interpreteridobject.h // skipped longintrepr.h @@ -111,7 +126,8 @@ mod complexobject; // TODO supports PEP-384 only; needs adjustment for Python 3. // skipped pydtrace.h // skipped pyexpat.h // skipped pyfpe.h -// skipped pyframe.h +mod pyframe; // TODO: incomplete + // skipped pymacconfig.h // skipped pymacro.h // skipped pymath.h @@ -142,25 +158,20 @@ mod typeslots; mod longobject; mod unicodeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // mod longintrepr; TODO excluded by PEP-384 -mod dictobject; -mod floatobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod listobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod memoryobject; // 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 odictobject; TODO new in 3.5 -mod enumobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 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 funcobject; TODO excluded by PEP-384 // mod classobject; TODO excluded by PEP-384 -mod fileobject; // 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 mod sliceobject; mod traceback; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // mod cellobject; TODO excluded by PEP-384 -mod descrobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod genobject; // TODO excluded by PEP-384 mod iterobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod structseq; @@ -185,14 +196,6 @@ mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 an mod objectabstract; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 -#[cfg(all(Py_3_8, not(Py_LIMITED_API)))] -mod context; // It's actually 3.7.1, but no cfg for patches. - -#[cfg(not(all(Py_3_8, not(Py_LIMITED_API))))] -mod context {} - -mod eval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 - // mod pyctype; TODO excluded by PEP-384 mod pystrtod; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 // mod pystrcmp; TODO nothing interesting for Rust? @@ -203,15 +206,6 @@ mod pystrtod; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and // Additional headers that are not exported by Python.h pub mod structmember; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 -#[cfg(not(Py_LIMITED_API))] -pub mod frameobject; -#[cfg(Py_LIMITED_API)] -pub mod frameobject { - opaque_struct!(PyFrameObject); -} - -#[cfg(not(Py_LIMITED_API))] -pub(crate) mod datetime; pub(crate) mod marshal; pub(crate) mod funcobject; diff --git a/src/ffi/object.rs b/src/ffi/object.rs index b16e1a12f8e..ddc608d1eec 100644 --- a/src/ffi/object.rs +++ b/src/ffi/object.rs @@ -892,3 +892,8 @@ pub fn PyObject_Check(_arg1: *mut PyObject) -> c_int { pub fn PySuper_Check(_arg1: *mut PyObject) -> c_int { 0 } + +#[cfg(not(PyPy))] +extern "C" { + pub fn _PyObject_GetDictPtr(obj: *mut PyObject) -> *mut *mut PyObject; +} diff --git a/src/ffi/pyframe.rs b/src/ffi/pyframe.rs new file mode 100644 index 00000000000..007cbf759bf --- /dev/null +++ b/src/ffi/pyframe.rs @@ -0,0 +1,12 @@ +#[cfg(not(Py_LIMITED_API))] +use crate::ffi::PyFrameObject; +use std::os::raw::c_int; + +#[cfg(Py_LIMITED_API)] +opaque_struct!(PyFrameObject); + +extern "C" { + pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int; +} +// skipped PyFrame_GetLineNumber +// skipped PyFrame_GetCode diff --git a/src/ffi/pystate.rs b/src/ffi/pystate.rs index 58e98875ab7..73bdf632017 100644 --- a/src/ffi/pystate.rs +++ b/src/ffi/pystate.rs @@ -1,7 +1,7 @@ use crate::ffi::ceval::_PyFrameEvalFunction; -use crate::ffi::frameobject::PyFrameObject; use crate::ffi::moduleobject::PyModuleDef; use crate::ffi::object::PyObject; +use crate::ffi::PyFrameObject; use std::os::raw::{c_int, c_long}; pub const MAX_CO_EXTRA_USERS: c_int = 255; diff --git a/src/pyclass.rs b/src/pyclass.rs index f82c4e829c8..22287a522f0 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -391,6 +391,7 @@ fn py_class_properties() -> Vec { match def { PyMethodDefType::Getter(getter) => { if !defs.contains_key(getter.name) { + #[allow(deprecated)] let _ = defs.insert(getter.name.to_owned(), ffi::PyGetSetDef_INIT); } let def = defs.get_mut(getter.name).expect("Failed to call get_mut"); @@ -398,6 +399,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 def = defs.get_mut(setter.name).expect("Failed to call get_mut");