From 213ed71e38a7596a3d75ebad14c0b9253dfc37ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:45:56 +0100 Subject: [PATCH] installer: do not fail on invalid wheels, print only a warning --- 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(