Skip to content

Commit dce486f

Browse files
committed
[GR-50443][GR-50378] Don't patch already patched wheels
PullRequest: graalpython/3083
2 parents 4b87f12 + d131ab3 commit dce486f

File tree

6 files changed

+124
-31
lines changed

6 files changed

+124
-31
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
diff --git a/joblib/externals/cloudpickle/cloudpickle.py b/joblib/externals/cloudpickle/cloudpickle.py
2+
index 317be69..0c23e88 100644
3+
--- a/joblib/externals/cloudpickle/cloudpickle.py
4+
+++ b/joblib/externals/cloudpickle/cloudpickle.py
5+
@@ -512,10 +512,12 @@ def _walk_global_ops(code):
6+
"""
7+
Yield referenced name for all global-referencing instructions in *code*.
8+
"""
9+
- for instr in dis.get_instructions(code):
10+
- op = instr.opcode
11+
- if op in GLOBAL_OPS:
12+
- yield instr.argval
13+
+ # GraalPy change: we don't support dis
14+
+ yield from code.co_names
15+
+ # for instr in dis.get_instructions(code):
16+
+ # op = instr.opcode
17+
+ # if op in GLOBAL_OPS:
18+
+ # yield instr.argval
19+
20+
21+
def _extract_class_dict(cls):
22+
diff --git a/joblib/externals/cloudpickle/cloudpickle_fast.py b/joblib/externals/cloudpickle/cloudpickle_fast.py
23+
index 8741dcb..6c8b938 100644
24+
--- a/joblib/externals/cloudpickle/cloudpickle_fast.py
25+
+++ b/joblib/externals/cloudpickle/cloudpickle_fast.py
26+
@@ -663,7 +663,7 @@ class CloudPickler(Pickler):
27+
self.globals_ref = {}
28+
assert hasattr(self, 'proto')
29+
30+
- if pickle.HIGHEST_PROTOCOL >= 5 and not PYPY:
31+
+ if pickle.HIGHEST_PROTOCOL >= 5 and not hasattr(Pickler, 'dispatch'):
32+
# Pickler is the C implementation of the CPython pickler and therefore
33+
# we rely on reduce_override method to customize the pickler behavior.
34+
35+
diff --git a/joblib/externals/loky/backend/fork_exec.py b/joblib/externals/loky/backend/fork_exec.py
36+
index 2353c42..f083a63 100644
37+
--- a/joblib/externals/loky/backend/fork_exec.py
38+
+++ b/joblib/externals/loky/backend/fork_exec.py
39+
@@ -35,9 +35,6 @@ def fork_exec(cmd, keep_fds, env=None):
40+
env = env or {}
41+
child_env = {**os.environ, **env}
42+
43+
- pid = os.fork()
44+
- if pid == 0: # pragma: no cover
45+
- close_fds(keep_fds)
46+
- os.execve(sys.executable, cmd, child_env)
47+
- else:
48+
- return pid
49+
+ import subprocess
50+
+ p = subprocess.Popen(cmd, executable=sys.executable, pass_fds=keep_fds, env=child_env)
51+
+ return p.pid
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[[rules]]
2+
patch = 'joblib.patch'

