Skip to content

Commit 7d8abfd

Browse files
committed
parallel get_wheel_elfdata
1 parent b586739 commit 7d8abfd

File tree

2 files changed

+63
-61
lines changed

2 files changed

+63
-61
lines changed

src/auditwheel/pool.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import time
21
from concurrent.futures import Future, ThreadPoolExecutor
32
from pathlib import Path
43
from typing import Any, Callable, Optional
@@ -21,16 +20,16 @@ class FileTaskExecutor:
2120
>>> executor.wait() # Wait for all tasks to complete
2221
"""
2322

24-
def __init__(self, concurrent: int = 1):
23+
def __init__(self, concurrent: int = 0):
2524
self.executor = (
2625
None
2726
if concurrent == 1
2827
else ThreadPoolExecutor(concurrent if concurrent > 1 else None)
2928
)
30-
self.working_map: dict[Path, Future[tuple[str, str]]] = {}
29+
self.working_map: dict[Path, Future[Any]] = {}
3130

3231
def submit(
33-
self, path: Path, fn: Callable[[Any], Any], /, *args: Any, **kwargs: Any
32+
self, path: Path, fn: Callable[..., Any], /, *args: Any, **kwargs: Any
3433
) -> None:
3534
if not path.is_absolute():
3635
path = path.absolute()
@@ -39,12 +38,11 @@ def submit(
3938
if self.executor is None:
4039
future = Future()
4140
future.set_result(fn(*args, **kwargs))
42-
return None
41+
return
4342

4443
assert path not in self.working_map, "path already in working_map"
4544
future = self.executor.submit(fn, *args, **kwargs)
4645
self.working_map[path] = future
47-
return future
4846

4947
def wait(self, path: Optional[Path] = None) -> None:
5048
"""Wait for tasks to complete.
@@ -62,18 +60,8 @@ def wait(self, path: Optional[Path] = None) -> None:
6260
for future in self.working_map.values():
6361
future.result()
6462
self.working_map.clear()
65-
elif future := self.working_map.pop(path, None):
66-
future.result()
67-
68-
69-
def fake_job(i: int) -> int:
70-
print(f"start {i}")
71-
time.sleep(i)
72-
print(f"end {i}")
63+
elif path in self.working_map:
64+
self.working_map.pop(path).result()
7365

7466

75-
if __name__ == "__main__":
76-
executor = FileTaskExecutor(concurrent=0)
77-
for i in range(10):
78-
executor.submit(Path(f"test{i}.txt"), fake_job, i)
79-
executor.wait()
67+
POOL = FileTaskExecutor()

src/auditwheel/wheel_abi.py

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
from pathlib import Path
1111
from typing import Optional, TypeVar
1212

13+
from elftools.elf.elffile import ELFFile
14+
15+
from auditwheel.pool import POOL
16+
1317
from . import json
1418
from .architecture import Architecture
1519
from .elfutils import (
@@ -94,6 +98,55 @@ def get_wheel_elfdata(
9498
shared_libraries_with_invalid_machine = []
9599

96100
platform_wheel = False
101+
102+
def inner(fn: Path, elf: ELFFile) -> None:
103+
nonlocal \
104+
platform_wheel, \
105+
shared_libraries_in_purelib, \
106+
uses_ucs2_symbols, \
107+
uses_PyFPE_jbuf
108+
109+
so_name = fn.name
110+
111+
log.debug("processing: %s", fn)
112+
elftree = ldd(fn, exclude=exclude)
113+
114+
try:
115+
arch = elftree.platform.baseline_architecture
116+
if arch != wheel_policy.architecture.baseline:
117+
shared_libraries_with_invalid_machine.append(so_name)
118+
log.warning("ignoring: %s with %s architecture", so_name, arch)
119+
return
120+
except ValueError:
121+
shared_libraries_with_invalid_machine.append(so_name)
122+
log.warning("ignoring: %s with unknown architecture", so_name)
123+
return
124+
125+
platform_wheel = True
126+
127+
for key, value in elf_find_versioned_symbols(elf):
128+
log.debug("key %s, value %s", key, value)
129+
versioned_symbols[key].add(value)
130+
131+
is_py_ext, py_ver = elf_is_python_extension(fn, elf)
132+
133+
# If the ELF is a Python extention, we definitely need to
134+
# include its external dependencies.
135+
if is_py_ext:
136+
full_elftree[fn] = elftree
137+
uses_PyFPE_jbuf |= elf_references_PyFPE_jbuf(elf)
138+
if py_ver == 2:
139+
uses_ucs2_symbols |= any(True for _ in elf_find_ucs2_symbols(elf))
140+
full_external_refs[fn] = wheel_policy.lddtree_external_references(
141+
elftree, ctx.path
142+
)
143+
else:
144+
# If the ELF is not a Python extension, it might be
145+
# included in the wheel already because auditwheel repair
146+
# vendored it, so we will check whether we should include
147+
# its internal references later.
148+
nonpy_elftree[fn] = elftree
149+
97150
for fn, elf in elf_file_filter(ctx.iter_files()):
98151
# Check for invalid binary wheel format: no shared library should
99152
# be found in purelib
@@ -104,49 +157,8 @@ def get_wheel_elfdata(
104157
if any(p.name == "purelib" for p in fn.parents):
105158
shared_libraries_in_purelib.append(so_name)
106159

107-
# If at least one shared library exists in purelib, this is going
108-
# to fail and there's no need to do further checks
109160
if not shared_libraries_in_purelib:
110-
log.debug("processing: %s", fn)
111-
elftree = ldd(fn, exclude=exclude)
112-
113-
try:
114-
arch = elftree.platform.baseline_architecture
115-
if arch != wheel_policy.architecture.baseline:
116-
shared_libraries_with_invalid_machine.append(so_name)
117-
log.warning("ignoring: %s with %s architecture", so_name, arch)
118-
continue
119-
except ValueError:
120-
shared_libraries_with_invalid_machine.append(so_name)
121-
log.warning("ignoring: %s with unknown architecture", so_name)
122-
continue
123-
124-
platform_wheel = True
125-
126-
for key, value in elf_find_versioned_symbols(elf):
127-
log.debug("key %s, value %s", key, value)
128-
versioned_symbols[key].add(value)
129-
130-
is_py_ext, py_ver = elf_is_python_extension(fn, elf)
131-
132-
# If the ELF is a Python extention, we definitely need to
133-
# include its external dependencies.
134-
if is_py_ext:
135-
full_elftree[fn] = elftree
136-
uses_PyFPE_jbuf |= elf_references_PyFPE_jbuf(elf)
137-
if py_ver == 2:
138-
uses_ucs2_symbols |= any(
139-
True for _ in elf_find_ucs2_symbols(elf)
140-
)
141-
full_external_refs[fn] = wheel_policy.lddtree_external_references(
142-
elftree, ctx.path
143-
)
144-
else:
145-
# If the ELF is not a Python extension, it might be
146-
# included in the wheel already because auditwheel repair
147-
# vendored it, so we will check whether we should include
148-
# its internal references later.
149-
nonpy_elftree[fn] = elftree
161+
POOL.submit(fn, inner, fn, elf)
150162

151163
# If at least one shared library exists in purelib, raise an error
152164
if shared_libraries_in_purelib:
@@ -164,6 +176,8 @@ def get_wheel_elfdata(
164176
wheel_policy.architecture, shared_libraries_with_invalid_machine
165177
)
166178

179+
POOL.wait()
180+
167181
# Get a list of all external libraries needed by ELFs in the wheel.
168182
needed_libs = {
169183
lib

0 commit comments

Comments
 (0)