From cdf86482d8c4a6755e8e4a6aa2d2515b4c137e28 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 4 Jun 2022 09:28:22 +0100 Subject: [PATCH] ffi: many fixes to pypy definitions --- CHANGELOG.md | 4 ++- pyo3-ffi/src/cpython/code.rs | 10 ++++++-- pyo3-ffi/src/cpython/compile.rs | 21 +++++++-------- pyo3-ffi/src/cpython/frameobject.rs | 13 ++++++---- pyo3-ffi/src/cpython/genobject.rs | 8 +++--- pyo3-ffi/src/cpython/import.rs | 9 ++++++- pyo3-ffi/src/cpython/listobject.rs | 7 +++++ pyo3-ffi/src/cpython/pyerrors.rs | 15 ++++++++++- pyo3-ffi/src/cpython/pymem.rs | 5 +++- pyo3-ffi/src/cpython/pystate.rs | 1 + pyo3-ffi/src/cpython/pythonrun.rs | 18 ++++++------- pyo3-ffi/src/cpython/unicodeobject.rs | 5 +++- pyo3-ffi/src/datetime.rs | 33 +++++++++++++----------- pyo3-ffi/src/lib.rs | 4 +-- pyo3-ffi/src/objimpl.rs | 8 +++--- pyo3-ffi/src/pyhash.rs | 8 +++--- pyo3-ffi/src/pythonrun.rs | 19 +++++++------- pyo3-ffi/src/setobject.rs | 6 ++--- pyo3-ffi/src/weakrefobject.rs | 1 + pytests/src/datetime.rs | 13 +++------- src/exceptions.rs | 16 ++++++++++++ src/ffi/tests.rs | 1 + src/types/datetime.rs | 16 +++--------- src/types/frozenset.rs | 8 ++++++ src/types/set.rs | 15 ++++++++++- tests/test_inheritance.rs | 37 +++++++++++++++------------ 26 files changed, 191 insertions(+), 110 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bb971ef..e591e565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add FFI definition `PyFrame_GetCode`. [#2406](https://github.com/PyO3/pyo3/pull/2406) - Added `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408) - Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423) +- Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) ### Changed @@ -47,7 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix FFI definition `PySyntaxErrorObject` missing members `end_lineno` and `end_offset` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyHeapTypeObject` missing member `ht_module` on Python 3.9 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyFrameObject` having multiple incorrect members on various Python versions. [#2424](https://github.com/PyO3/pyo3/pull/2424) -- Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2424](https://github.com/PyO3/pyo3/pull/2424) +- Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2428](https://github.com/PyO3/pyo3/pull/2428) +- Fix FFI definitions `PyDateTime_CAPI`. `PyDateTime_Date`, `PyASCIIObject`, `PyBaseExceptionObject`, `PyListObject`, and `PyTypeObject` on PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) ## [0.16.5] - 2022-05-15 diff --git a/pyo3-ffi/src/cpython/code.rs b/pyo3-ffi/src/cpython/code.rs index 91183c97..894e61c2 100644 --- a/pyo3-ffi/src/cpython/code.rs +++ b/pyo3-ffi/src/cpython/code.rs @@ -1,14 +1,17 @@ use crate::object::*; use crate::pyport::Py_ssize_t; -use std::os::raw::{c_char, c_int, c_uchar, c_void}; +#[cfg(not(PyPy))] +use std::os::raw::c_uchar; +use std::os::raw::{c_char, c_int, c_void}; // skipped _Py_CODEUNIT // skipped _Py_OPCODE // skipped _Py_OPARG -#[cfg(all(Py_3_8, not(Py_3_11)))] +#[cfg(all(Py_3_8, not(PyPy)))] opaque_struct!(_PyOpcache); +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { @@ -44,6 +47,9 @@ pub struct PyCodeObject { pub co_opcache_size: c_uchar, } +#[cfg(PyPy)] +opaque_struct!(PyCodeObject); + /* Masks for co_flags */ pub const CO_OPTIMIZED: c_int = 0x0001; pub const CO_NEWLOCALS: c_int = 0x0002; diff --git a/pyo3-ffi/src/cpython/compile.rs b/pyo3-ffi/src/cpython/compile.rs index f7aa7f8f..9a2afdb9 100644 --- a/pyo3-ffi/src/cpython/compile.rs +++ b/pyo3-ffi/src/cpython/compile.rs @@ -1,12 +1,12 @@ -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use crate::object::PyObject; -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use crate::pyarena::*; -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use crate::pythonrun::*; -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use crate::PyCodeObject; -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use std::os::raw::c_char; use std::os::raw::c_int; @@ -30,6 +30,7 @@ pub struct PyCompilerFlags { // skipped non-limited _PyCompilerFlags_INIT +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyFutureFeatures { @@ -49,10 +50,10 @@ pub const FUTURE_GENERATOR_STOP: &str = "generator_stop"; // skipped non-limited FUTURE_ANNOTATIONS extern "C" { - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyNode_Compile(arg1: *mut _node, arg2: *const c_char) -> *mut PyCodeObject; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyAST_CompileEx( _mod: *mut _mod, filename: *const c_char, @@ -61,7 +62,7 @@ extern "C" { arena: *mut PyArena, ) -> *mut PyCodeObject; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyAST_CompileObject( _mod: *mut _mod, filename: *mut PyObject, @@ -70,10 +71,10 @@ extern "C" { arena: *mut PyArena, ) -> *mut PyCodeObject; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyFuture_FromAST(_mod: *mut _mod, filename: *const c_char) -> *mut PyFutureFeatures; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyFuture_FromASTObject( _mod: *mut _mod, filename: *mut PyObject, diff --git a/pyo3-ffi/src/cpython/frameobject.rs b/pyo3-ffi/src/cpython/frameobject.rs index 5074f0fd..a8446244 100644 --- a/pyo3-ffi/src/cpython/frameobject.rs +++ b/pyo3-ffi/src/cpython/frameobject.rs @@ -1,14 +1,16 @@ use crate::cpython::code::PyCodeObject; use crate::object::*; use crate::pystate::PyThreadState; -use std::os::raw::{c_char, c_int}; +#[cfg(not(any(PyPy, Py_3_11)))] +use std::os::raw::c_char; +use std::os::raw::c_int; -#[cfg(not(Py_3_11))] +#[cfg(not(any(PyPy, Py_3_11)))] pub type PyFrameState = c_char; #[repr(C)] #[derive(Copy, Clone)] -#[cfg(not(Py_3_11))] +#[cfg(not(any(PyPy, Py_3_11)))] pub struct PyTryBlock { pub b_type: c_int, pub b_handler: c_int, @@ -17,7 +19,7 @@ pub struct PyTryBlock { #[repr(C)] #[derive(Copy, Clone)] -#[cfg(not(Py_3_11))] +#[cfg(not(any(PyPy, Py_3_11)))] pub struct PyFrameObject { pub ob_base: PyVarObject, pub f_back: *mut PyFrameObject, @@ -46,7 +48,7 @@ pub struct PyFrameObject { pub f_localsplus: [*mut PyObject; 1], } -#[cfg(Py_3_11)] +#[cfg(any(PyPy, Py_3_11))] opaque_struct!(PyFrameObject); // skipped _PyFrame_IsRunnable @@ -74,6 +76,7 @@ extern "C" { // skipped _PyFrame_New_NoTrack pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int); + #[cfg(not(any(PyPy, Py_3_11)))] pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int); diff --git a/pyo3-ffi/src/cpython/genobject.rs b/pyo3-ffi/src/cpython/genobject.rs index a9807118..88895a48 100644 --- a/pyo3-ffi/src/cpython/genobject.rs +++ b/pyo3-ffi/src/cpython/genobject.rs @@ -1,8 +1,10 @@ use crate::object::*; -use crate::pyport::Py_ssize_t; -use crate::{PyFrameObject, _PyErr_StackItem}; +use crate::PyFrameObject; +#[cfg(not(PyPy))] +use crate::{Py_ssize_t, _PyErr_StackItem}; use std::os::raw::c_int; +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyGenObject { @@ -44,7 +46,7 @@ extern "C" { // skipped _PyGen_FetchStopIterationValue // skipped _PyGen_yf // skipped _PyGen_Finalize - #[cfg(not(Py_3_9))] + #[cfg(not(any(Py_3_9, PyPy)))] #[deprecated(note = "This function was never documented in the Python API.")] pub fn PyGen_NeedsFinalizing(op: *mut PyGenObject) -> c_int; } diff --git a/pyo3-ffi/src/cpython/import.rs b/pyo3-ffi/src/cpython/import.rs index d85eb5fa..de58935a 100644 --- a/pyo3-ffi/src/cpython/import.rs +++ b/pyo3-ffi/src/cpython/import.rs @@ -1,5 +1,7 @@ use crate::{PyInterpreterState, PyObject}; -use std::os::raw::{c_char, c_int, c_uchar}; +#[cfg(not(PyPy))] +use std::os::raw::c_uchar; +use std::os::raw::{c_char, c_int}; // skipped PyInit__imp @@ -27,6 +29,7 @@ extern "C" { ) -> c_int; } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct _inittab { @@ -36,13 +39,16 @@ pub struct _inittab { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(PyPy))] pub static mut PyImport_Inittab: *mut _inittab; } extern "C" { + #[cfg(not(PyPy))] pub fn PyImport_ExtendInittab(newtab: *mut _inittab) -> c_int; } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct _frozen { @@ -53,5 +59,6 @@ pub struct _frozen { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(PyPy))] pub static mut PyImport_FrozenModules: *const _frozen; } diff --git a/pyo3-ffi/src/cpython/listobject.rs b/pyo3-ffi/src/cpython/listobject.rs index 13b82ff1..012221da 100644 --- a/pyo3-ffi/src/cpython/listobject.rs +++ b/pyo3-ffi/src/cpython/listobject.rs @@ -1,6 +1,8 @@ use crate::object::*; +#[cfg(not(PyPy))] use crate::pyport::Py_ssize_t; +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyListObject { @@ -9,6 +11,11 @@ pub struct PyListObject { pub allocated: Py_ssize_t, } +#[cfg(PyPy)] +pub struct PyListObject { + pub ob_base: PyObject, +} + // skipped _PyList_Extend // skipped _PyList_DebugMallocStats // skipped _PyList_CAST (used inline below) diff --git a/pyo3-ffi/src/cpython/pyerrors.rs b/pyo3-ffi/src/cpython/pyerrors.rs index 3058be47..34497676 100644 --- a/pyo3-ffi/src/cpython/pyerrors.rs +++ b/pyo3-ffi/src/cpython/pyerrors.rs @@ -1,17 +1,26 @@ -use crate::{PyObject, Py_ssize_t}; +use crate::PyObject; +#[cfg(not(PyPy))] +use crate::Py_ssize_t; #[repr(C)] #[derive(Debug)] pub struct PyBaseExceptionObject { pub ob_base: PyObject, + #[cfg(not(PyPy))] pub dict: *mut PyObject, + #[cfg(not(PyPy))] pub args: *mut PyObject, + #[cfg(not(PyPy))] pub traceback: *mut PyObject, + #[cfg(not(PyPy))] pub context: *mut PyObject, + #[cfg(not(PyPy))] pub cause: *mut PyObject, + #[cfg(not(PyPy))] pub suppress_context: char, } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug)] pub struct PySyntaxErrorObject { @@ -28,6 +37,7 @@ pub struct PySyntaxErrorObject { pub print_file_and_line: *mut PyObject, } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug)] pub struct PyImportErrorObject { @@ -37,6 +47,7 @@ pub struct PyImportErrorObject { pub path: *mut PyObject, } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug)] pub struct PyUnicodeErrorObject { @@ -48,6 +59,7 @@ pub struct PyUnicodeErrorObject { pub reason: *mut PyObject, } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug)] pub struct PySystemExitObject { @@ -55,6 +67,7 @@ pub struct PySystemExitObject { pub code: *mut PyObject, } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug)] pub struct PyOSErrorObject { diff --git a/pyo3-ffi/src/cpython/pymem.rs b/pyo3-ffi/src/cpython/pymem.rs index 7c07d5c9..2dfb3f3b 100644 --- a/pyo3-ffi/src/cpython/pymem.rs +++ b/pyo3-ffi/src/cpython/pymem.rs @@ -26,7 +26,7 @@ pub enum PyMemAllocatorDomain { } // skipped PyMemAllocatorName - +#[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyMemAllocatorEx { @@ -40,7 +40,10 @@ pub struct PyMemAllocatorEx { } extern "C" { + #[cfg(not(PyPy))] pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); + #[cfg(not(PyPy))] pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); + #[cfg(not(PyPy))] pub fn PyMem_SetupDebugHooks(); } diff --git a/pyo3-ffi/src/cpython/pystate.rs b/pyo3-ffi/src/cpython/pystate.rs index 19f3a3d0..2dcd6958 100644 --- a/pyo3-ffi/src/cpython/pystate.rs +++ b/pyo3-ffi/src/cpython/pystate.rs @@ -27,6 +27,7 @@ pub const PyTrace_OPCODE: c_int = 7; // skipped PyTraceInfo // skipped CFrame +#[cfg(not(PyPy))] #[repr(C)] #[derive(Clone, Copy)] pub struct _PyErr_StackItem { diff --git a/pyo3-ffi/src/cpython/pythonrun.rs b/pyo3-ffi/src/cpython/pythonrun.rs index ba86fe33..a92528b7 100644 --- a/pyo3-ffi/src/cpython/pythonrun.rs +++ b/pyo3-ffi/src/cpython/pythonrun.rs @@ -1,8 +1,8 @@ use crate::object::*; -#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] use crate::pyarena::PyArena; use crate::PyCompilerFlags; -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] use crate::{_mod, _node}; use libc::FILE; use std::os::raw::{c_char, c_int}; @@ -54,7 +54,7 @@ extern "C" { flags: *mut PyCompilerFlags, ) -> c_int; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyParser_ASTFromString( s: *const c_char, filename: *const c_char, @@ -62,7 +62,7 @@ extern "C" { flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyParser_ASTFromStringObject( s: *const c_char, filename: *mut PyObject, @@ -70,7 +70,7 @@ extern "C" { flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyParser_ASTFromFile( fp: *mut FILE, filename: *const c_char, @@ -82,7 +82,7 @@ extern "C" { errcode: *mut c_int, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyParser_ASTFromFileObject( fp: *mut FILE, filename: *mut PyObject, @@ -218,14 +218,14 @@ extern "C" { // skipped macro PyRun_AnyFileFlags extern "C" { - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlags( arg1: *const c_char, arg2: c_int, arg3: c_int, ) -> *mut _node; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlagsFilename( arg1: *const c_char, @@ -233,7 +233,7 @@ extern "C" { arg3: c_int, arg4: c_int, ) -> *mut _node; - #[cfg(not(Py_3_10))] + #[cfg(not(any(PyPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseFileFlags( arg1: *mut FILE, diff --git a/pyo3-ffi/src/cpython/unicodeobject.rs b/pyo3-ffi/src/cpython/unicodeobject.rs index 0fa355f9..cc9ec4aa 100644 --- a/pyo3-ffi/src/cpython/unicodeobject.rs +++ b/pyo3-ffi/src/cpython/unicodeobject.rs @@ -1,4 +1,6 @@ -use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_UNICODE, Py_hash_t, Py_ssize_t}; +#[cfg(not(PyPy))] +use crate::Py_hash_t; +use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_UNICODE, Py_ssize_t}; use libc::wchar_t; use std::os::raw::{c_char, c_int, c_uint, c_void}; @@ -32,6 +34,7 @@ use std::os::raw::{c_char, c_int, c_uint, c_void}; pub struct PyASCIIObject { pub ob_base: PyObject, pub length: Py_ssize_t, + #[cfg(not(PyPy))] pub hash: Py_hash_t, /// A bit field with various properties. /// diff --git a/pyo3-ffi/src/datetime.rs b/pyo3-ffi/src/datetime.rs index 166a8f31..112d9b24 100644 --- a/pyo3-ffi/src/datetime.rs +++ b/pyo3-ffi/src/datetime.rs @@ -11,12 +11,13 @@ use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE}; use std::cell::UnsafeCell; -use std::os::raw::{c_char, c_int, c_uchar}; +use std::os::raw::{c_char, c_int}; use std::ptr; #[cfg(not(PyPy))] use { crate::{PyCapsule_Import, Py_hash_t}, std::ffi::CString, + std::os::raw::c_uchar, }; // Type struct wrappers @@ -39,6 +40,7 @@ pub struct PyDateTime_Delta { // skipped non-limited PyDateTime_TZInfo // skipped non-limited _PyDateTime_BaseTZInfo +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time` without a `tzinfo` member. @@ -56,11 +58,6 @@ pub struct _PyDateTime_BaseTime { #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time`. -/// -/// # Safety -/// -/// Care should be taken when reading the `tzinfo` field of this type. If the time does not have a -/// tzinfo then the Python interpreter is free to allocate it as a [_PyDateTime_BaseTime]. pub struct PyDateTime_Time { pub ob_base: PyObject, #[cfg(not(PyPy))] @@ -70,6 +67,10 @@ pub struct PyDateTime_Time { pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], #[cfg(not(PyPy))] pub fold: c_uchar, + /// # Safety + /// + /// Care should be taken when reading this field. If the time does not have a + /// tzinfo then CPython may allocate as a `_PyDateTime_BaseTime` without this field. pub tzinfo: *mut PyObject, } @@ -80,10 +81,13 @@ pub struct PyDateTime_Date { pub ob_base: PyObject, #[cfg(not(PyPy))] pub hashcode: Py_hash_t, + #[cfg(not(PyPy))] pub hastzinfo: c_char, + #[cfg(not(PyPy))] pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], } +#[cfg(not(PyPy))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime` without a `tzinfo` member. @@ -101,11 +105,6 @@ pub struct _PyDateTime_BaseDateTime { #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime`. -/// -/// # Safety -/// -/// Care should be taken when reading the `tzinfo` field of this type. If the datetime does not have a -/// tzinfo then the Python interpreter is free to allocate it as a [_PyDateTime_BaseDateTime]. pub struct PyDateTime_DateTime { pub ob_base: PyObject, #[cfg(not(PyPy))] @@ -115,6 +114,10 @@ pub struct PyDateTime_DateTime { pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], #[cfg(not(PyPy))] pub fold: c_uchar, + /// # Safety + /// + /// Care should be taken when reading this field. If the time does not have a + /// tzinfo then CPython may allocate as a `_PyDateTime_BaseDateTime` without this field. pub tzinfo: *mut PyObject, } @@ -368,7 +371,8 @@ extern "C" { 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) + #[link_name = "PyPyDateTime_GET_FOLD"] + pub fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int; // skipped PyDateTime_DATE_GET_TZINFO (not in PyPy) #[link_name = "PyPyDateTime_TIME_GET_HOUR"] @@ -379,7 +383,8 @@ extern "C" { 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) + #[link_name = "PyPyDateTime_TIME_GET_FOLD"] + pub fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int; // skipped PyDateTime_TIME_GET_TZINFO (not in PyPy) #[link_name = "PyPyDateTime_DELTA_GET_DAYS"] @@ -441,7 +446,6 @@ pub struct PyDateTime_CAPI { ) -> *mut PyObject, pub Date_FromTimestamp: 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, @@ -454,7 +458,6 @@ pub struct PyDateTime_CAPI { fold: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, - #[cfg(not(PyPy))] pub Time_FromTimeAndFold: unsafe extern "C" fn( hour: c_int, minute: c_int, diff --git a/pyo3-ffi/src/lib.rs b/pyo3-ffi/src/lib.rs index 04ad398c..1e3ee855 100644 --- a/pyo3-ffi/src/lib.rs +++ b/pyo3-ffi/src/lib.rs @@ -314,7 +314,7 @@ pub use self::moduleobject::*; pub use self::object::*; pub use self::objimpl::*; pub use self::osmodule::*; -#[cfg(not(any(Py_LIMITED_API, Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] pub use self::pyarena::*; pub use self::pycapsule::*; pub use self::pyerrors::*; @@ -395,7 +395,7 @@ mod osmodule; // skipped picklebufobject.h // skipped pyctype.h // skipped py_curses.h -#[cfg(not(any(Py_LIMITED_API, Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] mod pyarena; mod pycapsule; // skipped pydecimal.h diff --git a/pyo3-ffi/src/objimpl.rs b/pyo3-ffi/src/objimpl.rs index deeaceb1..2a3307e6 100644 --- a/pyo3-ffi/src/objimpl.rs +++ b/pyo3-ffi/src/objimpl.rs @@ -39,25 +39,27 @@ extern "C" { pub fn PyGC_IsEnabled() -> c_int; } +#[cfg(not(any(Py_LIMITED_API, PyPy)))] #[repr(C)] #[derive(Copy, Clone)] -#[cfg(not(Py_LIMITED_API))] pub struct PyObjectArenaAllocator { pub ctx: *mut c_void, pub alloc: Option *mut c_void>, pub free: Option, } -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] impl Default for PyObjectArenaAllocator { #[inline] fn default() -> Self { unsafe { std::mem::zeroed() } } } -#[cfg(not(Py_LIMITED_API))] + extern "C" { + #[cfg(not(any(Py_LIMITED_API, PyPy)))] pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator); + #[cfg(not(any(Py_LIMITED_API, PyPy)))] pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator); } diff --git a/pyo3-ffi/src/pyhash.rs b/pyo3-ffi/src/pyhash.rs index bfff7341..f8072d85 100644 --- a/pyo3-ffi/src/pyhash.rs +++ b/pyo3-ffi/src/pyhash.rs @@ -1,6 +1,6 @@ -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] use crate::pyport::{Py_hash_t, Py_ssize_t}; -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] use std::os::raw::{c_char, c_void}; use std::os::raw::{c_int, c_ulong}; @@ -20,7 +20,7 @@ pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; // skipped non-limited _Py_HashSecret_t -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyHash_FuncDef { @@ -30,7 +30,7 @@ pub struct PyHash_FuncDef { pub seed_bits: c_int, } -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] impl Default for PyHash_FuncDef { #[inline] fn default() -> Self { diff --git a/pyo3-ffi/src/pythonrun.rs b/pyo3-ffi/src/pythonrun.rs index d3784236..196cf535 100644 --- a/pyo3-ffi/src/pythonrun.rs +++ b/pyo3-ffi/src/pythonrun.rs @@ -1,13 +1,12 @@ use crate::object::*; -#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] use libc::FILE; -#[cfg(any(Py_LIMITED_API, not(Py_3_10)))] +#[cfg(all(not(PyPy), any(Py_LIMITED_API, not(Py_3_10))))] use std::os::raw::c_char; use std::os::raw::c_int; extern "C" { - #[cfg(Py_LIMITED_API)] - #[cfg(not(PyPy))] + #[cfg(all(Py_LIMITED_API, not(PyPy)))] pub fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Print")] @@ -24,15 +23,15 @@ pub const PYOS_STACK_MARGIN: c_int = 2048; // skipped PyOS_CheckStack under Microsoft C -#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] opaque_struct!(_mod); -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] opaque_struct!(symtable); -#[cfg(not(Py_3_10))] +#[cfg(not(any(PyPy, Py_3_10)))] opaque_struct!(_node); -#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyParser_SimpleParseString(s: *const c_char, b: c_int) -> *mut _node { @@ -40,7 +39,7 @@ pub unsafe fn PyParser_SimpleParseString(s: *const c_char, b: c_int) -> *mut _no crate::PyParser_SimpleParseStringFlags(s, b, 0) } -#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] +#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyParser_SimpleParseFile(fp: *mut FILE, s: *const c_char, b: c_int) -> *mut _node { @@ -55,7 +54,7 @@ extern "C" { filename: *const c_char, start: c_int, ) -> *mut symtable; - #[cfg(not(any(Py_LIMITED_API, Py_3_10, PyPy)))] + #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] pub fn Py_SymtableStringObject( str: *const c_char, filename: *mut PyObject, diff --git a/pyo3-ffi/src/setobject.rs b/pyo3-ffi/src/setobject.rs index c90d26f5..c6297095 100644 --- a/pyo3-ffi/src/setobject.rs +++ b/pyo3-ffi/src/setobject.rs @@ -1,12 +1,12 @@ use crate::object::*; -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] use crate::pyport::Py_hash_t; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; pub const PySet_MINSIZE: usize = 8; -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] #[repr(C)] #[derive(Debug)] pub struct setentry { @@ -14,7 +14,7 @@ pub struct setentry { pub hash: Py_hash_t, } -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] #[repr(C)] #[derive(Debug)] pub struct PySetObject { diff --git a/pyo3-ffi/src/weakrefobject.rs b/pyo3-ffi/src/weakrefobject.rs index b9506115..fd5f83aa 100644 --- a/pyo3-ffi/src/weakrefobject.rs +++ b/pyo3-ffi/src/weakrefobject.rs @@ -1,6 +1,7 @@ use crate::object::*; use std::os::raw::c_int; +#[cfg(not(PyPy))] opaque_struct!(PyWeakReference); extern "C" { diff --git a/pytests/src/datetime.rs b/pytests/src/datetime.rs index b21d3e69..b0a306ec 100644 --- a/pytests/src/datetime.rs +++ b/pytests/src/datetime.rs @@ -43,7 +43,6 @@ fn make_time<'p>( ) } -#[cfg(not(PyPy))] #[pyfunction] fn time_with_fold<'p>( py: Python<'p>, @@ -78,7 +77,6 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple { ) } -#[cfg(not(PyPy))] #[pyfunction] fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple { PyTuple::new( @@ -152,7 +150,6 @@ fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple { ) } -#[cfg(not(PyPy))] #[pyfunction] fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple { PyTuple::new( @@ -227,13 +224,9 @@ pub fn datetime(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(get_datetime_tzinfo, m)?)?; m.add_function(wrap_pyfunction!(get_time_tzinfo, m)?)?; - // Functions not supported by PyPy - #[cfg(not(PyPy))] - { - m.add_function(wrap_pyfunction!(time_with_fold, m)?)?; - m.add_function(wrap_pyfunction!(get_time_tuple_fold, m)?)?; - m.add_function(wrap_pyfunction!(get_datetime_tuple_fold, m)?)?; - } + m.add_function(wrap_pyfunction!(time_with_fold, m)?)?; + m.add_function(wrap_pyfunction!(get_time_tuple_fold, m)?)?; + m.add_function(wrap_pyfunction!(get_datetime_tuple_fold, m)?)?; m.add_class::()?; diff --git a/src/exceptions.rs b/src/exceptions.rs index fb4be1e4..4a4d60ef 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -395,12 +395,15 @@ impl_native_exception!( PyExc_FloatingPointError, native_doc!("FloatingPointError") ); +#[cfg(not(PyPy))] impl_native_exception!( PyOSError, PyExc_OSError, native_doc!("OSError"), ffi::PyOSErrorObject ); +#[cfg(PyPy)] +impl_native_exception!(PyOSError, PyExc_OSError, native_doc!("OSError")); impl_native_exception!(PyImportError, PyExc_ImportError, native_doc!("ImportError")); impl_native_exception!( @@ -438,36 +441,49 @@ impl_native_exception!( PyExc_NotImplementedError, native_doc!("NotImplementedError") ); +#[cfg(not(PyPy))] impl_native_exception!( PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError"), ffi::PySyntaxErrorObject ); +#[cfg(PyPy)] +impl_native_exception!(PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError")); impl_native_exception!( PyReferenceError, PyExc_ReferenceError, native_doc!("ReferenceError") ); impl_native_exception!(PySystemError, PyExc_SystemError, native_doc!("SystemError")); +#[cfg(not(PyPy))] impl_native_exception!( PySystemExit, PyExc_SystemExit, native_doc!("SystemExit"), ffi::PySystemExitObject ); +#[cfg(PyPy)] +impl_native_exception!(PySystemExit, PyExc_SystemExit, native_doc!("SystemExit")); impl_native_exception!(PyTypeError, PyExc_TypeError, native_doc!("TypeError")); impl_native_exception!( PyUnboundLocalError, PyExc_UnboundLocalError, native_doc!("UnboundLocalError") ); +#[cfg(not(PyPy))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError"), ffi::PyUnicodeErrorObject ); +#[cfg(PyPy)] +impl_native_exception!( + PyUnicodeError, + PyExc_UnicodeError, + native_doc!("UnicodeError") +); // these three errors need arguments, so they're too annoying to write tests for using macros... impl_native_exception!( PyUnicodeDecodeError, diff --git a/src/ffi/tests.rs b/src/ffi/tests.rs index 0231b0ff..8508e6df 100644 --- a/src/ffi/tests.rs +++ b/src/ffi/tests.rs @@ -67,6 +67,7 @@ fn ascii_object_bitfield() { let mut o = PyASCIIObject { ob_base, length: 0, + #[cfg(not(PyPy))] hash: 0, state: 0, wstr: std::ptr::null_mut() as *mut wchar_t, diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 2edcc0e7..2d55caca 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -7,19 +7,17 @@ use crate::err::PyResult; use crate::ffi::{ self, PyDateTime_CAPI, PyDateTime_FromTimestamp, PyDateTime_IMPORT, PyDate_FromTimestamp, }; -#[cfg(not(PyPy))] -use crate::ffi::{PyDateTime_DATE_GET_FOLD, PyDateTime_TIME_GET_FOLD}; use crate::ffi::{ - PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, - PyDateTime_DATE_GET_SECOND, + PyDateTime_DATE_GET_FOLD, PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, + PyDateTime_DATE_GET_MINUTE, PyDateTime_DATE_GET_SECOND, }; use crate::ffi::{ PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS, }; use crate::ffi::{PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR}; use crate::ffi::{ - PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, - PyDateTime_TIME_GET_SECOND, + PyDateTime_TIME_GET_FOLD, PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, + PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND, }; use crate::instance::PyNativeType; use crate::types::PyTuple; @@ -156,7 +154,6 @@ pub trait PyTimeAccess { /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. - #[cfg(not(PyPy))] fn get_fold(&self) -> bool; } @@ -273,7 +270,6 @@ impl PyDateTime { /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. - #[cfg(not(PyPy))] #[allow(clippy::too_many_arguments)] pub fn new_with_fold<'p>( py: Python<'p>, @@ -363,7 +359,6 @@ impl PyTimeAccess for PyDateTime { unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 } } - #[cfg(not(PyPy))] fn get_fold(&self) -> bool { unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) > 0 } } @@ -417,7 +412,6 @@ impl PyTime { } } - #[cfg(not(PyPy))] /// Alternate constructor that takes a `fold` argument. See [`PyDateTime::new_with_fold`]. pub fn new_with_fold<'p>( py: Python<'p>, @@ -461,7 +455,6 @@ impl PyTimeAccess for PyTime { unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 } } - #[cfg(not(PyPy))] fn get_fold(&self) -> bool { unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) != 0 } } @@ -552,7 +545,6 @@ fn opt_to_pyobj(py: Python<'_>, opt: Option<&PyObject>) -> *mut ffi::PyObject { #[cfg(test)] mod tests { - #[cfg(not(PyPy))] #[test] fn test_new_with_fold() { crate::Python::with_gil(|py| { diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index d8584294..cfe6348f 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -12,6 +12,7 @@ use std::ptr; #[repr(transparent)] pub struct PyFrozenSet(PyAny); +#[cfg(not(PyPy))] pyobject_native_type!( PyFrozenSet, ffi::PySetObject, @@ -19,6 +20,13 @@ pyobject_native_type!( #checkfunction=ffi::PyFrozenSet_Check ); +#[cfg(PyPy)] +pyobject_native_type_core!( + PyFrozenSet, + ffi::PyFrozenSet_Type, + #checkfunction=ffi::PyFrozenSet_Check +); + impl PyFrozenSet { /// Creates a new frozenset. /// diff --git a/src/types/set.rs b/src/types/set.rs index 73908077..b083c476 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -13,7 +13,20 @@ use std::{collections, hash, ptr}; #[repr(transparent)] pub struct PySet(PyAny); -pyobject_native_type!(PySet, ffi::PySetObject, ffi::PySet_Type, #checkfunction=ffi::PySet_Check); +#[cfg(not(PyPy))] +pyobject_native_type!( + PySet, + ffi::PySetObject, + ffi::PySet_Type, + #checkfunction=ffi::PySet_Check +); + +#[cfg(PyPy)] +pyobject_native_type_core!( + PySet, + ffi::PySet_Type, + #checkfunction=ffi::PySet_Check +); impl PySet { /// Creates a new set with elements from the given slice. diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rs index 25dae983..f9ab69e5 100644 --- a/tests/test_inheritance.rs +++ b/tests/test_inheritance.rs @@ -173,25 +173,30 @@ except Exception as e: mod inheriting_native_type { use super::*; use pyo3::exceptions::PyException; - use pyo3::types::{IntoPyDict, PyDict, PySet}; - - #[pyclass(extends=PySet)] - #[derive(Debug)] - struct SetWithName { - #[pyo3(get, name = "name")] - _name: &'static str, - } - - #[pymethods] - impl SetWithName { - #[new] - fn new() -> Self { - SetWithName { _name: "Hello :)" } - } - } + use pyo3::types::{IntoPyDict, PyDict}; + #[cfg(not(PyPy))] #[test] fn inherit_set() { + use pyo3::types::PySet; + + #[cfg(not(PyPy))] + #[pyclass(extends=PySet)] + #[derive(Debug)] + struct SetWithName { + #[pyo3(get, name = "name")] + _name: &'static str, + } + + #[cfg(not(PyPy))] + #[pymethods] + impl SetWithName { + #[new] + fn new() -> Self { + SetWithName { _name: "Hello :)" } + } + } + let gil = Python::acquire_gil(); let py = gil.python(); let set_sub = pyo3::PyCell::new(py, SetWithName::new()).unwrap();