graalpython/lib-graalpython/patches/pip/pip-23.0.1.patch

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/pip/__init__.py b/pip/__init__.py
2-
index 3d4b45a..3aa11e8 100644
2+
index 42f6c45..26c9066 100644
33
--- a/pip/__init__.py
44
+++ b/pip/__init__.py
55
@@ -11,3 +11,6 @@ def main(args: Optional[List[str]] = None) -> int:
@@ -10,10 +10,10 @@ index 3d4b45a..3aa11e8 100644
1010
+
1111
+__GRAALPY_PATCHED = True
1212
diff --git a/pip/_internal/cli/cmdoptions.py b/pip/_internal/cli/cmdoptions.py
13-
index 47ed927..1d182de 100644
13+
index 1f80409..df7ebfc 100644
1414
--- a/pip/_internal/cli/cmdoptions.py
1515
+++ b/pip/_internal/cli/cmdoptions.py
16-
@@ -891,7 +891,7 @@ disable_pip_version_check: Callable[..., Option] = partial(
16+
@@ -879,7 +879,7 @@ disable_pip_version_check: Callable[..., Option] = partial(
1717
"--disable-pip-version-check",
1818
dest="disable_pip_version_check",
1919
action="store_true",
@@ -23,17 +23,17 @@ index 47ed927..1d182de 100644
2323
"of pip is available for download. Implied with --no-index.",
2424
)
2525
diff --git a/pip/_internal/index/package_finder.py b/pip/_internal/index/package_finder.py
26-
index 9bf247f..3e8f187 100644
26+
index b6f8d57..6c37e0b 100644
2727
--- a/pip/_internal/index/package_finder.py
2828
+++ b/pip/_internal/index/package_finder.py
29-
@@ -38,6 +38,7 @@ from pip._internal.utils.logging import indent_log
29+
@@ -35,6 +35,7 @@ from pip._internal.utils.logging import indent_log
3030
from pip._internal.utils.misc import build_netloc
3131
from pip._internal.utils.packaging import check_requires_python
3232
from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS
3333
+from pip._internal.utils.graalpy import apply_graalpy_sort_order, get_graalpy_candidates
3434

35-
__all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"]
36-
35+
if TYPE_CHECKING:
36+
from pip._vendor.typing_extensions import TypeGuard
3737
@@ -487,6 +488,7 @@ class CandidateEvaluator:
3838

3939
return sorted(filtered_applicable_candidates, key=self._sort_key)
@@ -42,7 +42,7 @@ index 9bf247f..3e8f187 100644
4242
def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey:
4343
"""
4444
Function to pass as the `key` argument to a call to sorted() to sort
45-
@@ -851,8 +853,11 @@ class PackageFinder:
45+
@@ -852,8 +854,11 @@ class PackageFinder:
4646

4747
logger.debug("Local files found: %s", ", ".join(paths))
4848

@@ -77,10 +77,10 @@ index 79b82a5..1eddfa3 100644
7777
ext: Optional[str] = splitext(filename)[1]
7878
if not ext:
7979
diff --git a/pip/_internal/operations/install/wheel.py b/pip/_internal/operations/install/wheel.py
80-
index 1af8978..15fee7f 100644
80+
index c799413..bf52f00 100644
8181
--- a/pip/_internal/operations/install/wheel.py
8282
+++ b/pip/_internal/operations/install/wheel.py
83-
@@ -587,6 +587,9 @@ def _install_wheel(
83+
@@ -589,6 +589,9 @@ def _install_wheel(
8484
file.save()
8585
record_installed(file.src_record_path, file.dest_path, file.changed)
8686

@@ -92,14 +92,15 @@ index 1af8978..15fee7f 100644
9292
# file in .data maps to same location as file in wheel root).
9393
diff --git a/pip/_internal/utils/graalpy.py b/pip/_internal/utils/graalpy.py
9494
new file mode 100644
95-
index 0000000..b8a506c
95+
index 0000000..f9b8dcc
9696
--- /dev/null
9797
+++ b/pip/_internal/utils/graalpy.py
98-
@@ -0,0 +1,195 @@
98+
@@ -0,0 +1,214 @@
9999
+# ATTENTION: GraalPy uses existence of this module to verify that it is
100100
+# running a patched pip in pip_hook.py
101101
+import os
102102
+import re
103+
+import zipfile
103104
+from pathlib import Path
104105
+from urllib.parse import urlparse
105106
+
@@ -113,11 +114,8 @@ index 0000000..b8a506c
113114
+if hasattr(__graalpython__, "tdebug"):
114115
+ PATCHES_BASE_DIRS += os.environ.get('PIPLOADER_PATCHES_BASE_DIRS', "").split(",")
115116
+
116-
+BUNDLED_WHEELS_PATH = None
117-
+
118-
+
119-
+def is_bundled_wheel(location, package_name):
120-
+ return os.path.exists(os.path.join(location, package_name, '.graalpy_bundled'))
117+
+DISABLE_PATCHING = os.environ.get('PIP_GRAALPY_DISABLE_PATCHING', '').lower() in ('true', '1')
118+
+DISABLE_VERSION_SELECTION = os.environ.get('PIP_GRAALPY_DISABLE_VERSION_SELECTION', '').lower() in ('true', '1')
121119
+
122120
+
123121
+def normalize_name(name):
@@ -188,19 +186,14 @@ index 0000000..b8a506c
188186
+ return __PATCH_REPOSITORY
189187
+
190188
+
191-
+__already_patched = set()
192-
+
193-
+
194189
+def apply_graalpy_patches(filename, location):
195190
+ """
196191
+ Applies any GraalPy patches to package extracted from 'filename' into 'location'.
197192
+ Note that 'location' must be the parent directory of the package directory itself.
198193
+ For example: /path/to/site-package and not /path/to/site-packages/mypackage.
199194
+ """
200-
+ import autopatch_capi
201-
+ import subprocess
202-
+
203-
+ autopatch_capi.auto_patch_tree(location)
195+
+ if DISABLE_PATCHING:
196+
+ return
204197
+
205198
+ # we expect filename to be something like "pytest-5.4.2-py3-none-any.whl"
206199
+ archive_name = os.path.basename(filename)
@@ -216,13 +209,14 @@ index 0000000..b8a506c
216209
+ suffix = name_ver_match.group('suffix')
217210
+ is_wheel = suffix == "whl"
218211
+
219-
+ # Avoid applying patches to bundled wheels, they are already patched
220-
+ if is_wheel and is_bundled_wheel(location, name):
212+
+ if is_wheel and is_wheel_marked(filename):
213+
+ # We already processed it when building from source
221214
+ return
222215
+
223-
+ # When we patch a sdist, pip may call us again to process the wheel produced from it
224-
+ if (name, version) in __already_patched:
225-
+ return
216+
+ import autopatch_capi
217+
+ import subprocess
218+
+
219+
+ autopatch_capi.auto_patch_tree(location)
226220
+
227221
+ print(f"Looking for GraalPy patches for {name}")
228222
+ repository = get_patch_repository()
@@ -251,7 +245,6 @@ index 0000000..b8a506c
251245
+ "WARNING: GraalPy needs the 'patch' utility to apply compatibility patches. Please install it using your system's package manager.")
252246
+ except subprocess.CalledProcessError:
253247
+ print(f"Applying GraalPy patch failed for {name}. The package may still work.")
254-
+ __already_patched.add((name, version))
255248
+ elif version_specs := repository.get_suggested_version_specs(name):
256249
+ print("We have patches to make this package work on GraalVM for some version(s).")
257250
+ print("If installing or running fails, consider using one of the versions that we have patches for:")
@@ -260,6 +253,9 @@ index 0000000..b8a506c
260253
+
261254
+
262255
+def apply_graalpy_sort_order(sort_key_func):
256+
+ if DISABLE_VERSION_SELECTION:
257+
+ return sort_key_func
258+
+
263259
+ def wrapper(self, candidate):
264260
+ default_sort_key = sort_key_func(self, candidate)
265261
+ priority = get_patch_repository().get_priority_for_version(candidate.name, str(candidate.version))
@@ -291,6 +287,29 @@ index 0000000..b8a506c
291287
+ link = LinkWithFilename(url, f'{name}-{version}.{suffix}')
292288
+ candidates.append(InstallationCandidate(name=name, version=version, link=link))
293289
+ return candidates
290+
+
291+
+
292+
+MARKER_NAME = 'GRAALPY_MARKER'
293+
+
294+
+
295+
+def mark_wheel(path):
296+
+ if DISABLE_PATCHING:
297+
+ return
298+
+ with zipfile.ZipFile(path, 'a') as z:
299+
+ dist_info = None
300+
+ for name in z.namelist():
301+
+ if m := re.match(r'([^/]+.dist-info)/', name):
302+
+ dist_info = m.group(1)
303+
+ break
304+
+ assert dist_info, "Cannot find .dist_info in built wheel"
305+
+ marker = f'{dist_info}/{MARKER_NAME}'
306+
+ with z.open(marker, 'w'):
307+
+ pass
308+
+
309+
+
310+
+def is_wheel_marked(path):
311+
+ with zipfile.ZipFile(path) as z:
312+
+ return any(re.match(rf'[^/]+.dist-info/{MARKER_NAME}$', f) for f in z.namelist())
294313
diff --git a/pip/_internal/utils/unpacking.py b/pip/_internal/utils/unpacking.py
295314
index 78b5c13..18a184c 100644
296315
--- a/pip/_internal/utils/unpacking.py
@@ -301,6 +320,27 @@ index 78b5c13..18a184c 100644
301320
raise InstallationError(f"Cannot determine archive format of {location}")
302321
+ from pip._internal.utils.graalpy import apply_graalpy_patches
303322
+ apply_graalpy_patches(filename, location)
323+
diff --git a/pip/_internal/wheel_builder.py b/pip/_internal/wheel_builder.py
324+
index 15b30af..f28355d 100644
325+
--- a/pip/_internal/wheel_builder.py
326+
+++ b/pip/_internal/wheel_builder.py
327+
@@ -7,6 +7,7 @@ import re
328+
import shutil
329+
from typing import Callable, Iterable, List, Optional, Tuple
330+
331+
+from pip._internal.utils import graalpy
332+
from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version
333+
from pip._vendor.packaging.version import InvalidVersion, Version
334+
335+
@@ -275,6 +276,8 @@ def _build_one_inside_env(
336+
)
337+
338+
if wheel_path is not None:
339+
+ # GraalPy change: watermark wheels that we built so that we don't try to patch them when installing
340+
+ graalpy.mark_wheel(wheel_path)
341+
wheel_name = os.path.basename(wheel_path)
342+
dest_path = os.path.join(output_dir, wheel_name)
343+
try:
304344
diff --git a/pip/_vendor/packaging/tags.py b/pip/_vendor/packaging/tags.py
305345
index 9a3d25a..e0e7b31 100644
306346
--- a/pip/_vendor/packaging/tags.py
Binary file not shown.
Binary file not shown.

scripts/repack-bundled-wheels.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ patch_wheel() {
7171
unzip ../tmp.whl
7272
rm ../tmp.whl
7373
patch -p1 < "../$patch"
74-
echo 'Marker file for GraalPy' > "$name/.graalpy_bundled"
74+
touch "$(echo $name-*.dist-info)/GRAALPY_MARKER"
7575
rm "../$wheel"
7676
zip -r "../$wheel" .
7777
rm -rf "$tmpdir"

0 commit comments

Comments
 (0)