Skip to content

Commit dab58ce

Browse files
committed
Add patch for pydantic-core-2.23.4
1 parent 2aecc54 commit dab58ce

File tree

2 files changed

+199
-0
lines changed

2 files changed

+199
-0
lines changed

graalpython/lib-graalpython/patches/metadata.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ version = '== 2.10.1'
442442
patch = 'pydantic-core-2.10.1.patch'
443443
license = 'MIT'
444444

445+
[[pydantic-core.rules]]
446+
version = '== 2.23.4'
447+
patch = 'pydantic-core-2.23.4.patch'
448+
license = 'MIT'
449+
445450
[[pydantic-core.rules]]
446451
version = '== 2.27.1'
447452
patch = 'pydantic-core-2.27.1.patch'
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
diff --git a/Cargo.toml b/Cargo.toml
2+
index 0871b8a..7bf96f3 100644
3+
--- a/Cargo.toml
4+
+++ b/Cargo.toml
5+
@@ -29,7 +29,7 @@ rust-version = "1.75"
6+
[dependencies]
7+
# TODO it would be very nice to remove the "py-clone" feature as it can panic,
8+
# but needs a bit of work to make sure it's not used in the codebase
9+
-pyo3 = { version = "0.22.2", features = ["generate-import-lib", "num-bigint", "py-clone"] }
10+
+pyo3 = { version = "0.22.2", features = ["generate-import-lib", "num-bigint", "py-clone"], path = "patched_crates/pyo3" }
11+
regex = "1.10.6"
12+
strum = { version = "0.26.3", features = ["derive"] }
13+
strum_macros = "0.26.4"
14+
@@ -46,7 +46,7 @@ base64 = "0.22.1"
15+
num-bigint = "0.4.6"
16+
python3-dll-a = "0.2.10"
17+
uuid = "1.10.0"
18+
-jiter = { version = "0.5", features = ["python"] }
19+
+jiter = { version = "0.5", features = ["python"], path = "patched_crates/jiter/crates/jiter" }
20+
hex = "0.4.3"
21+
22+
[lib]
23+
@@ -74,12 +74,12 @@ debug = true
24+
strip = false
25+
26+
[dev-dependencies]
27+
-pyo3 = { version = "0.22.2", features = ["auto-initialize"] }
28+
+pyo3 = { version = "0.22.2", features = ["auto-initialize"], path = "patched_crates/pyo3" }
29+
30+
[build-dependencies]
31+
version_check = "0.9.5"
32+
# used where logic has to be version/distribution specific, e.g. pypy
33+
-pyo3-build-config = { version = "0.22.0" }
34+
+pyo3-build-config = { version = "0.22.0", path = "patched_crates/pyo3/pyo3-build-config" }
35+
36+
[lints.clippy]
37+
dbg_macro = "warn"
38+
diff --git a/build_backend.py b/build_backend.py
39+
new file mode 100644
40+
index 0000000..beeb34b
41+
--- /dev/null
42+
+++ b/build_backend.py
43+
@@ -0,0 +1,30 @@
44+
+import maturin
45+
+import os
46+
+import shutil
47+
+import subprocess
48+
+import tarfile
49+
+
50+
+from pathlib import Path
51+
+from urllib.request import urlopen
52+
+
53+
+build_sdist = maturin.build_sdist
54+
+
55+
+
56+
+def get_crate_and_patch(namespace, name, version, patched_crates):
57+
+ with (
58+
+ urlopen(f'https://github.com/{namespace}/{name}/archive/refs/tags/v{version}.tar.gz') as f,
59+
+ tarfile.open(fileobj=f, mode='r:gz') as tar,
60+
+ ):
61+
+ tar.extractall(patched_crates, filter='data')
62+
+ crate = patched_crates / f'{name}-{version}'
63+
+ crate = crate.rename(patched_crates / name)
64+
+ subprocess.check_call(['patch', '-p1', '-d', str(crate), '-i', str((Path('patches') / f'{name}.patch').absolute())])
65+
+
66+
+
67+
+def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
68+
+ patched_crates = Path('patched_crates')
69+
+ shutil.rmtree(patched_crates, ignore_errors=True)
70+
+ patched_crates.mkdir()
71+
+ get_crate_and_patch('PyO3', 'pyo3', '0.22.2', patched_crates)
72+
+ get_crate_and_patch('pydantic', 'jiter', '0.5.0', patched_crates)
73+
+ return maturin.build_wheel(wheel_directory, config_settings, metadata_directory)
74+
diff --git a/patches/jiter.patch b/patches/jiter.patch
75+
new file mode 100644
76+
index 0000000..15bcb1a
77+
--- /dev/null
78+
+++ b/patches/jiter.patch
79+
@@ -0,0 +1,34 @@
80+
+diff --git a/Cargo.toml b/Cargo.toml
81+
+index d2b0781..ca9645a 100644
82+
+--- a/Cargo.toml
83+
++++ b/Cargo.toml
84+
+@@ -28,5 +28,5 @@ inherits = "release"
85+
+ debug = true
86+
+
87+
+ [workspace.dependencies]
88+
+-pyo3 = { version = "0.22.0" }
89+
+-pyo3-build-config = { version = "0.22.0" }
90+
++pyo3 = { version = "0.22.2", path = "../pyo3" }
91+
++pyo3-build-config = { version = "0.22.2", path = "../pyo3/pyo3-build-config" }
92+
+diff --git a/crates/jiter/src/py_string_cache.rs b/crates/jiter/src/py_string_cache.rs
93+
+index 96dcf66..21e6979 100644
94+
+--- a/crates/jiter/src/py_string_cache.rs
95+
++++ b/crates/jiter/src/py_string_cache.rs
96+
+@@ -200,7 +200,7 @@ pub fn pystring_fast_new<'py>(py: Python<'py>, s: &str, ascii_only: bool) -> Bou
97+
+
98+
+ /// Faster creation of PyString from an ASCII string, inspired by
99+
+ /// https://github.com/ijl/orjson/blob/3.10.0/src/str/create.rs#L41
100+
+-#[cfg(not(PyPy))]
101+
++#[cfg(all(not(PyPy), not(GraalPy)))]
102+
+ unsafe fn pystring_ascii_new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> {
103+
+ let ptr = pyo3::ffi::PyUnicode_New(s.len() as isize, 127);
104+
+ // see https://github.com/pydantic/jiter/pull/72#discussion_r1545485907
105+
+@@ -212,7 +212,7 @@ unsafe fn pystring_ascii_new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyStri
106+
+ }
107+
+
108+
+ // ffi::PyUnicode_DATA seems to be broken for pypy, hence this, marked as unsafe to avoid warnings
109+
+-#[cfg(PyPy)]
110+
++#[cfg(any(PyPy, GraalPy))]
111+
+ unsafe fn pystring_ascii_new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> {
112+
+ PyString::new_bound(py, s)
113+
+ }
114+
diff --git a/patches/pyo3.patch b/patches/pyo3.patch
115+
new file mode 100644
116+
index 0000000..3d52e98
117+
--- /dev/null
118+
+++ b/patches/pyo3.patch
119+
@@ -0,0 +1,31 @@
120+
+diff --git a/pyo3-ffi/src/cpython/pyerrors.rs b/pyo3-ffi/src/cpython/pyerrors.rs
121+
+index 6d17ebc..1d206f9 100644
122+
+--- a/pyo3-ffi/src/cpython/pyerrors.rs
123+
++++ b/pyo3-ffi/src/cpython/pyerrors.rs
124+
+@@ -6,19 +6,19 @@ use crate::Py_ssize_t;
125+
+ #[derive(Debug)]
126+
+ pub struct PyBaseExceptionObject {
127+
+ pub ob_base: PyObject,
128+
+- #[cfg(not(any(PyPy, GraalPy)))]
129+
++ #[cfg(not(PyPy))]
130+
+ pub dict: *mut PyObject,
131+
+- #[cfg(not(any(PyPy, GraalPy)))]
132+
++ #[cfg(not(PyPy))]
133+
+ pub args: *mut PyObject,
134+
+- #[cfg(all(Py_3_11, not(any(PyPy, GraalPy))))]
135+
++ #[cfg(all(Py_3_11, not(PyPy)))]
136+
+ pub notes: *mut PyObject,
137+
+- #[cfg(not(any(PyPy, GraalPy)))]
138+
++ #[cfg(not(PyPy))]
139+
+ pub traceback: *mut PyObject,
140+
+- #[cfg(not(any(PyPy, GraalPy)))]
141+
++ #[cfg(not(PyPy))]
142+
+ pub context: *mut PyObject,
143+
+- #[cfg(not(any(PyPy, GraalPy)))]
144+
++ #[cfg(not(PyPy))]
145+
+ pub cause: *mut PyObject,
146+
+- #[cfg(not(any(PyPy, GraalPy)))]
147+
++ #[cfg(not(PyPy))]
148+
+ pub suppress_context: char,
149+
+ }
150+
+
151+
diff --git a/pyproject.toml b/pyproject.toml
152+
index 9d8e5f0..b43c6c4 100644
153+
--- a/pyproject.toml
154+
+++ b/pyproject.toml
155+
@@ -3,7 +3,8 @@ requires = [
156+
'maturin>=1,<2',
157+
'typing-extensions >=4.6.0,!=4.7.0'
158+
]
159+
-build-backend = 'maturin'
160+
+backend-path = ['.']
161+
+build-backend = 'build_backend'
162+
163+
[project]
164+
name = 'pydantic_core'
165+
diff --git a/src/input/return_enums.rs b/src/input/return_enums.rs
166+
index 888dff7..17deb98 100644
167+
--- a/src/input/return_enums.rs
168+
+++ b/src/input/return_enums.rs
169+
@@ -10,7 +10,7 @@ use pyo3::exceptions::PyTypeError;
170+
use pyo3::ffi;
171+
use pyo3::intern;
172+
use pyo3::prelude::*;
173+
-#[cfg(not(PyPy))]
174+
+#[cfg(all(not(PyPy),not(GraalPy)))]
175+
use pyo3::types::PyFunction;
176+
use pyo3::types::{PyBytes, PyComplex, PyFloat, PyFrozenSet, PyIterator, PyMapping, PySet, PyString};
177+
178+
@@ -313,14 +313,14 @@ pub(crate) fn iterate_attributes<'a, 'py>(
179+
// the PyFunction::is_type_of(attr) catches `staticmethod`, but also any other function,
180+
// I think that's better than including static methods in the yielded attributes,
181+
// if someone really wants fields, they can use an explicit field, or a function to modify input
182+
- #[cfg(not(PyPy))]
183+
+ #[cfg(all(not(PyPy),not(GraalPy)))]
184+
if !is_bound && !attr.is_instance_of::<PyFunction>() {
185+
return Some(Ok((name, attr)));
186+
}
187+
// MASSIVE HACK! PyFunction doesn't exist for PyPy,
188+
// is_instance_of::<PyFunction> crashes with a null pointer, hence this hack, see
189+
// https://github.com/pydantic/pydantic-core/pull/161#discussion_r917257635
190+
- #[cfg(PyPy)]
191+
+ #[cfg(any(PyPy,GraalPy))]
192+
if !is_bound && attr.get_type().to_string() != "<class 'function'>" {
193+
return Some(Ok((name, attr)));
194+
}

0 commit comments

Comments
 (0)