diff --git a/docs/dev/api-reference/json.rst b/docs/dev/api-reference/json.rst index 261e14d470de..5e0a9b910685 100644 --- a/docs/dev/api-reference/json.rst +++ b/docs/dev/api-reference/json.rst @@ -1,502 +1,9 @@ JSON API ======== -PyPI offers two JSON endpoints. +.. important:: -Project -------- + This API documentation has been migrated to a new page in + the `user documentation `_: -.. attention:: - The ``releases`` key on this response should be considered deprecated, - and projects should shift to using the simple API (which can be accessed - as JSON via PEP 691) to get this information where possible. - - In the future, the ``releases`` key may be removed from this response. - - -.. attention:: - The ``downloads`` key on this response should be considered deprecated. - - It currently always returns ``-1`` and in the future, the ``downloads`` - key may be removed from this response. - - -.. attention:: - The ``has_sig`` key on this response should be considered deprecated. - - It currently always returns ``false`` and in the future, the ``has_sig`` - key may be removed from this response. - - -.. attention:: - The ``bugtrack_url`` key on this response should be considered deprecated. - - It currently always returns ``null`` and in the future, the ``bugtrack_url`` - key may be removed from this response. - - -.. http:get:: /pypi//json - - Returns metadata (info) about an individual project at the latest version, - a list of all releases for that project, and project URLs. Releases include - the release name, URL, and hash digests for MD5, SHA256, and BLAKE2b-256, - and are keyed by the release version string. Metadata returned comes from - the values provided at upload time and does not necessarily match the - content of the uploaded files. The first uploaded data for a release is - stored, subsequent uploads do not update it. - - **Example Request**: - - .. code:: http - - GET /pypi/sampleproject/json HTTP/1.1 - Host: pypi.org - Accept: application/json - - **Example response**: - - .. code:: http - - HTTP/1.1 200 OK - Content-Type: application/json; charset="UTF-8" - - { - "info": { - "author": "", - "author_email": "\"A. Random Developer\" ", - "bugtrack_url": null, - "classifiers": [ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Topic :: Software Development :: Build Tools" - ], - "description": "...", - "description_content_type": "text/markdown", - "docs_url": null, - "download_url": "", - "downloads": { - "last_day": -1, - "last_month": -1, - "last_week": -1 - }, - "dynamic": [ - "requires_dist" - ], - "home_page": "", - "keywords": "sample,setuptools,development", - "license": "...", - "maintainer": "", - "maintainer_email": "\"A. Great Maintainer\" ", - "name": "sampleproject", - "package_url": "https://pypi.org/project/sampleproject/", - "platform": null, - "project_url": "https://pypi.org/project/sampleproject/", - "project_urls": { - "Bug Reports": "https://github.com/pypa/sampleproject/issues", - "Funding": "https://donate.pypi.org", - "Homepage": "https://github.com/pypa/sampleproject", - "Say Thanks!": "http://saythanks.io/to/example", - "Source": "https://github.com/pypa/sampleproject/" - }, - "provides_extra": [ - "dev", - "test" - ], - "release_url": "https://pypi.org/project/sampleproject/3.0.0/", - "requires_dist": [ - "peppercorn", - "check-manifest ; extra == 'dev'", - "coverage ; extra == 'test'" - ], - "requires_python": ">=3.7", - "summary": "A sample Python project", - "version": "3.0.0", - "yanked": false, - "yanked_reason": null - }, - "last_serial": 15959178, - "releases": { - "1.0": [], - "1.2.0": [ - { - "comment_text": "", - "digests": { - "blake2b_256": "3052547eb3719d0e872bdd6fe3ab60cef92596f95262e925e1943f68f840df88", - "md5": "bab8eb22e6710eddae3c6c7ac3453bd9", - "sha256": "7a7a8b91086deccc54cac8d631e33f6a0e232ce5775c6be3dc44f86c2154019d" - }, - "downloads": -1, - "filename": "sampleproject-1.2.0-py2.py3-none-any.whl", - "has_sig": false, - "md5_digest": "bab8eb22e6710eddae3c6c7ac3453bd9", - "packagetype": "bdist_wheel", - "python_version": "2.7", - "requires_python": null, - "size": 3795, - "upload_time": "2015-06-14T14:38:05", - "upload_time_iso_8601": "2015-06-14T14:38:05.875222Z", - "url": "https://files.pythonhosted.org/packages/30/52/547eb3719d0e872bdd6fe3ab60cef92596f95262e925e1943f68f840df88/sampleproject-1.2.0-py2.py3-none-any.whl", - "yanked": false, - "yanked_reason": null - }, - { - "comment_text": "", - "digests": { - "blake2b_256": "eb4579be82bdeafcecb9dca474cad4003e32ef8e4a0dec6abbd4145ccb02abe1", - "md5": "d3bd605f932b3fb6e91f49be2d6f9479", - "sha256": "3427a8a5dd0c1e176da48a44efb410875b3973bd9843403a0997e4187c408dc1" - }, - "downloads": -1, - "filename": "sampleproject-1.2.0.tar.gz", - "has_sig": false, - "md5_digest": "d3bd605f932b3fb6e91f49be2d6f9479", - "packagetype": "sdist", - "python_version": "source", - "requires_python": null, - "size": 3148, - "upload_time": "2015-06-14T14:37:56", - "upload_time_iso_8601": "2015-06-14T14:37:56.383366Z", - "url": "https://files.pythonhosted.org/packages/eb/45/79be82bdeafcecb9dca474cad4003e32ef8e4a0dec6abbd4145ccb02abe1/sampleproject-1.2.0.tar.gz", - "yanked": false, - "yanked_reason": null - } - ], - "1.3.0": [ - "..." - ], - "1.3.1": [ - "..." - ], - "2.0.0": [ - "..." - ], - "3.0.0": [ - { - "comment_text": "", - "digests": { - "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", - "md5": "e46bfece301c915db29ade44a4932039", - "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0-py3-none-any.whl", - "has_sig": false, - "md5_digest": "e46bfece301c915db29ade44a4932039", - "packagetype": "bdist_wheel", - "python_version": "py3", - "requires_python": ">=3.7", - "size": 4662, - "upload_time": "2022-12-01T18:51:00", - "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", - "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", - "yanked": false, - "yanked_reason": null - }, - { - "comment_text": "", - "digests": { - "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", - "md5": "46a92a8a919062028405fdf232b508b0", - "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0.tar.gz", - "has_sig": false, - "md5_digest": "46a92a8a919062028405fdf232b508b0", - "packagetype": "sdist", - "python_version": "source", - "requires_python": ">=3.7", - "size": 5330, - "upload_time": "2022-12-01T18:51:01", - "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", - "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", - "yanked": false, - "yanked_reason": null - } - ] - }, - "urls": [ - { - "comment_text": "", - "digests": { - "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", - "md5": "e46bfece301c915db29ade44a4932039", - "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0-py3-none-any.whl", - "has_sig": false, - "md5_digest": "e46bfece301c915db29ade44a4932039", - "packagetype": "bdist_wheel", - "python_version": "py3", - "requires_python": ">=3.7", - "size": 4662, - "upload_time": "2022-12-01T18:51:00", - "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", - "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", - "yanked": false, - "yanked_reason": null - }, - { - "comment_text": "", - "digests": { - "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", - "md5": "46a92a8a919062028405fdf232b508b0", - "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0.tar.gz", - "has_sig": false, - "md5_digest": "46a92a8a919062028405fdf232b508b0", - "packagetype": "sdist", - "python_version": "source", - "requires_python": ">=3.7", - "size": 5330, - "upload_time": "2022-12-01T18:51:01", - "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", - "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", - "yanked": false, - "yanked_reason": null - } - ], - "vulnerabilities": [] - } - - :statuscode 200: no error - - On this endpoint, the ``vulnerabilities`` array provides a listing for - any known vulnerabilities in the most recent release (none, for the example - above). Use the release-specific endpoint documented below for precise - control over this field. - -Release -------- - -.. attention:: - Previously this response included the ``releases`` key, which had the URLs - for *all* files for every release of this project on PyPI. Due to stability - concerns, this had to be removed from the release specific page, which now - **ONLY** serves data specific to that release. - - To access all files, you should preferrably use the simple API, or otherwise - use the non versioned json api at ``/pypi//json``. - - -.. attention:: - The ``downloads`` key on this response should be considered deprecated. - - It currently always returns ``-1`` and in the future, the ``downloads`` - key may be removed from this response. - - -.. attention:: - The ``has_sig`` key on this response should be considered deprecated. - - It currently always returns ``false`` and in the future, the ``has_sig`` - key may be removed from this response. - - -.. attention:: - The ``bugtrack_url`` key on this response should be considered deprecated. - - It currently always returns ``null`` and in the future, the ``bugtrack_url`` - key may be removed from this response. - - -.. http:get:: /pypi///json - - Returns metadata about an individual release at a specific version, - otherwise identical to ``/pypi//json`` minus the - ``releases`` key. - - **Example Request**: - - .. code:: http - - GET /pypi/sampleproject/3.0.0/json HTTP/1.1 - Host: pypi.org - Accept: application/json - - **Example response**: - - .. code:: http - - HTTP/1.1 200 OK - Content-Type: application/json; charset="UTF-8" - - { - "info": { - "author": "", - "author_email": "\"A. Random Developer\" ", - "bugtrack_url": null, - "classifiers": [ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Topic :: Software Development :: Build Tools" - ], - "description": "...", - "description_content_type": "text/markdown", - "docs_url": null, - "download_url": "", - "downloads": { - "last_day": -1, - "last_month": -1, - "last_week": -1 - }, - "home_page": "", - "keywords": "sample,setuptools,development", - "license": "... ", - "maintainer": "", - "maintainer_email": "\"A. Great Maintainer\" ", - "name": "sampleproject", - "package_url": "https://pypi.org/project/sampleproject/", - "platform": null, - "project_url": "https://pypi.org/project/sampleproject/", - "project_urls": { - "Bug Reports": "https://github.com/pypa/sampleproject/issues", - "Funding": "https://donate.pypi.org", - "Homepage": "https://github.com/pypa/sampleproject", - "Say Thanks!": "http://saythanks.io/to/example", - "Source": "https://github.com/pypa/sampleproject/" - }, - "release_url": "https://pypi.org/project/sampleproject/3.0.0/", - "requires_dist": [ - "peppercorn", - "check-manifest ; extra == 'dev'", - "coverage ; extra == 'test'" - ], - "requires_python": ">=3.7", - "summary": "A sample Python project", - "version": "3.0.0", - "yanked": false, - "yanked_reason": null - }, - "last_serial": 15959178, - "urls": [ - { - "comment_text": "", - "digests": { - "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", - "md5": "e46bfece301c915db29ade44a4932039", - "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0-py3-none-any.whl", - "has_sig": false, - "md5_digest": "e46bfece301c915db29ade44a4932039", - "packagetype": "bdist_wheel", - "python_version": "py3", - "requires_python": ">=3.7", - "size": 4662, - "upload_time": "2022-12-01T18:51:00", - "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", - "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", - "yanked": false, - "yanked_reason": null - }, - { - "comment_text": "", - "digests": { - "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", - "md5": "46a92a8a919062028405fdf232b508b0", - "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" - }, - "downloads": -1, - "filename": "sampleproject-3.0.0.tar.gz", - "has_sig": false, - "md5_digest": "46a92a8a919062028405fdf232b508b0", - "packagetype": "sdist", - "python_version": "source", - "requires_python": ">=3.7", - "size": 5330, - "upload_time": "2022-12-01T18:51:01", - "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", - "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", - "yanked": false, - "yanked_reason": null - } - ], - "vulnerabilities": [] - } - - :statuscode 200: no error - -Known vulnerabilities -~~~~~~~~~~~~~~~~~~~~~ - -In the example above, the combination of the requested project and version -had no `known vulnerabilities `_. -An example of a response for a project with known vulnerabilities is -provided below, with unrelated fields collapsed for readability. - -.. code:: http - - GET /pypi/Django/3.0.2/json HTTP/1.1 - Host: pypi.org - Accept: application/json - - { - "info": {}, - "last_serial": 12089094, - "releases": {}, - "urls": [], - "vulnerabilities": [ - { - "aliases": [ - "CVE-2021-3281" - ], - "details": "In Django 2.2 before 2.2.18, 3.0 before 3.0.12, and 3.1 before 3.1.6, the django.utils.archive.extract method (used by \"startapp --template\" and \"startproject --template\") allows directory traversal via an archive with absolute paths or relative paths with dot segments.", - "summary": "A shorter summary of the vulnerability", - "fixed_in": [ - "2.2.18", - "3.0.12", - "3.1.6" - ], - "id": "PYSEC-2021-9", - "link": "https://osv.dev/vulnerability/PYSEC-2021-9", - "source": "osv", - "withdrawn": null - }, - ] - } - -The ``withdrawn`` field is of particular interest: when non-``null``, it -contains the RFC 3339 timestamp when the vulnerability was withdrawn by an -upstream vulnerability reporting source. API consumers can use this field to -retract vulnerability reports that are later determined to be invalid. - -For example, here is what a withdrawn vulnerability might look like: - -.. code:: json - - - { - "aliases": [ - "CVE-2022-XXXXX" - ], - "details": "A long description.", - "summary": "A shorter summary.", - "fixed_in": [ - "1.2.3" - ], - "id": "PYSEC-2022-XXX", - "link": "https://osv.dev/vulnerability/PYSEC-2022-XXX", - "source": "osv", - "withdrawn": "2022-06-28T16:39:06Z" - } + * `JSON API `_ diff --git a/docs/mkdocs-user-docs.yml b/docs/mkdocs-user-docs.yml index bd4e3d6e7a46..e286152fe19e 100644 --- a/docs/mkdocs-user-docs.yml +++ b/docs/mkdocs-user-docs.yml @@ -89,6 +89,7 @@ nav: - "APIs and Datasets": - "api/index.md" - "api/index-api.md" + - "api/json.md" - "api/upload.md" - "api/integrity.md" - "api/stats.md" diff --git a/docs/user/api/index.md b/docs/user/api/index.md index 340ea34d4b5d..c7a6a51482a4 100644 --- a/docs/user/api/index.md +++ b/docs/user/api/index.md @@ -117,4 +117,4 @@ As you’ll note, it is just a redirect to the canonical file. [Index API]: ./index-api.md -[JSON API]: https://warehouse.pypa.io/api-reference/json/ +[JSON API]: ./json.md diff --git a/docs/user/api/json.md b/docs/user/api/json.md new file mode 100644 index 000000000000..98ac7680884d --- /dev/null +++ b/docs/user/api/json.md @@ -0,0 +1,487 @@ +# JSON API + +!!! tip + + This page documents the **PyPI-specific** JSON API. + If all you need is a JSON index API (e.g. for retrieving) + all distributions or all versions for a package, you + can use the [Index API]. + +## Routes + +### Get a project + +Route: `GET /pypi//json` + +Returns metadata (info) about an individual project at the latest version, +a list of all releases for that project, and project URLs. Releases include +the release name, URL, and hash digests for MD5, SHA256, and BLAKE2b-256, +and are keyed by the release version string. Metadata returned comes from +the values provided at upload time and does not necessarily match the +content of the uploaded files. The first uploaded data for a release is +stored, subsequent uploads do not update it. + +On this endpoint, the `vulnerabilities` array provides a listing for +any known vulnerabilities in the most recent release (none, for the example +above). Use the release-specific endpoint documented below for precise +control over this field. + +!!! warning "Deprecated keys" + + The following keys are considered deprecated: + + * `releases`: projects should shift to using the [Index API] to + get this information, where possible. + * `downloads`: this key is always `-1` and should not be used. + * `has_sig`: this key is always `false` and should not be used. + * `bugtrack_url`: this key is always `null` and should not be used. + + In the future, each of these keys may be removed entirely from + this API response. + +Status codes: + +* `200 OK` - no error + +Example request: + +```http +GET /pypi/sampleproject/json HTTP/1.1 +Host: pypi.org +Accept: application/json +``` + +??? "Example JSON response" + + ```http + HTTP/1.1 200 OK + Content-Type: application/json; charset="UTF-8" + + { + "info": { + "author": "", + "author_email": "\"A. Random Developer\" ", + "bugtrack_url": null, + "classifiers": [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Topic :: Software Development :: Build Tools" + ], + "description": "...", + "description_content_type": "text/markdown", + "docs_url": null, + "download_url": "", + "downloads": { + "last_day": -1, + "last_month": -1, + "last_week": -1 + }, + "dynamic": [ + "requires_dist" + ], + "home_page": "", + "keywords": "sample,setuptools,development", + "license": "...", + "maintainer": "", + "maintainer_email": "\"A. Great Maintainer\" ", + "name": "sampleproject", + "package_url": "https://pypi.org/project/sampleproject/", + "platform": null, + "project_url": "https://pypi.org/project/sampleproject/", + "project_urls": { + "Bug Reports": "https://github.com/pypa/sampleproject/issues", + "Funding": "https://donate.pypi.org", + "Homepage": "https://github.com/pypa/sampleproject", + "Say Thanks!": "http://saythanks.io/to/example", + "Source": "https://github.com/pypa/sampleproject/" + }, + "provides_extra": [ + "dev", + "test" + ], + "release_url": "https://pypi.org/project/sampleproject/3.0.0/", + "requires_dist": [ + "peppercorn", + "check-manifest ; extra == 'dev'", + "coverage ; extra == 'test'" + ], + "requires_python": ">=3.7", + "summary": "A sample Python project", + "version": "3.0.0", + "yanked": false, + "yanked_reason": null + }, + "last_serial": 15959178, + "releases": { + "1.0": [], + "1.2.0": [ + { + "comment_text": "", + "digests": { + "blake2b_256": "3052547eb3719d0e872bdd6fe3ab60cef92596f95262e925e1943f68f840df88", + "md5": "bab8eb22e6710eddae3c6c7ac3453bd9", + "sha256": "7a7a8b91086deccc54cac8d631e33f6a0e232ce5775c6be3dc44f86c2154019d" + }, + "downloads": -1, + "filename": "sampleproject-1.2.0-py2.py3-none-any.whl", + "has_sig": false, + "md5_digest": "bab8eb22e6710eddae3c6c7ac3453bd9", + "packagetype": "bdist_wheel", + "python_version": "2.7", + "requires_python": null, + "size": 3795, + "upload_time": "2015-06-14T14:38:05", + "upload_time_iso_8601": "2015-06-14T14:38:05.875222Z", + "url": "https://files.pythonhosted.org/packages/30/52/547eb3719d0e872bdd6fe3ab60cef92596f95262e925e1943f68f840df88/sampleproject-1.2.0-py2.py3-none-any.whl", + "yanked": false, + "yanked_reason": null + }, + { + "comment_text": "", + "digests": { + "blake2b_256": "eb4579be82bdeafcecb9dca474cad4003e32ef8e4a0dec6abbd4145ccb02abe1", + "md5": "d3bd605f932b3fb6e91f49be2d6f9479", + "sha256": "3427a8a5dd0c1e176da48a44efb410875b3973bd9843403a0997e4187c408dc1" + }, + "downloads": -1, + "filename": "sampleproject-1.2.0.tar.gz", + "has_sig": false, + "md5_digest": "d3bd605f932b3fb6e91f49be2d6f9479", + "packagetype": "sdist", + "python_version": "source", + "requires_python": null, + "size": 3148, + "upload_time": "2015-06-14T14:37:56", + "upload_time_iso_8601": "2015-06-14T14:37:56.383366Z", + "url": "https://files.pythonhosted.org/packages/eb/45/79be82bdeafcecb9dca474cad4003e32ef8e4a0dec6abbd4145ccb02abe1/sampleproject-1.2.0.tar.gz", + "yanked": false, + "yanked_reason": null + } + ], + "1.3.0": [ + "..." + ], + "1.3.1": [ + "..." + ], + "2.0.0": [ + "..." + ], + "3.0.0": [ + { + "comment_text": "", + "digests": { + "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", + "md5": "e46bfece301c915db29ade44a4932039", + "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0-py3-none-any.whl", + "has_sig": false, + "md5_digest": "e46bfece301c915db29ade44a4932039", + "packagetype": "bdist_wheel", + "python_version": "py3", + "requires_python": ">=3.7", + "size": 4662, + "upload_time": "2022-12-01T18:51:00", + "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", + "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", + "yanked": false, + "yanked_reason": null + }, + { + "comment_text": "", + "digests": { + "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", + "md5": "46a92a8a919062028405fdf232b508b0", + "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0.tar.gz", + "has_sig": false, + "md5_digest": "46a92a8a919062028405fdf232b508b0", + "packagetype": "sdist", + "python_version": "source", + "requires_python": ">=3.7", + "size": 5330, + "upload_time": "2022-12-01T18:51:01", + "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", + "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", + "yanked": false, + "yanked_reason": null + } + ] + }, + "urls": [ + { + "comment_text": "", + "digests": { + "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", + "md5": "e46bfece301c915db29ade44a4932039", + "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0-py3-none-any.whl", + "has_sig": false, + "md5_digest": "e46bfece301c915db29ade44a4932039", + "packagetype": "bdist_wheel", + "python_version": "py3", + "requires_python": ">=3.7", + "size": 4662, + "upload_time": "2022-12-01T18:51:00", + "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", + "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", + "yanked": false, + "yanked_reason": null + }, + { + "comment_text": "", + "digests": { + "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", + "md5": "46a92a8a919062028405fdf232b508b0", + "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0.tar.gz", + "has_sig": false, + "md5_digest": "46a92a8a919062028405fdf232b508b0", + "packagetype": "sdist", + "python_version": "source", + "requires_python": ">=3.7", + "size": 5330, + "upload_time": "2022-12-01T18:51:01", + "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", + "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", + "yanked": false, + "yanked_reason": null + } + ], + "vulnerabilities": [] + } + ``` + +### Get a release + +Route: `GET /pypi///json` + +Returns metadata about an individual release at a specific version, +otherwise identical to `/pypi//json` minus the +`releases` key. + +!!! tip + + This response previously included the `releases` key, which had the URLs + for *all* files for every release of this project on PyPI. Due to stability + concerns, this had to be removed from the release specific page, which now + **only** serves data specific to that release. + + To access all files, you should preferably use the [Index API], or otherwise + use the project-level JSON api at `/pypi//json`. + + +!!! warning "Deprecated keys" + + The following keys are considered deprecated: + + * `downloads`: this key is always `-1` and should not be used. + * `has_sig`: this key is always `false` and should not be used. + * `bugtrack_url`: this key is always `null` and should not be used. + + In the future, each of these keys may be removed entirely from + this API response. + +Status codes: + +* `200 OK` - no error + +Example request: + +```http +GET /pypi/sampleproject/3.0.0/json HTTP/1.1 +Host: pypi.org +Accept: application/json +``` + +??? "Example JSON response" + + ```http + HTTP/1.1 200 OK + Content-Type: application/json; charset="UTF-8" + + { + "info": { + "author": "", + "author_email": "\"A. Random Developer\" ", + "bugtrack_url": null, + "classifiers": [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Topic :: Software Development :: Build Tools" + ], + "description": "...", + "description_content_type": "text/markdown", + "docs_url": null, + "download_url": "", + "downloads": { + "last_day": -1, + "last_month": -1, + "last_week": -1 + }, + "home_page": "", + "keywords": "sample,setuptools,development", + "license": "... ", + "maintainer": "", + "maintainer_email": "\"A. Great Maintainer\" ", + "name": "sampleproject", + "package_url": "https://pypi.org/project/sampleproject/", + "platform": null, + "project_url": "https://pypi.org/project/sampleproject/", + "project_urls": { + "Bug Reports": "https://github.com/pypa/sampleproject/issues", + "Funding": "https://donate.pypi.org", + "Homepage": "https://github.com/pypa/sampleproject", + "Say Thanks!": "http://saythanks.io/to/example", + "Source": "https://github.com/pypa/sampleproject/" + }, + "release_url": "https://pypi.org/project/sampleproject/3.0.0/", + "requires_dist": [ + "peppercorn", + "check-manifest ; extra == 'dev'", + "coverage ; extra == 'test'" + ], + "requires_python": ">=3.7", + "summary": "A sample Python project", + "version": "3.0.0", + "yanked": false, + "yanked_reason": null + }, + "last_serial": 15959178, + "urls": [ + { + "comment_text": "", + "digests": { + "blake2b_256": "eca85ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c", + "md5": "e46bfece301c915db29ade44a4932039", + "sha256": "2e52702990c22cf1ce50206606b769fe0dbd5646a32873916144bd5aec5473b3" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0-py3-none-any.whl", + "has_sig": false, + "md5_digest": "e46bfece301c915db29ade44a4932039", + "packagetype": "bdist_wheel", + "python_version": "py3", + "requires_python": ">=3.7", + "size": 4662, + "upload_time": "2022-12-01T18:51:00", + "upload_time_iso_8601": "2022-12-01T18:51:00.007372Z", + "url": "https://files.pythonhosted.org/packages/ec/a8/5ec62d18adde798d33a170e7f72930357aa69a60839194c93eb0fb05e59c/sampleproject-3.0.0-py3-none-any.whl", + "yanked": false, + "yanked_reason": null + }, + { + "comment_text": "", + "digests": { + "blake2b_256": "672a9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca", + "md5": "46a92a8a919062028405fdf232b508b0", + "sha256": "117ed88e5db073bb92969a7545745fd977ee85b7019706dd256a64058f70963d" + }, + "downloads": -1, + "filename": "sampleproject-3.0.0.tar.gz", + "has_sig": false, + "md5_digest": "46a92a8a919062028405fdf232b508b0", + "packagetype": "sdist", + "python_version": "source", + "requires_python": ">=3.7", + "size": 5330, + "upload_time": "2022-12-01T18:51:01", + "upload_time_iso_8601": "2022-12-01T18:51:01.420127Z", + "url": "https://files.pythonhosted.org/packages/67/2a/9f056e5fa36e43ef1037ff85581a2963cde420457de0ef29c779d41058ca/sampleproject-3.0.0.tar.gz", + "yanked": false, + "yanked_reason": null + } + ], + "vulnerabilities": [] + } + ``` + +#### Known vulnerabilities + +In the example above, the combination of the requested project and version +had no [known vulnerabilities]. + +An example of a response for a project with known vulnerabilities is +provided below, with unrelated fields collapsed for readability. + +```http +HTTP/1.1 200 OK +Content-Type: application/json; charset="UTF-8" + +{ + "info": {}, + "last_serial": 12089094, + "releases": {}, + "urls": [], + "vulnerabilities": [ + { + "aliases": [ + "CVE-2021-3281" + ], + "details": "In Django 2.2 before 2.2.18, 3.0 before 3.0.12, and 3.1 before 3.1.6, the django.utils.archive.extract method (used by \"startapp --template\" and \"startproject --template\") allows directory traversal via an archive with absolute paths or relative paths with dot segments.", + "summary": "A shorter summary of the vulnerability", + "fixed_in": [ + "2.2.18", + "3.0.12", + "3.1.6" + ], + "id": "PYSEC-2021-9", + "link": "https://osv.dev/vulnerability/PYSEC-2021-9", + "source": "osv", + "withdrawn": null + }, + ] +} +``` + +The `withdrawn` field is of particular interest: when non-`null`, it +contains the RFC 3339 timestamp when the vulnerability was withdrawn by an +upstream vulnerability reporting source. API consumers can use this field to +retract vulnerability reports that are later determined to be invalid. + +For example, here is what a withdrawn vulnerability might look like: + +```json +{ + "aliases": [ + "CVE-2022-XXXXX" + ], + "details": "A long description.", + "summary": "A shorter summary.", + "fixed_in": [ + "1.2.3" + ], + "id": "PYSEC-2022-XXX", + "link": "https://osv.dev/vulnerability/PYSEC-2022-XXX", + "source": "osv", + "withdrawn": "2022-06-28T16:39:06Z" +} +``` + + +[Index API]: ./index-api.md +[known vulnerabilities]: https://github.com/pypa/advisory-database diff --git a/docs/user/project_metadata.md b/docs/user/project_metadata.md index e19d64e99241..e065c09f76cd 100644 --- a/docs/user/project_metadata.md +++ b/docs/user/project_metadata.md @@ -1,9 +1,9 @@ # Project Metadata -Python packages can include additional metadata to provide more information -about the project. This document outlines the specific behaviors -implemented by PyPI to display project metadata and other details. The -comprehensive list of metadata fields is available in the [Python Packaging +Python packages can include additional metadata to provide more information +about the project. This document outlines the specific behaviors +implemented by PyPI to display project metadata and other details. The +comprehensive list of metadata fields is available in the [Python Packaging User Guide]. [Python Packaging User Guide]: https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-specifications @@ -11,12 +11,11 @@ User Guide]. ## Project URLs -Packages owners can specify various URLs related to their project using +Packages owners can specify various URLs related to their project using the [`[project.urls]` table](https://packaging.python.org/en/latest/specifications/pyproject-toml/#urls) in the package's `pyproject.toml`. -PyPI renders these URLs on the project page and splits them into `verified` and -`unverified` subgroups. They are also available using the -[JSON API](https://warehouse.pypa.io/api-reference/json.html). +PyPI renders these URLs on the project page and splits them into `verified` and +`unverified` subgroups. They are also available using the [JSON API](./api/json.md). ### Verified details @@ -52,7 +51,7 @@ following as verified: #### Via Trusted Publishing -[Trusted Publishing](trusted-publishers/index.md) allows PyPI to attest that the +[Trusted Publishing](trusted-publishers/index.md) allows PyPI to attest that the publishing workflow for a package is coming from a verified source. The URLs that can be verified depend on the Trusted Publisher used: @@ -70,7 +69,7 @@ The URLs that can be verified depend on the Trusted Publisher used: - `https://gitlab.com/pypa/pip/*` (all subpaths) - `https://gitlab.com/pypa/pip.git` - [Google Cloud][gc-tab]: No Google-specific URLs are currently verified. -- [ActiveState][active-tab]: Packages uploaded using ActiveState will have URLs linked to the project in ActiveState +- [ActiveState][active-tab]: Packages uploaded using ActiveState will have URLs linked to the project in ActiveState verified: - `https://platform.activestate.com/pypa/pip` - `https://platform.activestate.com/pypa/pip/*` (all subpaths) @@ -92,9 +91,9 @@ lists below and changes the default icon from #### General URL -To display a custom icon, an entry must match one of the pattern. The -recognition patterns are case-insensitive. Items marked with an asterisk (^*^) -indicate a prefix. It means that any name starting with the specified pattern +To display a custom icon, an entry must match one of the pattern. The +recognition patterns are case-insensitive. Items marked with an asterisk (^*^) +indicate a prefix. It means that any name starting with the specified pattern will be recognized. | Name | Icon | Description | Aliases | @@ -110,8 +109,8 @@ will be recognized. #### Hosting Platforms -An entry URL must point to a domain below to display a custom icon. Custom -subdomains are also matched. For instance, if `domain.com` is listed, a URL +An entry URL must point to a domain below to display a custom icon. Custom +subdomains are also matched. For instance, if `domain.com` is listed, a URL ending in `.domain.com` will also match. | Service | Icon | Domain | @@ -131,7 +130,7 @@ To display a custom icon, an entry must either : | Platform | Icon | Name | Domain | |:---------|:----------------------------------|:---------|:----------------------------------------------| -| Discord | :fontawesome-brands-discord: | | `discord.com`, `discordapp.com`, `discord.gg` | +| Discord | :fontawesome-brands-discord: | | `discord.com`, `discordapp.com`, `discord.gg` | | Gitter | :fontawesome-brands-gitter: | | `gitter.im` | | Mastodon | :fontawesome-brands-mastodon: | Mastodon | | | Reddit | :fontawesome-brands-reddit-alien: | | `reddit.com` | @@ -141,14 +140,14 @@ To display a custom icon, an entry must either : #### Continuous Integration Services -To display a custom icon (:fontawesome-solid-list-check:), an entry URL must -point to one of the service provider domains listed below. Custom subdomains are +To display a custom icon (:fontawesome-solid-list-check:), an entry URL must +point to one of the service provider domains listed below. Custom subdomains are supported. | Service | Domain | |:----------|:---------------------------------| | AppVeyor | `ci.appveyor.com` | -| CircleCI | `circleci.com` | +| CircleCI | `circleci.com` | | Codecov | `codecov.io` | | Coveralls | `coveralls.io` | | Travis CI | `travis-ci.com`, `travis-ci.org` |