diff --git a/src/python_inspector/utils_pypi.py b/src/python_inspector/utils_pypi.py index 4c15092f..a8d7687b 100644 --- a/src/python_inspector/utils_pypi.py +++ b/src/python_inspector/utils_pypi.py @@ -34,6 +34,7 @@ import attr import packageurl import requests +import zipfile from bs4 import BeautifulSoup from commoncode import fileutils from commoncode.hash import multi_checksums @@ -1698,6 +1699,20 @@ async def get( cache_valid = os.path.exists(cached) and os.path.getsize(cached) > 0 + # Validate cached wheel/egg files. + if cache_valid and not as_text: + if path_or_url.endswith((".whl", ".egg", ".zip")): + try: + if not zipfile.is_zipfile(cached): + if TRACE_DEEP: + print(f" FILE CACHE INVALID (corrupted zip): {path_or_url}") + cache_valid = False + except (FileNotFoundError, OSError): + # File was deleted/modified by another task - treat as cache miss + if TRACE_DEEP: + print(f" FILE CACHE VANISHED during validation: {path_or_url}") + cache_valid = False + if force or not cache_valid: if not cache_valid and os.path.exists(cached): if TRACE_DEEP: @@ -1715,17 +1730,54 @@ async def get( ) wmode = "w" if as_text else "wb" - # acquire lock and wait until timeout to get a lock or die - with lockfile.FileLock(lock_file).locked(timeout=PYINSP_CACHE_LOCK_TIMEOUT): - async with aiofiles.open(cached, mode=wmode) as fo: - await fo.write(content) + # Use atomic file operations. + temp_file = f"{cached}.tmp.{os.getpid()}" + + try: + # acquire lock and wait until timeout to get a lock or die + with lockfile.FileLock(lock_file).locked(timeout=PYINSP_CACHE_LOCK_TIMEOUT): + async with aiofiles.open(temp_file, mode=wmode) as fo: + await fo.write(content) + + # Validate zip files before making them "live" + if not as_text and path_or_url.endswith((".whl", ".egg", ".zip")): + if not zipfile.is_zipfile(temp_file): + raise Exception( + f"Downloaded file is not a valid zip: {path_or_url}\n" + f"Size: {os.path.getsize(temp_file)} bytes" + ) + + # Atomic rename - readers will never see partial/corrupt file + os.rename(temp_file, cached) + + except Exception: + # Clean up temp file on any error + if os.path.exists(temp_file): + os.remove(temp_file) + raise + return content, cached else: if TRACE_DEEP: print(f" FILE CACHE HIT: {path_or_url}") - # also lock on read to avoid race conditions - with lockfile.FileLock(lock_file).locked(timeout=PYINSP_CACHE_LOCK_TIMEOUT): - return await get_local_file_content(path=cached, as_text=as_text), cached + + # File passed validation, lock and read + # Handle race condition where file might be deleted between validation and lock + try: + with lockfile.FileLock(lock_file).locked(timeout=PYINSP_CACHE_LOCK_TIMEOUT): + return await get_local_file_content(path=cached, as_text=as_text), cached + except FileNotFoundError: + # File was deleted by another task after validation - retry with force. + if TRACE_DEEP: + print(f" FILE VANISHED after validation, re-downloading: {path_or_url}") + return await self.get( + credentials=credentials, + path_or_url=path_or_url, + as_text=as_text, + force=True, + verbose=verbose, + echo_func=echo_func, + ) CACHE = Cache() diff --git a/tests/data/azure-devops.req-310-expected.json b/tests/data/azure-devops.req-310-expected.json index 6620920b..3a7309c3 100644 --- a/tests/data/azure-devops.req-310-expected.json +++ b/tests/data/azure-devops.req-310-expected.json @@ -315,12 +315,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -347,11 +347,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -371,9 +371,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -522,12 +522,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -545,11 +545,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -564,9 +564,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -1267,7 +1267,7 @@ ] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -1281,13 +1281,14 @@ "dependencies": [] }, { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/cryptography@46.0.3", "dependencies": [ - "pkg:pypi/cffi@2.0.0" + "pkg:pypi/cffi@2.0.0", + "pkg:pypi/typing-extensions@4.15.0" ] }, { @@ -1302,7 +1303,7 @@ "package": "pkg:pypi/msrest@0.7.1", "dependencies": [ "pkg:pypi/azure-core@1.36.0", - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/isodate@0.7.2", "pkg:pypi/requests-oauthlib@2.0.0", "pkg:pypi/requests@2.32.5" @@ -1326,7 +1327,7 @@ { "package": "pkg:pypi/requests@2.32.5", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/charset-normalizer@3.4.4", "pkg:pypi/idna@3.11", "pkg:pypi/urllib3@2.5.0" diff --git a/tests/data/azure-devops.req-312-expected.json b/tests/data/azure-devops.req-312-expected.json index 88123147..d3b93977 100644 --- a/tests/data/azure-devops.req-312-expected.json +++ b/tests/data/azure-devops.req-312-expected.json @@ -315,12 +315,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -347,11 +347,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -371,9 +371,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -522,12 +522,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -545,11 +545,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -564,9 +564,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -1267,7 +1267,7 @@ ] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -1281,13 +1281,14 @@ "dependencies": [] }, { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/cryptography@46.0.3", "dependencies": [ - "pkg:pypi/cffi@2.0.0" + "pkg:pypi/cffi@2.0.0", + "pkg:pypi/typing-extensions@4.15.0" ] }, { @@ -1302,7 +1303,7 @@ "package": "pkg:pypi/msrest@0.7.1", "dependencies": [ "pkg:pypi/azure-core@1.36.0", - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/isodate@0.7.2", "pkg:pypi/requests-oauthlib@2.0.0", "pkg:pypi/requests@2.32.5" @@ -1326,7 +1327,7 @@ { "package": "pkg:pypi/requests@2.32.5", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/charset-normalizer@3.4.4", "pkg:pypi/idna@3.11", "pkg:pypi/urllib3@2.5.0" diff --git a/tests/data/azure-devops.req-313-expected.json b/tests/data/azure-devops.req-313-expected.json index 28451359..74500644 100644 --- a/tests/data/azure-devops.req-313-expected.json +++ b/tests/data/azure-devops.req-313-expected.json @@ -315,12 +315,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -347,11 +347,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -371,9 +371,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -522,12 +522,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -545,11 +545,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -564,9 +564,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -1267,7 +1267,7 @@ ] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -1281,13 +1281,14 @@ "dependencies": [] }, { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/cryptography@46.0.3", "dependencies": [ - "pkg:pypi/cffi@2.0.0" + "pkg:pypi/cffi@2.0.0", + "pkg:pypi/typing-extensions@4.15.0" ] }, { @@ -1302,7 +1303,7 @@ "package": "pkg:pypi/msrest@0.7.1", "dependencies": [ "pkg:pypi/azure-core@1.36.0", - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/isodate@0.7.2", "pkg:pypi/requests-oauthlib@2.0.0", "pkg:pypi/requests@2.32.5" @@ -1326,7 +1327,7 @@ { "package": "pkg:pypi/requests@2.32.5", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/charset-normalizer@3.4.4", "pkg:pypi/idna@3.11", "pkg:pypi/urllib3@2.5.0" diff --git a/tests/data/azure-devops.req-314-expected.json b/tests/data/azure-devops.req-314-expected.json index 22b2e4bf..42b47977 100644 --- a/tests/data/azure-devops.req-314-expected.json +++ b/tests/data/azure-devops.req-314-expected.json @@ -315,12 +315,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -347,11 +347,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -371,9 +371,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -522,12 +522,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -545,11 +545,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -564,9 +564,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -1267,7 +1267,7 @@ ] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -1281,13 +1281,14 @@ "dependencies": [] }, { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/cryptography@46.0.3", "dependencies": [ - "pkg:pypi/cffi@2.0.0" + "pkg:pypi/cffi@2.0.0", + "pkg:pypi/typing-extensions@4.15.0" ] }, { @@ -1302,7 +1303,7 @@ "package": "pkg:pypi/msrest@0.7.1", "dependencies": [ "pkg:pypi/azure-core@1.36.0", - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/isodate@0.7.2", "pkg:pypi/requests-oauthlib@2.0.0", "pkg:pypi/requests@2.32.5" @@ -1326,7 +1327,7 @@ { "package": "pkg:pypi/requests@2.32.5", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/charset-normalizer@3.4.4", "pkg:pypi/idna@3.11", "pkg:pypi/urllib3@2.5.0" diff --git a/tests/data/azure-devops.req-38-expected.json b/tests/data/azure-devops.req-38-expected.json index ff7fb157..956f2cd5 100644 --- a/tests/data/azure-devops.req-38-expected.json +++ b/tests/data/azure-devops.req-38-expected.json @@ -317,12 +317,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -349,11 +349,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -373,9 +373,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -576,17 +576,17 @@ "type": "pypi", "namespace": null, "name": "cryptography", - "version": "45.0.7", + "version": "46.0.0", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.\npyca/cryptography\n=================\n\n.. image:: https://img.shields.io/pypi/v/cryptography.svg\n :target: https://pypi.org/project/cryptography/\n :alt: Latest Version\n\n.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest\n :target: https://cryptography.io\n :alt: Latest Docs\n\n.. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=main\n :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amain\n\n\n``cryptography`` is a package which provides cryptographic recipes and\nprimitives to Python developers. Our goal is for it to be your \"cryptographic\nstandard library\". It supports Python 3.7+ and PyPy3 7.3.11+.\n\n``cryptography`` includes both high level recipes and low level interfaces to\ncommon cryptographic algorithms such as symmetric ciphers, message digests, and\nkey derivation functions. For example, to encrypt something with\n``cryptography``'s high level symmetric encryption recipe:\n\n.. code-block:: pycon\n\n >>> from cryptography.fernet import Fernet\n >>> # Put this somewhere safe!\n >>> key = Fernet.generate_key()\n >>> f = Fernet(key)\n >>> token = f.encrypt(b\"A really secret message. Not for prying eyes.\")\n >>> token\n b'...'\n >>> f.decrypt(token)\n b'A really secret message. Not for prying eyes.'\n\nYou can find more information in the `documentation`_.\n\nYou can install ``cryptography`` with:\n\n.. code-block:: console\n\n $ pip install cryptography\n\nFor full details see `the installation documentation`_.\n\nDiscussion\n~~~~~~~~~~\n\nIf you run into bugs, you can file them in our `issue tracker`_.\n\nWe maintain a `cryptography-dev`_ mailing list for development discussion.\n\nYou can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get\ninvolved.\n\nSecurity\n~~~~~~~~\n\nNeed to report a security issue? Please consult our `security reporting`_\ndocumentation.\n\n\n.. _`documentation`: https://cryptography.io/\n.. _`the installation documentation`: https://cryptography.io/en/latest/installation/\n.. _`issue tracker`: https://github.com/pyca/cryptography/issues\n.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev\n.. _`security reporting`: https://cryptography.io/en/latest/security/", - "release_date": "2025-09-01T11:14:24", + "description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.\npyca/cryptography\n=================\n\n.. image:: https://img.shields.io/pypi/v/cryptography.svg\n :target: https://pypi.org/project/cryptography/\n :alt: Latest Version\n\n.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest\n :target: https://cryptography.io\n :alt: Latest Docs\n\n.. image:: https://github.com/pyca/cryptography/actions/workflows/ci.yml/badge.svg\n :target: https://github.com/pyca/cryptography/actions/workflows/ci.yml?query=branch%3Amain\n\n``cryptography`` is a package which provides cryptographic recipes and\nprimitives to Python developers. Our goal is for it to be your \"cryptographic\nstandard library\". It supports Python 3.8+ and PyPy3 7.3.11+.\n\n``cryptography`` includes both high level recipes and low level interfaces to\ncommon cryptographic algorithms such as symmetric ciphers, message digests, and\nkey derivation functions. For example, to encrypt something with\n``cryptography``'s high level symmetric encryption recipe:\n\n.. code-block:: pycon\n\n >>> from cryptography.fernet import Fernet\n >>> # Put this somewhere safe!\n >>> key = Fernet.generate_key()\n >>> f = Fernet(key)\n >>> token = f.encrypt(b\"A really secret message. Not for prying eyes.\")\n >>> token\n b'...'\n >>> f.decrypt(token)\n b'A really secret message. Not for prying eyes.'\n\nYou can find more information in the `documentation`_.\n\nYou can install ``cryptography`` with:\n\n.. code-block:: console\n\n $ pip install cryptography\n\nFor full details see `the installation documentation`_.\n\nDiscussion\n~~~~~~~~~~\n\nIf you run into bugs, you can file them in our `issue tracker`_.\n\nWe maintain a `cryptography-dev`_ mailing list for development discussion.\n\nYou can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get\ninvolved.\n\nSecurity\n~~~~~~~~\n\nNeed to report a security issue? Please consult our `security reporting`_\ndocumentation.\n\n\n.. _`documentation`: https://cryptography.io/\n.. _`the installation documentation`: https://cryptography.io/en/latest/installation/\n.. _`issue tracker`: https://github.com/pyca/cryptography/issues\n.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev\n.. _`security reporting`: https://cryptography.io/en/latest/security/", + "release_date": "2025-09-16T21:07:03", "parties": [ { "type": "person", "role": "author", - "name": "The cryptography developers ", + "name": null, "email": "The Python Cryptographic Authority and individual contributors ", "url": null } @@ -607,28 +607,27 @@ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: Free Threading :: 3 - Stable", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Security :: Cryptography" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/eb/ac/59b7790b4ccaed739fc44775ce4645c9b8ce54cbec53edf16c74fd80cb2b/cryptography-45.0.7-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", - "size": 4423075, + "download_url": "https://files.pythonhosted.org/packages/da/94/f1c1f30110c05fa5247bf460b17acfd52fa3f5c77e94ba19cff8957dc5e6/cryptography-46.0.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", + "size": 4562561, "sha1": null, - "md5": "d7c4a989694c8af7d27560ff4125516f", - "sha256": "3994c809c17fc570c2af12c9b840d7cea85a9fd3e5c0e0491f4fa3c029216d59", + "md5": "4fe77bef21236be92883b98ea2b89580", + "sha256": "c3cd09b1490c1509bf3892bde9cef729795fae4a2fee0621f19be3321beca7e4", "sha512": null, "bug_tracking_url": null, "code_view_url": null, "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "license": "Apache-2.0 OR BSD-3-Clause" - }, + "license_expression": "Apache-2.0 OR BSD-3-Clause", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -636,9 +635,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/cryptography/45.0.7/json", + "api_data_url": "https://pypi.org/pypi/cryptography/46.0.0/json", "datasource_id": null, - "purl": "pkg:pypi/cryptography@45.0.7" + "purl": "pkg:pypi/cryptography@46.0.0" }, { "type": "pypi", @@ -1328,13 +1327,13 @@ "package": "pkg:pypi/azure-storage-blob@12.26.0", "dependencies": [ "pkg:pypi/azure-core@1.33.0", - "pkg:pypi/cryptography@45.0.7", + "pkg:pypi/cryptography@46.0.0", "pkg:pypi/isodate@0.7.2", "pkg:pypi/typing-extensions@4.13.2" ] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -1352,9 +1351,10 @@ "dependencies": [] }, { - "package": "pkg:pypi/cryptography@45.0.7", + "package": "pkg:pypi/cryptography@46.0.0", "dependencies": [ - "pkg:pypi/cffi@1.17.1" + "pkg:pypi/cffi@1.17.1", + "pkg:pypi/typing-extensions@4.13.2" ] }, { @@ -1369,7 +1369,7 @@ "package": "pkg:pypi/msrest@0.7.1", "dependencies": [ "pkg:pypi/azure-core@1.33.0", - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/isodate@0.7.2", "pkg:pypi/requests-oauthlib@2.0.0", "pkg:pypi/requests@2.32.4" @@ -1393,7 +1393,7 @@ { "package": "pkg:pypi/requests@2.32.4", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/charset-normalizer@3.4.4", "pkg:pypi/idna@3.11", "pkg:pypi/urllib3@2.2.3" diff --git a/tests/data/example-requirements-ignore-errors-expected.json b/tests/data/example-requirements-ignore-errors-expected.json index 4ccb2901..5a1ffda5 100644 --- a/tests/data/example-requirements-ignore-errors-expected.json +++ b/tests/data/example-requirements-ignore-errors-expected.json @@ -106,12 +106,12 @@ "type": "pypi", "namespace": null, "name": "exceptiongroup", - "version": "1.3.0", + "version": "1.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Backport of PEP 654 (exception groups)\n.. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg\n :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml\n :alt: Build Status\n.. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main\n :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main\n :alt: Code Coverage\n\nThis is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from\nPython 3.11.\n\nIt contains the following:\n\n* The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup``\n classes\n* A utility function (``exceptiongroup.catch()``) for catching exceptions possibly\n nested in an exception group\n* Patches to the ``TracebackException`` class that properly formats exception groups\n (installed on import)\n* An exception hook that handles formatting of exception groups through\n ``TracebackException`` (installed on import)\n* Special versions of some of the functions from the ``traceback`` module, modified to\n correctly handle exception groups even when monkey patching is disabled, or blocked by\n another custom exception hook:\n\n * ``traceback.format_exception()``\n * ``traceback.format_exception_only()``\n * ``traceback.print_exception()``\n * ``traceback.print_exc()``\n* A backported version of ``contextlib.suppress()`` from Python 3.12.1 which also\n handles suppressing exceptions inside exception groups\n\nIf this package is imported on Python 3.11 or later, the built-in implementations of the\nexception group classes are used instead, ``TracebackException`` is not monkey patched\nand the exception hook won't be installed.\n\nSee the `standard library documentation`_ for more information on exception groups.\n\n.. _standard library documentation: https://docs.python.org/3/library/exceptions.html\n\nCatching exceptions\n===================\n\nDue to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python\nversions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are\npotentially nested inside an exception group. This function returns a context manager\nthat calls the given handler for any exceptions matching the sole argument.\n\nThe argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either\nan exception class or an iterable of exception classes. Each value must be a callable\nthat takes a single positional argument. The handler will be called at most once, with\nan exception group as an argument which will contain all the exceptions that are any\nof the given types, or their subclasses. The exception group may contain nested groups\ncontaining more matching exceptions.\n\nThus, the following Python 3.11+ code:\n\n.. code-block:: python\n\n try:\n ...\n except* (ValueError, KeyError) as excgroup:\n for exc in excgroup.exceptions:\n print('Caught exception:', type(exc))\n except* RuntimeError:\n print('Caught runtime error')\n\nwould be written with this backport like this:\n\n.. code-block:: python\n\n from exceptiongroup import BaseExceptionGroup, catch\n\n def value_key_err_handler(excgroup: BaseExceptionGroup) -> None:\n for exc in excgroup.exceptions:\n print('Caught exception:', type(exc))\n\n def runtime_err_handler(exc: BaseExceptionGroup) -> None:\n print('Caught runtime error')\n\n with catch({\n (ValueError, KeyError): value_key_err_handler,\n RuntimeError: runtime_err_handler\n }):\n ...\n\n**NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or\n``ExceptionGroup`` with ``catch()``.\n\nSuppressing exceptions\n======================\n\nThis library contains a backport of the ``contextlib.suppress()`` context manager from\nPython 3.12.1. It allows you to selectively ignore certain exceptions, even when they're\ninside exception groups:\n\n.. code-block:: python\n\n from exceptiongroup import suppress\n\n with suppress(RuntimeError):\n raise ExceptionGroup(\"\", [RuntimeError(\"boo\")])\n\nNotes on monkey patching\n========================\n\nTo make exception groups render properly when an unhandled exception group is being\nprinted out, this package does two things when it is imported on any Python version\nearlier than 3.11:\n\n#. The ``traceback.TracebackException`` class is monkey patched to store extra\n information about exception groups (in ``__init__()``) and properly format them (in\n ``format()``)\n#. An exception hook is installed at ``sys.excepthook``, provided that no other hook is\n already present. This hook causes the exception to be formatted using\n ``traceback.TracebackException`` rather than the built-in rendered.\n\nIf ``sys.exceptionhook`` is found to be set to something else than the default when\n``exceptiongroup`` is imported, no monkeypatching is done at all.\n\nTo prevent the exception hook and patches from being installed, set the environment\nvariable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``.\n\nFormatting exception groups\n---------------------------\n\nNormally, the monkey patching applied by this library on import will cause exception\ngroups to be printed properly in tracebacks. But in cases when the monkey patching is\nblocked by a third party exception hook, or monkey patching is explicitly disabled,\nyou can still manually format exceptions using the special versions of the ``traceback``\nfunctions, like ``format_exception()``, listed at the top of this page. They work just\nlike their counterparts in the ``traceback`` module, except that they use a separately\npatched subclass of ``TracebackException`` to perform the rendering.\n\nParticularly in cases where a library installs its own exception hook, it is recommended\nto use these special versions to do the actual formatting of exceptions/tracebacks.\n\n.. _PEP 654: https://www.python.org/dev/peps/pep-0654/", - "release_date": "2025-05-10T17:42:49", + "release_date": "2025-11-21T23:01:53", "parties": [ { "type": "person", @@ -129,11 +129,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", - "size": 16674, + "download_url": "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", + "size": 16740, "sha1": null, - "md5": "23ce45ace6329e74ea58448cb6fc4a5b", - "sha256": "4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", + "md5": "ae266455b7797174f2d91304ccaf1275", + "sha256": "a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", "sha512": null, "bug_tracking_url": "https://github.com/agronholm/exceptiongroup/issues", "code_view_url": null, @@ -152,9 +152,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/exceptiongroup/1.3.0/json", + "api_data_url": "https://pypi.org/pypi/exceptiongroup/1.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/exceptiongroup@1.3.0" + "purl": "pkg:pypi/exceptiongroup@1.3.1" }, { "type": "pypi", @@ -424,12 +424,12 @@ "type": "pypi", "namespace": null, "name": "pytest", - "version": "8.4.2", + "version": "9.0.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "pytest: simple powerful testing with Python\n.. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nDue to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial)\n test suites out of the box\n\n- Python 3.9+ or PyPy3\n\n- Rich plugin architecture, with over 1300+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE", - "release_date": "2025-09-04T14:34:20", + "description": "pytest: simple powerful testing with Python\n.. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nThanks to ``pytest``'s detailed assertion introspection, you can simply use plain ``assert`` statements. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial)\n test suites out of the box\n\n- Python 3.10+ or PyPy3\n\n- Rich plugin architecture, with over 1300+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE", + "release_date": "2025-11-12T13:05:07", "parties": [ { "type": "person", @@ -454,29 +454,23 @@ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: 3.9", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing", "Topic :: Utilities" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", - "size": 365750, + "download_url": "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", + "size": 373668, "sha1": null, - "md5": "f2cf4b89fbd6145531a1606f96a89503", - "sha256": "872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", + "md5": "8b3c5d7ec589309f841d6f0d6ec1fa46", + "sha256": "67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", "sha512": null, "bug_tracking_url": "https://github.com/pytest-dev/pytest/issues", "code_view_url": "https://github.com/pytest-dev/pytest", "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "license": "MIT", - "classifiers": [ - "License :: OSI Approved :: MIT License" - ] - }, + "license_expression": "MIT", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -484,9 +478,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/pytest/8.4.2/json", + "api_data_url": "https://pypi.org/pypi/pytest/9.0.1/json", "datasource_id": null, - "purl": "pkg:pypi/pytest@8.4.2" + "purl": "pkg:pypi/pytest@9.0.1" }, { "type": "pypi", @@ -615,7 +609,7 @@ ], "resolved_dependencies_graph": [ { - "package": "pkg:pypi/exceptiongroup@1.3.0", + "package": "pkg:pypi/exceptiongroup@1.3.1", "dependencies": [ "pkg:pypi/typing-extensions@4.15.0" ] @@ -641,9 +635,9 @@ "dependencies": [] }, { - "package": "pkg:pypi/pytest@8.4.2", + "package": "pkg:pypi/pytest@9.0.1", "dependencies": [ - "pkg:pypi/exceptiongroup@1.3.0", + "pkg:pypi/exceptiongroup@1.3.1", "pkg:pypi/iniconfig@2.3.0", "pkg:pypi/packaging@25.0", "pkg:pypi/pluggy@1.6.0", diff --git a/tests/data/hash-requirements.txt-expected.json b/tests/data/hash-requirements.txt-expected.json index a95f5aa5..244e95b6 100644 --- a/tests/data/hash-requirements.txt-expected.json +++ b/tests/data/hash-requirements.txt-expected.json @@ -169,12 +169,12 @@ "type": "pypi", "namespace": null, "name": "certifi", - "version": "2025.10.5", + "version": "2025.11.12", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Python package for providing Mozilla's CA Bundle.\nCertifi: Python SSL Certificates\n================================\n\nCertifi provides Mozilla's carefully curated collection of Root Certificates for\nvalidating the trustworthiness of SSL certificates while verifying the identity\nof TLS hosts. It has been extracted from the `Requests`_ project.\n\nInstallation\n------------\n\n``certifi`` is available on PyPI. Simply install it with ``pip``::\n\n $ pip install certifi\n\nUsage\n-----\n\nTo reference the installed certificate authority (CA) bundle, you can use the\nbuilt-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'\n\nOr from the command line::\n\n $ python -m certifi\n /usr/local/lib/python3.7/site-packages/certifi/cacert.pem\n\nEnjoy!\n\n.. _`Requests`: https://requests.readthedocs.io/en/master/\n\nAddition/Removal of Certificates\n--------------------------------\n\nCertifi does not support any addition/removal or other modification of the\nCA trust store content. This project is intended to provide a reliable and\nhighly portable root of trust to python deployments. Look to upstream projects\nfor methods to use alternate trust.", - "release_date": "2025-10-05T04:12:14", + "release_date": "2025-11-12T02:54:49", "parties": [ { "type": "person", @@ -201,11 +201,11 @@ "Programming Language :: Python :: 3.9" ], "homepage_url": "https://github.com/certifi/python-certifi", - "download_url": "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", - "size": 163286, + "download_url": "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", + "size": 159438, "sha1": null, - "md5": "7b56f7121949a196441739c539fd01be", - "sha256": "0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "md5": "7cf85392819e7d6f24c8589826df5d95", + "sha256": "97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/certifi/python-certifi", @@ -225,9 +225,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/certifi/2025.10.5/json", + "api_data_url": "https://pypi.org/pypi/certifi/2025.11.12/json", "datasource_id": null, - "purl": "pkg:pypi/certifi@2025.10.5" + "purl": "pkg:pypi/certifi@2025.11.12" }, { "type": "pypi", @@ -514,7 +514,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/certifi@2025.10.5", + "package": "pkg:pypi/certifi@2025.11.12", "dependencies": [] }, { @@ -528,7 +528,7 @@ { "package": "pkg:pypi/requests@2.25.1", "dependencies": [ - "pkg:pypi/certifi@2025.10.5", + "pkg:pypi/certifi@2025.11.12", "pkg:pypi/chardet@4.0.0", "pkg:pypi/idna@2.10", "pkg:pypi/urllib3@1.26.20" diff --git a/tests/data/resolved_deps/flask-310-expected.json b/tests/data/resolved_deps/flask-310-expected.json index 7397ebe6..7bdb3b8f 100644 --- a/tests/data/resolved_deps/flask-310-expected.json +++ b/tests/data/resolved_deps/flask-310-expected.json @@ -1,16 +1,16 @@ [ [ { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/flask@2.1.2", "dependencies": [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -28,18 +28,18 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ] } ], [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/flask@2.1.2", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", "pkg:pypi/markupsafe@3.0.3", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] ] \ No newline at end of file diff --git a/tests/data/resolved_deps/flask-310-win-expected.json b/tests/data/resolved_deps/flask-310-win-expected.json index ca427261..1dd8c7be 100644 --- a/tests/data/resolved_deps/flask-310-win-expected.json +++ b/tests/data/resolved_deps/flask-310-win-expected.json @@ -1,7 +1,7 @@ [ [ { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [ "pkg:pypi/colorama@0.4.6" ] @@ -13,10 +13,10 @@ { "package": "pkg:pypi/flask@2.1.2", "dependencies": [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -34,19 +34,19 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ] } ], [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/colorama@0.4.6", "pkg:pypi/flask@2.1.2", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", "pkg:pypi/markupsafe@3.0.3", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] ] \ No newline at end of file diff --git a/tests/data/resolved_deps/flask-39-expected.json b/tests/data/resolved_deps/flask-39-expected.json index 2b38e8d0..721b6452 100644 --- a/tests/data/resolved_deps/flask-39-expected.json +++ b/tests/data/resolved_deps/flask-39-expected.json @@ -11,7 +11,7 @@ "pkg:pypi/importlib-metadata@8.7.0", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -35,7 +35,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ] @@ -52,7 +52,7 @@ "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", "pkg:pypi/markupsafe@3.0.3", - "pkg:pypi/werkzeug@3.1.3", + "pkg:pypi/werkzeug@3.1.4", "pkg:pypi/zipp@3.23.0" ] ] \ No newline at end of file diff --git a/tests/data/test-api-expected.json b/tests/data/test-api-expected.json index 824147dd..78663c63 100644 --- a/tests/data/test-api-expected.json +++ b/tests/data/test-api-expected.json @@ -5,12 +5,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -28,11 +28,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -47,9 +47,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -286,12 +286,12 @@ "type": "pypi", "namespace": null, "name": "werkzeug", - "version": "3.1.3", + "version": "3.1.4", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "The comprehensive WSGI web application library.\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate", - "release_date": "2024-11-08T15:52:16", + "description": "The comprehensive WSGI web application library.\n
\"\"
\n\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", + "release_date": "2025-11-29T02:15:21", "parties": [ { "type": "person", @@ -315,22 +315,18 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", - "size": 224498, + "download_url": "https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", + "size": 224960, "sha1": null, - "md5": "ff3a2b0d0953eadee90c945d879c5aac", - "sha256": "54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", + "md5": "392e2a5069eee7ee66927848dc21051d", + "sha256": "2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", "sha512": null, - "bug_tracking_url": "https://github.com/pallets/werkzeug/issues/", + "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/werkzeug/", "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "classifiers": [ - "License :: OSI Approved :: BSD License" - ] - }, + "license_expression": "BSD-3-Clause", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -338,23 +334,23 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.3/json", + "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.4/json", "datasource_id": null, - "purl": "pkg:pypi/werkzeug@3.1.3" + "purl": "pkg:pypi/werkzeug@3.1.4" } ], "resolution": [ { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/flask@2.1.2", "dependencies": [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -372,7 +368,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ] diff --git a/tests/data/test-api-pdt-expected.json b/tests/data/test-api-pdt-expected.json index e64605da..1d1bb2e9 100644 --- a/tests/data/test-api-pdt-expected.json +++ b/tests/data/test-api-pdt-expected.json @@ -5,12 +5,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:22", + "release_date": "2025-11-15T20:45:41", "parties": [ { "type": "person", @@ -28,11 +28,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", - "size": 107295, + "download_url": "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", + "size": 108274, "sha1": null, - "md5": "dd99757a403a5728bb37a5cab4d46c83", - "sha256": "9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", + "md5": "f032502934a5979330da77e3f09d889c", + "sha256": "981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -47,9 +47,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -286,12 +286,12 @@ "type": "pypi", "namespace": null, "name": "werkzeug", - "version": "3.1.3", + "version": "3.1.4", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "The comprehensive WSGI web application library.\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate", - "release_date": "2024-11-08T15:52:16", + "description": "The comprehensive WSGI web application library.\n
\"\"
\n\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", + "release_date": "2025-11-29T02:15:21", "parties": [ { "type": "person", @@ -315,22 +315,18 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", - "size": 224498, + "download_url": "https://files.pythonhosted.org/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", + "size": 224960, "sha1": null, - "md5": "ff3a2b0d0953eadee90c945d879c5aac", - "sha256": "54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", + "md5": "392e2a5069eee7ee66927848dc21051d", + "sha256": "2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", "sha512": null, - "bug_tracking_url": "https://github.com/pallets/werkzeug/issues/", + "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/werkzeug/", "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "classifiers": [ - "License :: OSI Approved :: BSD License" - ] - }, + "license_expression": "BSD-3-Clause", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -338,9 +334,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.3/json", + "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.4/json", "datasource_id": null, - "purl": "pkg:pypi/werkzeug@3.1.3" + "purl": "pkg:pypi/werkzeug@3.1.4" } ], "resolution": [ @@ -352,7 +348,7 @@ { "key": "click", "package_name": "click", - "installed_version": "8.3.0", + "installed_version": "8.3.1", "dependencies": [] }, { @@ -377,7 +373,7 @@ { "key": "werkzeug", "package_name": "werkzeug", - "installed_version": "3.1.3", + "installed_version": "3.1.4", "dependencies": [ { "key": "markupsafe", diff --git a/tests/data/test-api-with-prefer-source.json b/tests/data/test-api-with-prefer-source.json index d77eb908..a1b7ead9 100644 --- a/tests/data/test-api-with-prefer-source.json +++ b/tests/data/test-api-with-prefer-source.json @@ -5,12 +5,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:23", + "release_date": "2025-11-15T20:45:42", "parties": [ { "type": "person", @@ -28,11 +28,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", - "size": 276943, + "download_url": "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", + "size": 295065, "sha1": null, - "md5": "fa228744ff03a339957e847fb7890823", - "sha256": "e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", + "md5": "5f89d725a424b101607ec40927f78773", + "sha256": "12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -47,9 +47,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -286,12 +286,12 @@ "type": "pypi", "namespace": null, "name": "werkzeug", - "version": "3.1.3", + "version": "3.1.4", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "The comprehensive WSGI web application library.\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate", - "release_date": "2024-11-08T15:52:18", + "description": "The comprehensive WSGI web application library.\n
\"\"
\n\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", + "release_date": "2025-11-29T02:15:22", "parties": [ { "type": "person", @@ -315,22 +315,18 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", - "size": 806925, + "download_url": "https://files.pythonhosted.org/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", + "size": 864687, "sha1": null, - "md5": "b6005d403d01d08b9fe2330a0cfea05a", - "sha256": "60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", + "md5": "601c4ad4d597c665da5642550d6740a9", + "sha256": "cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", "sha512": null, - "bug_tracking_url": "https://github.com/pallets/werkzeug/issues/", + "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/werkzeug/", "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "classifiers": [ - "License :: OSI Approved :: BSD License" - ] - }, + "license_expression": "BSD-3-Clause", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -338,23 +334,23 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.3/json", + "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.4/json", "datasource_id": null, - "purl": "pkg:pypi/werkzeug@3.1.3" + "purl": "pkg:pypi/werkzeug@3.1.4" } ], "resolution": [ { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/flask@2.1.2", "dependencies": [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -372,7 +368,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ] diff --git a/tests/data/test-api-with-python-311.json b/tests/data/test-api-with-python-311.json index d77eb908..a1b7ead9 100644 --- a/tests/data/test-api-with-python-311.json +++ b/tests/data/test-api-with-python-311.json @@ -5,12 +5,12 @@ "type": "pypi", "namespace": null, "name": "click", - "version": "8.3.0", + "version": "8.3.1", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "Composable command line interface toolkit\n
\"\"
\n\n# Click\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\n## A Simple Example\n\n```python\nimport click\n\n@click.command()\n@click.option(\"--count\", default=1, help=\"Number of greetings.\")\n@click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\ndef hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\nif __name__ == '__main__':\n hello()\n```\n\n```\n$ python hello.py --count=3\nYour name: Click\nHello, Click!\nHello, Click!\nHello, Click!\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, [please\ndonate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", - "release_date": "2025-09-18T17:32:23", + "release_date": "2025-11-15T20:45:42", "parties": [ { "type": "person", @@ -28,11 +28,11 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", - "size": 276943, + "download_url": "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", + "size": 295065, "sha1": null, - "md5": "fa228744ff03a339957e847fb7890823", - "sha256": "e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", + "md5": "5f89d725a424b101607ec40927f78773", + "sha256": "12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/click/", @@ -47,9 +47,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/click/8.3.0/json", + "api_data_url": "https://pypi.org/pypi/click/8.3.1/json", "datasource_id": null, - "purl": "pkg:pypi/click@8.3.0" + "purl": "pkg:pypi/click@8.3.1" }, { "type": "pypi", @@ -286,12 +286,12 @@ "type": "pypi", "namespace": null, "name": "werkzeug", - "version": "3.1.3", + "version": "3.1.4", "qualifiers": {}, "subpath": null, "primary_language": "Python", - "description": "The comprehensive WSGI web application library.\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate", - "release_date": "2024-11-08T15:52:18", + "description": "The comprehensive WSGI web application library.\n
\"\"
\n\n# Werkzeug\n\n*werkzeug* German noun: \"tool\". Etymology: *werk* (\"work\"), *zeug* (\"stuff\")\n\nWerkzeug is a comprehensive [WSGI][] web application library. It began as\na simple collection of various utilities for WSGI applications and has\nbecome one of the most advanced WSGI utility libraries.\n\nIt includes:\n\n- An interactive debugger that allows inspecting stack traces and\n source code in the browser with an interactive interpreter for any\n frame in the stack.\n- A full-featured request object with objects to interact with\n headers, query args, form data, files, and cookies.\n- A response object that can wrap other WSGI applications and handle\n streaming data.\n- A routing system for matching URLs to endpoints and generating URLs\n for endpoints, with an extensible system for capturing variables\n from URLs.\n- HTTP utilities to handle entity tags, cache control, dates, user\n agents, cookies, files, and more.\n- A threaded WSGI server for use while developing applications\n locally.\n- A test client for simulating HTTP requests during testing without\n requiring running a server.\n\nWerkzeug doesn't enforce any dependencies. It is up to the developer to\nchoose a template engine, database adapter, and even how to handle\nrequests. It can be used to build all sorts of end user applications\nsuch as blogs, wikis, or bulletin boards.\n\n[Flask][] wraps Werkzeug, using it to handle the details of WSGI while\nproviding more structure and patterns for defining powerful\napplications.\n\n[WSGI]: https://wsgi.readthedocs.io/en/latest/\n[Flask]: https://www.palletsprojects.com/p/flask/\n\n\n## A Simple Example\n\n```python\n# save this as app.py\nfrom werkzeug.wrappers import Request, Response\n\n@Request.application\ndef application(request: Request) -> Response:\n return Response(\"Hello, World!\")\n\nif __name__ == \"__main__\":\n from werkzeug.serving import run_simple\n run_simple(\"127.0.0.1\", 5000, application)\n```\n\n```\n$ python -m app\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n```\n\n\n## Donate\n\nThe Pallets organization develops and supports Werkzeug and other\npopular packages. In order to grow the community of contributors and\nusers, and allow the maintainers to devote more time to the projects,\n[please donate today][].\n\n[please donate today]: https://palletsprojects.com/donate\n\n## Contributing\n\nSee our [detailed contributing documentation][contrib] for many ways to\ncontribute, including reporting issues, requesting features, asking or answering\nquestions, and making PRs.\n\n[contrib]: https://palletsprojects.com/contributing/", + "release_date": "2025-11-29T02:15:22", "parties": [ { "type": "person", @@ -315,22 +315,18 @@ "Typing :: Typed" ], "homepage_url": null, - "download_url": "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", - "size": 806925, + "download_url": "https://files.pythonhosted.org/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", + "size": 864687, "sha1": null, - "md5": "b6005d403d01d08b9fe2330a0cfea05a", - "sha256": "60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", + "md5": "601c4ad4d597c665da5642550d6740a9", + "sha256": "cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", "sha512": null, - "bug_tracking_url": "https://github.com/pallets/werkzeug/issues/", + "bug_tracking_url": null, "code_view_url": "https://github.com/pallets/werkzeug/", "vcs_url": null, "copyright": null, - "license_expression": null, - "declared_license": { - "classifiers": [ - "License :: OSI Approved :: BSD License" - ] - }, + "license_expression": "BSD-3-Clause", + "declared_license": {}, "notice_text": null, "source_packages": [], "file_references": [], @@ -338,23 +334,23 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.3/json", + "api_data_url": "https://pypi.org/pypi/werkzeug/3.1.4/json", "datasource_id": null, - "purl": "pkg:pypi/werkzeug@3.1.3" + "purl": "pkg:pypi/werkzeug@3.1.4" } ], "resolution": [ { - "package": "pkg:pypi/click@8.3.0", + "package": "pkg:pypi/click@8.3.1", "dependencies": [] }, { "package": "pkg:pypi/flask@2.1.2", "dependencies": [ - "pkg:pypi/click@8.3.0", + "pkg:pypi/click@8.3.1", "pkg:pypi/itsdangerous@2.2.0", "pkg:pypi/jinja2@3.1.6", - "pkg:pypi/werkzeug@3.1.3" + "pkg:pypi/werkzeug@3.1.4" ] }, { @@ -372,7 +368,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/werkzeug@3.1.3", + "package": "pkg:pypi/werkzeug@3.1.4", "dependencies": [ "pkg:pypi/markupsafe@3.0.3" ]