From c2a7a8d6ea412d021a65068551fa814f0925dc40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Randy=20D=C3=B6ring?=
<30527984+radoering@users.noreply.github.com>
Date: Fri, 31 Mar 2023 21:39:33 +0200
Subject: [PATCH] installer: do not fail on invalid wheels, print only a
warning (#7694)
---
src/poetry/installation/executor.py | 8 +++
src/poetry/installation/wheel_installer.py | 8 ++-
..._invalid_record-0.1.0-py2.py3-none-any.whl | Bin 0 -> 1169 bytes
...invalid_record2-0.1.0-py2.py3-none-any.whl | Bin 0 -> 1307 bytes
tests/installation/test_executor.py | 66 +++++++++++++++++-
tests/utils/test_cache.py | 4 +-
6 files changed, 81 insertions(+), 5 deletions(-)
create mode 100644 tests/fixtures/distributions/demo_invalid_record-0.1.0-py2.py3-none-any.whl
create mode 100644 tests/fixtures/distributions/demo_invalid_record2-0.1.0-py2.py3-none-any.whl
diff --git a/src/poetry/installation/executor.py b/src/poetry/installation/executor.py
index 5d3f699d13c..7f8b5701cd9 100644
--- a/src/poetry/installation/executor.py
+++ b/src/poetry/installation/executor.py
@@ -207,6 +207,14 @@ def execute(self, operations: list[Operation]) -> int:
for warning in self._yanked_warnings:
self._io.write_error_line(f"Warning: {warning}")
+ for path, issues in self._wheel_installer.invalid_wheels.items():
+ formatted_issues = "\n".join(issues)
+ warning = (
+ f"Validation of the RECORD file of {path.name} failed."
+ " Please report to the maintainers of that package so they can fix"
+ f" their build process. Details:\n{formatted_issues}\n"
+ )
+ self._io.write_error_line(f"Warning: {warning}")
return 1 if self._shutdown else 0
diff --git a/src/poetry/installation/wheel_installer.py b/src/poetry/installation/wheel_installer.py
index d81fe479cae..eb324fd630c 100644
--- a/src/poetry/installation/wheel_installer.py
+++ b/src/poetry/installation/wheel_installer.py
@@ -10,6 +10,7 @@
from installer import install
from installer.destinations import SchemeDictionaryDestination
from installer.sources import WheelFile
+from installer.sources import _WheelFileValidationError
from poetry.__version__ import __version__
from poetry.utils._compat import WINDOWS
@@ -93,12 +94,17 @@ def __init__(self, env: Env) -> None:
schemes, interpreter=str(self._env.python), script_kind=script_kind
)
+ self.invalid_wheels: dict[Path, list[str]] = {}
+
def enable_bytecode_compilation(self, enable: bool = True) -> None:
self._destination.bytecode_optimization_levels = (-1,) if enable else ()
def install(self, wheel: Path) -> None:
with WheelFile.open(wheel) as source:
- source.validate_record()
+ try:
+ source.validate_record()
+ except _WheelFileValidationError as e:
+ self.invalid_wheels[wheel] = e.issues
install(
source=source,
destination=self._destination.for_source(source),
diff --git a/tests/fixtures/distributions/demo_invalid_record-0.1.0-py2.py3-none-any.whl b/tests/fixtures/distributions/demo_invalid_record-0.1.0-py2.py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..184475aa2766a660ce6fac5b681ee128845088bc
GIT binary patch
literal 1169
zcmWIWW@Zs#U|`??Vnv1~uELiRK$aK~3jlFSYHq%Me0*kJW=VX!UO{DdzrMGw*10q1
zyZgg8ga(*jFur0O@SKSu0B(wFRY_Q8KW*zWEPj`X6B{k>-)NfIJ!87I8L2-*YA*nKCvZ^rdwT?E?Jk@w2SX!n!v^XGj|0>M$hAqHv5%ZX_s-=
zBKxjI{#}Vp9&1xX=NtX|AjW#;;=j*gY40n|FI6(8IzMB|nCv{ySzT$abDHNaF5iFx
zn^VDd51J=CACkVh$8*2E#=G|$@)4oUuw%Zv!&Dyja9}7$0I?>Kp&jnw>gvOL%8{!<
zL4ftb-sK;dl+!L8;&$2Hv104N+V?o^~j+GN6ywDT*uN}61HICp+#jtS4{+B
zEh1ePEV}{&CA4&&N=*g@8_H?22Ro0(0BCtqkR=Mx;G-GEx9|dQ1;L4
zjZDk##~YW#O==4)kn_If#;G}_m%;t^pDr`Y>20k!#M(owTKPxa1U2kAKp`r
zTn!2WtQYn!|G=c2cHt1W%kGX9TMsU8nbGMfesABsUvI?=F0<8cF4!{na~g|tuwd^u
zL6O{RyY+S))KO|(HvQSE9iIhrFLG^O_PJko$MUa74lOuxwg%z6FFhq;8y?JFbrt9=
zYhaSlCf0dDuFn2JF1=^(mN^?RFg*Be=e?pxKz#QF&MuwDOP20F`BKOv`DEK)yT8}E
z?|o<8=f7or)!7*#MTuu>elvdlnX>!dUB3N1Gb~PD-}y(@o-gFEdcKq0tKNk7>}x!V
z&OG0BV*6pi8{b|X`lCF5c_5eB))@aoW;(^mQOhQLPV%_=($vkQ$4M%#|8daUiML+u
zJDJ&CFm0!unn`Deie(Vje(ry=DZw#(0zbA@M+YtE5WTK=_d?vS%qw3O2UoT0txJDs
za$c`TIL}7u^eZbpxiZ$3rVSsqEpYn2q>CZqFJpi=Ba;X-?o0;^A~5*h2%^xlAV{}8
z14K7wW>bM^Wl#XpZcyDsXFV>kHUWarning: Validation of the RECORD file of {wheel1} failed.\
+ Please report to the maintainers of that package so they can fix their build process.\
+ Details:
+In .*?{wheel1}, demo/__init__.py is not mentioned in RECORD
+In .*?{wheel1}, demo_invalid_record-0.1.0.dist-info/WHEEL is not mentioned in RECORD
+"""
+
+ warning2 = f"""\
+Warning: Validation of the RECORD file of {wheel2} failed.\
+ Please report to the maintainers of that package so they can fix their build process.\
+ Details:
+In .*?{wheel2}, hash / size of demo_invalid_record2-0.1.0.dist-info/METADATA didn't\
+ match RECORD
+"""
+
+ output = io.fetch_output()
+ error = io.fetch_error()
+ assert return_code == 0, f"\noutput: {output}\nerror: {error}\n"
+ assert re.match(f"{warning1}\n{warning2}", error) or re.match(
+ f"{warning2}\n{warning1}", error
+ ), error
+
+
def test_execute_shows_skipped_operations_if_verbose(
config: Config,
pool: RepositoryPool,
diff --git a/tests/utils/test_cache.py b/tests/utils/test_cache.py
index e9489688e94..c2cd47f6d68 100644
--- a/tests/utils/test_cache.py
+++ b/tests/utils/test_cache.py
@@ -286,7 +286,9 @@ def test_get_cached_archives_for_link(
)
assert archives
- assert set(archives) == set(distributions.glob("demo-0.1.*"))
+ assert set(archives) == set(distributions.glob("*.whl")) | set(
+ distributions.glob("*.tar.gz")
+ )
@pytest.mark.parametrize(