From 59af7b66c6c35173c4a2199d1f6f3ef244ef164e Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 14 May 2024 14:16:38 +0100 Subject: [PATCH] defer to PyO3 i64 extraction to avoid implicit integer casts --- pyproject.toml | 7 +++---- src/tools.rs | 29 ++++++++++------------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d56dc1255..e1edd165f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,10 +73,9 @@ testpaths = 'tests' log_format = '%(name)s %(levelname)s: %(message)s' filterwarnings = [ 'error', - # Work around https://github.com/pytest-dev/pytest/issues/10977 for Python 3.12 - 'ignore:(ast\.Str|ast\.NameConstant|ast\.Num|Attribute s) is deprecated and will be removed.*:DeprecationWarning:', - # issue with pytz - https://github.com/stub42/pytz/issues/105 for Python 3.12 - 'ignore:datetime\.utcfromtimestamp\(\) is deprecated.*:DeprecationWarning:', + # Python 3.9 and below allowed truncation of float to integers in some + # cases, by not making this an error we can test for this behaviour + 'ignore:(.+)Implicit conversion to integers using __int__ is deprecated', ] timeout = 30 xfail_strict = true diff --git a/src/tools.rs b/src/tools.rs index 28c661d8f..adf64c91a 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use pyo3::exceptions::PyKeyError; use pyo3::prelude::*; use pyo3::types::{PyDict, PyString}; -use pyo3::{ffi, intern, FromPyObject}; +use pyo3::{intern, FromPyObject}; use jiter::{cached_py_string, pystring_fast_new, StringCacheMode}; @@ -124,26 +124,17 @@ pub fn safe_repr<'py>(v: &Bound<'py, PyAny>) -> ReprOutput<'py> { } } -/// Extract an i64 from a python object more quickly, see -/// https://github.com/PyO3/pyo3/pull/3742#discussion_r1451763928 -#[cfg(not(any(target_pointer_width = "32", windows, PyPy)))] -pub fn extract_i64(obj: &Bound<'_, PyAny>) -> Option { - let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) }; - if val == -1 && PyErr::occurred(obj.py()) { - unsafe { ffi::PyErr_Clear() }; - None - } else { - Some(val) - } -} - -#[cfg(any(target_pointer_width = "32", windows, PyPy))] pub fn extract_i64(v: &Bound<'_, PyAny>) -> Option { - if v.is_instance_of::() { - v.extract().ok() - } else { - None + #[cfg(PyPy)] + if !v.is_instance_of::() { + // PyPy used __int__ to cast floats to ints after CPython removed it, + // see https://github.com/pypy/pypy/issues/4949 + // + // Can remove this after PyPy 7.3.17 is released + return None; } + + v.extract().ok() } pub(crate) fn new_py_string<'py>(py: Python<'py>, s: &str, cache_str: StringCacheMode) -> Bound<'py, PyString> {