Python packaging doesn't always go exactly as planned. With the wide range of versions of packaging infrastructure and build backends and deployments, sometimes things go wrong and in confusing ways. This page collects some of the problems and solutions that I've had to work out. # Editable install imports not found by mypy and pyright (Added [[2025-09-17|September 17, 2025]]) [[mypy]] and [[pyright]] may fail to find imports from editable package installs. The reason for this is that newer editable installs (in [[setuptools]] 64+ and others) use a new import hook mechanism that requires dynamic lookups that neither type checker will do. The older style was to use `.pth` files, which could be scanned statically. Workarounds may not work forever, but for now, [[setuptools]]-based packages can be installed in compat mode: ```console $ pip install -e . --config-settings editable_mode=compat ``` > [!seealso] See Also: > * [Development Mode (a.k.a. “Editable Installs”) - setuptools documentation](https://setuptools.pypa.io/en/latest/userguide/development_mode.html#legacy-behavior) > * [Editable Installs - Pyright](https://microsoft.github.io/pyright/#/import-resolution?id=editable-installs) > * [Editable installs are not recognized as having typing when using py.typed (setuptools v64 issue) · Issue #13392 · python/mypy · GitHub](https://github.com/python/mypy/issues/13392) # InvalidDistribution: Invalid distribution metadata: unrecognized or malformed field 'license-file' Package metadata accepted by PyPI has changed in Metadata 2.4 ([PEP 639 – Improving License Clarity with Better Package Metadata \| peps.python.org](https://peps.python.org/pep-0639/)), and unfortunately it seems [[setuptools]] can end up generating the wrong combination of fields Out of the box, we're seeing breakages with [[twine]] 6.1.0, `pkginfo` 1.12.1.2, [[setuptools]] 77 through 80.9, and `packaging` 24.1. This is after upgrading from earlier releases (versions unknown) to try to resolve the fix. Let's go over what we expect, what isn't working, and how to resolve this. ### Metadata Generation [[setuptools]] 77 adds support for the PEP 639 license metadata. As a demonstration, take this configuration: ```toml [build-system] requires = ['setuptools>=77'] build_backend = 'setuptools.build_meta' [project] license = 'MIT' license-files = [ 'COPYING', 'AUTHORS' ] # Optional ... ``` We end up with the following metadata recorded for the package: ``` Metadata-Version: 2.4 ... License-Expression: MIT License-File: COPYING License-File: AUTHORS Dynamic: license-file ``` This is correct (except it's unclear to me if `Dynamic: license-file` is right here). ### Core Problem and Solution Versions really need to align for this to work, and so does metadata. Make sure the following versions are installed in the environment running [[twine]]: * [[twine]] 6.1.0+ * `packaging` 24.2+ Make sure the following is set for the package build backend: * [[setuptools]] 77+ This aligns everything to support PEP 639. You will also need to modify the `pyproject.toml` configuration: 1. Remove any `classifiers` entry containing a `License ::` prefix in `pyproject.toml` 2. Add `license = "<license name>` This replaces the old table form (`license = { text = "<string>" }`) 3. Optionally add `license-files = ["<file-pattern">, ...]` * [[setuptools]] docs says this is optional, as it provides its own default. This should allow the correct metadata to be generated and uploaded to PyPI.