PyPI
- class
- PyPIRegistry
- purl type
- pkg:pypi
- api
- pypi.org
- version status
- yanked
Address it
await fetchPackageFromPURL("pkg:pypi/flask");
await fetchPackageFromPURL("pkg:pypi/Flask"); // the same package
await fetchPackageFromPURL("pkg:pypi/typing_extensions"); // normalized to typing-extensions
Names are normalized the way PEP 503 says: lowercase, runs of -, _ and . collapsed to -. parsePURL does it for PyPI types, and the adapter does it again on any name it receives, so PyPIRegistry called directly behaves the same.
What it reads
| Call | Endpoint |
|---|---|
fetchPackage | GET /pypi/{name}/json |
fetchVersions | GET /simple/{name}/ with Accept: application/vnd.pypi.simple.v1+json (PEP 691) |
fetchDependencies | GET /pypi/{name}/{version}/json, requires_dist |
fetchMaintainers | GET /pypi/{name}/json, author and author_email |
latestVersion is info.version. repository is the first of the Repository, Source, Source Code, GitHub and Homepage project URLs, normalized. documentation is the Documentation project URL. Keywords are split from the keywords string on commas or spaces.
Versions
The Simple API lists every version and every file. The adapter groups files by version, matching wheel and sdist filenames against the version list, and takes the sdist when there is one. publishedAt is that file's upload-time, integrity its sha256-, status is yanked when the file is yanked. A version with no files has no date and no hash.
Dependencies
requires_dist entries are parsed for the name, the version specifier and the environment marker. An extra == "…" marker sets the scope:
| Extra | scope | optional |
|---|---|---|
| none | runtime | false |
dev, development | development | true |
test, tests, testing | test | true |
| anything else | runtime | true |
Other markers, such as python_version, are dropped; the dependency stays.
Maintainers
One entry, the author, with role: "author", when the project declares one. PyPI's maintainer field and the project's owners on pypi.org are not read.
URLs
urls.registry("flask"); // https://pypi.org/project/flask/
urls.download("flask", "3.1.3"); // the sdist URL seen during fetchVersions, else the project page
urls.documentation("flask"); // https://pypi.org/project/flask
urls.readme("flask", "3.1.3"); // https://pypi.org/project/flask/3.1.3/
Gotchas
download()only knows a file URL afterfetchVersionsran on the same adapter instance; before that it points at the project page.requires_distis what the sdist or wheel declared, not what pip resolved. Conditional dependencies show up unconditionally.- Licenses on PyPI are free text.
normalizeLicensemaps the common spellings; a long license body is returned as is.
Where it lives
src/registries/pypi.ts.