diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e198f699..1e43f2a68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,8 +71,8 @@ jobs: - '3.13t' - '3.14' - '3.14t' - - 'pypy3.9' - 'pypy3.10' + - 'pypy3.11' runs-on: ubuntu-latest @@ -424,7 +424,7 @@ jobs: - os: linux manylinux: auto target: x86_64 - interpreter: pypy3.9 pypy3.10 pypy3.11 + interpreter: pypy3.10 pypy3.11 # musllinux - os: linux @@ -444,7 +444,7 @@ jobs: target: x86_64 - os: macos target: aarch64 - interpreter: 3.9 pypy3.9 pypy3.10 pypy3.11 + interpreter: 3.9 pypy3.10 pypy3.11 # windows; # x86_64 pypy builds are not PGO optimized @@ -452,7 +452,7 @@ jobs: # aarch64 only 3.11 and up, also not PGO optimized - os: windows target: x86_64 - interpreter: pypy3.9 pypy3.10 pypy3.11 + interpreter: pypy3.10 pypy3.11 - os: windows target: i686 python-architecture: x86 @@ -483,7 +483,7 @@ jobs: with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux }} - args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 3.14 pypy3.9 pypy3.10 pypy3.11' }} + args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 3.14 pypy3.10 pypy3.11' }} rust-toolchain: stable docker-options: -e CI diff --git a/src/input/return_enums.rs b/src/input/return_enums.rs index 6ac382430..bada53ace 100644 --- a/src/input/return_enums.rs +++ b/src/input/return_enums.rs @@ -11,7 +11,6 @@ use pyo3::exceptions::PyTypeError; use pyo3::ffi; use pyo3::intern; use pyo3::prelude::*; -#[cfg(not(PyPy))] use pyo3::types::PyFunction; use pyo3::types::{PyBytes, PyComplex, PyFloat, PyFrozenSet, PyIterator, PyMapping, PySet, PyString}; @@ -348,17 +347,9 @@ pub(crate) fn iterate_attributes<'a, 'py>( // the PyFunction::is_type_of(attr) catches `staticmethod`, but also any other function, // I think that's better than including static methods in the yielded attributes, // if someone really wants fields, they can use an explicit field, or a function to modify input - #[cfg(not(PyPy))] if !is_bound && !attr.is_instance_of::() { return Some(Ok((name, attr))); } - // MASSIVE HACK! PyFunction doesn't exist for PyPy, - // is_instance_of:: crashes with a null pointer, hence this hack, see - // https://github.com/pydantic/pydantic-core/pull/161#discussion_r917257635 - #[cfg(PyPy)] - if !is_bound && attr.get_type().to_string() != "" { - return Some(Ok((name, attr))); - } } } None diff --git a/src/tools.rs b/src/tools.rs index f001eeb84..edf9b6bac 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -129,14 +129,6 @@ pub fn truncate_safe_repr(v: &Bound<'_, PyAny>, max_len: Option) -> Strin } pub fn extract_i64(v: &Bound<'_, PyAny>) -> Option { - #[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() } diff --git a/tests/validators/test_arguments.py b/tests/validators/test_arguments.py index ec7c409bb..5a147cc40 100644 --- a/tests/validators/test_arguments.py +++ b/tests/validators/test_arguments.py @@ -1,3 +1,4 @@ +import platform import re import sys from functools import wraps @@ -1137,6 +1138,9 @@ def test_invalid_schema(): ) +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_error_display(pydantic_version): v = SchemaValidator( core_schema.arguments_schema( diff --git a/tests/validators/test_definitions_recursive.py b/tests/validators/test_definitions_recursive.py index 34b8ca445..b36d4aa07 100644 --- a/tests/validators/test_definitions_recursive.py +++ b/tests/validators/test_definitions_recursive.py @@ -1,5 +1,6 @@ import datetime import platform +import sys from dataclasses import dataclass from typing import Optional @@ -752,6 +753,9 @@ def test_many_uses_of_ref(): assert v.validate_python(long_input) == long_input +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_error_inside_definition_wrapper(): with pytest.raises(SchemaError) as exc_info: SchemaValidator( diff --git a/tests/validators/test_string.py b/tests/validators/test_string.py index 4f295056b..0ea5c23a3 100644 --- a/tests/validators/test_string.py +++ b/tests/validators/test_string.py @@ -1,3 +1,4 @@ +import platform import re import sys from decimal import Decimal @@ -172,6 +173,10 @@ def test_str_constrained_config(): @pytest.mark.parametrize('engine', [None, 'rust-regex', 'python-re']) def test_invalid_regex(engine): + if platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11): + # pypy 3.11 type formatting + pytest.xfail() + # TODO uncomment and fix once #150 is done # with pytest.raises(SchemaError) as exc_info: # SchemaValidator({'type': 'str', 'pattern': 123}) @@ -343,6 +348,9 @@ def test_coerce_numbers_to_str_from_json(number: str, expected_str: str) -> None @pytest.mark.parametrize('mode', (None, 'schema', 'config')) +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_backtracking_regex_rust_unsupported(mode) -> None: pattern = r'r(#*)".*?"\1' diff --git a/tests/validators/test_union.py b/tests/validators/test_union.py index 8f54d00e8..ad785921d 100644 --- a/tests/validators/test_union.py +++ b/tests/validators/test_union.py @@ -1,3 +1,5 @@ +import platform +import sys from dataclasses import dataclass from datetime import date, time from enum import Enum, IntEnum @@ -231,6 +233,9 @@ def test_union_list_bool_int(): ] +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_empty_choices(): msg = r'Error building "union" validator:\s+SchemaError: One or more union choices required' with pytest.raises(SchemaError, match=msg):