diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4768e55..7ace764 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog ========= +v0.9.1 +------ + +- Add --prefer-source option, to prefer source packages over binary ones + if no source distribution is available then binary distributions are used. + + v0.9.0 ------ diff --git a/docs/source/dependencies-design.rst b/docs/source/dependencies-design.rst index f1b9579..7acd7b9 100644 --- a/docs/source/dependencies-design.rst +++ b/docs/source/dependencies-design.rst @@ -223,6 +223,9 @@ repositories. PyPI "simple" API. Both the "simple" API and the PyPI JSON "warehouse-style" API are supported. +- ``--prefer-source``: when set, prefer source distribution instead + of binary distribution. In case there is no source distribution + available, the tool should provide binary distribution. Strategy and error processing: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/python_inspector/api.py b/src/python_inspector/api.py index 562cad0..35d7ebd 100644 --- a/src/python_inspector/api.py +++ b/src/python_inspector/api.py @@ -77,6 +77,7 @@ def resolve_dependencies( use_pypi_json_api=False, verbose=False, analyze_setup_py_insecurely=False, + prefer_source=False, printer=print, ): """ @@ -249,7 +250,9 @@ def resolve_dependencies( [ pkg.to_dict() for pkg in list( - get_pypi_data_from_purl(package, repos=repos, environment=environment) + get_pypi_data_from_purl( + package, repos=repos, environment=environment, prefer_source=prefer_source + ) ) ], ) diff --git a/src/python_inspector/package_data.py b/src/python_inspector/package_data.py index 6e71fe5..938d0df 100644 --- a/src/python_inspector/package_data.py +++ b/src/python_inspector/package_data.py @@ -25,7 +25,7 @@ def get_pypi_data_from_purl( - purl: str, environment: Environment, repos: List[PypiSimpleRepository] + purl: str, environment: Environment, repos: List[PypiSimpleRepository], prefer_source: bool ) -> PackageData: """ Generate `Package` object from the `purl` string of pypi type @@ -33,6 +33,8 @@ def get_pypi_data_from_purl( ``purl`` is a package-url of pypi type ``environment`` is a `Environment` object defaulting Python version 3.8 and linux OS ``repos`` is a list of `PypiSimpleRepository` objects + ``prefer_source`` is a boolean value to prefer source distribution over wheel, + if no source distribution is available then wheel is used """ purl = PackageURL.from_string(purl) name = purl.name @@ -53,16 +55,7 @@ def get_pypi_data_from_purl( bug_tracking_url = get_pypi_bugtracker_url(project_urls) python_version = get_python_version_from_env_tag(python_version=environment.python_version) valid_distribution_urls = [] - valid_distribution_urls.extend( - list( - get_wheel_download_urls( - purl=purl, - repos=repos, - environment=environment, - python_version=python_version, - ) - ) - ) + valid_distribution_urls.append( get_sdist_download_url( purl=purl, @@ -70,6 +63,21 @@ def get_pypi_data_from_purl( python_version=python_version, ) ) + + # if prefer_source is True then only source distribution is used + # in case of no source distribution available then wheel is used + if not valid_distribution_urls or not prefer_source: + valid_distribution_urls.extend( + list( + get_wheel_download_urls( + purl=purl, + repos=repos, + environment=environment, + python_version=python_version, + ) + ) + ) + urls = response.get("urls") or [] for url in urls: dist_url = url.get("url") diff --git a/src/python_inspector/resolve_cli.py b/src/python_inspector/resolve_cli.py index 350aa38..7c3c5f4 100644 --- a/src/python_inspector/resolve_cli.py +++ b/src/python_inspector/resolve_cli.py @@ -20,7 +20,7 @@ TRACE = False -__version__ = "0.9.0" +__version__ = "0.9.1" DEFAULT_PYTHON_VERSION = "38" PYPI_SIMPLE_URL = "https://pypi.org/simple" @@ -151,6 +151,12 @@ def print_version(ctx, param, value): help="Enable collection of requirements in setup.py that compute these" " dynamically. This is an insecure operation as it can run arbitrary code.", ) +@click.option( + "--prefer-source", + is_flag=True, + help="Prefer source distributions over binary distributions" + " if no source distribution is available then binary distributions are used", +) @click.option( "--verbose", is_flag=True, @@ -182,6 +188,7 @@ def resolve_dependencies( use_cached_index=False, use_pypi_json_api=False, analyze_setup_py_insecurely=False, + prefer_source=False, verbose=TRACE, ): """ @@ -194,7 +201,10 @@ def resolve_dependencies( linux OS. Download from the provided PyPI simple --index-url INDEX(s) URLs defaulting - to PyPI.org + to PyPI.org. + + Provide source distributions over binary distributions with the --prefer-source + option. If no source distribution is available then binary distributions are used. Error and progress are printed to stderr. @@ -250,6 +260,7 @@ def resolve_dependencies( verbose=verbose, analyze_setup_py_insecurely=analyze_setup_py_insecurely, printer=click.secho, + prefer_source=prefer_source, ) output = dict( headers=headers, diff --git a/src/python_inspector/utils_pypi.py b/src/python_inspector/utils_pypi.py index 959753a..be320df 100644 --- a/src/python_inspector/utils_pypi.py +++ b/src/python_inspector/utils_pypi.py @@ -336,7 +336,7 @@ def download_sdist( fetched_sdist_filename = None for repo in repos: - sdist = get_valid_sdist(repo, name, version, python_version=DEFAULT_PYTHON_VERSION) + sdist = get_valid_sdist(repo, name, version, python_version=python_version) if not sdist: if TRACE_DEEP: print(f" download_sdist: No valid sdist for {name}=={version}") diff --git a/tests/data/azure-devops.req-310-expected.json b/tests/data/azure-devops.req-310-expected.json index c95a66b..f94930a 100644 --- a/tests/data/azure-devops.req-310-expected.json +++ b/tests/data/azure-devops.req-310-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/azure-devops.req.txt", "--index-url https://pypi.org/simple", @@ -945,12 +945,12 @@ "type": "pypi", "namespace": null, "name": "cryptography", - "version": "38.0.2", + "version": "38.0.3", "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.6+ and PyPy3 7.2+.\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 '...'\n >>> f.decrypt(token)\n '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": "2022-10-11T18:57:26", + "release_date": "2022-11-01T21:48:36", "parties": [ { "type": "person", @@ -982,11 +982,11 @@ "Topic :: Security :: Cryptography" ], "homepage_url": "https://github.com/pyca/cryptography", - "download_url": "https://files.pythonhosted.org/packages/92/3d/6f9b9f562c2cc7ff4985bc18822308edbf546de1475563ad51410874c7e3/cryptography-38.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", - "size": 4151333, + "download_url": "https://files.pythonhosted.org/packages/bd/b4/2f8532124bda7470af31b6d9322b5bbb74e3bde94030f9b3a88450f12c8e/cryptography-38.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "size": 4151214, "sha1": null, - "md5": "78cc9f5b632f9a44b51566366ed5e37c", - "sha256": "9b99713109d76ad35736dcc4e47d54fbaa36cce761adc0333db75e86621fa68c", + "md5": "5f979c7f0729477e2fb830f8fe525799", + "sha256": "b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pyca/cryptography/", @@ -1007,20 +1007,20 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/cryptography/38.0.2/json", + "api_data_url": "https://pypi.org/pypi/cryptography/38.0.3/json", "datasource_id": null, - "purl": "pkg:pypi/cryptography@38.0.2" + "purl": "pkg:pypi/cryptography@38.0.3" }, { "type": "pypi", "namespace": null, "name": "cryptography", - "version": "38.0.2", + "version": "38.0.3", "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.6+ and PyPy3 7.2+.\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 '...'\n >>> f.decrypt(token)\n '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": "2022-10-11T18:59:25", + "release_date": "2022-11-01T21:53:57", "parties": [ { "type": "person", @@ -1052,11 +1052,11 @@ "Topic :: Security :: Cryptography" ], "homepage_url": "https://github.com/pyca/cryptography", - "download_url": "https://files.pythonhosted.org/packages/63/82/a6e21842f2e31b3874f01c112093b8bf8af119f5ed999bbd667a81de720b/cryptography-38.0.2.tar.gz", - "size": 599757, + "download_url": "https://files.pythonhosted.org/packages/13/dd/a9608b7aebe5d2dc0c98a4b2090a6b815628efa46cc1c046b89d8cd25f4c/cryptography-38.0.3.tar.gz", + "size": 599876, "sha1": null, - "md5": "5560580a72fe2d7a1731a84ee191dd1f", - "sha256": "7a022ec87c7a8bdad99f516a4ee6ffcb3a2bc31487577f9eccbc9b2edb1a8fd4", + "md5": "2148f1283f22df0677e204e46bccaf06", + "sha256": "bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pyca/cryptography/", @@ -1077,9 +1077,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/cryptography/38.0.2/json", + "api_data_url": "https://pypi.org/pypi/cryptography/38.0.3/json", "datasource_id": null, - "purl": "pkg:pypi/cryptography@38.0.2" + "purl": "pkg:pypi/cryptography@38.0.3" }, { "type": "pypi", @@ -2419,7 +2419,7 @@ "package": "pkg:pypi/azure-storage-blob@12.13.1", "dependencies": [ "pkg:pypi/azure-core@1.26.0", - "pkg:pypi/cryptography@38.0.2", + "pkg:pypi/cryptography@38.0.3", "pkg:pypi/msrest@0.6.21" ] }, @@ -2442,7 +2442,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/cryptography@38.0.2", + "package": "pkg:pypi/cryptography@38.0.3", "dependencies": [ "pkg:pypi/cffi@1.15.1" ] diff --git a/tests/data/azure-devops.req-38-expected.json b/tests/data/azure-devops.req-38-expected.json index 283db7e..9659808 100644 --- a/tests/data/azure-devops.req-38-expected.json +++ b/tests/data/azure-devops.req-38-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/azure-devops.req.txt", "--index-url https://pypi.org/simple", @@ -945,12 +945,12 @@ "type": "pypi", "namespace": null, "name": "cryptography", - "version": "38.0.2", + "version": "38.0.3", "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.6+ and PyPy3 7.2+.\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 '...'\n >>> f.decrypt(token)\n '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": "2022-10-11T18:57:26", + "release_date": "2022-11-01T21:48:36", "parties": [ { "type": "person", @@ -982,11 +982,11 @@ "Topic :: Security :: Cryptography" ], "homepage_url": "https://github.com/pyca/cryptography", - "download_url": "https://files.pythonhosted.org/packages/92/3d/6f9b9f562c2cc7ff4985bc18822308edbf546de1475563ad51410874c7e3/cryptography-38.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", - "size": 4151333, + "download_url": "https://files.pythonhosted.org/packages/bd/b4/2f8532124bda7470af31b6d9322b5bbb74e3bde94030f9b3a88450f12c8e/cryptography-38.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "size": 4151214, "sha1": null, - "md5": "78cc9f5b632f9a44b51566366ed5e37c", - "sha256": "9b99713109d76ad35736dcc4e47d54fbaa36cce761adc0333db75e86621fa68c", + "md5": "5f979c7f0729477e2fb830f8fe525799", + "sha256": "b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pyca/cryptography/", @@ -1007,20 +1007,20 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/cryptography/38.0.2/json", + "api_data_url": "https://pypi.org/pypi/cryptography/38.0.3/json", "datasource_id": null, - "purl": "pkg:pypi/cryptography@38.0.2" + "purl": "pkg:pypi/cryptography@38.0.3" }, { "type": "pypi", "namespace": null, "name": "cryptography", - "version": "38.0.2", + "version": "38.0.3", "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.6+ and PyPy3 7.2+.\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 '...'\n >>> f.decrypt(token)\n '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": "2022-10-11T18:59:25", + "release_date": "2022-11-01T21:53:57", "parties": [ { "type": "person", @@ -1052,11 +1052,11 @@ "Topic :: Security :: Cryptography" ], "homepage_url": "https://github.com/pyca/cryptography", - "download_url": "https://files.pythonhosted.org/packages/63/82/a6e21842f2e31b3874f01c112093b8bf8af119f5ed999bbd667a81de720b/cryptography-38.0.2.tar.gz", - "size": 599757, + "download_url": "https://files.pythonhosted.org/packages/13/dd/a9608b7aebe5d2dc0c98a4b2090a6b815628efa46cc1c046b89d8cd25f4c/cryptography-38.0.3.tar.gz", + "size": 599876, "sha1": null, - "md5": "5560580a72fe2d7a1731a84ee191dd1f", - "sha256": "7a022ec87c7a8bdad99f516a4ee6ffcb3a2bc31487577f9eccbc9b2edb1a8fd4", + "md5": "2148f1283f22df0677e204e46bccaf06", + "sha256": "bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd", "sha512": null, "bug_tracking_url": null, "code_view_url": "https://github.com/pyca/cryptography/", @@ -1077,9 +1077,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/cryptography/38.0.2/json", + "api_data_url": "https://pypi.org/pypi/cryptography/38.0.3/json", "datasource_id": null, - "purl": "pkg:pypi/cryptography@38.0.2" + "purl": "pkg:pypi/cryptography@38.0.3" }, { "type": "pypi", @@ -2419,7 +2419,7 @@ "package": "pkg:pypi/azure-storage-blob@12.13.1", "dependencies": [ "pkg:pypi/azure-core@1.26.0", - "pkg:pypi/cryptography@38.0.2", + "pkg:pypi/cryptography@38.0.3", "pkg:pypi/msrest@0.6.21" ] }, @@ -2442,7 +2442,7 @@ "dependencies": [] }, { - "package": "pkg:pypi/cryptography@38.0.2", + "package": "pkg:pypi/cryptography@38.0.3", "dependencies": [ "pkg:pypi/cffi@1.15.1" ] diff --git a/tests/data/default-url-expected.json b/tests/data/default-url-expected.json index 75daf91..ab1496e 100644 --- a/tests/data/default-url-expected.json +++ b/tests/data/default-url-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--specifier zipp==3.8.0", "--index-url https://pypi.org/simple", diff --git a/tests/data/environment-marker-test-requirements.txt-expected.json b/tests/data/environment-marker-test-requirements.txt-expected.json index 6199ee1..337c40b 100644 --- a/tests/data/environment-marker-test-requirements.txt-expected.json +++ b/tests/data/environment-marker-test-requirements.txt-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/environment-marker-test-requirements.txt", "--index-url https://pypi.org/simple", diff --git a/tests/data/frozen-requirements.txt-expected.json b/tests/data/frozen-requirements.txt-expected.json index c60fda6..95663b4 100644 --- a/tests/data/frozen-requirements.txt-expected.json +++ b/tests/data/frozen-requirements.txt-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/frozen-requirements.txt", "--index-url https://pypi.org/simple", diff --git a/tests/data/insecure-setup-2/setup.py-expected.json b/tests/data/insecure-setup-2/setup.py-expected.json index 84c5f4c..d9cfdf6 100644 --- a/tests/data/insecure-setup-2/setup.py-expected.json +++ b/tests/data/insecure-setup-2/setup.py-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--index-url https://pypi.org/simple", "--python-version 27", @@ -6809,12 +6809,12 @@ "type": "pypi", "namespace": null, "name": "pytz", - "version": "2022.5", + "version": "2022.6", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "World timezone definitions, modern and historical\npytz - World Timezone Definitions for Python\n============================================\n\n:Author: Stuart Bishop \n\nIntroduction\n~~~~~~~~~~~~\n\npytz brings the Olson tz database into Python. This library allows\naccurate and cross platform timezone calculations using Python 2.4\nor higher. It also solves the issue of ambiguous times at the end\nof daylight saving time, which you can read more about in the Python\nLibrary Reference (``datetime.tzinfo``).\n\nAlmost all of the Olson timezones are supported.\n\n.. note::\n\n This library differs from the documented Python API for\n tzinfo implementations; if you want to create local wallclock\n times you need to use the ``localize()`` method documented in this\n document. In addition, if you perform date arithmetic on local\n times that cross DST boundaries, the result may be in an incorrect\n timezone (ie. subtract 1 minute from 2002-10-27 1:00 EST and you get\n 2002-10-27 0:59 EST instead of the correct 2002-10-27 1:59 EDT). A\n ``normalize()`` method is provided to correct this. Unfortunately these\n issues cannot be resolved without modifying the Python datetime\n implementation (see PEP-431).\n\n\nInstallation\n~~~~~~~~~~~~\n\nThis package can either be installed using ``pip`` or from a tarball using the\nstandard Python distutils.\n\nIf you are installing using ``pip``, you don't need to download anything as the\nlatest version will be downloaded for you from PyPI::\n\n pip install pytz\n\nIf you are installing from a tarball, run the following command as an\nadministrative user::\n\n python setup.py install\n\n\npytz for Enterprise\n~~~~~~~~~~~~~~~~~~~\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytz and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. `Learn more. `_.\n\n\nExample & Usage\n~~~~~~~~~~~~~~~\n\nLocalized times and date arithmetic\n-----------------------------------\n\n>>> from datetime import datetime, timedelta\n>>> from pytz import timezone\n>>> import pytz\n>>> utc = pytz.utc\n>>> utc.zone\n'UTC'\n>>> eastern = timezone('US/Eastern')\n>>> eastern.zone\n'US/Eastern'\n>>> amsterdam = timezone('Europe/Amsterdam')\n>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'\n\nThis library only supports two ways of building a localized time. The\nfirst is to use the ``localize()`` method provided by the pytz library.\nThis is used to localize a naive datetime (datetime with no timezone\ninformation):\n\n>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))\n>>> print(loc_dt.strftime(fmt))\n2002-10-27 06:00:00 EST-0500\n\nThe second way of building a localized time is by converting an existing\nlocalized time using the standard ``astimezone()`` method:\n\n>>> ams_dt = loc_dt.astimezone(amsterdam)\n>>> ams_dt.strftime(fmt)\n'2002-10-27 12:00:00 CET+0100'\n\nUnfortunately using the tzinfo argument of the standard datetime\nconstructors ''does not work'' with pytz for many timezones.\n\n>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) # /!\\ Does not work this way!\n'2002-10-27 12:00:00 LMT+0018'\n\nIt is safe for timezones without daylight saving transitions though, such\nas UTC:\n\n>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) # /!\\ Not recommended except for UTC\n'2002-10-27 12:00:00 UTC+0000'\n\nThe preferred way of dealing with times is to always work in UTC,\nconverting to localtime only when generating output to be read\nby humans.\n\n>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)\n>>> loc_dt = utc_dt.astimezone(eastern)\n>>> loc_dt.strftime(fmt)\n'2002-10-27 01:00:00 EST-0500'\n\nThis library also allows you to do date arithmetic using local\ntimes, although it is more complicated than working in UTC as you\nneed to use the ``normalize()`` method to handle daylight saving time\nand other timezone transitions. In this example, ``loc_dt`` is set\nto the instant when daylight saving time ends in the US/Eastern\ntimezone.\n\n>>> before = loc_dt - timedelta(minutes=10)\n>>> before.strftime(fmt)\n'2002-10-27 00:50:00 EST-0500'\n>>> eastern.normalize(before).strftime(fmt)\n'2002-10-27 01:50:00 EDT-0400'\n>>> after = eastern.normalize(before + timedelta(minutes=20))\n>>> after.strftime(fmt)\n'2002-10-27 01:10:00 EST-0500'\n\nCreating local times is also tricky, and the reason why working with\nlocal times is not recommended. Unfortunately, you cannot just pass\na ``tzinfo`` argument when constructing a datetime (see the next\nsection for more details)\n\n>>> dt = datetime(2002, 10, 27, 1, 30, 0)\n>>> dt1 = eastern.localize(dt, is_dst=True)\n>>> dt1.strftime(fmt)\n'2002-10-27 01:30:00 EDT-0400'\n>>> dt2 = eastern.localize(dt, is_dst=False)\n>>> dt2.strftime(fmt)\n'2002-10-27 01:30:00 EST-0500'\n\nConverting between timezones is more easily done, using the\nstandard astimezone method.\n\n>>> utc_dt = utc.localize(datetime.utcfromtimestamp(1143408899))\n>>> utc_dt.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> au_tz = timezone('Australia/Sydney')\n>>> au_dt = utc_dt.astimezone(au_tz)\n>>> au_dt.strftime(fmt)\n'2006-03-27 08:34:59 AEDT+1100'\n>>> utc_dt2 = au_dt.astimezone(utc)\n>>> utc_dt2.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> utc_dt == utc_dt2\nTrue\n\nYou can take shortcuts when dealing with the UTC side of timezone\nconversions. ``normalize()`` and ``localize()`` are not really\nnecessary when there are no daylight saving time transitions to\ndeal with.\n\n>>> utc_dt = datetime.utcfromtimestamp(1143408899).replace(tzinfo=utc)\n>>> utc_dt.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> au_tz = timezone('Australia/Sydney')\n>>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz))\n>>> au_dt.strftime(fmt)\n'2006-03-27 08:34:59 AEDT+1100'\n>>> utc_dt2 = au_dt.astimezone(utc)\n>>> utc_dt2.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n\n\n``tzinfo`` API\n--------------\n\nThe ``tzinfo`` instances returned by the ``timezone()`` function have\nbeen extended to cope with ambiguous times by adding an ``is_dst``\nparameter to the ``utcoffset()``, ``dst()`` && ``tzname()`` methods.\n\n>>> tz = timezone('America/St_Johns')\n\n>>> normal = datetime(2009, 9, 1)\n>>> ambiguous = datetime(2009, 10, 31, 23, 30)\n\nThe ``is_dst`` parameter is ignored for most timestamps. It is only used\nduring DST transition ambiguous periods to resolve that ambiguity.\n\n>>> print(tz.utcoffset(normal, is_dst=True))\n-1 day, 21:30:00\n>>> print(tz.dst(normal, is_dst=True))\n1:00:00\n>>> tz.tzname(normal, is_dst=True)\n'NDT'\n\n>>> print(tz.utcoffset(ambiguous, is_dst=True))\n-1 day, 21:30:00\n>>> print(tz.dst(ambiguous, is_dst=True))\n1:00:00\n>>> tz.tzname(ambiguous, is_dst=True)\n'NDT'\n\n>>> print(tz.utcoffset(normal, is_dst=False))\n-1 day, 21:30:00\n>>> tz.dst(normal, is_dst=False).seconds\n3600\n>>> tz.tzname(normal, is_dst=False)\n'NDT'\n\n>>> print(tz.utcoffset(ambiguous, is_dst=False))\n-1 day, 20:30:00\n>>> tz.dst(ambiguous, is_dst=False)\ndatetime.timedelta(0)\n>>> tz.tzname(ambiguous, is_dst=False)\n'NST'\n\nIf ``is_dst`` is not specified, ambiguous timestamps will raise\nan ``pytz.exceptions.AmbiguousTimeError`` exception.\n\n>>> print(tz.utcoffset(normal))\n-1 day, 21:30:00\n>>> print(tz.dst(normal))\n1:00:00\n>>> tz.tzname(normal)\n'NDT'\n\n>>> import pytz.exceptions\n>>> try:\n... tz.utcoffset(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n>>> try:\n... tz.dst(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n>>> try:\n... tz.tzname(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n\n\nProblems with Localtime\n~~~~~~~~~~~~~~~~~~~~~~~\n\nThe major problem we have to deal with is that certain datetimes\nmay occur twice in a year. For example, in the US/Eastern timezone\non the last Sunday morning in October, the following sequence\nhappens:\n\n - 01:00 EDT occurs\n - 1 hour later, instead of 2:00am the clock is turned back 1 hour\n and 01:00 happens again (this time 01:00 EST)\n\nIn fact, every instant between 01:00 and 02:00 occurs twice. This means\nthat if you try and create a time in the 'US/Eastern' timezone\nthe standard datetime syntax, there is no way to specify if you meant\nbefore of after the end-of-daylight-saving-time transition. Using the\npytz custom syntax, the best you can do is make an educated guess:\n\n>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 1, 30, 00))\n>>> loc_dt.strftime(fmt)\n'2002-10-27 01:30:00 EST-0500'\n\nAs you can see, the system has chosen one for you and there is a 50%\nchance of it being out by one hour. For some applications, this does\nnot matter. However, if you are trying to schedule meetings with people\nin different timezones or analyze log files it is not acceptable.\n\nThe best and simplest solution is to stick with using UTC. The pytz\npackage encourages using UTC for internal timezone representation by\nincluding a special UTC implementation based on the standard Python\nreference implementation in the Python documentation.\n\nThe UTC timezone unpickles to be the same instance, and pickles to a\nsmaller size than other pytz tzinfo instances. The UTC implementation\ncan be obtained as pytz.utc, pytz.UTC, or pytz.timezone('UTC').\n\n>>> import pickle, pytz\n>>> dt = datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)\n>>> naive = dt.replace(tzinfo=None)\n>>> p = pickle.dumps(dt, 1)\n>>> naive_p = pickle.dumps(naive, 1)\n>>> len(p) - len(naive_p)\n17\n>>> new = pickle.loads(p)\n>>> new == dt\nTrue\n>>> new is dt\nFalse\n>>> new.tzinfo is dt.tzinfo\nTrue\n>>> pytz.utc is pytz.UTC is pytz.timezone('UTC')\nTrue\n\nNote that some other timezones are commonly thought of as the same (GMT,\nGreenwich, Universal, etc.). The definition of UTC is distinct from these\nother timezones, and they are not equivalent. For this reason, they will\nnot compare the same in Python.\n\n>>> utc == pytz.timezone('GMT')\nFalse\n\nSee the section `What is UTC`_, below.\n\nIf you insist on working with local times, this library provides a\nfacility for constructing them unambiguously:\n\n>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00)\n>>> est_dt = eastern.localize(loc_dt, is_dst=True)\n>>> edt_dt = eastern.localize(loc_dt, is_dst=False)\n>>> print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))\n2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500\n\nIf you pass None as the is_dst flag to localize(), pytz will refuse to\nguess and raise exceptions if you try to build ambiguous or non-existent\ntimes.\n\nFor example, 1:30am on 27th Oct 2002 happened twice in the US/Eastern\ntimezone when the clocks where put back at the end of Daylight Saving\nTime:\n\n>>> dt = datetime(2002, 10, 27, 1, 30, 00)\n>>> try:\n... eastern.localize(dt, is_dst=None)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % dt)\npytz.exceptions.AmbiguousTimeError: 2002-10-27 01:30:00\n\nSimilarly, 2:30am on 7th April 2002 never happened at all in the\nUS/Eastern timezone, as the clocks where put forward at 2:00am skipping\nthe entire hour:\n\n>>> dt = datetime(2002, 4, 7, 2, 30, 00)\n>>> try:\n... eastern.localize(dt, is_dst=None)\n... except pytz.exceptions.NonExistentTimeError:\n... print('pytz.exceptions.NonExistentTimeError: %s' % dt)\npytz.exceptions.NonExistentTimeError: 2002-04-07 02:30:00\n\nBoth of these exceptions share a common base class to make error handling\neasier:\n\n>>> isinstance(pytz.AmbiguousTimeError(), pytz.InvalidTimeError)\nTrue\n>>> isinstance(pytz.NonExistentTimeError(), pytz.InvalidTimeError)\nTrue\n\n\nA special case is where countries change their timezone definitions\nwith no daylight savings time switch. For example, in 1915 Warsaw\nswitched from Warsaw time to Central European time with no daylight savings\ntransition. So at the stroke of midnight on August 5th 1915 the clocks\nwere wound back 24 minutes creating an ambiguous time period that cannot\nbe specified without referring to the timezone abbreviation or the\nactual UTC offset. In this case midnight happened twice, neither time\nduring a daylight saving time period. pytz handles this transition by\ntreating the ambiguous period before the switch as daylight savings\ntime, and the ambiguous period after as standard time.\n\n\n>>> warsaw = pytz.timezone('Europe/Warsaw')\n>>> amb_dt1 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=True)\n>>> amb_dt1.strftime(fmt)\n'1915-08-04 23:59:59 WMT+0124'\n>>> amb_dt2 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=False)\n>>> amb_dt2.strftime(fmt)\n'1915-08-04 23:59:59 CET+0100'\n>>> switch_dt = warsaw.localize(datetime(1915, 8, 5, 00, 00, 00), is_dst=False)\n>>> switch_dt.strftime(fmt)\n'1915-08-05 00:00:00 CET+0100'\n>>> str(switch_dt - amb_dt1)\n'0:24:01'\n>>> str(switch_dt - amb_dt2)\n'0:00:01'\n\nThe best way of creating a time during an ambiguous time period is\nby converting from another timezone such as UTC:\n\n>>> utc_dt = datetime(1915, 8, 4, 22, 36, tzinfo=pytz.utc)\n>>> utc_dt.astimezone(warsaw).strftime(fmt)\n'1915-08-04 23:36:00 CET+0100'\n\nThe standard Python way of handling all these ambiguities is not to\nhandle them, such as demonstrated in this example using the US/Eastern\ntimezone definition from the Python documentation (Note that this\nimplementation only works for dates between 1987 and 2006 - it is\nincluded for tests only!):\n\n>>> from pytz.reference import Eastern # pytz.reference only for tests\n>>> dt = datetime(2002, 10, 27, 0, 30, tzinfo=Eastern)\n>>> str(dt)\n'2002-10-27 00:30:00-04:00'\n>>> str(dt + timedelta(hours=1))\n'2002-10-27 01:30:00-05:00'\n>>> str(dt + timedelta(hours=2))\n'2002-10-27 02:30:00-05:00'\n>>> str(dt + timedelta(hours=3))\n'2002-10-27 03:30:00-05:00'\n\nNotice the first two results? At first glance you might think they are\ncorrect, but taking the UTC offset into account you find that they are\nactually two hours appart instead of the 1 hour we asked for.\n\n>>> from pytz.reference import UTC # pytz.reference only for tests\n>>> str(dt.astimezone(UTC))\n'2002-10-27 04:30:00+00:00'\n>>> str((dt + timedelta(hours=1)).astimezone(UTC))\n'2002-10-27 06:30:00+00:00'\n\n\nCountry Information\n~~~~~~~~~~~~~~~~~~~\n\nA mechanism is provided to access the timezones commonly in use\nfor a particular country, looked up using the ISO 3166 country code.\nIt returns a list of strings that can be used to retrieve the relevant\ntzinfo instance using ``pytz.timezone()``:\n\n>>> print(' '.join(pytz.country_timezones['nz']))\nPacific/Auckland Pacific/Chatham\n\nThe Olson database comes with a ISO 3166 country code to English country\nname mapping that pytz exposes as a dictionary:\n\n>>> print(pytz.country_names['nz'])\nNew Zealand\n\n\nWhat is UTC\n~~~~~~~~~~~\n\n'UTC' is `Coordinated Universal Time`_. It is a successor to, but distinct\nfrom, Greenwich Mean Time (GMT) and the various definitions of Universal\nTime. UTC is now the worldwide standard for regulating clocks and time\nmeasurement.\n\nAll other timezones are defined relative to UTC, and include offsets like\nUTC+0800 - hours to add or subtract from UTC to derive the local time. No\ndaylight saving time occurs in UTC, making it a useful timezone to perform\ndate arithmetic without worrying about the confusion and ambiguities caused\nby daylight saving time transitions, your country changing its timezone, or\nmobile computers that roam through multiple timezones.\n\n.. _Coordinated Universal Time: https://en.wikipedia.org/wiki/Coordinated_Universal_Time\n\n\nHelpers\n~~~~~~~\n\nThere are two lists of timezones provided.\n\n``all_timezones`` is the exhaustive list of the timezone names that can\nbe used.\n\n>>> from pytz import all_timezones\n>>> len(all_timezones) >= 500\nTrue\n>>> 'Etc/Greenwich' in all_timezones\nTrue\n\n``common_timezones`` is a list of useful, current timezones. It doesn't\ncontain deprecated zones or historical zones, except for a few I've\ndeemed in common usage, such as US/Eastern (open a bug report if you\nthink other timezones are deserving of being included here). It is also\na sequence of strings.\n\n>>> from pytz import common_timezones\n>>> len(common_timezones) < len(all_timezones)\nTrue\n>>> 'Etc/Greenwich' in common_timezones\nFalse\n>>> 'Australia/Melbourne' in common_timezones\nTrue\n>>> 'US/Eastern' in common_timezones\nTrue\n>>> 'Canada/Eastern' in common_timezones\nTrue\n>>> 'Australia/Yancowinna' in all_timezones\nTrue\n>>> 'Australia/Yancowinna' in common_timezones\nFalse\n\nBoth ``common_timezones`` and ``all_timezones`` are alphabetically\nsorted:\n\n>>> common_timezones_dupe = common_timezones[:]\n>>> common_timezones_dupe.sort()\n>>> common_timezones == common_timezones_dupe\nTrue\n>>> all_timezones_dupe = all_timezones[:]\n>>> all_timezones_dupe.sort()\n>>> all_timezones == all_timezones_dupe\nTrue\n\n``all_timezones`` and ``common_timezones`` are also available as sets.\n\n>>> from pytz import all_timezones_set, common_timezones_set\n>>> 'US/Eastern' in all_timezones_set\nTrue\n>>> 'US/Eastern' in common_timezones_set\nTrue\n>>> 'Australia/Victoria' in common_timezones_set\nFalse\n\nYou can also retrieve lists of timezones used by particular countries\nusing the ``country_timezones()`` function. It requires an ISO-3166\ntwo letter country code.\n\n>>> from pytz import country_timezones\n>>> print(' '.join(country_timezones('ch')))\nEurope/Zurich\n>>> print(' '.join(country_timezones('CH')))\nEurope/Zurich\n\n\nInternationalization - i18n/l10n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nPytz is an interface to the IANA database, which uses ASCII names. The `Unicode Consortium's Unicode Locales (CLDR) `_\nproject provides translations. Thomas Khyn's\n`l18n `_ package can be used to access\nthese translations from Python.\n\n\nLicense\n~~~~~~~\n\nMIT license.\n\nThis code is also available as part of Zope 3 under the Zope Public\nLicense, Version 2.1 (ZPL).\n\nI'm happy to relicense this code if necessary for inclusion in other\nopen source projects.\n\n\nLatest Versions\n~~~~~~~~~~~~~~~\n\nThis package will be updated after releases of the Olson timezone\ndatabase. The latest version can be downloaded from the `Python Package\nIndex `_. The code that is used\nto generate this distribution is hosted on launchpad.net and available\nusing git::\n\n git clone https://git.launchpad.net/pytz\n\nA mirror on github is also available at https://github.com/stub42/pytz\n\nAnnouncements of new releases are made on\n`Launchpad `_, and the\n`Atom feed `_\nhosted there.\n\n\nBugs, Feature Requests & Patches\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBugs can be reported using `Launchpad Bugs `_.\n\n\nSecurity Issues\n~~~~~~~~~~~~~~~\n\nReports about security issues can be made via `Tidelift `_.\n\n\nIssues & Limitations\n~~~~~~~~~~~~~~~~~~~~\n\n- Offsets from UTC are rounded to the nearest whole minute, so timezones\n such as Europe/Amsterdam pre 1937 will be up to 30 seconds out. This\n is a limitation of the Python datetime library.\n\n- If you think a timezone definition is incorrect, I probably can't fix\n it. pytz is a direct translation of the Olson timezone database, and\n changes to the timezone definitions need to be made to this source.\n If you find errors they should be reported to the time zone mailing\n list, linked from http://www.iana.org/time-zones.\n\n\nFurther Reading\n~~~~~~~~~~~~~~~\n\nMore info than you want to know about timezones:\nhttps://data.iana.org/time-zones/tz-link.html\n\n\nContact\n~~~~~~~\n\nStuart Bishop ", - "release_date": "2022-10-18T11:30:43", + "release_date": "2022-10-31T23:58:42", "parties": [ { "type": "person", @@ -6850,6 +6850,7 @@ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", @@ -6861,11 +6862,11 @@ "Topic :: Software Development :: Libraries :: Python Modules" ], "homepage_url": "http://pythonhosted.org/pytz", - "download_url": "https://files.pythonhosted.org/packages/b5/d7/91fd8911d22e7fac794803095dd192bf1ebd70c7603272085230d915e738/pytz-2022.5-py2.py3-none-any.whl", - "size": 500659, + "download_url": "https://files.pythonhosted.org/packages/85/ac/92f998fc52a70afd7f6b788142632afb27cd60c8c782d1452b7466603332/pytz-2022.6-py2.py3-none-any.whl", + "size": 498053, "sha1": null, - "md5": "e1764805376e047e5978bb4dc6925515", - "sha256": "335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22", + "md5": "ee5792704836da32fa2a51aa10b6d1b9", + "sha256": "222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", "sha512": null, "bug_tracking_url": null, "code_view_url": null, @@ -6885,20 +6886,20 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/pytz/2022.5/json", + "api_data_url": "https://pypi.org/pypi/pytz/2022.6/json", "datasource_id": null, - "purl": "pkg:pypi/pytz@2022.5" + "purl": "pkg:pypi/pytz@2022.6" }, { "type": "pypi", "namespace": null, "name": "pytz", - "version": "2022.5", + "version": "2022.6", "qualifiers": {}, "subpath": null, "primary_language": "Python", "description": "World timezone definitions, modern and historical\npytz - World Timezone Definitions for Python\n============================================\n\n:Author: Stuart Bishop \n\nIntroduction\n~~~~~~~~~~~~\n\npytz brings the Olson tz database into Python. This library allows\naccurate and cross platform timezone calculations using Python 2.4\nor higher. It also solves the issue of ambiguous times at the end\nof daylight saving time, which you can read more about in the Python\nLibrary Reference (``datetime.tzinfo``).\n\nAlmost all of the Olson timezones are supported.\n\n.. note::\n\n This library differs from the documented Python API for\n tzinfo implementations; if you want to create local wallclock\n times you need to use the ``localize()`` method documented in this\n document. In addition, if you perform date arithmetic on local\n times that cross DST boundaries, the result may be in an incorrect\n timezone (ie. subtract 1 minute from 2002-10-27 1:00 EST and you get\n 2002-10-27 0:59 EST instead of the correct 2002-10-27 1:59 EDT). A\n ``normalize()`` method is provided to correct this. Unfortunately these\n issues cannot be resolved without modifying the Python datetime\n implementation (see PEP-431).\n\n\nInstallation\n~~~~~~~~~~~~\n\nThis package can either be installed using ``pip`` or from a tarball using the\nstandard Python distutils.\n\nIf you are installing using ``pip``, you don't need to download anything as the\nlatest version will be downloaded for you from PyPI::\n\n pip install pytz\n\nIf you are installing from a tarball, run the following command as an\nadministrative user::\n\n python setup.py install\n\n\npytz for Enterprise\n~~~~~~~~~~~~~~~~~~~\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytz and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. `Learn more. `_.\n\n\nExample & Usage\n~~~~~~~~~~~~~~~\n\nLocalized times and date arithmetic\n-----------------------------------\n\n>>> from datetime import datetime, timedelta\n>>> from pytz import timezone\n>>> import pytz\n>>> utc = pytz.utc\n>>> utc.zone\n'UTC'\n>>> eastern = timezone('US/Eastern')\n>>> eastern.zone\n'US/Eastern'\n>>> amsterdam = timezone('Europe/Amsterdam')\n>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'\n\nThis library only supports two ways of building a localized time. The\nfirst is to use the ``localize()`` method provided by the pytz library.\nThis is used to localize a naive datetime (datetime with no timezone\ninformation):\n\n>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))\n>>> print(loc_dt.strftime(fmt))\n2002-10-27 06:00:00 EST-0500\n\nThe second way of building a localized time is by converting an existing\nlocalized time using the standard ``astimezone()`` method:\n\n>>> ams_dt = loc_dt.astimezone(amsterdam)\n>>> ams_dt.strftime(fmt)\n'2002-10-27 12:00:00 CET+0100'\n\nUnfortunately using the tzinfo argument of the standard datetime\nconstructors ''does not work'' with pytz for many timezones.\n\n>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) # /!\\ Does not work this way!\n'2002-10-27 12:00:00 LMT+0018'\n\nIt is safe for timezones without daylight saving transitions though, such\nas UTC:\n\n>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) # /!\\ Not recommended except for UTC\n'2002-10-27 12:00:00 UTC+0000'\n\nThe preferred way of dealing with times is to always work in UTC,\nconverting to localtime only when generating output to be read\nby humans.\n\n>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)\n>>> loc_dt = utc_dt.astimezone(eastern)\n>>> loc_dt.strftime(fmt)\n'2002-10-27 01:00:00 EST-0500'\n\nThis library also allows you to do date arithmetic using local\ntimes, although it is more complicated than working in UTC as you\nneed to use the ``normalize()`` method to handle daylight saving time\nand other timezone transitions. In this example, ``loc_dt`` is set\nto the instant when daylight saving time ends in the US/Eastern\ntimezone.\n\n>>> before = loc_dt - timedelta(minutes=10)\n>>> before.strftime(fmt)\n'2002-10-27 00:50:00 EST-0500'\n>>> eastern.normalize(before).strftime(fmt)\n'2002-10-27 01:50:00 EDT-0400'\n>>> after = eastern.normalize(before + timedelta(minutes=20))\n>>> after.strftime(fmt)\n'2002-10-27 01:10:00 EST-0500'\n\nCreating local times is also tricky, and the reason why working with\nlocal times is not recommended. Unfortunately, you cannot just pass\na ``tzinfo`` argument when constructing a datetime (see the next\nsection for more details)\n\n>>> dt = datetime(2002, 10, 27, 1, 30, 0)\n>>> dt1 = eastern.localize(dt, is_dst=True)\n>>> dt1.strftime(fmt)\n'2002-10-27 01:30:00 EDT-0400'\n>>> dt2 = eastern.localize(dt, is_dst=False)\n>>> dt2.strftime(fmt)\n'2002-10-27 01:30:00 EST-0500'\n\nConverting between timezones is more easily done, using the\nstandard astimezone method.\n\n>>> utc_dt = utc.localize(datetime.utcfromtimestamp(1143408899))\n>>> utc_dt.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> au_tz = timezone('Australia/Sydney')\n>>> au_dt = utc_dt.astimezone(au_tz)\n>>> au_dt.strftime(fmt)\n'2006-03-27 08:34:59 AEDT+1100'\n>>> utc_dt2 = au_dt.astimezone(utc)\n>>> utc_dt2.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> utc_dt == utc_dt2\nTrue\n\nYou can take shortcuts when dealing with the UTC side of timezone\nconversions. ``normalize()`` and ``localize()`` are not really\nnecessary when there are no daylight saving time transitions to\ndeal with.\n\n>>> utc_dt = datetime.utcfromtimestamp(1143408899).replace(tzinfo=utc)\n>>> utc_dt.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n>>> au_tz = timezone('Australia/Sydney')\n>>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz))\n>>> au_dt.strftime(fmt)\n'2006-03-27 08:34:59 AEDT+1100'\n>>> utc_dt2 = au_dt.astimezone(utc)\n>>> utc_dt2.strftime(fmt)\n'2006-03-26 21:34:59 UTC+0000'\n\n\n``tzinfo`` API\n--------------\n\nThe ``tzinfo`` instances returned by the ``timezone()`` function have\nbeen extended to cope with ambiguous times by adding an ``is_dst``\nparameter to the ``utcoffset()``, ``dst()`` && ``tzname()`` methods.\n\n>>> tz = timezone('America/St_Johns')\n\n>>> normal = datetime(2009, 9, 1)\n>>> ambiguous = datetime(2009, 10, 31, 23, 30)\n\nThe ``is_dst`` parameter is ignored for most timestamps. It is only used\nduring DST transition ambiguous periods to resolve that ambiguity.\n\n>>> print(tz.utcoffset(normal, is_dst=True))\n-1 day, 21:30:00\n>>> print(tz.dst(normal, is_dst=True))\n1:00:00\n>>> tz.tzname(normal, is_dst=True)\n'NDT'\n\n>>> print(tz.utcoffset(ambiguous, is_dst=True))\n-1 day, 21:30:00\n>>> print(tz.dst(ambiguous, is_dst=True))\n1:00:00\n>>> tz.tzname(ambiguous, is_dst=True)\n'NDT'\n\n>>> print(tz.utcoffset(normal, is_dst=False))\n-1 day, 21:30:00\n>>> tz.dst(normal, is_dst=False).seconds\n3600\n>>> tz.tzname(normal, is_dst=False)\n'NDT'\n\n>>> print(tz.utcoffset(ambiguous, is_dst=False))\n-1 day, 20:30:00\n>>> tz.dst(ambiguous, is_dst=False)\ndatetime.timedelta(0)\n>>> tz.tzname(ambiguous, is_dst=False)\n'NST'\n\nIf ``is_dst`` is not specified, ambiguous timestamps will raise\nan ``pytz.exceptions.AmbiguousTimeError`` exception.\n\n>>> print(tz.utcoffset(normal))\n-1 day, 21:30:00\n>>> print(tz.dst(normal))\n1:00:00\n>>> tz.tzname(normal)\n'NDT'\n\n>>> import pytz.exceptions\n>>> try:\n... tz.utcoffset(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n>>> try:\n... tz.dst(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n>>> try:\n... tz.tzname(ambiguous)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)\npytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00\n\n\nProblems with Localtime\n~~~~~~~~~~~~~~~~~~~~~~~\n\nThe major problem we have to deal with is that certain datetimes\nmay occur twice in a year. For example, in the US/Eastern timezone\non the last Sunday morning in October, the following sequence\nhappens:\n\n - 01:00 EDT occurs\n - 1 hour later, instead of 2:00am the clock is turned back 1 hour\n and 01:00 happens again (this time 01:00 EST)\n\nIn fact, every instant between 01:00 and 02:00 occurs twice. This means\nthat if you try and create a time in the 'US/Eastern' timezone\nthe standard datetime syntax, there is no way to specify if you meant\nbefore of after the end-of-daylight-saving-time transition. Using the\npytz custom syntax, the best you can do is make an educated guess:\n\n>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 1, 30, 00))\n>>> loc_dt.strftime(fmt)\n'2002-10-27 01:30:00 EST-0500'\n\nAs you can see, the system has chosen one for you and there is a 50%\nchance of it being out by one hour. For some applications, this does\nnot matter. However, if you are trying to schedule meetings with people\nin different timezones or analyze log files it is not acceptable.\n\nThe best and simplest solution is to stick with using UTC. The pytz\npackage encourages using UTC for internal timezone representation by\nincluding a special UTC implementation based on the standard Python\nreference implementation in the Python documentation.\n\nThe UTC timezone unpickles to be the same instance, and pickles to a\nsmaller size than other pytz tzinfo instances. The UTC implementation\ncan be obtained as pytz.utc, pytz.UTC, or pytz.timezone('UTC').\n\n>>> import pickle, pytz\n>>> dt = datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)\n>>> naive = dt.replace(tzinfo=None)\n>>> p = pickle.dumps(dt, 1)\n>>> naive_p = pickle.dumps(naive, 1)\n>>> len(p) - len(naive_p)\n17\n>>> new = pickle.loads(p)\n>>> new == dt\nTrue\n>>> new is dt\nFalse\n>>> new.tzinfo is dt.tzinfo\nTrue\n>>> pytz.utc is pytz.UTC is pytz.timezone('UTC')\nTrue\n\nNote that some other timezones are commonly thought of as the same (GMT,\nGreenwich, Universal, etc.). The definition of UTC is distinct from these\nother timezones, and they are not equivalent. For this reason, they will\nnot compare the same in Python.\n\n>>> utc == pytz.timezone('GMT')\nFalse\n\nSee the section `What is UTC`_, below.\n\nIf you insist on working with local times, this library provides a\nfacility for constructing them unambiguously:\n\n>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00)\n>>> est_dt = eastern.localize(loc_dt, is_dst=True)\n>>> edt_dt = eastern.localize(loc_dt, is_dst=False)\n>>> print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))\n2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500\n\nIf you pass None as the is_dst flag to localize(), pytz will refuse to\nguess and raise exceptions if you try to build ambiguous or non-existent\ntimes.\n\nFor example, 1:30am on 27th Oct 2002 happened twice in the US/Eastern\ntimezone when the clocks where put back at the end of Daylight Saving\nTime:\n\n>>> dt = datetime(2002, 10, 27, 1, 30, 00)\n>>> try:\n... eastern.localize(dt, is_dst=None)\n... except pytz.exceptions.AmbiguousTimeError:\n... print('pytz.exceptions.AmbiguousTimeError: %s' % dt)\npytz.exceptions.AmbiguousTimeError: 2002-10-27 01:30:00\n\nSimilarly, 2:30am on 7th April 2002 never happened at all in the\nUS/Eastern timezone, as the clocks where put forward at 2:00am skipping\nthe entire hour:\n\n>>> dt = datetime(2002, 4, 7, 2, 30, 00)\n>>> try:\n... eastern.localize(dt, is_dst=None)\n... except pytz.exceptions.NonExistentTimeError:\n... print('pytz.exceptions.NonExistentTimeError: %s' % dt)\npytz.exceptions.NonExistentTimeError: 2002-04-07 02:30:00\n\nBoth of these exceptions share a common base class to make error handling\neasier:\n\n>>> isinstance(pytz.AmbiguousTimeError(), pytz.InvalidTimeError)\nTrue\n>>> isinstance(pytz.NonExistentTimeError(), pytz.InvalidTimeError)\nTrue\n\n\nA special case is where countries change their timezone definitions\nwith no daylight savings time switch. For example, in 1915 Warsaw\nswitched from Warsaw time to Central European time with no daylight savings\ntransition. So at the stroke of midnight on August 5th 1915 the clocks\nwere wound back 24 minutes creating an ambiguous time period that cannot\nbe specified without referring to the timezone abbreviation or the\nactual UTC offset. In this case midnight happened twice, neither time\nduring a daylight saving time period. pytz handles this transition by\ntreating the ambiguous period before the switch as daylight savings\ntime, and the ambiguous period after as standard time.\n\n\n>>> warsaw = pytz.timezone('Europe/Warsaw')\n>>> amb_dt1 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=True)\n>>> amb_dt1.strftime(fmt)\n'1915-08-04 23:59:59 WMT+0124'\n>>> amb_dt2 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=False)\n>>> amb_dt2.strftime(fmt)\n'1915-08-04 23:59:59 CET+0100'\n>>> switch_dt = warsaw.localize(datetime(1915, 8, 5, 00, 00, 00), is_dst=False)\n>>> switch_dt.strftime(fmt)\n'1915-08-05 00:00:00 CET+0100'\n>>> str(switch_dt - amb_dt1)\n'0:24:01'\n>>> str(switch_dt - amb_dt2)\n'0:00:01'\n\nThe best way of creating a time during an ambiguous time period is\nby converting from another timezone such as UTC:\n\n>>> utc_dt = datetime(1915, 8, 4, 22, 36, tzinfo=pytz.utc)\n>>> utc_dt.astimezone(warsaw).strftime(fmt)\n'1915-08-04 23:36:00 CET+0100'\n\nThe standard Python way of handling all these ambiguities is not to\nhandle them, such as demonstrated in this example using the US/Eastern\ntimezone definition from the Python documentation (Note that this\nimplementation only works for dates between 1987 and 2006 - it is\nincluded for tests only!):\n\n>>> from pytz.reference import Eastern # pytz.reference only for tests\n>>> dt = datetime(2002, 10, 27, 0, 30, tzinfo=Eastern)\n>>> str(dt)\n'2002-10-27 00:30:00-04:00'\n>>> str(dt + timedelta(hours=1))\n'2002-10-27 01:30:00-05:00'\n>>> str(dt + timedelta(hours=2))\n'2002-10-27 02:30:00-05:00'\n>>> str(dt + timedelta(hours=3))\n'2002-10-27 03:30:00-05:00'\n\nNotice the first two results? At first glance you might think they are\ncorrect, but taking the UTC offset into account you find that they are\nactually two hours appart instead of the 1 hour we asked for.\n\n>>> from pytz.reference import UTC # pytz.reference only for tests\n>>> str(dt.astimezone(UTC))\n'2002-10-27 04:30:00+00:00'\n>>> str((dt + timedelta(hours=1)).astimezone(UTC))\n'2002-10-27 06:30:00+00:00'\n\n\nCountry Information\n~~~~~~~~~~~~~~~~~~~\n\nA mechanism is provided to access the timezones commonly in use\nfor a particular country, looked up using the ISO 3166 country code.\nIt returns a list of strings that can be used to retrieve the relevant\ntzinfo instance using ``pytz.timezone()``:\n\n>>> print(' '.join(pytz.country_timezones['nz']))\nPacific/Auckland Pacific/Chatham\n\nThe Olson database comes with a ISO 3166 country code to English country\nname mapping that pytz exposes as a dictionary:\n\n>>> print(pytz.country_names['nz'])\nNew Zealand\n\n\nWhat is UTC\n~~~~~~~~~~~\n\n'UTC' is `Coordinated Universal Time`_. It is a successor to, but distinct\nfrom, Greenwich Mean Time (GMT) and the various definitions of Universal\nTime. UTC is now the worldwide standard for regulating clocks and time\nmeasurement.\n\nAll other timezones are defined relative to UTC, and include offsets like\nUTC+0800 - hours to add or subtract from UTC to derive the local time. No\ndaylight saving time occurs in UTC, making it a useful timezone to perform\ndate arithmetic without worrying about the confusion and ambiguities caused\nby daylight saving time transitions, your country changing its timezone, or\nmobile computers that roam through multiple timezones.\n\n.. _Coordinated Universal Time: https://en.wikipedia.org/wiki/Coordinated_Universal_Time\n\n\nHelpers\n~~~~~~~\n\nThere are two lists of timezones provided.\n\n``all_timezones`` is the exhaustive list of the timezone names that can\nbe used.\n\n>>> from pytz import all_timezones\n>>> len(all_timezones) >= 500\nTrue\n>>> 'Etc/Greenwich' in all_timezones\nTrue\n\n``common_timezones`` is a list of useful, current timezones. It doesn't\ncontain deprecated zones or historical zones, except for a few I've\ndeemed in common usage, such as US/Eastern (open a bug report if you\nthink other timezones are deserving of being included here). It is also\na sequence of strings.\n\n>>> from pytz import common_timezones\n>>> len(common_timezones) < len(all_timezones)\nTrue\n>>> 'Etc/Greenwich' in common_timezones\nFalse\n>>> 'Australia/Melbourne' in common_timezones\nTrue\n>>> 'US/Eastern' in common_timezones\nTrue\n>>> 'Canada/Eastern' in common_timezones\nTrue\n>>> 'Australia/Yancowinna' in all_timezones\nTrue\n>>> 'Australia/Yancowinna' in common_timezones\nFalse\n\nBoth ``common_timezones`` and ``all_timezones`` are alphabetically\nsorted:\n\n>>> common_timezones_dupe = common_timezones[:]\n>>> common_timezones_dupe.sort()\n>>> common_timezones == common_timezones_dupe\nTrue\n>>> all_timezones_dupe = all_timezones[:]\n>>> all_timezones_dupe.sort()\n>>> all_timezones == all_timezones_dupe\nTrue\n\n``all_timezones`` and ``common_timezones`` are also available as sets.\n\n>>> from pytz import all_timezones_set, common_timezones_set\n>>> 'US/Eastern' in all_timezones_set\nTrue\n>>> 'US/Eastern' in common_timezones_set\nTrue\n>>> 'Australia/Victoria' in common_timezones_set\nFalse\n\nYou can also retrieve lists of timezones used by particular countries\nusing the ``country_timezones()`` function. It requires an ISO-3166\ntwo letter country code.\n\n>>> from pytz import country_timezones\n>>> print(' '.join(country_timezones('ch')))\nEurope/Zurich\n>>> print(' '.join(country_timezones('CH')))\nEurope/Zurich\n\n\nInternationalization - i18n/l10n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nPytz is an interface to the IANA database, which uses ASCII names. The `Unicode Consortium's Unicode Locales (CLDR) `_\nproject provides translations. Thomas Khyn's\n`l18n `_ package can be used to access\nthese translations from Python.\n\n\nLicense\n~~~~~~~\n\nMIT license.\n\nThis code is also available as part of Zope 3 under the Zope Public\nLicense, Version 2.1 (ZPL).\n\nI'm happy to relicense this code if necessary for inclusion in other\nopen source projects.\n\n\nLatest Versions\n~~~~~~~~~~~~~~~\n\nThis package will be updated after releases of the Olson timezone\ndatabase. The latest version can be downloaded from the `Python Package\nIndex `_. The code that is used\nto generate this distribution is hosted on launchpad.net and available\nusing git::\n\n git clone https://git.launchpad.net/pytz\n\nA mirror on github is also available at https://github.com/stub42/pytz\n\nAnnouncements of new releases are made on\n`Launchpad `_, and the\n`Atom feed `_\nhosted there.\n\n\nBugs, Feature Requests & Patches\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBugs can be reported using `Launchpad Bugs `_.\n\n\nSecurity Issues\n~~~~~~~~~~~~~~~\n\nReports about security issues can be made via `Tidelift `_.\n\n\nIssues & Limitations\n~~~~~~~~~~~~~~~~~~~~\n\n- Offsets from UTC are rounded to the nearest whole minute, so timezones\n such as Europe/Amsterdam pre 1937 will be up to 30 seconds out. This\n is a limitation of the Python datetime library.\n\n- If you think a timezone definition is incorrect, I probably can't fix\n it. pytz is a direct translation of the Olson timezone database, and\n changes to the timezone definitions need to be made to this source.\n If you find errors they should be reported to the time zone mailing\n list, linked from http://www.iana.org/time-zones.\n\n\nFurther Reading\n~~~~~~~~~~~~~~~\n\nMore info than you want to know about timezones:\nhttps://data.iana.org/time-zones/tz-link.html\n\n\nContact\n~~~~~~~\n\nStuart Bishop ", - "release_date": "2022-10-18T11:30:46", + "release_date": "2022-10-31T23:58:44", "parties": [ { "type": "person", @@ -6934,6 +6935,7 @@ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", @@ -6945,11 +6947,11 @@ "Topic :: Software Development :: Libraries :: Python Modules" ], "homepage_url": "http://pythonhosted.org/pytz", - "download_url": "https://files.pythonhosted.org/packages/fe/dd/182cc5ed8e64a0d6d6c34fd27391041d542270000825410d294bd6902207/pytz-2022.5.tar.gz", - "size": 316295, + "download_url": "https://files.pythonhosted.org/packages/76/63/1be349ff0a44e4795d9712cc0b2d806f5e063d4d34631b71b832fac715a8/pytz-2022.6.tar.gz", + "size": 313766, "sha1": null, - "md5": "91747f483e2906cddda91b0df0b01254", - "sha256": "c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914", + "md5": "bf46b54a7e9bcb65ea38f54646181979", + "sha256": "e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2", "sha512": null, "bug_tracking_url": null, "code_view_url": null, @@ -6969,9 +6971,9 @@ "dependencies": [], "repository_homepage_url": null, "repository_download_url": null, - "api_data_url": "https://pypi.org/pypi/pytz/2022.5/json", + "api_data_url": "https://pypi.org/pypi/pytz/2022.6/json", "datasource_id": null, - "purl": "pkg:pypi/pytz@2022.5" + "purl": "pkg:pypi/pytz@2022.6" }, { "type": "pypi", @@ -8460,7 +8462,7 @@ { "package": "pkg:pypi/babel@2.9.1", "dependencies": [ - "pkg:pypi/pytz@2022.5" + "pkg:pypi/pytz@2022.6" ] }, { @@ -8496,7 +8498,7 @@ "dependencies": [ "pkg:pypi/billiard@3.6.4.0", "pkg:pypi/kombu@4.6.11", - "pkg:pypi/pytz@2022.5", + "pkg:pypi/pytz@2022.6", "pkg:pypi/vine@1.3.0" ] }, @@ -8823,7 +8825,7 @@ ] }, { - "package": "pkg:pypi/pytz@2022.5", + "package": "pkg:pypi/pytz@2022.6", "dependencies": [] }, { diff --git a/tests/data/insecure-setup/setup.py-expected.json b/tests/data/insecure-setup/setup.py-expected.json index 7a5f338..150edae 100644 --- a/tests/data/insecure-setup/setup.py-expected.json +++ b/tests/data/insecure-setup/setup.py-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--index-url https://pypi.org/simple", "--python-version 27", diff --git a/tests/data/pdt-requirements.txt-expected.json b/tests/data/pdt-requirements.txt-expected.json index fa1237a..0d7516c 100644 --- a/tests/data/pdt-requirements.txt-expected.json +++ b/tests/data/pdt-requirements.txt-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/pdt-requirements.txt", "--index-url https://pypi.org/simple", diff --git a/tests/data/pinned-pdt-requirements.txt-expected.json b/tests/data/pinned-pdt-requirements.txt-expected.json index 89f3369..9b5f805 100644 --- a/tests/data/pinned-pdt-requirements.txt-expected.json +++ b/tests/data/pinned-pdt-requirements.txt-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/pinned-pdt-requirements.txt", "--index-url https://pypi.org/simple", diff --git a/tests/data/pinned-requirements.txt-expected.json b/tests/data/pinned-requirements.txt-expected.json index a45df58..186b6ea 100644 --- a/tests/data/pinned-requirements.txt-expected.json +++ b/tests/data/pinned-requirements.txt-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--requirement /home/tg1999/Desktop/python-inspector-1/tests/data/pinned-requirements.txt", "--index-url https://pypi.org/simple", diff --git a/tests/data/prefer-source-expected.json b/tests/data/prefer-source-expected.json new file mode 100644 index 0000000..4cbe11d --- /dev/null +++ b/tests/data/prefer-source-expected.json @@ -0,0 +1,79 @@ +{ + "headers": { + "tool_name": "python-inspector", + "tool_homepageurl": "https://github.com/nexB/python-inspector", + "tool_version": "0.9.1", + "options": [ + "--specifier zipp==3.8.0", + "--index-url https://pypi.org/simple", + "--python-version 38", + "--operating-system linux", + "--json " + ], + "notice": "Dependency tree generated with python-inspector.\npython-inspector is a free software tool from nexB Inc. and others.\nVisit https://github.com/nexB/python-inspector/ for support and download.", + "warnings": [], + "errors": [] + }, + "files": [], + "packages": [ + { + "type": "pypi", + "namespace": null, + "name": "zipp", + "version": "3.8.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Backport of pathlib-compatible object wrapper for zip files\n.. image:: https://img.shields.io/pypi/v/zipp.svg\n :target: `PyPI link`_\n\n.. image:: https://img.shields.io/pypi/pyversions/zipp.svg\n :target: `PyPI link`_\n\n.. _PyPI link: https://pypi.org/project/zipp\n\n.. image:: https://github.com/jaraco/zipp/workflows/tests/badge.svg\n :target: https://github.com/jaraco/zipp/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. .. image:: https://readthedocs.org/projects/skeleton/badge/?version=latest\n.. :target: https://skeleton.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2022-informational\n :target: https://blog.jaraco.com/skeleton\n\n\nA pathlib-compatible Zipfile object wrapper. Official backport of the standard library\n`Path object `_.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - zipp\n - stdlib\n * - 3.5\n - 3.11\n * - 3.3\n - 3.9\n * - 1.0\n - 3.8\n\n\nUsage\n=====\n\nUse ``zipp.Path`` in place of ``zipfile.Path`` on any Python.", + "release_date": "2022-04-03T15:07:28", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Jason R. Coombs", + "email": "jaraco@jaraco.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only" + ], + "homepage_url": "https://github.com/jaraco/zipp", + "download_url": "https://files.pythonhosted.org/packages/cc/3c/3e8c69cd493297003da83f26ccf1faea5dd7da7892a0a7c965ac3bcba7bf/zipp-3.8.0.tar.gz", + "size": 13344, + "sha1": null, + "md5": "8864ff5ed01cd28755cc87f1443dbc67", + "sha256": "56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "classifiers": [ + "License :: OSI Approved :: MIT License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/zipp/3.8.0/json", + "datasource_id": null, + "purl": "pkg:pypi/zipp@3.8.0" + } + ], + "resolved_dependencies_graph": [ + { + "package": "pkg:pypi/zipp@3.8.0", + "dependencies": [] + } + ] +} \ No newline at end of file diff --git a/tests/data/setup/no-direct-dependencies-setup.py-expected.json b/tests/data/setup/no-direct-dependencies-setup.py-expected.json index 6d28e2a..5a0500d 100644 --- a/tests/data/setup/no-direct-dependencies-setup.py-expected.json +++ b/tests/data/setup/no-direct-dependencies-setup.py-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--index-url https://pypi.org/simple", "--python-version 27", diff --git a/tests/data/setup/simple-setup.py-expected.json b/tests/data/setup/simple-setup.py-expected.json index 9c3ee9a..5619439 100644 --- a/tests/data/setup/simple-setup.py-expected.json +++ b/tests/data/setup/simple-setup.py-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--index-url https://pypi.org/simple", "--python-version 27", diff --git a/tests/data/setup/spdx-setup.py-expected.json b/tests/data/setup/spdx-setup.py-expected.json index 1dc4ecd..ce439aa 100644 --- a/tests/data/setup/spdx-setup.py-expected.json +++ b/tests/data/setup/spdx-setup.py-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--index-url https://pypi.org/simple", "--python-version 27", diff --git a/tests/data/single-url-except-simple-expected.json b/tests/data/single-url-except-simple-expected.json index dd4cae7..2c13dd2 100644 --- a/tests/data/single-url-except-simple-expected.json +++ b/tests/data/single-url-except-simple-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--specifier flask", "--index-url https://thirdparty.aboutcode.org/pypi/simple/", diff --git a/tests/data/single-url-expected.json b/tests/data/single-url-expected.json index f8de9cd..4a5fc85 100644 --- a/tests/data/single-url-expected.json +++ b/tests/data/single-url-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--specifier zipp==3.8.0", "--index-url https://pypi.org/simple", diff --git a/tests/data/test-api-with-prefer-source.json b/tests/data/test-api-with-prefer-source.json new file mode 100644 index 0000000..563efac --- /dev/null +++ b/tests/data/test-api-with-prefer-source.json @@ -0,0 +1,424 @@ +{ + "files": [], + "packages": [ + { + "type": "pypi", + "namespace": null, + "name": "click", + "version": "8.1.3", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Composable command line interface toolkit\n\\$ click\\_\n==========\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\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U click\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n import 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.\")\n def 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\n if __name__ == '__main__':\n hello()\n\n.. code-block:: text\n\n $ python hello.py --count=3\n Your name: Click\n Hello, Click!\n Hello, Click!\n Hello, Click!\n\n\nDonate\n------\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\nLinks\n-----\n\n- Documentation: https://click.palletsprojects.com/\n- Changes: https://click.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/click/\n- Source Code: https://github.com/pallets/click\n- Issue Tracker: https://github.com/pallets/click/issues\n- Website: https://palletsprojects.com/p/click\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-04-28T17:36:09", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python" + ], + "homepage_url": "https://palletsprojects.com/p/click/", + "download_url": "https://files.pythonhosted.org/packages/59/87/84326af34517fca8c58418d148f2403df25303e02736832403587318e9e8/click-8.1.3.tar.gz", + "size": 331147, + "sha1": null, + "md5": "a804b085de7a3ff96968e38e0f6f2e05", + "sha256": "7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/click/issues/", + "code_view_url": "https://github.com/pallets/click/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/click/8.1.3/json", + "datasource_id": null, + "purl": "pkg:pypi/click@8.1.3" + }, + { + "type": "pypi", + "namespace": null, + "name": "flask", + "version": "2.1.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "A simple framework for building complex web applications.\nFlask\n=====\n\nFlask is a lightweight `WSGI`_ web application framework. It is designed\nto make getting started quick and easy, with the ability to scale up to\ncomplex applications. It began as a simple wrapper around `Werkzeug`_\nand `Jinja`_ and has become one of the most popular Python web\napplication frameworks.\n\nFlask offers suggestions, but doesn't enforce any dependencies or\nproject layout. It is up to the developer to choose the tools and\nlibraries they want to use. There are many extensions provided by the\ncommunity that make adding new functionality easy.\n\n.. _WSGI: https://wsgi.readthedocs.io/\n.. _Werkzeug: https://werkzeug.palletsprojects.com/\n.. _Jinja: https://jinja.palletsprojects.com/\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U Flask\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n # save this as app.py\n from flask import Flask\n\n app = Flask(__name__)\n\n @app.route(\"/\")\n def hello():\n return \"Hello, World!\"\n\n.. code-block:: text\n\n $ flask run\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n\n\nContributing\n------------\n\nFor guidance on setting up a development environment and how to make a\ncontribution to Flask, see the `contributing guidelines`_.\n\n.. _contributing guidelines: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Flask and the libraries\nit uses. 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\nLinks\n-----\n\n- Documentation: https://flask.palletsprojects.com/\n- Changes: https://flask.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/Flask/\n- Source Code: https://github.com/pallets/flask/\n- Issue Tracker: https://github.com/pallets/flask/issues/\n- Website: https://palletsprojects.com/p/flask/\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-04-28T17:47:40", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Framework :: Flask", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Internet :: WWW/HTTP :: WSGI", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + "Topic :: Software Development :: Libraries :: Application Frameworks" + ], + "homepage_url": "https://palletsprojects.com/p/flask", + "download_url": "https://files.pythonhosted.org/packages/d3/3c/94f38d4db919a9326a706ad56f05a7e6f0c8f7b7d93e2997cca54d3bc14b/Flask-2.1.2.tar.gz", + "size": 631846, + "sha1": null, + "md5": "93f1832e5be704ef6ff2a4124579cd85", + "sha256": "315ded2ddf8a6281567edb27393010fe3406188bafbfe65a3339d5787d89e477", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/flask/issues/", + "code_view_url": "https://github.com/pallets/flask/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/flask/2.1.2/json", + "datasource_id": null, + "purl": "pkg:pypi/flask@2.1.2" + }, + { + "type": "pypi", + "namespace": null, + "name": "itsdangerous", + "version": "2.1.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Safely pass data to untrusted environments and back.\nItsDangerous\n============\n\n... so better sign this\n\nVarious helpers to pass data to untrusted environments and to get it\nback safe and sound. Data is cryptographically signed to ensure that a\ntoken has not been tampered with.\n\nIt's possible to customize how data is serialized. Data is compressed as\nneeded. A timestamp can be added and verified automatically while\nloading a token.\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n pip install -U itsdangerous\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\nHere's how you could generate a token for transmitting a user's id and\nname between web requests.\n\n.. code-block:: python\n\n from itsdangerous import URLSafeSerializer\n auth_s = URLSafeSerializer(\"secret key\", \"auth\")\n token = auth_s.dumps({\"id\": 5, \"name\": \"itsdangerous\"})\n\n print(token)\n # eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg\n\n data = auth_s.loads(token)\n print(data[\"name\"])\n # itsdangerous\n\n\nDonate\n------\n\nThe Pallets organization develops and supports ItsDangerous 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\nLinks\n-----\n\n- Documentation: https://itsdangerous.palletsprojects.com/\n- Changes: https://itsdangerous.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/ItsDangerous/\n- Source Code: https://github.com/pallets/itsdangerous/\n- Issue Tracker: https://github.com/pallets/itsdangerous/issues/\n- Website: https://palletsprojects.com/p/itsdangerous/\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-03-24T15:12:15", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python" + ], + "homepage_url": "https://palletsprojects.com/p/itsdangerous/", + "download_url": "https://files.pythonhosted.org/packages/7f/a1/d3fb83e7a61fa0c0d3d08ad0a94ddbeff3731c05212617dff3a94e097f08/itsdangerous-2.1.2.tar.gz", + "size": 56143, + "sha1": null, + "md5": "c1bc730ddf53b8374eaa823f24eb6438", + "sha256": "5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/itsdangerous/issues/", + "code_view_url": "https://github.com/pallets/itsdangerous/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/itsdangerous/2.1.2/json", + "datasource_id": null, + "purl": "pkg:pypi/itsdangerous@2.1.2" + }, + { + "type": "pypi", + "namespace": null, + "name": "jinja2", + "version": "3.1.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "A very fast and expressive template engine.\nJinja\n=====\n\nJinja is a fast, expressive, extensible templating engine. Special\nplaceholders in the template allow writing code similar to Python\nsyntax. Then the template is passed data to render the final document.\n\nIt includes:\n\n- Template inheritance and inclusion.\n- Define and import macros within templates.\n- HTML templates can use autoescaping to prevent XSS from untrusted\n user input.\n- A sandboxed environment can safely render untrusted templates.\n- AsyncIO support for generating templates and calling async\n functions.\n- I18N support with Babel.\n- Templates are compiled to optimized Python code just-in-time and\n cached, or can be compiled ahead-of-time.\n- Exceptions point to the correct line in templates to make debugging\n easier.\n- Extensible filters, tests, functions, and even syntax.\n\nJinja's philosophy is that while application logic belongs in Python if\npossible, it shouldn't make the template designer's job difficult by\nrestricting functionality too much.\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U Jinja2\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nIn A Nutshell\n-------------\n\n.. code-block:: jinja\n\n {% extends \"base.html\" %}\n {% block title %}Members{% endblock %}\n {% block content %}\n \n {% endblock %}\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Jinja 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\nLinks\n-----\n\n- Documentation: https://jinja.palletsprojects.com/\n- Changes: https://jinja.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/Jinja2/\n- Source Code: https://github.com/pallets/jinja/\n- Issue Tracker: https://github.com/pallets/jinja/issues/\n- Website: https://palletsprojects.com/p/jinja/\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-04-28T17:21:27", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Text Processing :: Markup :: HTML" + ], + "homepage_url": "https://palletsprojects.com/p/jinja/", + "download_url": "https://files.pythonhosted.org/packages/7a/ff/75c28576a1d900e87eb6335b063fab47a8ef3c8b4d88524c4bf78f670cce/Jinja2-3.1.2.tar.gz", + "size": 268239, + "sha1": null, + "md5": "d31148abd89c1df1cdb077a55db27d02", + "sha256": "31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/jinja/issues/", + "code_view_url": "https://github.com/pallets/jinja/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/jinja2/3.1.2/json", + "datasource_id": null, + "purl": "pkg:pypi/jinja2@3.1.2" + }, + { + "type": "pypi", + "namespace": null, + "name": "markupsafe", + "version": "2.1.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Safely add untrusted strings to HTML/XML markup.\nMarkupSafe\n==========\n\nMarkupSafe implements a text object that escapes characters so it is\nsafe to use in HTML and XML. Characters that have special meanings are\nreplaced so that they display as the actual characters. This mitigates\ninjection attacks, meaning untrusted user input can safely be displayed\non a page.\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n pip install -U MarkupSafe\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nExamples\n--------\n\n.. code-block:: pycon\n\n >>> from markupsafe import Markup, escape\n\n >>> # escape replaces special characters and wraps in Markup\n >>> escape(\"\")\n Markup('<script>alert(document.cookie);</script>')\n\n >>> # wrap in Markup to mark text \"safe\" and prevent escaping\n >>> Markup(\"Hello\")\n Markup('hello')\n\n >>> escape(Markup(\"Hello\"))\n Markup('hello')\n\n >>> # Markup is a str subclass\n >>> # methods and operators escape their arguments\n >>> template = Markup(\"Hello {name}\")\n >>> template.format(name='\"World\"')\n Markup('Hello "World"')\n\n\nDonate\n------\n\nThe Pallets organization develops and supports MarkupSafe 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\nLinks\n-----\n\n- Documentation: https://markupsafe.palletsprojects.com/\n- Changes: https://markupsafe.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/MarkupSafe/\n- Source Code: https://github.com/pallets/markupsafe/\n- Issue Tracker: https://github.com/pallets/markupsafe/issues/\n- Website: https://palletsprojects.com/p/markupsafe/\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-03-15T13:23:27", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Text Processing :: Markup :: HTML" + ], + "homepage_url": "https://palletsprojects.com/p/markupsafe/", + "download_url": "https://files.pythonhosted.org/packages/1d/97/2288fe498044284f39ab8950703e88abbac2abbdf65524d576157af70556/MarkupSafe-2.1.1.tar.gz", + "size": 18668, + "sha1": null, + "md5": "9809f9fdd98bc835b0c21aa8f79cbf30", + "sha256": "7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/markupsafe/issues/", + "code_view_url": "https://github.com/pallets/markupsafe/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/markupsafe/2.1.1/json", + "datasource_id": null, + "purl": "pkg:pypi/markupsafe@2.1.1" + }, + { + "type": "pypi", + "namespace": null, + "name": "werkzeug", + "version": "2.2.2", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "The comprehensive WSGI web application library.\nWerkzeug\n========\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\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n pip install -U Werkzeug\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n from werkzeug.wrappers import Request, Response\n\n @Request.application\n def application(request):\n return Response('Hello, World!')\n\n if __name__ == '__main__':\n from werkzeug.serving import run_simple\n run_simple('localhost', 4000, application)\n\n\nDonate\n------\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\nLinks\n-----\n\n- Documentation: https://werkzeug.palletsprojects.com/\n- Changes: https://werkzeug.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/Werkzeug/\n- Source Code: https://github.com/pallets/werkzeug/\n- Issue Tracker: https://github.com/pallets/werkzeug/issues/\n- Website: https://palletsprojects.com/p/werkzeug/\n- Twitter: https://twitter.com/PalletsTeam\n- Chat: https://discord.gg/pallets", + "release_date": "2022-08-08T21:44:15", + "parties": [ + { + "type": "person", + "role": "author", + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "url": null + }, + { + "type": "person", + "role": "maintainer", + "name": "Pallets", + "email": "contact@palletsprojects.com", + "url": null + } + ], + "keywords": [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Internet :: WWW/HTTP :: WSGI", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware", + "Topic :: Software Development :: Libraries :: Application Frameworks" + ], + "homepage_url": "https://palletsprojects.com/p/werkzeug/", + "download_url": "https://files.pythonhosted.org/packages/f8/c1/1c8e539f040acd80f844c69a5ef8e2fccdf8b442dabb969e497b55d544e1/Werkzeug-2.2.2.tar.gz", + "size": 844378, + "sha1": null, + "md5": "9d7e50c5bb3a9fc12823b5faf374b90e", + "sha256": "7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f", + "sha512": null, + "bug_tracking_url": "https://github.com/pallets/werkzeug/issues/", + "code_view_url": "https://github.com/pallets/werkzeug/", + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": { + "license": "BSD-3-Clause", + "classifiers": [ + "License :: OSI Approved :: BSD License" + ] + }, + "notice_text": null, + "source_packages": [], + "file_references": [], + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": "https://pypi.org/pypi/werkzeug/2.2.2/json", + "datasource_id": null, + "purl": "pkg:pypi/werkzeug@2.2.2" + } + ], + "resolution": [ + { + "package": "pkg:pypi/click@8.1.3", + "dependencies": [] + }, + { + "package": "pkg:pypi/flask@2.1.2", + "dependencies": [ + "pkg:pypi/click@8.1.3", + "pkg:pypi/itsdangerous@2.1.2", + "pkg:pypi/jinja2@3.1.2", + "pkg:pypi/werkzeug@2.2.2" + ] + }, + { + "package": "pkg:pypi/itsdangerous@2.1.2", + "dependencies": [] + }, + { + "package": "pkg:pypi/jinja2@3.1.2", + "dependencies": [ + "pkg:pypi/markupsafe@2.1.1" + ] + }, + { + "package": "pkg:pypi/markupsafe@2.1.1", + "dependencies": [] + }, + { + "package": "pkg:pypi/werkzeug@2.2.2", + "dependencies": [ + "pkg:pypi/markupsafe@2.1.1" + ] + } + ] +} \ No newline at end of file diff --git a/tests/data/tilde_req-expected.json b/tests/data/tilde_req-expected.json index 4b15d8d..31a2cd8 100644 --- a/tests/data/tilde_req-expected.json +++ b/tests/data/tilde_req-expected.json @@ -2,7 +2,7 @@ "headers": { "tool_name": "python-inspector", "tool_homepageurl": "https://github.com/nexB/python-inspector", - "tool_version": "0.9.0", + "tool_version": "0.9.1", "options": [ "--specifier zipp~=3.8.0", "--index-url https://pypi.org/simple", diff --git a/tests/test_api.py b/tests/test_api.py index 3571063..a602140 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -81,3 +81,24 @@ def test_api_with_requirement_file(): expected_file=expected_file, clean=True, ) + + +def test_api_with_prefer_source(): + result_file = test_env.get_temp_file("json") + expected_file = test_env.get_test_loc("test-api-with-prefer-source.json", must_exist=False) + with open(result_file, "w") as result: + result.write( + json.dumps( + resolver_api( + specifiers=["flask==2.1.2"], + python_version="3.10", + operating_system="linux", + prefer_source=True, + ).to_dict() + ) + ) + check_json_results( + result_file=result_file, + expected_file=expected_file, + clean=True, + ) diff --git a/tests/test_cli.py b/tests/test_cli.py index 6d8ff17..f5de4d2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -237,6 +237,19 @@ def test_cli_with_multiple_index_url_and_tilde_req_and_netrc_file_without_matchi ) +@pytest.mark.online +def test_cli_with_prefer_source(): + expected_file = test_env.get_test_loc("prefer-source-expected.json", must_exist=False) + specifier = "zipp==3.8.0" + extra_options = ["--prefer-source"] + check_specs_resolution( + specifier=specifier, + expected_file=expected_file, + extra_options=extra_options, + regen=REGEN_TEST_FIXTURES, + ) + + @pytest.mark.online def test_cli_with_pinned_requirements_file(): requirements_file = test_env.get_test_loc("pinned-requirements.txt") @@ -352,7 +365,7 @@ def test_passing_of_json_pdt_and_json_flags(): def test_version_option(): options = ["--version"] result = run_cli(options=options) - assert "0.9.0" in result.output + assert "0.9.1" in result.output def test_passing_of_netrc_file_that_does_not_exist(): diff --git a/tests/test_resolution.py b/tests/test_resolution.py index 24c10ce..331230f 100644 --- a/tests/test_resolution.py +++ b/tests/test_resolution.py @@ -146,7 +146,7 @@ def test_without_supported_wheels(): assert plist == [ "pkg:pypi/autobahn@22.3.2", "pkg:pypi/cffi@1.15.1", - "pkg:pypi/cryptography@38.0.2", + "pkg:pypi/cryptography@38.0.3", "pkg:pypi/hyperlink@21.0.0", "pkg:pypi/idna@3.4", "pkg:pypi/pycparser@2.21",