Skip to content

Commit b3bdf29

Browse files
committed
[GR-63323] A couple of fixes for PyMuPDF
PullRequest: graalpython/3732
2 parents 9ed37ce + 98e11fb commit b3bdf29

File tree

7 files changed

+156
-17
lines changed

7 files changed

+156
-17
lines changed

graalpython/com.oracle.graal.python.cext/src/unicodeobject.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
1+
/* Copyright (c) 2018, 2025, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2020 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -6220,16 +6220,17 @@ _PyUnicode_DecodeRawUnicodeEscapeStateful(const char *s,
62206220
Py_XDECREF(exc);
62216221
return NULL;
62226222
}
6223-
6223+
#endif // GraalPy change
62246224
PyObject *
62256225
PyUnicode_DecodeRawUnicodeEscape(const char *s,
62266226
Py_ssize_t size,
62276227
const char *errors)
62286228
{
6229-
return _PyUnicode_DecodeRawUnicodeEscapeStateful(s, size, errors, NULL);
6229+
return PyUnicode_Decode(s, size, "raw_unicode_escape", errors);
6230+
// return _PyUnicode_DecodeRawUnicodeEscapeStateful(s, size, errors, NULL);
62306231
}
62316232

6232-
6233+
#if 0 // GraalPy change
62336234
PyObject *
62346235
PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
62356236
{

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,20 +229,24 @@ static Object doIt(PythonAbstractNativeObject clazz,
229229

230230
@CApiBuiltin(ret = ArgDescriptor.Void, args = {PyTypeObject}, call = Direct)
231231
abstract static class PyType_Modified extends CApiUnaryBuiltinNode {
232-
233232
@TruffleBoundary
234233
@Specialization
235-
static Object doIt(PythonAbstractNativeObject clazz,
234+
static Object doIt(PythonAbstractClass object,
236235
@Bind("this") Node inliningTarget) {
237-
PythonContext context = PythonContext.get(inliningTarget);
238-
CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
239-
if (nativeClassStableAssumption != null) {
240-
nativeClassStableAssumption.invalidate("PyType_Modified(\"" + TypeNodes.GetNameNode.executeUncached(clazz).toJavaStringUncached() + "\") called");
236+
if (object instanceof PythonAbstractNativeObject clazz) {
237+
PythonContext context = PythonContext.get(inliningTarget);
238+
CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
239+
if (nativeClassStableAssumption != null) {
240+
nativeClassStableAssumption.invalidate("PyType_Modified(\"" + TypeNodes.GetNameNode.executeUncached(clazz).toJavaStringUncached() + "\") called");
241+
}
242+
MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(clazz);
243+
mroStorage.lookupChanged();
244+
// Reload slots from native, which also invalidates cached slot lookups
245+
clazz.setTpSlots(TpSlots.fromNative(clazz, context));
246+
} else {
247+
MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(object);
248+
mroStorage.lookupChanged();
241249
}
242-
MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(clazz);
243-
mroStorage.lookupChanged();
244-
// Reload slots from native, which also invalidates cached slot lookups
245-
clazz.setTpSlots(TpSlots.fromNative(clazz, context));
246250
return PNone.NO_VALUE;
247251
}
248252
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ public final class CApiFunction {
515515
@CApiBuiltin(name = "PyUnicode_DecodeLatin1", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
516516
@CApiBuiltin(name = "PyUnicode_DecodeLocale", ret = PyObject, args = {ConstCharPtrAsTruffleString, ConstCharPtrAsTruffleString}, call = CImpl)
517517
@CApiBuiltin(name = "PyUnicode_DecodeLocaleAndSize", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
518+
@CApiBuiltin(name = "PyUnicode_DecodeRawUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
518519
@CApiBuiltin(name = "PyUnicode_DecodeUTF16", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST}, call = CImpl)
519520
@CApiBuiltin(name = "PyUnicode_DecodeUTF16Stateful", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST, PY_SSIZE_T_PTR}, call = CImpl)
520521
@CApiBuiltin(name = "PyUnicode_DecodeUTF32", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST}, call = CImpl)
@@ -953,7 +954,6 @@ public final class CApiFunction {
953954
@CApiBuiltin(name = "PyUnicode_BuildEncodingMap", ret = PyObject, args = {PyObject}, call = NotImplemented)
954955
@CApiBuiltin(name = "PyUnicode_CopyCharacters", ret = Py_ssize_t, args = {PyObject, Py_ssize_t, PyObject, Py_ssize_t, Py_ssize_t}, call = NotImplemented)
955956
@CApiBuiltin(name = "PyUnicode_DecodeCharmap", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, PyObject, ConstCharPtrAsTruffleString}, call = NotImplemented)
956-
@CApiBuiltin(name = "PyUnicode_DecodeRawUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)
957957
@CApiBuiltin(name = "PyUnicode_DecodeUTF7", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)
958958
@CApiBuiltin(name = "PyUnicode_DecodeUTF7Stateful", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, PY_SSIZE_T_PTR}, call = NotImplemented)
959959
@CApiBuiltin(name = "PyUnicode_DecodeUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ public MethNoargsRoot(PythonLanguage language, TruffleString name, boolean isSta
12861286

12871287
@Override
12881288
protected Object[] prepareCArguments(VirtualFrame frame) {
1289-
return new Object[]{readSelf(frame), PNone.NONE};
1289+
return new Object[]{readSelf(frame), PNone.NO_VALUE};
12901290
}
12911291

12921292
@Override

graalpython/lib-graalpython/patches/metadata.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,15 @@ version = ">= 4.8.0"
508508
patch = 'pymongo-4.8.0.patch'
509509
license = 'Apache-2.0'
510510

511+
[[PyMuPDF.rules]]
512+
version = "== 1.25.4"
513+
patch = "pymupdf.patch"
514+
# That project is AGPL, so do not actually include *any* code of pymupdf in the patch, not even an
515+
# empty line, in the diff context. The code we write in the patch is UPL - that is compatible with
516+
# AGPL in the sense that if someone were to apply it and distribute *that*, our patch is now part
517+
# of the AGPL'd codebase
518+
license = 'UPL'
519+
511520
[[pyOpenSSL.rules]]
512521
# Pin this version to avoid pulling newer cryptography than we have patch for
513522
version = "== 23.2.0"
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
diff --git a/graalpy-config b/graalpy-config
2+
new file mode 100755
3+
index 00000000..1f69f726
4+
--- /dev/null
5+
+++ b/graalpy-config
6+
@@ -0,0 +1,78 @@
7+
+#!/bin/sh
8+
+
9+
+# Adapted from CPython but deferring to GraalPy
10+
+
11+
+exit_with_usage ()
12+
+{
13+
+ echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir|--embed"
14+
+ exit $1
15+
+}
16+
+
17+
+if [ "$1" = "" ] ; then
18+
+ exit_with_usage 1
19+
+fi
20+
+
21+
+# Returns the actual prefix where this script was installed to.
22+
+EXE=$(cd $(dirname "$0") && pwd -P)
23+
+if which readlink >/dev/null 2>&1 ; then
24+
+ if readlink -f "$RESULT" >/dev/null 2>&1; then
25+
+ EXE=$(readlink -f "$RESULT")
26+
+ fi
27+
+fi
28+
+EXE=$EXE/graalpy
29+
+
30+
+if ! test -x "$EXE" ; then
31+
+ EXE=graalpy
32+
+fi
33+
+
34+
+# Scan for --help or unknown argument.
35+
+for ARG in $*
36+
+do
37+
+ case $ARG in
38+
+ --help)
39+
+ exit_with_usage 0
40+
+ ;;
41+
+ --embed)
42+
+ echo "graalpy-config does not print embedding flags"
43+
+ exit 1
44+
+ ;;
45+
+ --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--abiflags|--configdir)
46+
+ ;;
47+
+ *)
48+
+ exit_with_usage 1
49+
+ ;;
50+
+ esac
51+
+done
52+
+
53+
+for ARG in "$@"
54+
+do
55+
+ case "$ARG" in
56+
+ --prefix)
57+
+ $EXE -c "print(__import__('sysconfig').get_config_var('prefix'))"
58+
+ ;;
59+
+ --exec-prefix)
60+
+ $EXE -c "print(__import__('sysconfig').get_config_var('exec_prefix'))"
61+
+ ;;
62+
+ --includes)
63+
+ $EXE -c "from sysconfig import get_path; print('-I'+get_path('include'), '-I'+get_path('platinclude'))"
64+
+ ;;
65+
+ --cflags)
66+
+ $EXE -c "import sysconfig as s; print('-I' + s.get_path('include'), '-I' + s.get_path('platinclude'), s.get_config_var('CFLAGS').replace('NDEBUG', 'DEBUG'), s.get_config_var('OPT').replace('NDEBUG', 'DEBUG'))"
67+
+ ;;
68+
+ --libs)
69+
+ $EXE -c "import sysconfig as s; print('-L' + s.get_config_var('LIBDIR'))"
70+
+ ;;
71+
+ --ldflags)
72+
+ $EXE -c "import sysconfig as s; print('-L' + s.get_config_var('LIBDIR'))"
73+
+ ;;
74+
+ --extension-suffix)
75+
+ $EXE -c "import sysconfig as s; print(s.get_config_var('EXT_SUFFIX'))"
76+
+ ;;
77+
+ --abiflags)
78+
+ $EXE -c "import sysconfig as s; print(s.get_config_var('ABIFLAGS'))"
79+
+ ;;
80+
+ --configdir)
81+
+ echo ""
82+
+ ;;
83+
+esac
84+
+done
85+
diff --git a/setup.py b/setup.py
86+
index 5fba2c97..3fe63b07 100755
87+
--- a/setup.py
88+
+++ b/setup.py
89+
@@ -1452,0 +1452,35 @@
90+
+if sys.implementation.name == "graalpy":
91+
+ import os
92+
+ import re
93+
+ import subprocess
94+
+ import shutil
95+
+ import sysconfig
96+
+ from pathlib import Path
97+
+
98+
+ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
99+
+ wheel_directory = Path(wheel_directory).absolute()
100+
+ sdir = Path(__file__).absolute().parent
101+
+ python311 = shutil.which("python3.11")
102+
+ if not python311:
103+
+ raise RuntimeError("python3.11 must be available on the PATH for cross-compilation")
104+
+ env = os.environ.copy()
105+
+ env["PIPCL_PYTHON_CONFIG"] = str(sdir / "graalpy-config")
106+
+ env["PYMUPDF_SETUP_PY_LIMITED_API"] = "1"
107+
+ subprocess.run(
108+
+ [python311, "setup.py", "bdist_wheel"],
109+
+ env=env,
110+
+ cwd=sdir,
111+
+ check=True,
112+
+ )
113+
+ wheels = list((sdir / 'dist').glob('*.whl'))
114+
+ assert len(wheels) == 1, f"Expected 1 wheel, found {len(wheels)}"
115+
+ wheel = wheels[0]
116+
+ assert "-cp311-abi3" in wheel.name, f"Expected wheel to be for CPython 3.11 ABI 3, got {wheel.name}"
117+
+ graalpy_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
118+
+ m = re.match(r"\.graalpy(\d+[^\-]*)-(\d+)", sysconfig.get_config_var("EXT_SUFFIX"))
119+
+ gpver = m[1]
120+
+ cpver = m[2]
121+
+ graalpy_wheel_tag = f"graalpy{cpver}-graalpy{gpver}_{cpver}_native"
122+
+ name = wheel.name.replace("cp311-abi3", graalpy_wheel_tag)
123+
+ shutil.copyfile(wheel, wheel_directory / name)
124+
+ return str(name)

mx.graalpython/verify_patches.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -45,6 +45,7 @@
4545

4646
# Approved license identifiers in SPDX "short identifier" format
4747
ALLOWED_LICENSES = {
48+
'UPL', # https://spdx.org/licenses/UPL-1.0.html
4849
'MIT', # https://spdx.org/licenses/MIT.html
4950
'BSD-3-Clause', # https://spdx.org/licenses/BSD-3-Clause.html
5051
'BSD-2-Clause', # https://spdx.org/licenses/BSD-2-Clause.html

0 commit comments

Comments
 (0)