pypi-simple
Advanced tools
| { | ||
| "files": [ | ||
| { | ||
| "filename": "argset-0.1.0-py3-none-any.whl", | ||
| "hashes": { | ||
| "sha256": "107a632c7112faceb9fd6e93658dd461154713db250f7ffde5bd473e17cf1db5" | ||
| }, | ||
| "requires-python": "~=3.6", | ||
| "url": "https://files.pythonhosted.org/packages/b5/2b/7aa284f345e37f955d86e4cd57b1039b573552b0fc29d1a522ec05c1ee41/argset-0.1.0-py3-none-any.whl", | ||
| "yanked": false, | ||
| "size": 5219, | ||
| "upload-time": "2021-06-05T00:15:37.534150Z" | ||
| }, | ||
| { | ||
| "filename": "argset-0.1.0.tar.gz", | ||
| "hashes": { | ||
| "sha256": "8a41ee4789d37517c259984c11f2aa3639a90dc8fa446ff905ecc5fe6623c12d" | ||
| }, | ||
| "requires-python": "~=3.6", | ||
| "url": "https://files.pythonhosted.org/packages/d0/ee/1c25e68d029e8daaf3228dababbf3261fa5d9569f6f705867b2ad4df9b6d/argset-0.1.0.tar.gz", | ||
| "yanked": false, | ||
| "size": 6565, | ||
| "upload-time": "2021-06-05T00:15:39.003726Z" | ||
| } | ||
| ], | ||
| "meta": { | ||
| "_last-serial": 10562871, | ||
| "api-version": "1.2", | ||
| "tracks": ["https://tracks.package/pypi/argset/", "https://test.tracks.package/pypi/argset"], | ||
| "alternate-locations": ["https://alt.package/pypi/argset/", "https://test.alt.package/pypi/argset"] | ||
| }, | ||
| "name": "argset", | ||
| "versions": ["0.1.0"] | ||
| } |
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>Links for qypi</title> | ||
| <meta name="pypi:repository-version" content="1.2"/> | ||
| <meta name="pypi:tracks" content="https://tracks.package/pypi/qypi/"/> | ||
| <meta name="pypi:alternate-locations" content="https://alt.package/pypi/qypi/"/> | ||
| <meta name="pypi:tracks" content="https://test.tracks.package/pypi/qypi/"/> | ||
| <meta name="pypi:alternate-locations" content="https://test.alt.package/pypi/qypi/"/> | ||
| </head> | ||
| <body> | ||
| <h1>Links for qypi</h1> | ||
| <a href="https://files.pythonhosted.org/packages/82/fc/9e25534641d7f63be93079bc07fa92bab136ddf5d4181059a1308a346f96/qypi-0.1.0-py3-none-any.whl#sha256=da69d28dcd527c0e372b3fa7b92fc333b327f8470175f035abc4e351b539189f" data-requires-python="~=3.4">qypi-0.1.0-py3-none-any.whl</a><br/> | ||
| <a href="https://files.pythonhosted.org/packages/e4/fe/3fdb222a2916b94e9ca12d80c92dbbad1f7068c82fca42872d6c1739fead/qypi-0.1.0.tar.gz#sha256=212093de95b4f5f22e19fa18fe57fa33eccd63adb9b325fe1b673bf71912c551" data-requires-python="~=3.4">qypi-0.1.0.tar.gz</a><br/> | ||
| </body> | ||
| </html> | ||
| <!--SERIAL 2875636--> |
+8
-0
@@ -0,1 +1,9 @@ | ||
| v1.4.0 (2023-11-01) | ||
| ------------------- | ||
| - Support PEP 708 | ||
| - `tracks` and `alternate_locations` attributes added to `ProjectPage` | ||
| - `pypi_meta`, `tracks`, and `alternate_locations` attributes added to | ||
| `RepositoryPage` | ||
| - `SUPPORTED_REPOSITORY_VERSION` increased to `"1.2"` | ||
| v1.3.0 (2023-11-01) | ||
@@ -2,0 +10,0 @@ ------------------- |
+12
-1
@@ -6,2 +6,13 @@ .. currentmodule:: pypi_simple | ||
| v1.4.0 (2023-11-01) | ||
| ------------------- | ||
| - Support :pep:`708` | ||
| - `~ProjectPage.tracks` and `~ProjectPage.alternate_locations` attributes | ||
| added to `ProjectPage` | ||
| - `~RepositoryPage.pypi_meta`, `~RepositoryPage.tracks`, and | ||
| `~RepositoryPage.alternate_locations` attributes added to `RepositoryPage` | ||
| - `SUPPORTED_REPOSITORY_VERSION` increased to ``"1.2"`` | ||
| v1.3.0 (2023-11-01) | ||
@@ -25,3 +36,3 @@ ------------------- | ||
| - ``versions`` field added to `ProjectPage` | ||
| - ``size` and ``upload_time`` fields added to `DistributionPackage` | ||
| - ``size`` and ``upload_time`` fields added to `DistributionPackage` | ||
| - `SUPPORTED_REPOSITORY_VERSION` increased to ``"1.1"`` | ||
@@ -28,0 +39,0 @@ |
+2
-2
@@ -22,4 +22,4 @@ .. module:: pypi_simple | ||
| specified in :pep:`503` and updated by :pep:`592`, :pep:`629`, :pep:`658`, | ||
| :pep:`691`, :pep:`700`, and :pep:`714`. With it, you can query `the Python | ||
| Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| :pep:`691`, :pep:`700`, :pep:`708`, and :pep:`714`. With it, you can query | ||
| `the Python Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| <https://pip.pypa.io>`_-compatible repositories for a list of their available | ||
@@ -26,0 +26,0 @@ projects and lists of each project's available package files. The library also |
+3
-3
| Metadata-Version: 2.1 | ||
| Name: pypi-simple | ||
| Version: 1.3.0 | ||
| Version: 1.4.0 | ||
| Summary: PyPI Simple Repository API client library | ||
@@ -67,4 +67,4 @@ Home-page: https://github.com/jwodder/pypi-simple | ||
| specified in :pep:`503` and updated by :pep:`592`, :pep:`629`, :pep:`658`, | ||
| :pep:`691`, :pep:`700`, and :pep:`714`. With it, you can query `the Python | ||
| Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| :pep:`691`, :pep:`700`, :pep:`708`, and :pep:`714`. With it, you can query | ||
| `the Python Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| <https://pip.pypa.io>`_-compatible repositories for a list of their available | ||
@@ -71,0 +71,0 @@ projects and lists of each project's available package files. The library also |
+2
-2
@@ -28,4 +28,4 @@ .. image:: http://www.repostatus.org/badges/latest/active.svg | ||
| specified in :pep:`503` and updated by :pep:`592`, :pep:`629`, :pep:`658`, | ||
| :pep:`691`, :pep:`700`, and :pep:`714`. With it, you can query `the Python | ||
| Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| :pep:`691`, :pep:`700`, :pep:`708`, and :pep:`714`. With it, you can query | ||
| `the Python Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| <https://pip.pypa.io>`_-compatible repositories for a list of their available | ||
@@ -32,0 +32,0 @@ projects and lists of each project's available package files. The library also |
| Metadata-Version: 2.1 | ||
| Name: pypi-simple | ||
| Version: 1.3.0 | ||
| Version: 1.4.0 | ||
| Summary: PyPI Simple Repository API client library | ||
@@ -67,4 +67,4 @@ Home-page: https://github.com/jwodder/pypi-simple | ||
| specified in :pep:`503` and updated by :pep:`592`, :pep:`629`, :pep:`658`, | ||
| :pep:`691`, :pep:`700`, and :pep:`714`. With it, you can query `the Python | ||
| Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| :pep:`691`, :pep:`700`, :pep:`708`, and :pep:`714`. With it, you can query | ||
| `the Python Package Index (PyPI) <https://pypi.org>`_ and other `pip | ||
| <https://pip.pypa.io>`_-compatible repositories for a list of their available | ||
@@ -71,0 +71,0 @@ projects and lists of each project's available package files. The library also |
@@ -39,2 +39,3 @@ CHANGELOG.md | ||
| test/data/argset-700.json | ||
| test/data/argset-708.json | ||
| test/data/argset-relative.json | ||
@@ -45,2 +46,3 @@ test/data/argset.json | ||
| test/data/devpi_devpi.html | ||
| test/data/qypi-708.html | ||
| test/data/qypi.html | ||
@@ -47,0 +49,0 @@ test/data/qypi_base.html |
@@ -17,3 +17,3 @@ """ | ||
| __version__ = "1.3.0" | ||
| __version__ = "1.4.0" | ||
| __author__ = "John Thorvald Wodder II" | ||
@@ -28,3 +28,3 @@ __author_email__ = "pypi-simple@varonathe.org" | ||
| #: The maximum supported simple repository version (See :pep:`629`) | ||
| SUPPORTED_REPOSITORY_VERSION: str = "1.1" | ||
| SUPPORTED_REPOSITORY_VERSION: str = "1.2" | ||
@@ -31,0 +31,0 @@ #: :mailheader:`Accept` header value for accepting either the HTML or JSON |
| from __future__ import annotations | ||
| from dataclasses import dataclass | ||
| from dataclasses import dataclass, field | ||
| from datetime import datetime | ||
@@ -246,2 +246,16 @@ import re | ||
| #: .. versionadded:: 1.4.0 | ||
| #: | ||
| #: Repository "tracks" metadata. See `PEP 708`__. | ||
| #: | ||
| #: __ https://peps.python.org/pep-0708/#repository-tracks-metadata | ||
| tracks: list[str] = field(default_factory=list) | ||
| #: .. versionadded:: 1.4.0 | ||
| #: | ||
| #: Repository "alternate locations" metadata. See `PEP 708`__. | ||
| #: | ||
| #: __ https://peps.python.org/pep-0708/#alternate-locations-metadata | ||
| alternate_locations: list[str] = field(default_factory=list) | ||
| @classmethod | ||
@@ -285,2 +299,4 @@ def from_html( | ||
| versions=None, | ||
| tracks=page.tracks, | ||
| alternate_locations=page.alternate_locations, | ||
| ) | ||
@@ -319,2 +335,4 @@ | ||
| versions=project.versions, | ||
| tracks=project.meta.tracks, | ||
| alternate_locations=project.meta.alternate_locations, | ||
| ) | ||
@@ -321,0 +339,0 @@ |
@@ -407,2 +407,4 @@ from __future__ import annotations | ||
| """ | ||
| .. versionadded:: 1.3.0 | ||
| Raised by `PyPISimple.get_package_metadata()` when a request for | ||
@@ -409,0 +411,0 @@ distribution metadata fails with a 404 error code |
@@ -55,4 +55,5 @@ class UnsupportedRepoVersionError(Exception): | ||
| """ | ||
| Raised by `PyPISimple.download_package()` with ``verify=True`` when the | ||
| given package does not have any digests with known algorithms | ||
| Raised by `PyPISimple.download_package()` and | ||
| `PyPISimple.get_package_metadata()` with ``verify=True`` when the given | ||
| package or package metadata does not have any digests with known algorithms | ||
| """ | ||
@@ -65,4 +66,5 @@ | ||
| """ | ||
| Raised by `PyPISimple.download_package()` with ``verify=True`` when the | ||
| digest of the downloaded file does not match the expected value | ||
| Raised by `PyPISimple.download_package()` and | ||
| `PyPISimple.get_package_metadata()` with ``verify=True`` when the digest of | ||
| the downloaded data does not match the expected value | ||
| """ | ||
@@ -77,3 +79,3 @@ | ||
| self.expected_digest = expected_digest | ||
| #: The digest of the file that was actually received | ||
| #: The digest of the data that was actually received | ||
| self.actual_digest = actual_digest | ||
@@ -83,3 +85,3 @@ | ||
| return ( | ||
| f"{self.algorithm} digest of downloaded file is" | ||
| f"{self.algorithm} digest of downloaded data is" | ||
| f" {self.actual_digest!r} instead of expected {self.expected_digest!r}" | ||
@@ -86,0 +88,0 @@ ) |
+47
-11
| from __future__ import annotations | ||
| from dataclasses import dataclass | ||
| import re | ||
| from typing import Optional | ||
@@ -24,2 +25,32 @@ from urllib.parse import urljoin | ||
| #: .. versionadded:: 1.4.0 | ||
| #: | ||
| #: ``<meta/>`` tags found on the page whose ``name`` attributes start with | ||
| #: ``pypi:``. This is a dict in which the keys are ``name`` attributes | ||
| #: with leading ``"pypi:"`` removed and in which the values are the | ||
| #: corresponding ``content`` attributes. | ||
| pypi_meta: dict[str, list[str]] | ||
| @property | ||
| def tracks(self) -> list[str]: | ||
| """ | ||
| .. versionadded:: 1.4.0 | ||
| Repository "tracks" metadata. See `PEP 708`__. | ||
| __ https://peps.python.org/pep-0708/#repository-tracks-metadata | ||
| """ | ||
| return self.pypi_meta.get("tracks", []) | ||
| @property | ||
| def alternate_locations(self) -> list[str]: | ||
| """ | ||
| .. versionadded:: 1.4.0 | ||
| Repository "alternate locations" metadata. See `PEP 708`__. | ||
| __ https://peps.python.org/pep-0708/#alternate-locations-metadata | ||
| """ | ||
| return self.pypi_meta.get("alternate-locations", []) | ||
| @classmethod | ||
@@ -59,14 +90,19 @@ def from_html( | ||
| base_url = urljoin(base_url, href) | ||
| pep629_meta = soup.find( | ||
| "meta", | ||
| attrs={"name": "pypi:repository-version", "content": True}, | ||
| ) | ||
| if pep629_meta is not None: | ||
| assert isinstance(pep629_meta, Tag) | ||
| content = pep629_meta["content"] | ||
| meta: dict[str, list[str]] = {} | ||
| for tag in soup.find_all( | ||
| "meta", attrs={"name": re.compile(r"^pypi:"), "content": True} | ||
| ): | ||
| assert isinstance(tag, Tag) | ||
| name = tag["name"] | ||
| assert isinstance(name, str) | ||
| assert name.startswith("pypi:") | ||
| content = tag["content"] | ||
| assert isinstance(content, str) | ||
| repository_version = content | ||
| meta.setdefault(name[5:], []).append(content) | ||
| try: | ||
| repository_version = meta["repository-version"][0] | ||
| except LookupError: | ||
| repository_version = None | ||
| if repository_version is not None: | ||
| check_repo_version(repository_version) | ||
| else: | ||
| repository_version = None | ||
| links = [] | ||
@@ -81,3 +117,3 @@ for link in soup.find_all("a", href=True): | ||
| ) | ||
| return cls(repository_version=repository_version, links=links) | ||
| return cls(repository_version=repository_version, links=links, pypi_meta=meta) | ||
@@ -84,0 +120,0 @@ |
@@ -11,4 +11,4 @@ from __future__ import annotations | ||
| class Meta(BaseModel): | ||
| api_version: str = Field(alias="api-version") | ||
| class Meta(BaseModel, alias_generator=shishkebab): | ||
| api_version: str | ||
| last_serial: Optional[str] = Field(None, alias="_last-serial") | ||
@@ -25,2 +25,7 @@ | ||
| class ProjectMeta(Meta): | ||
| tracks: List[str] = Field(default_factory=list) | ||
| alternate_locations: List[str] = Field(default_factory=list) | ||
| class File(BaseModel, alias_generator=shishkebab): | ||
@@ -71,3 +76,3 @@ filename: str | ||
| files: List[File] | ||
| meta: Meta | ||
| meta: ProjectMeta | ||
| versions: Optional[List[str]] = None | ||
@@ -74,0 +79,0 @@ |
@@ -701,3 +701,3 @@ from __future__ import annotations | ||
| assert str(excinfo.value) == ( | ||
| "sha256 digest of downloaded file is" | ||
| "sha256 digest of downloaded data is" | ||
| " '17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43'" | ||
@@ -739,3 +739,3 @@ " instead of expected" | ||
| assert str(excinfo.value) == ( | ||
| "sha256 digest of downloaded file is" | ||
| "sha256 digest of downloaded data is" | ||
| " '17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43'" | ||
@@ -742,0 +742,0 @@ " instead of expected" |
@@ -449,2 +449,55 @@ from datetime import datetime, timezone | ||
| ( | ||
| "qypi", | ||
| "qypi-708.html", | ||
| PYPI_SIMPLE_ENDPOINT + "qypi/", | ||
| "utf-8", | ||
| ProjectPage( | ||
| project="qypi", | ||
| packages=[ | ||
| DistributionPackage( | ||
| filename="qypi-0.1.0-py3-none-any.whl", | ||
| project="qypi", | ||
| version="0.1.0", | ||
| package_type="wheel", | ||
| url="https://files.pythonhosted.org/packages/82/fc/9e25534641d7f63be93079bc07fa92bab136ddf5d4181059a1308a346f96/qypi-0.1.0-py3-none-any.whl", | ||
| digests={ | ||
| "sha256": "da69d28dcd527c0e372b3fa7b92fc333b327f8470175f035abc4e351b539189f" | ||
| }, | ||
| requires_python="~=3.4", | ||
| has_sig=None, | ||
| is_yanked=False, | ||
| yanked_reason=None, | ||
| metadata_digests=None, | ||
| has_metadata=False, | ||
| ), | ||
| DistributionPackage( | ||
| filename="qypi-0.1.0.tar.gz", | ||
| project="qypi", | ||
| version="0.1.0", | ||
| package_type="sdist", | ||
| url="https://files.pythonhosted.org/packages/e4/fe/3fdb222a2916b94e9ca12d80c92dbbad1f7068c82fca42872d6c1739fead/qypi-0.1.0.tar.gz", | ||
| digests={ | ||
| "sha256": "212093de95b4f5f22e19fa18fe57fa33eccd63adb9b325fe1b673bf71912c551" | ||
| }, | ||
| requires_python="~=3.4", | ||
| has_sig=None, | ||
| is_yanked=False, | ||
| yanked_reason=None, | ||
| metadata_digests=None, | ||
| has_metadata=False, | ||
| ), | ||
| ], | ||
| repository_version="1.2", | ||
| last_serial=None, | ||
| tracks=[ | ||
| "https://tracks.package/pypi/qypi/", | ||
| "https://test.tracks.package/pypi/qypi/", | ||
| ], | ||
| alternate_locations=[ | ||
| "https://alt.package/pypi/qypi/", | ||
| "https://test.alt.package/pypi/qypi/", | ||
| ], | ||
| ), | ||
| ), | ||
| ( | ||
| "devpi", | ||
@@ -687,2 +740,61 @@ "devpi_devpi.html", | ||
| ( | ||
| "argset-708.json", | ||
| ProjectPage( | ||
| project="argset", | ||
| packages=[ | ||
| DistributionPackage( | ||
| filename="argset-0.1.0-py3-none-any.whl", | ||
| project="argset", | ||
| version="0.1.0", | ||
| package_type="wheel", | ||
| url="https://files.pythonhosted.org/packages/b5/2b/7aa284f345e37f955d86e4cd57b1039b573552b0fc29d1a522ec05c1ee41/argset-0.1.0-py3-none-any.whl", | ||
| requires_python="~=3.6", | ||
| has_sig=None, | ||
| is_yanked=False, | ||
| yanked_reason=None, | ||
| metadata_digests=None, | ||
| has_metadata=None, | ||
| digests={ | ||
| "sha256": "107a632c7112faceb9fd6e93658dd461154713db250f7ffde5bd473e17cf1db5" | ||
| }, | ||
| size=5219, | ||
| upload_time=datetime( | ||
| 2021, 6, 5, 0, 15, 37, 534150, tzinfo=timezone.utc | ||
| ), | ||
| ), | ||
| DistributionPackage( | ||
| filename="argset-0.1.0.tar.gz", | ||
| project="argset", | ||
| version="0.1.0", | ||
| package_type="sdist", | ||
| url="https://files.pythonhosted.org/packages/d0/ee/1c25e68d029e8daaf3228dababbf3261fa5d9569f6f705867b2ad4df9b6d/argset-0.1.0.tar.gz", | ||
| requires_python="~=3.6", | ||
| has_sig=None, | ||
| is_yanked=False, | ||
| yanked_reason=None, | ||
| metadata_digests=None, | ||
| has_metadata=None, | ||
| digests={ | ||
| "sha256": "8a41ee4789d37517c259984c11f2aa3639a90dc8fa446ff905ecc5fe6623c12d" | ||
| }, | ||
| size=6565, | ||
| upload_time=datetime( | ||
| 2021, 6, 5, 0, 15, 39, 3726, tzinfo=timezone.utc | ||
| ), | ||
| ), | ||
| ], | ||
| repository_version="1.2", | ||
| last_serial="10562871", | ||
| versions=["0.1.0"], | ||
| tracks=[ | ||
| "https://tracks.package/pypi/argset/", | ||
| "https://test.tracks.package/pypi/argset", | ||
| ], | ||
| alternate_locations=[ | ||
| "https://alt.package/pypi/argset/", | ||
| "https://test.alt.package/pypi/argset", | ||
| ], | ||
| ), | ||
| ), | ||
| ( | ||
| "yanked.json", | ||
@@ -689,0 +801,0 @@ ProjectPage( |
@@ -33,2 +33,3 @@ from __future__ import annotations | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -62,2 +63,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -94,2 +96,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -118,2 +121,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -151,2 +155,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -186,2 +191,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -218,2 +224,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -250,2 +257,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -282,2 +290,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -310,2 +319,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -329,2 +339,3 @@ ), | ||
| links=[Link("link1", "one.html", {"href": "one.html"})], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -345,2 +356,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -375,2 +387,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -395,2 +408,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -415,2 +429,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -439,2 +454,3 @@ ), | ||
| ], | ||
| pypi_meta={"repository-version": ["1.0"]}, | ||
| ), | ||
@@ -463,2 +479,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -487,2 +504,3 @@ ), | ||
| ], | ||
| pypi_meta={}, | ||
| ), | ||
@@ -512,2 +530,3 @@ ), | ||
| ], | ||
| pypi_meta={"repository-version": ["1.0", "5.0"]}, | ||
| ), | ||
@@ -514,0 +533,0 @@ ), |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
281646
4.04%57
3.64%5607
4.01%