Repository: python-poetry/poetry

Issue:
Poetry 1.4.0: There is no item named `<package>/WHEEL` in the archive
<!--
    Hi there! Thank you for submitting a bug report!

    Before you submit your issue, please review and follow the instructions at
    https://python-poetry.org/docs/contributing/#reporting-bugs. Fully fill out the template below; insufficient
    information or bad reproduction instructions will impair the ability of others to help you.
-->

<!-- All the below information must be provided for others to understand and help with your issue. -->
- **Poetry version**: 1.4.0<!-- Replace with version, e.g. from `poetry --version` -->
- **Python version**: 3.11<!-- Replace with the version of Python being used to run Poetry, as reported by `poetry debug info` -->
- **OS version and name**: macOS 13.2.1/MacPorts <!-- Replace with version + name, e.g. Ubuntu 22.04 or macOS 12.6 -->
- **pyproject.toml**: https://gist.github.com/elventear/2410f2f8a05926df27488767cfcab780<!-- Replace with a link to a Gist (https://gist.github.com/) containing your sanitized pyproject.toml -->

<!-- All the below steps should be completed before submitting your issue. Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a recommended method.
- [x] I have searched the [issues](https://github.com/python-poetry/poetry/issues) of this repo and believe that this is not a duplicate.
- [x] I have consulted the [FAQ](https://python-poetry.org/docs/faq/) and [blog](https://python-poetry.org/blog/) for any relevant entries or release notes.
- [x] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option) and have included the output below.

## Issue

Hypercorn can't be installed with poetry 1.4.0, it used to be possible to install it:

<!-- Now feel free to write your issue, and please be as descriptive as possible! Make sure to include detailed reproduction steps. -->
<!-- Thanks again 🙌 ❤ -->

```
poetry install                                                                                                                                                                                                          
Creating virtualenv test in /path/to/.venv
Updating dependencies
Resolving dependencies... (0.4s)

Writing lock file

Package operations: 8 installs, 0 updates, 0 removals

  • Installing h11 (0.14.0)
  • Installing hpack (4.0.0)
  • Installing hyperframe (6.0.1)
  • Installing h2 (4.1.0)
  • Installing priority (2.0.0)
  • Installing toml (0.10.2)
  • Installing wsproto (1.2.0)
  • Installing hypercorn (0.14.3): Failed

  Stack trace:

  10  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/installation/executor.py:271 in _execute_operation
       269│
       270│             try:
     → 271│                 result = self._do_execute_operation(operation)
       272│             except EnvCommandError as e:
       273│                 if e.e.returncode == -2:

   9  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/installation/executor.py:357 in _do_execute_operation
       355│             return 0
       356│
     → 357│         result: int = getattr(self, f"_execute_{method}")(operation)
       358│
       359│         if result != 0:

   8  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/installation/executor.py:477 in _execute_install
       475│
       476│     def _execute_install(self, operation: Install | Update) -> int:
     → 477│         status_code = self._install(operation)
       478│
       479│         self._save_url_reference(operation)

   7  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/installation/executor.py:535 in _install
       533│                 self._remove(operation.initial_package)
       534│
     → 535│             self._wheel_installer.install(archive)
       536│         finally:
       537│             if cleanup_archive:

   6  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/installation/wheel_installer.py:101 in install
        99│     def install(self, wheel: Path) -> None:
       100│         with WheelFile.open(Path(wheel.as_posix())) as source:
     → 101│             install(
       102│                 source=source,
       103│                 destination=self._destination.for_source(source),

   5  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/installer/_core.py:77 in install
        75│
        76│     """
     →  77│     root_scheme = _process_WHEEL_file(source)
        78│
        79│     # RECORD handling

   4  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/installer/_core.py:21 in _process_WHEEL_file
        19│     Returns the scheme that the archive root should go in.
        20│     """
     →  21│     stream = source.read_dist_info("WHEEL")
        22│     metadata = parse_metadata_file(stream)
        23│

   3  ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/installer/sources.py:139 in read_dist_info
       137│         """Get contents, from ``filename`` in the dist-info directory."""
       138│         path = posixpath.join(self.dist_info_dir, filename)
     → 139│         return self._zipfile.read(path).decode("utf-8")
       140│
       141│     def get_contents(self) -> Iterator[WheelContentElement]:

   2  /opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/zipfile.py:1507 in read
       1505│     def read(self, name, pwd=None):
       1506│         """Return file bytes for name."""
     → 1507│         with self.open(name, "r", pwd) as fp:
       1508│             return fp.read()
       1509│

   1  /opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/zipfile.py:1544 in open
       1542│         else:
       1543│             # Get info object for name
     → 1544│             zinfo = self.getinfo(name)
       1545│
       1546│         if mode == 'w':

  KeyError

  "There is no item named 'Hypercorn-0.14.3.dist-info/WHEEL' in the archive"

  at /opt/local/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/zipfile.py:1473 in getinfo
      1469│     def getinfo(self, name):
      1470│         """Return the instance of ZipInfo given 'name'."""
      1471│         info = self.NameToInfo.get(name)
      1472│         if info is None:
    → 1473│             raise KeyError(
      1474│                 'There is no item named %r in the archive' % name)
      1475│
      1476│         return info
```

Wondering if there is a case sensitivity issue. Looking at the wheel, I do see there is a file in `hypercorn-0.14.3.dist-info/WHEEL`. 

Latest 1.4.0 release causes unclear Issue with aws_psycopg2 install
- **Poetry version**: `1.4.0`
- **Python version**: `python3.9`

<!-- All the below steps should be completed before submitting your issue. Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a recommended method.
- [x] I have searched the [issues](https://github.com/python-poetry/poetry/issues) of this repo and believe that this is not a duplicate.
- [ ] I have consulted the [FAQ](https://python-poetry.org/docs/faq/) and [blog](https://python-poetry.org/blog/) for any relevant entries or release notes.
- [ ] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option) and have included the output below.

## Issue
<!-- Now feel free to write your issue, and please be as descriptive as possible! Make sure to include detailed reproduction steps. -->
<!-- Thanks again 🙌 ❤ -->

When using the latest version, `1.4.0` we get the following runtime error:

```
  Installing sqlalchemy (1.4.46)

  AssertionError

  In /builds/project-0/.cache/pypoetry/artifacts/39/96/f1/0f021ed26225e8d9035c9bac5a886b024840f841af84bd33f2be466dcb/aws_psycopg2-1.3.8-py3-none-any.whl, psycopg2/_psycopg.cpython-38-aarch64-linux-gnu.so is not mentioned in RECORD

  at venv/lib/python3.9/site-packages/installer/sources.py:158 in get_contents
      154│             if item.filename[-1:] == "/":  # looks like a directory
      155│                 continue
      156│ 
      157│             record = record_mapping.pop(item.filename, None)
    → 158│             assert record is not None, "In {}, {} is not mentioned in RECORD".format(
      159│                 self._zipfile.filename,
      160│                 item.filename,
      161│             )  # should not happen for valid wheels
      162│ 
```

However, when we downgrade to `poetry==1.3.2` this problem goes away...


Discussion:
+1 to this, getting it when installing detectron2 from a wheel with 

```
 "There is no item named 'detectron2-0.6+cu117.dist-info/WHEEL' in the archive"
 ```
 
 Downgrading to 1.3.2 solved the problem.
Hit me too, looks like `1.4.0` is a corked release... 🙈 
The rest of packages can be installed fine, so maybe someone can look specifically at `hypercorn` 
it seems that there is a dir named `hypercorn-0.14.3.dist-info` but not `Hypercorn-0.14.3.dist-info` in the wheel. The name is lowered.
Hey everyone,

thanks a lot for reporting. This seems to be an issue within the [installer](https://pypi.org/project/installer/) package which is now used for installing packages. I'm able to reproduce this error with the code example given in the [docs](https://installer.pypa.io/en/stable/#basic-usage). @pradyunsg can you have a look into this?

For now one can disable the new installer with `poetry config installer.modern-installation false`. (https://python-poetry.org/docs/master/configuration/#installermodern-installation)

fin swimmer
I see that the hypercorn wheel on pypi is called `Hypercorn-0.14.3-py3-none-any.whl` with a capital H.   I expect that is what has confused `installer`.

I notice that hypercorn itself uses poetry, and I guess that unusual capitalisation comes from https://github.com/pgjones/hypercorn/blob/8ae17ca68204d9718389fb3649ca0ed6ba851906/pyproject.toml#L2.

recent versions of poetry normalize the wheel filename, so likely this can be resolved either by

- `installer` being tolerant of unnormalized distribution file names (probably there are a lot of these out there)
  - and poetry picking up a new release of `installer`
- or, `hypercorn` publishing a new release built from a recent poetry
Also getting it on version 0.81 of `xgboost` (Whether newer versions work I don't know)

This is a major issue that can break every CICD workflow in a project, if a patch will not be available in the next few hours, what are the odds that poetry 1.4.0 will be yanked until a fix is released?
Hey @bentheiii,

as you've probably read in the comments by @dimbleby and me, this is not a Poetry issue per se. So I don't think we will yank 1.4.0 nor there will be a fix "in the next few hours".

You should always pin the Poetry version used in your CI Pipeline: https://python-poetry.org/docs/master/#ci-recommendations.

Also you can fallback  to the old installer as described [above](https://github.com/python-poetry/poetry/issues/7572#issuecomment-1447608308).

fin swimmer
This is https://github.com/pypa/installer/issues/134, and it's gonna have to wait until after my work day for a fix to be released.
> Wondering if there is a case sensitivity issue. Looking at the wheel, I do see there is a file in `hypercorn-0.14.3.dist-info/WHEEL`.

I think so too, we observed the problem in another package. https://github.com/EntilZha/PyFunctional/issues/176

> When I inspect the contents of wheel file, I see that the path to the file is `pyfunctional-1.4.3.dist-info/WHEEL` not `PyFunctional-1.4.3.dist-info/WHEEL`. Could the case difference in the directory name be causing this error?
Experiencing the same issue in [kazhala/InquirerPy#57](https://github.com/kazhala/InquirerPy/issues/57). Downgrading to 1.3.2 resolved the issue for now. 
Same issue. Downgrading to 1.3.2 helped. For me it was `flask-mailman` package. It seems that it's due to case sensitivity: package name itself / wheel / zip file uses `Flask-Mailman` but wheel contains folder that is all lowercase.
Same issue with hypercorn on poetry 1.4.0. Disabling the new installer with `poetry config installer.modern-installation false` as suggested worked for me as a workaround.
hypercorn is literally where this issue started.  If y'all could please refrain from "me too" it would save on noise.
Same issue
```
#0 29.88   KeyError
#0 29.88 
#0 29.88   "There is no item named 'Hypercorn-0.14.3.dist-info/WHEEL' in the archive"
#0 29.88 
#0 29.88   at /usr/local/lib/python3.11/zipfile.py:1473 in getinfo
#0 29.92       1469│     def getinfo(self, name):
#0 29.92       1470│         """Return the instance of ZipInfo given 'name'."""
#0 29.92       1471│         info = self.NameToInfo.get(name)
#0 29.92       1472│         if info is None:
#0 29.92     → 1473│             raise KeyError(
#0 29.92       1474│                 'There is no item named %r in the archive' % name)
#0 29.92       1475│ 
#0 29.92       1476│         return info
#0 29.92       1477│
```

Pinning poetry to `1.3.2` helped.
It's not just case sensitivity, Poetry 1.4.0 normalization is messing up punctuation.

```
• Installing sphinxcontrib-applehelp (1.0.3)

  KeyError

  "There is no item named 'sphinxcontrib.applehelp-1.0.3.dist-info/WHEEL' in the archive"

  at /opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/zipfile.py:1441 in getinfo
      1437│     def getinfo(self, name):
      1438│         """Return the instance of ZipInfo given 'name'."""
      1439│         info = self.NameToInfo.get(name)
      1440│         if info is None:
      1441│             raise KeyError(
      1442│                 'There is no item named %r in the archive' % name)
      1443│ 
      1444│         return info
      1445│
```

Poetry is looking for a dot in the name but the package has an underscore:

```
EXPECTED: sphinxcontrib.applehelp-1.0.3.dist-info/WHEEL
ACTUAL:   sphinxcontrib_applehelp-1.0.3.dist-info/WHEEL
                       ^
```

This is going to break _a lot_ of CI builds.
there's already a more recent release of sphinxcontrib-applehelp fixing their package name (and I suspect you overestimate the amount of CI builds that care about it!)

Can I again encourage y'all to think twice before adding yet another example here.  

- The issue is known, and well understood
- There's a fix in the main branch of https://github.com/pypa/installer
- if and when that is released, poetry will pick that fix up in due course
- meanwhile you can sidestep it by disabling the modern installer as introduced at poetry 1.4.0: `poetry config installer.modern-installation false`

It's unlikely that further comments will either add new information, or change what happens next.
All of the other comments here are about capitalization, so I was pointing out that it's also about punctuation. I thought maybe the developers would like to have a more complete picture of what the buggy behavior is. 

I'm sorry that I took time out of my morning to google this issue, find this thread, reproduce it on 1.4.0, make sure it does not reproduce on 1.3.2, download an archive from pypi, identify the discrepancy that nobody else has noticed yet, put together a concise and informative post on the topic, and then edit it several times. 

Believe me, it will not happen again. /unsubscribe
> This is https://github.com/pypa/installer/issues/134, and it's gonna have to wait until after my work day for a fix to be released.

@pradyunsg Any update on getting a new [`installer` released to PyPI](https://pypi.org/project/installer/#history)? Anything the community can help with? ❤️ 
The `installer` release is out -- things should be better now?
the new installer uses https://github.com/pypa/installer, which apparently is stricter about these things.  Your choices are

- ask the aws_psycopg2 project to build valid wheels
- ask the installer project to tolerate invalid wheels
- disable the new installer

https://packaging.python.org/en/latest/specifications/binary-distribution-format/ is clear that 

>  installation will fail if any file in the archive is not both mentioned and correctly hashed in RECORD

so `installer` (and therefore `poetry`) is behaving correctly here
unreleased https://github.com/pypa/installer/pull/147 refactors this, it's not entirely clear to me but I think that the result will be that (by default) this validation does not happen.

so I expect poetry will pick that up in due course if and when the next installer release arrives


fwiw when that new `installer` release arrives IMO poetry should call the now-optional validation: per the reference above, a compliant installer _should_ fail to install a wheel that is mis-built in this way
I had the same issue and going back to ```1.3.2``` didn't work. Mind you that I'm doing this inside a Dockerfile.
Using ```poetry config installer.modern-installation false``` did it for me whilst using ```1.4.0```. The reference is #7572 
> Hey everyone,
> 
> thanks a lot for reporting. This seems to be an issue within the [installer](https://pypi.org/project/installer/) package which is now used for installing packages. I'm able to reproduce this error with the code example given in the [docs](https://installer.pypa.io/en/stable/#basic-usage). @pradyunsg can you have a look into this?
> 
> For now one can disable the new installer with `poetry config installer.modern-installation false`. (https://python-poetry.org/docs/master/configuration/#installermodern-installation)
> 
> fin swimmer


My working Dockerfile.
```
...
RUN pip install poetry


COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false
RUN poetry --version
RUN poetry config installer.modern-installation false
RUN poetry  install --no-interaction --no-ansi --no-root

...
```

@miguelvalente this issue is _also_ not the one that contains the comment that you are replying to.  Please stop pasting this comment in irrelevant places.
> @miguelvalente this issue is _also_ not the one that contains the comment that you are replying to.  Please stop pasting this comment in irrelevant places.

It actually is.  I was having the same issue as @jakebrinkmann. Dowgrading the version did not help. Disabling the instaler did as suggested in another issue.
The key difference between 1.3.2 and 1.4.0 is the new installer. Downgrading not solving this exact stack trace is impossible as this code is not used on 1.3.2.

I'm going to close this issue as a duplicate of #7585.
this issue _is_ 7585, I don't think it has a duplicate

(specifically this one is about `installer` being strict in validation of malformed wheels)
Oh, shoot, I apparently crossed a wire pretty badly this morning.
+1 package producing the same error: `pyqt5-qt5==5.15.2`

Poetry: 1.4.0 release & current master
Python: 3.10.10

```
  • Installing pyqt5-qt5 (5.15.2): Failed

  AssertionError

  In C:\Users\R\AppData\Local\pypoetry\Cache\artifacts\5a\64\78\eb3dc30bf7097835ba9ef2d55725a0480f1b97738287b90a24cd9edf1d\PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl, PyQt5_Qt5-5.15.2.dist-info/RECORD is not mentioned in RECORD

  at ~\AppData\Roaming\pypoetry\venv\Lib\site-packages\installer\sources.py:158 in get_contents
      154│             if item.filename[-1:] == "/":  # looks like a directory
      155│                 continue
      156│
      157│             record = record_mapping.pop(item.filename, None)
    → 158│             assert record is not None, "In {}, {} is not mentioned in RECORD".format(
      159│                 self._zipfile.filename,
      160│                 item.filename,
      161│             )  # should not happen for valid wheels
      162│
```

`pyproject.toml`:
```toml
[tool.poetry]
name = "temp"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "~3.10"
pyqt5-qt5 = "^5.15.2"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
```

Installation is successful with pre-1.4, non-modern installer (`installer.modern-installation=false`).

Resolving patch:
diff --git a/src/poetry/installation/wheel_installer.py b/src/poetry/installation/wheel_installer.py
--- a/src/poetry/installation/wheel_installer.py
+++ b/src/poetry/installation/wheel_installer.py
@@ -97,7 +97,8 @@ 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(Path(wheel.as_posix())) as source:
+        with WheelFile.open(wheel) as source:
+            source.validate_record()
             install(
                 source=source,
                 destination=self._destination.for_source(source),


Test patch:
diff --git a/tests/fixtures/distributions/demo-0.1.2-py2.py3-none-any.whl b/tests/fixtures/distributions/demo-0.1.2-py2.py3-none-any.whl
Binary files a/tests/fixtures/distributions/demo-0.1.2-py2.py3-none-any.whl and b/tests/fixtures/distributions/demo-0.1.2-py2.py3-none-any.whl differ
diff --git a/tests/repositories/fixtures/pypi.org/dists/pytest-3.5.1-py2.py3-none-any.whl b/tests/repositories/fixtures/pypi.org/dists/pytest-3.5.1-py2.py3-none-any.whl
Binary files a/tests/repositories/fixtures/pypi.org/dists/pytest-3.5.1-py2.py3-none-any.whl and b/tests/repositories/fixtures/pypi.org/dists/pytest-3.5.1-py2.py3-none-any.whl differ