From b46795488c85ba39712a07ad6514f69c3b150ef1 Mon Sep 17 00:00:00 2001 From: Ayan Sinha Mahapatra Date: Wed, 26 Jun 2024 21:27:15 +0530 Subject: [PATCH] Add support for pip-inspect.deplock files Add parser for pip-inspect.deplock files generated by deplock which has all the package metadata, i.e. the resolved versions and the dependency relationships. Reference: https://github.com/nexB/scancode.io/issues/1262 Signed-off-by: Ayan Sinha Mahapatra --- src/packagedcode/__init__.py | 3 + src/packagedcode/pypi.py | 99 +- tests/packagedcode/data/plugin/help.txt | 7 + .../pypi/deplock/univers/pip-inspect.deplock | 519 +++++ .../univers/pip-inspect.deplock-expected.json | 1672 +++++++++++++++++ tests/packagedcode/test_pypi.py | 14 + 6 files changed, 2313 insertions(+), 1 deletion(-) create mode 100644 tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock create mode 100644 tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock-expected.json diff --git a/src/packagedcode/__init__.py b/src/packagedcode/__init__.py index fc4028fc13d..aef9936ea69 100644 --- a/src/packagedcode/__init__.py +++ b/src/packagedcode/__init__.py @@ -207,6 +207,9 @@ windows.MicrosoftUpdateManifestHandler, win_pe.WindowsExecutableHandler, + + # These are handlers for deplock generated files + pypi.PipInspectDeplockHandler, ] if on_linux: diff --git a/src/packagedcode/pypi.py b/src/packagedcode/pypi.py index 445a0562969..32784a210fe 100644 --- a/src/packagedcode/pypi.py +++ b/src/packagedcode/pypi.py @@ -563,6 +563,102 @@ def parse(cls, location, package_only=False): yield models.PackageData.from_data(package_data, package_only) +class PipInspectDeplockHandler(models.DatafileHandler): + datasource_id = 'pypi_inspect_deplock' + path_patterns = ('*pip-inspect.deplock',) + default_package_type = 'pypi' + default_primary_language = 'Python' + description = 'Python poetry pyproject.toml' + # These are files generated by deplock, see https://github.com/nexB/dependency-inspector + documentation_url = 'https://pip.pypa.io/en/stable/cli/pip_inspect/' + + @classmethod + def get_resolved_package_from_metadata(cls, metadata, package_only=False): + + requires_dist = metadata.get('requires_dist') + dependencies_for_resolved = get_requires_dependencies( + requires=requires_dist, + ) + package_data = dict( + datasource_id=cls.datasource_id, + type=cls.default_package_type, + primary_language='Python', + name=metadata.get('name'), + version=metadata.get('version'), + extracted_license_statement=metadata.get('license'), + description=metadata.get('description'), + keywords=metadata.get('keywords'), + is_virtual=True, + dependencies=[ + dep.to_dict() + for dep in dependencies_for_resolved + ], + ) + return models.PackageData.from_data(package_data, package_only) + + @classmethod + def parse(cls, location, package_only=False): + + with open(location) as f: + content = f.read() + + data = json.loads(content) + installed_packages = data.get('installed') + if not installed_packages: + return + + main_package_metadata = {} + dependencies = [] + + for package_metadata in installed_packages: + package_metadata_dep = package_metadata.get('metadata') + + # `direct_url` is only present for root package + # `requested` is true for root package and direct dependencies only + if package_metadata.get('requested') and 'direct_url' in package_metadata: + main_package_metadata = package_metadata_dep + main_package_requires = main_package_metadata.get('requires_dist') + dependencies_for_main = get_requires_dependencies( + requires=main_package_requires, + ) + dependencies.extend([ + dep.to_dict() + for dep in dependencies_for_main + ]) + continue + + package_data_dep = cls.get_resolved_package_from_metadata( + metadata=package_metadata_dep, + package_only=package_only, + ) + dep_purl = package_data_dep.purl + + dependency = models.DependentPackage( + purl=dep_purl, + extracted_requirement=None, + scope=None, + is_runtime=True, + is_optional=False, + is_direct=False, + is_resolved=True, + resolved_package=package_data_dep.to_dict() + ) + dependencies.append(dependency.to_dict()) + + pip_version = data.get('pip_version') + inspect_version = data.get('version') + extra_data = { + "pip_version": pip_version, + "inspect_version": inspect_version, + } + + package_data_main = cls.get_resolved_package_from_metadata( + metadata=main_package_metadata, + package_only=package_only, + ) + package_data_main.dependencies = dependencies + package_data_main.extra_data = extra_data + yield package_data_main META_DIR_SUFFIXES = '.dist-info', '.egg-info', 'EGG-INFO', @@ -1494,7 +1590,7 @@ def get_dist_dependencies(dist): return get_requires_dependencies(requires=dist.requires) -def get_requires_dependencies(requires, default_scope='install'): +def get_requires_dependencies(requires, default_scope='install', is_direct=True): """ Return a list of DependentPackage found in a ``requires`` list of requirement strings or an empty list. @@ -1539,6 +1635,7 @@ def get_requires_dependencies(requires, default_scope='install'): is_runtime=True, is_optional=True if bool(extra) else False, is_resolved=is_resolved, + is_direct=is_direct, extracted_requirement=str(req), )) diff --git a/tests/packagedcode/data/plugin/help.txt b/tests/packagedcode/data/plugin/help.txt index 7b2caac9cc7..5712bb11dad 100755 --- a/tests/packagedcode/data/plugin/help.txt +++ b/tests/packagedcode/data/plugin/help.txt @@ -713,6 +713,13 @@ Package type: pypi description: PyPI extracted egg PKG-INFO path_patterns: '*/EGG-INFO/PKG-INFO' -------------------------------------------- +Package type: pypi + datasource_id: pypi_inspect_deplock + documentation URL: https://pip.pypa.io/en/stable/cli/pip_inspect/ + primary language: Python + description: Python poetry pyproject.toml + path_patterns: '*pip-inspect.deplock' +-------------------------------------------- Package type: pypi datasource_id: pypi_poetry_pyproject_toml documentation URL: https://packaging.python.org/en/latest/specifications/pyproject-toml/ diff --git a/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock b/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock new file mode 100644 index 00000000000..6eac7b58711 --- /dev/null +++ b/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock @@ -0,0 +1,519 @@ +{ + "version": "1", + "pip_version": "24.1", + "installed": [ + { + "metadata": { + "metadata_version": "2.1", + "name": "attrs", + "version": "21.2.0", + "platform": [ + "UNKNOWN" + ], + "summary": "Classes Without Boilerplate", + "description_content_type": "text/x-rst", + "keywords": [ + "class", + "attribute", + "boilerplate" + ], + "home_page": "https://www.attrs.org/", + "author": "Hynek Schlawack", + "author_email": "hs@ox.cx", + "maintainer": "Hynek Schlawack", + "maintainer_email": "hs@ox.cx", + "license": "MIT", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Natural Language :: English", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Software Development :: Libraries :: Python Modules" + ], + "requires_dist": [ + "coverage[toml] (>=5.0.2) ; extra == 'dev'", + "hypothesis ; extra == 'dev'", + "pympler ; extra == 'dev'", + "pytest (>=4.3.0) ; extra == 'dev'", + "six ; extra == 'dev'", + "mypy ; extra == 'dev'", + "pytest-mypy-plugins ; extra == 'dev'", + "zope.interface ; extra == 'dev'", + "furo ; extra == 'dev'", + "sphinx ; extra == 'dev'", + "sphinx-notfound-page ; extra == 'dev'", + "pre-commit ; extra == 'dev'", + "furo ; extra == 'docs'", + "sphinx ; extra == 'docs'", + "zope.interface ; extra == 'docs'", + "sphinx-notfound-page ; extra == 'docs'", + "coverage[toml] (>=5.0.2) ; extra == 'tests'", + "hypothesis ; extra == 'tests'", + "pympler ; extra == 'tests'", + "pytest (>=4.3.0) ; extra == 'tests'", + "six ; extra == 'tests'", + "mypy ; extra == 'tests'", + "pytest-mypy-plugins ; extra == 'tests'", + "zope.interface ; extra == 'tests'", + "coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope'", + "hypothesis ; extra == 'tests_no_zope'", + "pympler ; extra == 'tests_no_zope'", + "pytest (>=4.3.0) ; extra == 'tests_no_zope'", + "six ; extra == 'tests_no_zope'", + "mypy ; extra == 'tests_no_zope'", + "pytest-mypy-plugins ; extra == 'tests_no_zope'" + ], + "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", + "project_url": [ + "Documentation, https://www.attrs.org/", + "Changelog, https://www.attrs.org/en/stable/changelog.html", + "Bug Tracker, https://github.com/python-attrs/attrs/issues", + "Source Code, https://github.com/python-attrs/attrs", + "Funding, https://github.com/sponsors/hynek", + "Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi", + "Ko-fi, https://ko-fi.com/the_hynek" + ], + "provides_extra": [ + "dev", + "docs", + "tests", + "tests_no_zope" + ], + "description": "======================================\n``attrs``: Classes Without Boilerplate\n======================================\n\n\n``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder `_ methods).\n`Trusted by NASA `_ for Mars missions since 2020!\n\nIts main goal is to help you to write **concise** and **correct** software without slowing down your code.\n\n.. teaser-end\n\nFor that, it gives you a class decorator and a way to declaratively define the attributes on that class:\n\n.. -code-begin-\n\n.. code-block:: pycon\n\n >>> import attr\n\n >>> @attr.s\n ... class SomeClass(object):\n ... a_number = attr.ib(default=42)\n ... list_of_numbers = attr.ib(factory=list)\n ...\n ... def hard_math(self, another_number):\n ... return self.a_number + sum(self.list_of_numbers) * another_number\n\n\n >>> sc = SomeClass(1, [1, 2, 3])\n >>> sc\n SomeClass(a_number=1, list_of_numbers=[1, 2, 3])\n\n >>> sc.hard_math(3)\n 19\n >>> sc == SomeClass(1, [1, 2, 3])\n True\n >>> sc != SomeClass(2, [3, 2, 1])\n True\n\n >>> attr.asdict(sc)\n {'a_number': 1, 'list_of_numbers': [1, 2, 3]}\n\n >>> SomeClass()\n SomeClass(a_number=42, list_of_numbers=[])\n\n >>> C = attr.make_class(\"C\", [\"a\", \"b\"])\n >>> C(\"foo\", \"bar\")\n C(a='foo', b='bar')\n\n\nAfter *declaring* your attributes ``attrs`` gives you:\n\n- a concise and explicit overview of the class's attributes,\n- a nice human-readable ``__repr__``,\n- a complete set of comparison methods (equality and ordering),\n- an initializer,\n- and much more,\n\n*without* writing dull boilerplate code again and again and *without* runtime performance penalties.\n\nOn Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations `_.\n\nThis gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\\ s or `confusingly behaving `_ ``namedtuple``\\ s.\nWhich in turn encourages you to write *small classes* that do `one thing well `_.\nNever again violate the `single responsibility principle `_ just because implementing ``__init__`` et al is a painful drag.\n\n\n.. -getting-help-\n\nGetting Help\n============\n\nPlease use the ``python-attrs`` tag on `StackOverflow `_ to get help.\n\nAnswering questions of your fellow developers is also a great way to help the project!\n\n\n.. -project-information-\n\nProject Information\n===================\n\n``attrs`` is released under the `MIT `_ license,\nits documentation lives at `Read the Docs `_,\nthe code on `GitHub `_,\nand the latest release on `PyPI `_.\nIt’s rigorously tested on Python 2.7, 3.5+, and PyPy.\n\nWe collect information on **third-party extensions** in our `wiki `_.\nFeel free to browse and add your own!\n\nIf you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started!\n\n\n``attrs`` for Enterprise\n------------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.\n`Learn more. `_\n\n\nRelease Information\n===================\n\n21.2.0 (2021-05-07)\n-------------------\n\nBackward-incompatible Changes\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n- We had to revert the recursive feature for ``attr.evolve()`` because it broke some use-cases -- sorry!\n `#806 `_\n- Python 3.4 is now blocked using packaging metadata because ``attrs`` can't be imported on it anymore.\n To ensure that 3.4 users can keep installing ``attrs`` easily, we will `yank `_ 21.1.0 from PyPI.\n This has **no** consequences if you pin ``attrs`` to 21.1.0.\n `#807 `_\n\n`Full changelog `_.\n\nCredits\n=======\n\n``attrs`` is written and maintained by `Hynek Schlawack `_.\n\nThe development is kindly supported by `Variomedia AG `_.\n\nA full list of contributors can be found in `GitHub's overview `_.\n\nIt’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions.\nBoth were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay?\n\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/attrs-21.2.0.dist-info", + "installer": "pip", + "requested": false + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "packaging", + "version": "21.0", + "platform": [ + "UNKNOWN" + ], + "summary": "Core utilities for Python packages", + "description_content_type": "text/x-rst", + "home_page": "https://github.com/pypa/packaging", + "author": "Donald Stufft and individual contributors", + "author_email": "donald@stufft.io", + "license": "BSD-2-Clause or Apache-2.0", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy" + ], + "requires_dist": [ + "pyparsing (>=2.0.2)" + ], + "requires_python": ">=3.6", + "description": "packaging\n=========\n\n.. start-intro\n\nReusable core utilities for various Python Packaging\n`interoperability specifications `_.\n\nThis library provides utilities that implement the interoperability\nspecifications which have clearly one correct behaviour (eg: :pep:`440`)\nor benefit greatly from having a single shared implementation (eg: :pep:`425`).\n\n.. end-intro\n\nThe ``packaging`` project includes the following: version handling, specifiers,\nmarkers, requirements, tags, utilities.\n\nDocumentation\n-------------\n\nThe `documentation`_ provides information and the API for the following:\n\n- Version Handling\n- Specifiers\n- Markers\n- Requirements\n- Tags\n- Utilities\n\nInstallation\n------------\n\nUse ``pip`` to install these utilities::\n\n pip install packaging\n\nDiscussion\n----------\n\nIf you run into bugs, you can file them in our `issue tracker`_.\n\nYou can also join ``#pypa`` on Freenode to ask questions or get involved.\n\n\n.. _`documentation`: https://packaging.pypa.io/\n.. _`issue tracker`: https://github.com/pypa/packaging/issues\n\n\nCode of Conduct\n---------------\n\nEveryone interacting in the packaging project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n\nContributing\n------------\n\nThe ``CONTRIBUTING.rst`` file outlines how to contribute to this project as\nwell as how to report a potential security issue. The documentation for this\nproject also covers information about `project development`_ and `security`_.\n\n.. _`project development`: https://packaging.pypa.io/en/latest/development/\n.. _`security`: https://packaging.pypa.io/en/latest/security/\n\nProject History\n---------------\n\nPlease review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for\nrecent changes and project history.\n\n.. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/\n\nChangelog\n---------\n\n21.0 - 2021-07-03\n~~~~~~~~~~~~~~~~~\n\n* `packaging` is now only compatible with Python 3.6 and above.\n* Add support for zip files in ``parse_sdist_filename`` (`#429 `__)\n\n20.9 - 2021-01-29\n~~~~~~~~~~~~~~~~~\n\n* Run `isort `_ over the code base (`#377 `__)\n* Add support for the ``macosx_10_*_universal2`` platform tags (`#379 `__)\n* Introduce ``packaging.utils.parse_wheel_filename()`` and ``parse_sdist_filename()``\n (`#387 `__ and `#389 `__)\n\n20.8 - 2020-12-11\n~~~~~~~~~~~~~~~~~\n\n* Revert back to setuptools for compatibility purposes for some Linux distros (`#363 `__)\n* Do not insert an underscore in wheel tags when the interpreter version number\n is more than 2 digits (`#372 `__)\n\n20.7 - 2020-11-28\n~~~~~~~~~~~~~~~~~\n\nNo unreleased changes.\n\n20.6 - 2020-11-28\n~~~~~~~~~~~~~~~~~\n\n.. note:: This release was subsequently yanked, and these changes were included in 20.7.\n\n* Fix flit configuration, to include LICENSE files (`#357 `__)\n* Make `intel` a recognized CPU architecture for the `universal` macOS platform tag (`#361 `__)\n* Add some missing type hints to `packaging.requirements` (issue:`350`)\n\n20.5 - 2020-11-27\n~~~~~~~~~~~~~~~~~\n\n* Officially support Python 3.9 (`#343 `__)\n* Deprecate the ``LegacyVersion`` and ``LegacySpecifier`` classes (`#321 `__)\n* Handle ``OSError`` on non-dynamic executables when attempting to resolve\n the glibc version string.\n\n20.4 - 2020-05-19\n~~~~~~~~~~~~~~~~~\n\n* Canonicalize version before comparing specifiers. (`#282 `__)\n* Change type hint for ``canonicalize_name`` to return\n ``packaging.utils.NormalizedName``.\n This enables the use of static typing tools (like mypy) to detect mixing of\n normalized and un-normalized names.\n\n20.3 - 2020-03-05\n~~~~~~~~~~~~~~~~~\n\n* Fix changelog for 20.2.\n\n20.2 - 2020-03-05\n~~~~~~~~~~~~~~~~~\n\n* Fix a bug that caused a 32-bit OS that runs on a 64-bit ARM CPU (e.g. ARM-v8,\n aarch64), to report the wrong bitness.\n\n20.1 - 2020-01-24\n~~~~~~~~~~~~~~~~~~~\n\n* Fix a bug caused by reuse of an exhausted iterator. (`#257 `__)\n\n20.0 - 2020-01-06\n~~~~~~~~~~~~~~~~~\n\n* Add type hints (`#191 `__)\n\n* Add proper trove classifiers for PyPy support (`#198 `__)\n\n* Scale back depending on ``ctypes`` for manylinux support detection (`#171 `__)\n\n* Use ``sys.implementation.name`` where appropriate for ``packaging.tags`` (`#193 `__)\n\n* Expand upon the API provided by ``packaging.tags``: ``interpreter_name()``, ``mac_platforms()``, ``compatible_tags()``, ``cpython_tags()``, ``generic_tags()`` (`#187 `__)\n\n* Officially support Python 3.8 (`#232 `__)\n\n* Add ``major``, ``minor``, and ``micro`` aliases to ``packaging.version.Version`` (`#226 `__)\n\n* Properly mark ``packaging`` has being fully typed by adding a `py.typed` file (`#226 `__)\n\n19.2 - 2019-09-18\n~~~~~~~~~~~~~~~~~\n\n* Remove dependency on ``attrs`` (`#178 `__, `#179 `__)\n\n* Use appropriate fallbacks for CPython ABI tag (`#181 `__, `#185 `__)\n\n* Add manylinux2014 support (`#186 `__)\n\n* Improve ABI detection (`#181 `__)\n\n* Properly handle debug wheels for Python 3.8 (`#172 `__)\n\n* Improve detection of debug builds on Windows (`#194 `__)\n\n19.1 - 2019-07-30\n~~~~~~~~~~~~~~~~~\n\n* Add the ``packaging.tags`` module. (`#156 `__)\n\n* Correctly handle two-digit versions in ``python_version`` (`#119 `__)\n\n\n19.0 - 2019-01-20\n~~~~~~~~~~~~~~~~~\n\n* Fix string representation of PEP 508 direct URL requirements with markers.\n\n* Better handling of file URLs\n\n This allows for using ``file:///absolute/path``, which was previously\n prevented due to the missing ``netloc``.\n\n This allows for all file URLs that ``urlunparse`` turns back into the\n original URL to be valid.\n\n\n18.0 - 2018-09-26\n~~~~~~~~~~~~~~~~~\n\n* Improve error messages when invalid requirements are given. (`#129 `__)\n\n\n17.1 - 2017-02-28\n~~~~~~~~~~~~~~~~~\n\n* Fix ``utils.canonicalize_version`` when supplying non PEP 440 versions.\n\n\n17.0 - 2017-02-28\n~~~~~~~~~~~~~~~~~\n\n* Drop support for python 2.6, 3.2, and 3.3.\n\n* Define minimal pyparsing version to 2.0.2 (`#91 `__).\n\n* Add ``epoch``, ``release``, ``pre``, ``dev``, and ``post`` attributes to\n ``Version`` and ``LegacyVersion`` (`#34 `__).\n\n* Add ``Version().is_devrelease`` and ``LegacyVersion().is_devrelease`` to\n make it easy to determine if a release is a development release.\n\n* Add ``utils.canonicalize_version`` to canonicalize version strings or\n ``Version`` instances (`#121 `__).\n\n\n16.8 - 2016-10-29\n~~~~~~~~~~~~~~~~~\n\n* Fix markers that utilize ``in`` so that they render correctly.\n\n* Fix an erroneous test on Python RC releases.\n\n\n16.7 - 2016-04-23\n~~~~~~~~~~~~~~~~~\n\n* Add support for the deprecated ``python_implementation`` marker which was\n an undocumented setuptools marker in addition to the newer markers.\n\n\n16.6 - 2016-03-29\n~~~~~~~~~~~~~~~~~\n\n* Add support for the deprecated, PEP 345 environment markers in addition to\n the newer markers.\n\n\n16.5 - 2016-02-26\n~~~~~~~~~~~~~~~~~\n\n* Fix a regression in parsing requirements with whitespaces between the comma\n separators.\n\n\n16.4 - 2016-02-22\n~~~~~~~~~~~~~~~~~\n\n* Fix a regression in parsing requirements like ``foo (==4)``.\n\n\n16.3 - 2016-02-21\n~~~~~~~~~~~~~~~~~\n\n* Fix a bug where ``packaging.requirements:Requirement`` was overly strict when\n matching legacy requirements.\n\n\n16.2 - 2016-02-09\n~~~~~~~~~~~~~~~~~\n\n* Add a function that implements the name canonicalization from PEP 503.\n\n\n16.1 - 2016-02-07\n~~~~~~~~~~~~~~~~~\n\n* Implement requirement specifiers from PEP 508.\n\n\n16.0 - 2016-01-19\n~~~~~~~~~~~~~~~~~\n\n* Relicense so that packaging is available under *either* the Apache License,\n Version 2.0 or a 2 Clause BSD license.\n\n* Support installation of packaging when only distutils is available.\n\n* Fix ``==`` comparison when there is a prefix and a local version in play.\n (`#41 `__).\n\n* Implement environment markers from PEP 508.\n\n\n15.3 - 2015-08-01\n~~~~~~~~~~~~~~~~~\n\n* Normalize post-release spellings for rev/r prefixes. `#35 `__\n\n\n15.2 - 2015-05-13\n~~~~~~~~~~~~~~~~~\n\n* Fix an error where the arbitrary specifier (``===``) was not correctly\n allowing pre-releases when it was being used.\n\n* Expose the specifier and version parts through properties on the\n ``Specifier`` classes.\n\n* Allow iterating over the ``SpecifierSet`` to get access to all of the\n ``Specifier`` instances.\n\n* Allow testing if a version is contained within a specifier via the ``in``\n operator.\n\n\n15.1 - 2015-04-13\n~~~~~~~~~~~~~~~~~\n\n* Fix a logic error that was causing inconsistent answers about whether or not\n a pre-release was contained within a ``SpecifierSet`` or not.\n\n\n15.0 - 2015-01-02\n~~~~~~~~~~~~~~~~~\n\n* Add ``Version().is_postrelease`` and ``LegacyVersion().is_postrelease`` to\n make it easy to determine if a release is a post release.\n\n* Add ``Version().base_version`` and ``LegacyVersion().base_version`` to make\n it easy to get the public version without any pre or post release markers.\n\n* Support the update to PEP 440 which removed the implied ``!=V.*`` when using\n either ``>V`` or ``V`` or ````) operator.\n\n\n14.3 - 2014-11-19\n~~~~~~~~~~~~~~~~~\n\n* **BACKWARDS INCOMPATIBLE** Refactor specifier support so that it can sanely\n handle legacy specifiers as well as PEP 440 specifiers.\n\n* **BACKWARDS INCOMPATIBLE** Move the specifier support out of\n ``packaging.version`` into ``packaging.specifiers``.\n\n\n14.2 - 2014-09-10\n~~~~~~~~~~~~~~~~~\n\n* Add prerelease support to ``Specifier``.\n* Remove the ability to do ``item in Specifier()`` and replace it with\n ``Specifier().contains(item)`` in order to allow flags that signal if a\n prerelease should be accepted or not.\n* Add a method ``Specifier().filter()`` which will take an iterable and returns\n an iterable with items that do not match the specifier filtered out.\n\n\n14.1 - 2014-09-08\n~~~~~~~~~~~~~~~~~\n\n* Allow ``LegacyVersion`` and ``Version`` to be sorted together.\n* Add ``packaging.version.parse()`` to enable easily parsing a version string\n as either a ``Version`` or a ``LegacyVersion`` depending on it's PEP 440\n validity.\n\n\n14.0 - 2014-09-05\n~~~~~~~~~~~~~~~~~\n\n* Initial release.\n\n\n.. _`master`: https://github.com/pypa/packaging/\n\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/packaging-21.0.dist-info", + "installer": "pip", + "requested": false + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "pip", + "version": "24.1", + "summary": "The PyPA recommended tool for installing Python packages.", + "description_content_type": "text/x-rst", + "author_email": "The pip developers ", + "license": "MIT", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Topic :: Software Development :: Build Tools", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy" + ], + "requires_python": ">=3.8", + "project_url": [ + "Homepage, https://pip.pypa.io/", + "Documentation, https://pip.pypa.io", + "Source, https://github.com/pypa/pip", + "Changelog, https://pip.pypa.io/en/stable/news/" + ], + "description": "pip - The Python Package Installer\n==================================\n\n.. |pypi-version| image:: https://img.shields.io/pypi/v/pip.svg\n :target: https://pypi.org/project/pip/\n :alt: PyPI\n\n.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pip\n :target: https://pypi.org/project/pip\n :alt: PyPI - Python Version\n\n.. |docs-badge| image:: https://readthedocs.org/projects/pip/badge/?version=latest\n :target: https://pip.pypa.io/en/latest\n :alt: Documentation\n\n|pypi-version| |python-versions| |docs-badge|\n\npip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.\n\nPlease take a look at our documentation for how to install and use pip:\n\n* `Installation`_\n* `Usage`_\n\nWe release updates regularly, with a new version every 3 months. Find more details in our documentation:\n\n* `Release notes`_\n* `Release process`_\n\nIf you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:\n\n* `Issue tracking`_\n* `Discourse channel`_\n* `User IRC`_\n\nIf you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms:\n\n* `GitHub page`_\n* `Development documentation`_\n* `Development IRC`_\n\nCode of Conduct\n---------------\n\nEveryone interacting in the pip project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _package installer: https://packaging.python.org/guides/tool-recommendations/\n.. _Python Package Index: https://pypi.org\n.. _Installation: https://pip.pypa.io/en/stable/installation/\n.. _Usage: https://pip.pypa.io/en/stable/\n.. _Release notes: https://pip.pypa.io/en/stable/news.html\n.. _Release process: https://pip.pypa.io/en/latest/development/release-process/\n.. _GitHub page: https://github.com/pypa/pip\n.. _Development documentation: https://pip.pypa.io/en/latest/development\n.. _Issue tracking: https://github.com/pypa/pip/issues\n.. _Discourse channel: https://discuss.python.org/c/packaging\n.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa\n.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/pip-24.1.dist-info", + "installer": "pip", + "requested": true + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "pyparsing", + "version": "2.4.7", + "platform": [ + "UNKNOWN" + ], + "summary": "Python parsing module", + "home_page": "https://github.com/pyparsing/pyparsing/", + "download_url": "https://pypi.org/project/pyparsing/", + "author": "Paul McGuire", + "author_email": "ptmcg@users.sourceforge.net", + "license": "MIT License", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8" + ], + "requires_python": ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*", + "description": "PyParsing -- A Python Parsing Module\n====================================\n\n|Build Status|\n\nIntroduction\n============\n\nThe pyparsing module is an alternative approach to creating and\nexecuting simple grammars, vs. the traditional lex/yacc approach, or the\nuse of regular expressions. The pyparsing module provides a library of\nclasses that client code uses to construct the grammar directly in\nPython code.\n\n*[Since first writing this description of pyparsing in late 2003, this\ntechnique for developing parsers has become more widespread, under the\nname Parsing Expression Grammars - PEGs. See more information on PEGs at*\nhttps://en.wikipedia.org/wiki/Parsing_expression_grammar *.]*\n\nHere is a program to parse ``\"Hello, World!\"`` (or any greeting of the form\n``\"salutation, addressee!\"``):\n\n.. code:: python\n\n from pyparsing import Word, alphas\n greet = Word(alphas) + \",\" + Word(alphas) + \"!\"\n hello = \"Hello, World!\"\n print(hello, \"->\", greet.parseString(hello))\n\nThe program outputs the following::\n\n Hello, World! -> ['Hello', ',', 'World', '!']\n\nThe Python representation of the grammar is quite readable, owing to the\nself-explanatory class names, and the use of '+', '|' and '^' operator\ndefinitions.\n\nThe parsed results returned from ``parseString()`` can be accessed as a\nnested list, a dictionary, or an object with named attributes.\n\nThe pyparsing module handles some of the problems that are typically\nvexing when writing text parsers:\n\n- extra or missing whitespace (the above program will also handle ``\"Hello,World!\"``, ``\"Hello , World !\"``, etc.)\n- quoted strings\n- embedded comments\n\nThe examples directory includes a simple SQL parser, simple CORBA IDL\nparser, a config file parser, a chemical formula parser, and a four-\nfunction algebraic notation parser, among many others.\n\nDocumentation\n=============\n\nThere are many examples in the online docstrings of the classes\nand methods in pyparsing. You can find them compiled into online docs\nat https://pyparsing-docs.readthedocs.io/en/latest/. Additional\ndocumentation resources and project info are listed in the online\nGitHub wiki, at https://github.com/pyparsing/pyparsing/wiki. An\nentire directory of examples is at\nhttps://github.com/pyparsing/pyparsing/tree/master/examples.\n\nLicense\n=======\n\nMIT License. See header of pyparsing.py\n\nHistory\n=======\n\nSee CHANGES file.\n\n.. |Build Status| image:: https://travis-ci.org/pyparsing/pyparsing.svg?branch=master\n :target: https://travis-ci.org/pyparsing/pyparsing\n\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/pyparsing-2.4.7.dist-info", + "installer": "pip", + "requested": false + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "semantic-version", + "version": "2.8.5", + "platform": [ + "UNKNOWN" + ], + "summary": "A library implementing the 'SemVer' scheme.", + "keywords": [ + "semantic version", + "versioning", + "version" + ], + "home_page": "https://github.com/rbarrois/python-semanticversion", + "download_url": "http://pypi.python.org/pypi/semantic_version/", + "author": "Raphaël Barrois", + "author_email": "raphael.barrois+semver@polytechnique.org", + "license": "BSD", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Topic :: Software Development :: Libraries :: Python Modules", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Software Development :: Libraries :: Python Modules" + ], + "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + "description": "python-semanticversion\n======================\n\nThis small python library provides a few tools to handle `SemVer`_ in Python.\nIt follows strictly the 2.0.0 version of the SemVer scheme.\n\n.. image:: https://secure.travis-ci.org/rbarrois/python-semanticversion.png?branch=master\n :target: http://travis-ci.org/rbarrois/python-semanticversion/\n\n.. image:: https://img.shields.io/pypi/v/semantic_version.svg\n :target: https://python-semanticversion.readthedocs.io/en/latest/changelog.html\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: Supported Python versions\n\n.. image:: https://img.shields.io/pypi/wheel/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: Wheel status\n\n.. image:: https://img.shields.io/pypi/l/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: License\n\nLinks\n-----\n\n- Package on `PyPI`_: http://pypi.python.org/pypi/semantic_version/\n- Doc on `ReadTheDocs `_: https://python-semanticversion.readthedocs.io/\n- Source on `GitHub `_: http://github.com/rbarrois/python-semanticversion/\n- Build on `Travis CI `_: http://travis-ci.org/rbarrois/python-semanticversion/\n- Semantic Version specification: `SemVer`_\n\n\nGetting started\n===============\n\nInstall the package from `PyPI`_, using pip:\n\n.. code-block:: sh\n\n pip install semantic_version\n\nOr from GitHub:\n\n.. code-block:: sh\n\n $ git clone git://github.com/rbarrois/python-semanticversion.git\n\n\nImport it in your code:\n\n\n.. code-block:: python\n\n import semantic_version\n\n\n\nThis module provides classes to handle semantic versions:\n\n- ``Version`` represents a version number (``0.1.1-alpha+build.2012-05-15``)\n- ``BaseSpec``-derived classes represent requirement specifications (``>=0.1.1,<0.3.0``):\n\n - ``SimpleSpec`` describes a natural description syntax\n - ``NpmSpec`` is used for NPM-style range descriptions.\n\nVersions\n--------\n\nDefining a ``Version`` is quite simple:\n\n\n.. code-block:: pycon\n\n >>> import semantic_version\n >>> v = semantic_version.Version('0.1.1')\n >>> v.major\n 0\n >>> v.minor\n 1\n >>> v.patch\n 1\n >>> v.prerelease\n []\n >>> v.build\n []\n >>> list(v)\n [0, 1, 1, [], []]\n\nIf the provided version string is invalid, a ``ValueError`` will be raised:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version('0.1')\n Traceback (most recent call last):\n File \"\", line 1, in \n File \"/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py\", line 64, in __init__\n major, minor, patch, prerelease, build = self.parse(version_string, partial)\n File \"/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py\", line 86, in parse\n raise ValueError('Invalid version string: %r' % version_string)\n ValueError: Invalid version string: '0.1'\n\n\nObviously, ``Versions`` can be compared:\n\n\n.. code-block:: pycon\n\n >>> semantic_version.Version('0.1.1') < semantic_version.Version('0.1.2')\n True\n >>> semantic_version.Version('0.1.1') > semantic_version.Version('0.1.1-alpha')\n True\n >>> semantic_version.Version('0.1.1') <= semantic_version.Version('0.1.1-alpha')\n False\n\nYou can also get a new version that represents a bump in one of the version levels:\n\n.. code-block:: pycon\n\n >>> v = semantic_version.Version('0.1.1+build')\n >>> new_v = v.next_major()\n >>> str(new_v)\n '1.0.0'\n >>> v = semantic_version.Version('1.1.1+build')\n >>> new_v = v.next_minor()\n >>> str(new_v)\n '1.2.0'\n >>> v = semantic_version.Version('1.1.1+build')\n >>> new_v = v.next_patch()\n >>> str(new_v)\n '1.1.2'\n\nIt is also possible to check whether a given string is a proper semantic version string:\n\n\n.. code-block:: pycon\n\n >>> semantic_version.validate('0.1.3')\n True\n >>> semantic_version.validate('0a2')\n False\n\n\nFinally, one may create a ``Version`` with named components instead:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version(major=0, minor=1, patch=2)\n Version('0.1.2')\n\nIn that case, ``major``, ``minor`` and ``patch`` are mandatory, and must be integers.\n``prerelease`` and ``patch``, if provided, must be tuples of strings:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version(major=0, minor=1, patch=2, prerelease=('alpha', '2'))\n Version('0.1.2-alpha.2')\n\n\nRequirement specification\n-------------------------\n\nThe ``SimpleSpec`` object describes a range of accepted versions:\n\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.1') # At least 0.1.1\n >>> s.match(Version('0.1.1'))\n True\n >>> s.match(Version('0.1.1-alpha1')) # pre-release doesn't satisfy version spec\n False\n >>> s.match(Version('0.1.0'))\n False\n\nSimpler test syntax is also available using the ``in`` keyword:\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('==0.1.1')\n >>> Version('0.1.1-alpha1') in s\n True\n >>> Version('0.1.2') in s\n False\n\n\nCombining specifications can be expressed as follows:\n\n .. code-block:: pycon\n\n >>> SimpleSpec('>=0.1.1,<0.3.0')\n\n\nUsing a specification\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThe ``SimpleSpec.filter`` method filters an iterable of ``Version``:\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.0,<0.4.0')\n >>> versions = (Version('0.%d.0' % i) for i in range(6))\n >>> for v in s.filter(versions):\n ... print v\n 0.1.0\n 0.2.0\n 0.3.0\n\nIt is also possible to select the 'best' version from such iterables:\n\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.0,<0.4.0')\n >>> versions = (Version('0.%d.0' % i) for i in range(6))\n >>> s.select(versions)\n Version('0.3.0')\n\n\nCoercing an arbitrary version string\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nSome user-supplied input might not match the semantic version scheme.\nFor such cases, the ``Version.coerce`` method will try to convert any\nversion-like string into a valid semver version:\n\n.. code-block:: pycon\n\n >>> Version.coerce('0')\n Version('0.0.0')\n >>> Version.coerce('0.1.2.3.4')\n Version('0.1.2+3.4')\n >>> Version.coerce('0.1.2a3')\n Version('0.1.2-a3')\n\n\nIncluding pre-release identifiers in specifications\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nWhen testing a ``Version`` against a ``SimpleSpec``, comparisons are\nadjusted for common user expectations; thus, a pre-release version (``1.0.0-alpha``)\nwill not satisfy the ``==1.0.0`` ``SimpleSpec``.\n\nPre-release identifiers will only be compared if included in the ``BaseSpec``\ndefinition or (for the empty pre-release number) if a single dash is appended\n(``1.0.0-``):\n\n\n.. code-block:: pycon\n\n >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0') # No pre-release identifier\n False\n >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0-') # Include pre-release in checks\n True\n\n\nIncluding build metadata in specifications\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nBuild metadata has no ordering; thus, the only meaningful comparison including\nbuild metadata is equality.\n\n\n.. code-block:: pycon\n\n >>> Version('1.0.0+build2') in SimpleSpec('<=1.0.0') # Build metadata ignored\n True\n >>> Version('1.0.0+build1') in SimpleSpec('==1.0.0+build2') # Include build in checks\n False\n\n\nNPM-based ranges\n----------------\n\nThe ``NpmSpec`` class handles NPM-style ranges:\n\n.. code-block:: pycon\n\n >>> Version('1.2.3') in NpmSpec('1.2.2 - 1.4')\n True\n >>> Version('1.2.3') in NpmSpec('<1.x || >=1.2.3')\n True\n\nRefer to https://docs.npmjs.com/misc/semver.html for a detailed description of NPM\nrange syntax.\n\n\nUsing with Django\n=================\n\nThe ``semantic_version.django_fields`` module provides django fields to\nstore ``Version`` or ``BaseSpec`` objects.\n\nMore documentation is available in the ``django`` section.\n\n\nContributing\n============\n\nIn order to contribute to the source code:\n\n- Open an issue on `GitHub`_: https://github.com/rbarrois/python-semanticversion/issues\n- Fork the `repository `_\n and submit a pull request on `GitHub`_\n- Or send me a patch (mailto:raphael.barrois+semver@polytechnique.org)\n\nWhen submitting patches or pull requests, you should respect the following rules:\n\n- Coding conventions are based on ``8``\n- The whole test suite must pass after adding the changes\n- The test coverage for a new feature must be 100%\n- New features and methods should be documented in the ``reference`` section\n and included in the ``changelog``\n- Include your name in the ``contributors`` section\n\n.. note:: All files should contain the following header::\n\n # -*- encoding: utf-8 -*-\n # Copyright (c) The python-semanticversion project\n\n\nContents\n========\n\n :maxdepth: 2\n\n reference\n django\n changelog\n credits\n\n\n.. _SemVer: http://semver.org/\n.. _PyPI: http://pypi.python.org/\n\nIndices and tables\n==================\n\n* ``genindex``\n* ``modindex``\n* ``search``\n\n\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/semantic_version-2.8.5.dist-info", + "installer": "pip", + "requested": false + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "semver", + "version": "2.13.0", + "platform": [ + "UNKNOWN" + ], + "summary": "Python helper for Semantic Versioning (http://semver.org/)", + "description_content_type": "text/x-rst", + "home_page": "https://github.com/python-semver/python-semver", + "download_url": "https://github.com/python-semver/python-semver/downloads", + "author": "Kostiantyn Rybnikov", + "author_email": "k-bx@k-bx.com", + "license": "BSD", + "classifier": [ + "Environment :: Web Environment", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Software Development :: Libraries :: Python Modules" + ], + "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + "project_url": [ + "Documentation, https://python-semver.rtfd.io", + "Releases, https://github.com/python-semver/python-semver/releases", + "Bug Tracker, https://github.com/python-semver/python-semver/issues" + ], + "description": "Quickstart\n==========\n\n.. teaser-begin\n\nA Python module for `semantic versioning`_. Simplifies comparing versions.\n\n|build-status| |python-support| |downloads| |license| |docs| |black|\n\n.. teaser-end\n\n.. warning::\n\n As anything comes to an end, this project will focus on Python 3.x only.\n New features and bugfixes will be integrated into the 3.x.y branch only.\n\n Major version 3 of semver will contain some incompatible changes:\n\n * removes support for Python 2.7 and 3.3\n * removes deprecated functions.\n\n The last version of semver which supports Python 2.7 and 3.4 will be\n 2.10.x. However, keep in mind, version 2.10.x is frozen: no new\n features nor backports will be integrated.\n\n We recommend to upgrade your workflow to Python 3.x to gain support,\n bugfixes, and new features.\n\nThe module follows the ``MAJOR.MINOR.PATCH`` style:\n\n* ``MAJOR`` version when you make incompatible API changes,\n* ``MINOR`` version when you add functionality in a backwards compatible manner, and\n* ``PATCH`` version when you make backwards compatible bug fixes.\n\nAdditional labels for pre-release and build metadata are supported.\n\nTo import this library, use:\n\n.. code-block:: python\n\n >>> import semver\n\nWorking with the library is quite straightforward. To turn a version string into the\ndifferent parts, use the ``semver.VersionInfo.parse`` function:\n\n.. code-block:: python\n\n >>> ver = semver.VersionInfo.parse('1.2.3-pre.2+build.4')\n >>> ver.major\n 1\n >>> ver.minor\n 2\n >>> ver.patch\n 3\n >>> ver.prerelease\n 'pre.2'\n >>> ver.build\n 'build.4'\n\nTo raise parts of a version, there are a couple of functions available for\nyou. The function ``semver.VersionInfo.bump_major`` leaves the original object untouched, but\nreturns a new ``semver.VersionInfo`` instance with the raised major part:\n\n.. code-block:: python\n\n >>> ver = semver.VersionInfo.parse(\"3.4.5\")\n >>> ver.bump_major()\n VersionInfo(major=4, minor=0, patch=0, prerelease=None, build=None)\n\nIt is allowed to concatenate different \"bump functions\":\n\n.. code-block:: python\n\n >>> ver.bump_major().bump_minor()\n VersionInfo(major=4, minor=1, patch=0, prerelease=None, build=None)\n\nTo compare two versions, semver provides the ``semver.compare`` function.\nThe return value indicates the relationship between the first and second\nversion:\n\n.. code-block:: python\n\n >>> semver.compare(\"1.0.0\", \"2.0.0\")\n -1\n >>> semver.compare(\"2.0.0\", \"1.0.0\")\n 1\n >>> semver.compare(\"2.0.0\", \"2.0.0\")\n 0\n\n\nThere are other functions to discover. Read on!\n\n\n.. |latest-version| image:: https://img.shields.io/pypi/v/semver.svg\n :alt: Latest version on PyPI\n :target: https://pypi.org/project/semver\n.. |build-status| image:: https://travis-ci.com/python-semver/python-semver.svg?branch=master\n :alt: Build status\n :target: https://travis-ci.com/python-semver/python-semver\n.. |python-support| image:: https://img.shields.io/pypi/pyversions/semver.svg\n :target: https://pypi.org/project/semver\n :alt: Python versions\n.. |downloads| image:: https://img.shields.io/pypi/dm/semver.svg\n :alt: Monthly downloads from PyPI\n :target: https://pypi.org/project/semver\n.. |license| image:: https://img.shields.io/pypi/l/semver.svg\n :alt: Software license\n :target: https://github.com/python-semver/python-semver/blob/master/LICENSE.txt\n.. |docs| image:: https://readthedocs.org/projects/python-semver/badge/?version=latest\n :target: http://python-semver.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n.. _semantic versioning: http://semver.org/\n.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Black Formatter\n\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/semver-2.13.0.dist-info", + "installer": "pip", + "requested": false + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "setuptools", + "version": "70.1.0", + "summary": "Easily download, build, install, upgrade, and uninstall Python packages", + "description_content_type": "text/x-rst", + "keywords": [ + "CPAN", + "PyPI", + "distutils", + "eggs", + "package", + "management" + ], + "author_email": "Python Packaging Authority ", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: System :: Archiving :: Packaging", + "Topic :: System :: Systems Administration", + "Topic :: Utilities" + ], + "requires_dist": [ + "sphinx >=3.5 ; extra == 'docs'", + "jaraco.packaging >=9.3 ; extra == 'docs'", + "rst.linker >=1.9 ; extra == 'docs'", + "furo ; extra == 'docs'", + "sphinx-lint ; extra == 'docs'", + "jaraco.tidelift >=1.4 ; extra == 'docs'", + "pygments-github-lexers ==0.0.5 ; extra == 'docs'", + "sphinx-favicon ; extra == 'docs'", + "sphinx-inline-tabs ; extra == 'docs'", + "sphinx-reredirects ; extra == 'docs'", + "sphinxcontrib-towncrier ; extra == 'docs'", + "sphinx-notfound-page <2,>=1 ; extra == 'docs'", + "pyproject-hooks !=1.1 ; extra == 'docs'", + "pytest !=8.1.1,>=6 ; extra == 'testing'", + "pytest-checkdocs >=2.4 ; extra == 'testing'", + "pytest-mypy ; extra == 'testing'", + "pytest-enabler >=2.2 ; extra == 'testing'", + "virtualenv >=13.0.0 ; extra == 'testing'", + "wheel ; extra == 'testing'", + "pip >=19.1 ; extra == 'testing'", + "packaging >=23.2 ; extra == 'testing'", + "jaraco.envs >=2.2 ; extra == 'testing'", + "pytest-xdist >=3 ; extra == 'testing'", + "jaraco.path >=3.2.0 ; extra == 'testing'", + "build[virtualenv] >=1.0.3 ; extra == 'testing'", + "filelock >=3.4.0 ; extra == 'testing'", + "ini2toml[lite] >=0.14 ; extra == 'testing'", + "tomli-w >=1.0.0 ; extra == 'testing'", + "pytest-timeout ; extra == 'testing'", + "pytest-home >=0.5 ; extra == 'testing'", + "mypy ==1.10.0 ; extra == 'testing'", + "tomli ; extra == 'testing'", + "importlib-metadata ; extra == 'testing'", + "pytest-subprocess ; extra == 'testing'", + "pyproject-hooks !=1.1 ; extra == 'testing'", + "jaraco.test ; extra == 'testing'", + "pytest-cov ; (platform_python_implementation != \"PyPy\") and extra == 'testing'", + "jaraco.develop >=7.21 ; (python_version >= \"3.9\" and sys_platform != \"cygwin\") and extra == 'testing'", + "pytest-ruff >=0.3.2 ; (sys_platform != \"cygwin\") and extra == 'testing'", + "pytest-perf ; (sys_platform != \"cygwin\") and extra == 'testing'" + ], + "requires_python": ">=3.8", + "project_url": [ + "Homepage, https://github.com/pypa/setuptools", + "Documentation, https://setuptools.pypa.io/", + "Changelog, https://setuptools.pypa.io/en/stable/history.html" + ], + "provides_extra": [ + "certs", + "docs", + "ssl", + "testing" + ], + "description": ".. |pypi-version| image:: https://img.shields.io/pypi/v/setuptools.svg\n :target: https://pypi.org/project/setuptools\n\n.. |py-version| image:: https://img.shields.io/pypi/pyversions/setuptools.svg\n\n.. |test-badge| image:: https://github.com/pypa/setuptools/actions/workflows/main.yml/badge.svg\n :target: https://github.com/pypa/setuptools/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. |ruff-badge| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. |docs-badge| image:: https://img.shields.io/readthedocs/setuptools/latest.svg\n :target: https://setuptools.pypa.io\n\n.. |skeleton-badge| image:: https://img.shields.io/badge/skeleton-2024-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. |codecov-badge| image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white\n :target: https://codecov.io/gh/pypa/setuptools\n\n.. |tidelift-badge| image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat\n :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme\n\n.. |discord-badge| image:: https://img.shields.io/discord/803025117553754132\n :target: https://discord.com/channels/803025117553754132/815945031150993468\n :alt: Discord\n\n|pypi-version| |py-version| |test-badge| |ruff-badge| |docs-badge| |skeleton-badge| |codecov-badge| |discord-badge|\n\nSee the `Quickstart `_\nand the `User's Guide `_ for\ninstructions on how to use Setuptools.\n\nQuestions and comments should be directed to `GitHub Discussions\n`_.\nBug reports and especially tested patches may be\nsubmitted directly to the `bug tracker\n`_.\n\n\nCode of Conduct\n===============\n\nEveryone interacting in the setuptools project's codebases, issue trackers,\nchat rooms, and fora is expected to follow the\n`PSF Code of Conduct `_.\n\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nSetuptools and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/setuptools-70.1.0.dist-info", + "installer": "pip", + "requested": true + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "univers", + "version": "0.0.0", + "summary": "A mostly universal library to parse and compare software package versions and version ranges. A companion to Package URLs.", + "description_content_type": "text/x-rst", + "keywords": [ + "semver", + "utilities", + "version", + "release", + "version range", + "package URL", + "purl", + "arch", + "pacman", + "pypi", + "rpm", + "gentoo", + "ebuild", + "maven", + "debian", + "rubygems" + ], + "home_page": "https://github.com/nexB/univers", + "author": "Shivam Sandbhor, nexB. Inc. and others", + "author_email": "info@aboutcode.org", + "license": "Apache-2.0 AND BSD-3-Clause AND MIT", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Software Development", + "Topic :: Utilities" + ], + "requires_dist": [ + "attrs", + "packaging", + "semantic-version", + "semver", + "Sphinx >=5.0.2 ; extra == 'docs'", + "sphinx-rtd-theme >=1.0.0 ; extra == 'docs'", + "sphinx-reredirects >=0.1.2 ; extra == 'docs'", + "doc8 >=0.11.2 ; extra == 'docs'", + "pytest !=7.0.0,>=6 ; extra == 'testing'", + "pytest-xdist >=2 ; extra == 'testing'", + "aboutcode-toolkit >=7.0.2 ; extra == 'testing'", + "pycodestyle >=2.8.0 ; extra == 'testing'", + "twine ; extra == 'testing'", + "black ; extra == 'testing'", + "commoncode ; extra == 'testing'", + "isort >=5.10.1 ; extra == 'testing'" + ], + "requires_python": ">=3.7", + "provides_extra": [ + "docs", + "testing" + ], + "description": "univers: mostly universal version and version ranges comparison and conversion\n===============================================================================\n\n|Build Status| |License| |Python 3.6+|\n\n.. |Build Status| image:: https://api.travis-ci.com/sbs2001/univers.svg?branch=main&status=passed\n.. |License| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg\n :target: https://scancode-licensedb.aboutcode.org/apache-2.0.html\n.. |Python 3.6+| image:: https://img.shields.io/badge/python-3.6+-blue.svg\n :target: https://www.python.org/downloads/release/python-380/\n\n\n**univers** was born out of the need for a mostly universal way to store version\nranges and to compare two software package versions in VulnerableCode.\n\nPackage version ranges and version constraints are useful and essential:\n\n- When relating a known vulnerability or bug to a range of affected package\n versions. For instance a statement such as \"vulnerability 123 affects \n package bar, version 3.1 and version 4.2 but not version 5\" defines a\n range of bar versions affected by a vulnerability.\n\n- When resolving the dependencies of a package to express which subset of the\n versions are supported. For instance a dependency requirement statement such\n as \"I require package foo, version 2.0 and later versions\" defines a range of\n acceptable foo versions.\n\nVersion syntaxes and range notations are quite different across ecosystems,\nmaking it is difficult to process versions and version ranges across ecosystems\nin a consistent way.\n\nExisting tools and libraries typically support a single algorithms to parse and\ncompare versions with a single version range notation for a single package\necosystem.\n\n\n**univers** is different:\n\n- It tracks each ecosystem versioning scheme and how two versions are compared.\n\n- It support a growing number of package ecosystems versioning in a single\n library.\n\n- It can parse version range strings using their native notation (such as an npm\n range) into the common \"vers\" notation and internal object model and can\n return back a native version range string rebuilt from a \"vers\" range.\n\n- It is designed to work with `Package URLs (purl) `_.\n\n\nHow does **univers** work ?\n============================\n\n**univers** wraps, embeds and implements multiple version comparison libraries,\neach focused on a specific ecosystem versioning scheme.\n\nFor each scheme, **univers** provides an implementation for:\n\n- the version comparison procedure e.g, how to compare two versions,\n- parsing and converting from a native version range notation to the\n **univers** normalized and unified internal model,\n- converting a range back to its scheme-native range syntax and to the\n ``vers`` syntax.\n\n**univers** implements ``vers``, an experimental unified and mostly universal\nversion range syntax. It can parse and convert an existing native version range\nstrings to this unified syntax. For example, this means:\n\n- converting \">=1.2.3\" as used in a Python package into ``vers:pypi/>=1.2.3``,\n\n- or converting \"^1.0.2\" as used in an npm package dependency declaration into\n ``vers:npm/>=1.0.2|<2.0.0``\n\nThe supported package ecosystems versioning schemes and underlying libraries\ninclude:\n\n- npm that use the \"node-semver\" ranges notation and the semver versions syntax\n This is supported in part by the `semantic_version\n `_ library.\n\n- pypi: handled by Python's packaging library and the standard \n ``packaging.version`` module.\n\n- Rubygems which use a semver-like but not-quite-semver scheme and there can be\n commonly more than three version segments.\n Gems also use a slightly different range notation from node-semver with\n different operators and slightly different semantics: for instance it uses \"~>\"\n as a pessimistic operator and supports exclusion with != and does not support\n \"OR\" between constraints (that it call requirements).\n Gem are handled by Python port of the Rubygems requirements and version\n handling code from the `puppeteer tool\n `_\n\n- debian: handled by the `debian-inspector library\n `_.\n\n- maven: handled by the embedded `pymaven library\n `_.\n\n- rpm: handled by the embedded `rpm_vercmp library\n `_.\n\n- golang (using semver)\n\n- PHP composer\n\n- ebuild/gentoo: handled by the embedded `gentoo_vercmp module\n `_.\n\n- arch linux: handled by the embedded `arch utility module borrowed from msys2\n `_.\n\n- Alpine linux: handled using the base Gentoo version support and extras\n specific to Alpine.\n\n\nThe level of support for each ecosystem may not be even for now and new schemes\nand support for more package types are implemented on a continuous basis.\n\n\nAlternative\n============\n\nRather than using ecosystem-specific version schemes and code, another approach\nis to use a single procedure for all the versions as implemented in `libversion\n`_. ``libversion`` works in the most\ncommon case but may not work correctly when a task that demand precise version\ncomparisons such as for dependency resolution and vulnerability lookup where\na \"good enough\" comparison accuracy is not acceptable. ``libversion`` does not\nhandle version range notations.\n\n\nInstallation\n============\n\n $ pip install univers\n\n\nExamples\n========\n\nCompare two native Python versions:\n\n.. code:: python\n\n from univers.versions import PypiVersion\n assert PypiVersion(\"1.2.3\") < PypiVersion(\"1.2.4\")\n\n\nNormalize a version range from an npm:\n\n.. code:: python\n\n from univers.version_range import NpmVersionRange\n range = NpmVersionRange.from_native(\"^1.0.2\")\n assert str(range) == \"vers:npm/>=1.0.2|<2.0.0\"\n\n\nTest if a version is within or outside a version range:\n\n.. code:: python\n\n from univers.versions import PypiVersion\n from univers.version_range import VersionRange\n\n range = VersionRange.from_string(\"vers:pypi/>=1.2.4\")\n\n assert PypiVersion(\"1.2.4\") in range\n assert PypiVersion(\"1.2.3\") not in range\n\n\nDevelopment\n============\n\nRun these commands, starting from a git clone of https://github.com/nexB/univers ::\n\n $ ./configure --dev\n $ source venv/bin/active\n $ pytest -vvs\n\n\nWe use the same development process as other AboutCode projects.\n\nVisit https://github.com/nexB/univers and\nhttps://gitter.im/aboutcode-org/vulnerablecode and\nhttps://gitter.im/aboutcode-org/aboutcode for support and chat.\n\n\nPrimary license: Apache-2.0\nSPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause AND MIT\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/univers-0.0.0.dist-info", + "direct_url": { + "url": "file:///home/ayansinha/nexB/write_access/univers", + "dir_info": { + "editable": true + } + }, + "installer": "pip", + "requested": true + }, + { + "metadata": { + "metadata_version": "2.1", + "name": "wheel", + "version": "0.43.0", + "summary": "A built-package format for Python", + "description_content_type": "text/x-rst", + "keywords": [ + "wheel", + "packaging" + ], + "author_email": "Daniel Holth ", + "maintainer_email": "Alex Grönholm ", + "classifier": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: System :: Archiving :: Packaging", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12" + ], + "requires_dist": [ + "pytest >= 6.0.0 ; extra == \"test\"", + "setuptools >= 65 ; extra == \"test\"" + ], + "requires_python": ">=3.8", + "project_url": [ + "Changelog, https://wheel.readthedocs.io/en/stable/news.html", + "Documentation, https://wheel.readthedocs.io/", + "Issue Tracker, https://github.com/pypa/wheel/issues", + "Source, https://github.com/pypa/wheel" + ], + "provides_extra": [ + "test" + ], + "description": "wheel\n=====\n\nThis library is the reference implementation of the Python wheel packaging\nstandard, as defined in `PEP 427`_.\n\nIt has two different roles:\n\n#. A setuptools_ extension for building wheels that provides the\n ``bdist_wheel`` setuptools command\n#. A command line tool for working with wheel files\n\nIt should be noted that wheel is **not** intended to be used as a library, and\nas such there is no stable, public API.\n\n.. _PEP 427: https://www.python.org/dev/peps/pep-0427/\n.. _setuptools: https://pypi.org/project/setuptools/\n\nDocumentation\n-------------\n\nThe documentation_ can be found on Read The Docs.\n\n.. _documentation: https://wheel.readthedocs.io/\n\nCode of Conduct\n---------------\n\nEveryone interacting in the wheel project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n\n" + }, + "metadata_location": "/home/ayansinha/nexB/write_access/univers/venv/lib/python3.10/site-packages/wheel-0.43.0.dist-info", + "installer": "pip", + "requested": true + } + ], + "environment": { + "implementation_name": "cpython", + "implementation_version": "3.10.12", + "os_name": "posix", + "platform_machine": "x86_64", + "platform_release": "5.15.0-112-generic", + "platform_system": "Linux", + "platform_version": "#122-Ubuntu SMP Thu May 23 07:48:21 UTC 2024", + "python_full_version": "3.10.12", + "platform_python_implementation": "CPython", + "python_version": "3.10", + "sys_platform": "linux" + } +} diff --git a/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock-expected.json b/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock-expected.json new file mode 100644 index 00000000000..051969f6f01 --- /dev/null +++ b/tests/packagedcode/data/pypi/deplock/univers/pip-inspect.deplock-expected.json @@ -0,0 +1,1672 @@ +[ + { + "type": "pypi", + "namespace": null, + "name": "univers", + "version": "0.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "univers: mostly universal version and version ranges comparison and conversion\n===============================================================================\n\n|Build Status| |License| |Python 3.6+|\n\n.. |Build Status| image:: https://api.travis-ci.com/sbs2001/univers.svg?branch=main&status=passed\n.. |License| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg\n :target: https://scancode-licensedb.aboutcode.org/apache-2.0.html\n.. |Python 3.6+| image:: https://img.shields.io/badge/python-3.6+-blue.svg\n :target: https://www.python.org/downloads/release/python-380/\n\n\n**univers** was born out of the need for a mostly universal way to store version\nranges and to compare two software package versions in VulnerableCode.\n\nPackage version ranges and version constraints are useful and essential:\n\n- When relating a known vulnerability or bug to a range of affected package\n versions. For instance a statement such as \"vulnerability 123 affects \n package bar, version 3.1 and version 4.2 but not version 5\" defines a\n range of bar versions affected by a vulnerability.\n\n- When resolving the dependencies of a package to express which subset of the\n versions are supported. For instance a dependency requirement statement such\n as \"I require package foo, version 2.0 and later versions\" defines a range of\n acceptable foo versions.\n\nVersion syntaxes and range notations are quite different across ecosystems,\nmaking it is difficult to process versions and version ranges across ecosystems\nin a consistent way.\n\nExisting tools and libraries typically support a single algorithms to parse and\ncompare versions with a single version range notation for a single package\necosystem.\n\n\n**univers** is different:\n\n- It tracks each ecosystem versioning scheme and how two versions are compared.\n\n- It support a growing number of package ecosystems versioning in a single\n library.\n\n- It can parse version range strings using their native notation (such as an npm\n range) into the common \"vers\" notation and internal object model and can\n return back a native version range string rebuilt from a \"vers\" range.\n\n- It is designed to work with `Package URLs (purl) `_.\n\n\nHow does **univers** work ?\n============================\n\n**univers** wraps, embeds and implements multiple version comparison libraries,\neach focused on a specific ecosystem versioning scheme.\n\nFor each scheme, **univers** provides an implementation for:\n\n- the version comparison procedure e.g, how to compare two versions,\n- parsing and converting from a native version range notation to the\n **univers** normalized and unified internal model,\n- converting a range back to its scheme-native range syntax and to the\n ``vers`` syntax.\n\n**univers** implements ``vers``, an experimental unified and mostly universal\nversion range syntax. It can parse and convert an existing native version range\nstrings to this unified syntax. For example, this means:\n\n- converting \">=1.2.3\" as used in a Python package into ``vers:pypi/>=1.2.3``,\n\n- or converting \"^1.0.2\" as used in an npm package dependency declaration into\n ``vers:npm/>=1.0.2|<2.0.0``\n\nThe supported package ecosystems versioning schemes and underlying libraries\ninclude:\n\n- npm that use the \"node-semver\" ranges notation and the semver versions syntax\n This is supported in part by the `semantic_version\n `_ library.\n\n- pypi: handled by Python's packaging library and the standard \n ``packaging.version`` module.\n\n- Rubygems which use a semver-like but not-quite-semver scheme and there can be\n commonly more than three version segments.\n Gems also use a slightly different range notation from node-semver with\n different operators and slightly different semantics: for instance it uses \"~>\"\n as a pessimistic operator and supports exclusion with != and does not support\n \"OR\" between constraints (that it call requirements).\n Gem are handled by Python port of the Rubygems requirements and version\n handling code from the `puppeteer tool\n `_\n\n- debian: handled by the `debian-inspector library\n `_.\n\n- maven: handled by the embedded `pymaven library\n `_.\n\n- rpm: handled by the embedded `rpm_vercmp library\n `_.\n\n- golang (using semver)\n\n- PHP composer\n\n- ebuild/gentoo: handled by the embedded `gentoo_vercmp module\n `_.\n\n- arch linux: handled by the embedded `arch utility module borrowed from msys2\n `_.\n\n- Alpine linux: handled using the base Gentoo version support and extras\n specific to Alpine.\n\n\nThe level of support for each ecosystem may not be even for now and new schemes\nand support for more package types are implemented on a continuous basis.\n\n\nAlternative\n============\n\nRather than using ecosystem-specific version schemes and code, another approach\nis to use a single procedure for all the versions as implemented in `libversion\n`_. ``libversion`` works in the most\ncommon case but may not work correctly when a task that demand precise version\ncomparisons such as for dependency resolution and vulnerability lookup where\na \"good enough\" comparison accuracy is not acceptable. ``libversion`` does not\nhandle version range notations.\n\n\nInstallation\n============\n\n $ pip install univers\n\n\nExamples\n========\n\nCompare two native Python versions:\n\n.. code:: python\n\n from univers.versions import PypiVersion\n assert PypiVersion(\"1.2.3\") < PypiVersion(\"1.2.4\")\n\n\nNormalize a version range from an npm:\n\n.. code:: python\n\n from univers.version_range import NpmVersionRange\n range = NpmVersionRange.from_native(\"^1.0.2\")\n assert str(range) == \"vers:npm/>=1.0.2|<2.0.0\"\n\n\nTest if a version is within or outside a version range:\n\n.. code:: python\n\n from univers.versions import PypiVersion\n from univers.version_range import VersionRange\n\n range = VersionRange.from_string(\"vers:pypi/>=1.2.4\")\n\n assert PypiVersion(\"1.2.4\") in range\n assert PypiVersion(\"1.2.3\") not in range\n\n\nDevelopment\n============\n\nRun these commands, starting from a git clone of https://github.com/nexB/univers ::\n\n $ ./configure --dev\n $ source venv/bin/active\n $ pytest -vvs\n\n\nWe use the same development process as other AboutCode projects.\n\nVisit https://github.com/nexB/univers and\nhttps://gitter.im/aboutcode-org/vulnerablecode and\nhttps://gitter.im/aboutcode-org/aboutcode for support and chat.\n\n\nPrimary license: Apache-2.0\nSPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause AND MIT\n", + "release_date": null, + "parties": [], + "keywords": [ + "semver", + "utilities", + "version", + "release", + "version range", + "package URL", + "purl", + "arch", + "pacman", + "pypi", + "rpm", + "gentoo", + "ebuild", + "maven", + "debian", + "rubygems" + ], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "apache-2.0 AND bsd-new AND mit", + "declared_license_expression_spdx": "Apache-2.0 AND BSD-3-Clause AND MIT", + "license_detections": [ + { + "license_expression": "apache-2.0 AND bsd-new AND mit", + "license_expression_spdx": "Apache-2.0 AND BSD-3-Clause AND MIT", + "matches": [ + { + "license_expression": "apache-2.0 AND bsd-new AND mit", + "spdx_license_expression": "Apache-2.0 AND BSD-3-Clause AND MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 9, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-apache_2_0_and_bsd_new_and_mit-5a0e0d1daea60cb9191d19fe5324c57e89cbcbf8", + "rule_url": null, + "matched_text": "Apache-2.0 AND BSD-3-Clause AND MIT" + } + ], + "identifier": "apache_2_0_and_bsd_new_and_mit-4d4f1034-453c-8cde-3ab0-bd35ddc243e6" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "Apache-2.0 AND BSD-3-Clause AND MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": { + "pip_version": "24.1", + "inspect_version": "1" + }, + "dependencies": [ + { + "purl": "pkg:pypi/attrs@21.2.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "attrs", + "version": "21.2.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "======================================\n``attrs``: Classes Without Boilerplate\n======================================\n\n\n``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder `_ methods).\n`Trusted by NASA `_ for Mars missions since 2020!\n\nIts main goal is to help you to write **concise** and **correct** software without slowing down your code.\n\n.. teaser-end\n\nFor that, it gives you a class decorator and a way to declaratively define the attributes on that class:\n\n.. -code-begin-\n\n.. code-block:: pycon\n\n >>> import attr\n\n >>> @attr.s\n ... class SomeClass(object):\n ... a_number = attr.ib(default=42)\n ... list_of_numbers = attr.ib(factory=list)\n ...\n ... def hard_math(self, another_number):\n ... return self.a_number + sum(self.list_of_numbers) * another_number\n\n\n >>> sc = SomeClass(1, [1, 2, 3])\n >>> sc\n SomeClass(a_number=1, list_of_numbers=[1, 2, 3])\n\n >>> sc.hard_math(3)\n 19\n >>> sc == SomeClass(1, [1, 2, 3])\n True\n >>> sc != SomeClass(2, [3, 2, 1])\n True\n\n >>> attr.asdict(sc)\n {'a_number': 1, 'list_of_numbers': [1, 2, 3]}\n\n >>> SomeClass()\n SomeClass(a_number=42, list_of_numbers=[])\n\n >>> C = attr.make_class(\"C\", [\"a\", \"b\"])\n >>> C(\"foo\", \"bar\")\n C(a='foo', b='bar')\n\n\nAfter *declaring* your attributes ``attrs`` gives you:\n\n- a concise and explicit overview of the class's attributes,\n- a nice human-readable ``__repr__``,\n- a complete set of comparison methods (equality and ordering),\n- an initializer,\n- and much more,\n\n*without* writing dull boilerplate code again and again and *without* runtime performance penalties.\n\nOn Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations `_.\n\nThis gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\\ s or `confusingly behaving `_ ``namedtuple``\\ s.\nWhich in turn encourages you to write *small classes* that do `one thing well `_.\nNever again violate the `single responsibility principle `_ just because implementing ``__init__`` et al is a painful drag.\n\n\n.. -getting-help-\n\nGetting Help\n============\n\nPlease use the ``python-attrs`` tag on `StackOverflow `_ to get help.\n\nAnswering questions of your fellow developers is also a great way to help the project!\n\n\n.. -project-information-\n\nProject Information\n===================\n\n``attrs`` is released under the `MIT `_ license,\nits documentation lives at `Read the Docs `_,\nthe code on `GitHub `_,\nand the latest release on `PyPI `_.\nIt\u2019s rigorously tested on Python 2.7, 3.5+, and PyPy.\n\nWe collect information on **third-party extensions** in our `wiki `_.\nFeel free to browse and add your own!\n\nIf you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started!\n\n\n``attrs`` for Enterprise\n------------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.\n`Learn more. `_\n\n\nRelease Information\n===================\n\n21.2.0 (2021-05-07)\n-------------------\n\nBackward-incompatible Changes\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n- We had to revert the recursive feature for ``attr.evolve()`` because it broke some use-cases -- sorry!\n `#806 `_\n- Python 3.4 is now blocked using packaging metadata because ``attrs`` can't be imported on it anymore.\n To ensure that 3.4 users can keep installing ``attrs`` easily, we will `yank `_ 21.1.0 from PyPI.\n This has **no** consequences if you pin ``attrs`` to 21.1.0.\n `#807 `_\n\n`Full changelog `_.\n\nCredits\n=======\n\n``attrs`` is written and maintained by `Hynek Schlawack `_.\n\nThe development is kindly supported by `Variomedia AG `_.\n\nA full list of contributors can be found in `GitHub's overview `_.\n\nIt\u2019s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions.\nBoth were inspired by Twisted\u2019s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m\u2019kay?\n\n\n", + "release_date": null, + "parties": [], + "keywords": [ + "class", + "attribute", + "boilerplate" + ], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "spdx_license_expression": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 1, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-mit-5da48780aba670b0860c46d899ed42a0f243ff06", + "rule_url": null, + "matched_text": "MIT" + } + ], + "identifier": "mit-a822f434-d61f-f2b1-c792-8b8cb9e7b9bf" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:pypi/coverage", + "extracted_requirement": "coverage[toml]>=5.0.2; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/hypothesis", + "extracted_requirement": "hypothesis; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pympler", + "extracted_requirement": "pympler; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest>=4.3.0; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/six", + "extracted_requirement": "six; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/mypy", + "extracted_requirement": "mypy; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-mypy-plugins", + "extracted_requirement": "pytest-mypy-plugins; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/zope-interface", + "extracted_requirement": "zope.interface; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/furo", + "extracted_requirement": "furo; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx", + "extracted_requirement": "sphinx; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-notfound-page", + "extracted_requirement": "sphinx-notfound-page; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pre-commit", + "extracted_requirement": "pre-commit; extra == \"dev\"", + "scope": "dev", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/furo", + "extracted_requirement": "furo; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx", + "extracted_requirement": "sphinx; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/zope-interface", + "extracted_requirement": "zope.interface; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-notfound-page", + "extracted_requirement": "sphinx-notfound-page; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/coverage", + "extracted_requirement": "coverage[toml]>=5.0.2; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/hypothesis", + "extracted_requirement": "hypothesis; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pympler", + "extracted_requirement": "pympler; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest>=4.3.0; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/six", + "extracted_requirement": "six; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/mypy", + "extracted_requirement": "mypy; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-mypy-plugins", + "extracted_requirement": "pytest-mypy-plugins; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/zope-interface", + "extracted_requirement": "zope.interface; extra == \"tests\"", + "scope": "tests", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/coverage", + "extracted_requirement": "coverage[toml]>=5.0.2; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/hypothesis", + "extracted_requirement": "hypothesis; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pympler", + "extracted_requirement": "pympler; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest>=4.3.0; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/six", + "extracted_requirement": "six; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/mypy", + "extracted_requirement": "mypy; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-mypy-plugins", + "extracted_requirement": "pytest-mypy-plugins; extra == \"tests_no_zope\"", + "scope": "tests_no_zope", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/attrs@21.2.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/packaging@21.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "packaging", + "version": "21.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "packaging\n=========\n\n.. start-intro\n\nReusable core utilities for various Python Packaging\n`interoperability specifications `_.\n\nThis library provides utilities that implement the interoperability\nspecifications which have clearly one correct behaviour (eg: :pep:`440`)\nor benefit greatly from having a single shared implementation (eg: :pep:`425`).\n\n.. end-intro\n\nThe ``packaging`` project includes the following: version handling, specifiers,\nmarkers, requirements, tags, utilities.\n\nDocumentation\n-------------\n\nThe `documentation`_ provides information and the API for the following:\n\n- Version Handling\n- Specifiers\n- Markers\n- Requirements\n- Tags\n- Utilities\n\nInstallation\n------------\n\nUse ``pip`` to install these utilities::\n\n pip install packaging\n\nDiscussion\n----------\n\nIf you run into bugs, you can file them in our `issue tracker`_.\n\nYou can also join ``#pypa`` on Freenode to ask questions or get involved.\n\n\n.. _`documentation`: https://packaging.pypa.io/\n.. _`issue tracker`: https://github.com/pypa/packaging/issues\n\n\nCode of Conduct\n---------------\n\nEveryone interacting in the packaging project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n\nContributing\n------------\n\nThe ``CONTRIBUTING.rst`` file outlines how to contribute to this project as\nwell as how to report a potential security issue. The documentation for this\nproject also covers information about `project development`_ and `security`_.\n\n.. _`project development`: https://packaging.pypa.io/en/latest/development/\n.. _`security`: https://packaging.pypa.io/en/latest/security/\n\nProject History\n---------------\n\nPlease review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for\nrecent changes and project history.\n\n.. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/\n\nChangelog\n---------\n\n21.0 - 2021-07-03\n~~~~~~~~~~~~~~~~~\n\n* `packaging` is now only compatible with Python 3.6 and above.\n* Add support for zip files in ``parse_sdist_filename`` (`#429 `__)\n\n20.9 - 2021-01-29\n~~~~~~~~~~~~~~~~~\n\n* Run `isort `_ over the code base (`#377 `__)\n* Add support for the ``macosx_10_*_universal2`` platform tags (`#379 `__)\n* Introduce ``packaging.utils.parse_wheel_filename()`` and ``parse_sdist_filename()``\n (`#387 `__ and `#389 `__)\n\n20.8 - 2020-12-11\n~~~~~~~~~~~~~~~~~\n\n* Revert back to setuptools for compatibility purposes for some Linux distros (`#363 `__)\n* Do not insert an underscore in wheel tags when the interpreter version number\n is more than 2 digits (`#372 `__)\n\n20.7 - 2020-11-28\n~~~~~~~~~~~~~~~~~\n\nNo unreleased changes.\n\n20.6 - 2020-11-28\n~~~~~~~~~~~~~~~~~\n\n.. note:: This release was subsequently yanked, and these changes were included in 20.7.\n\n* Fix flit configuration, to include LICENSE files (`#357 `__)\n* Make `intel` a recognized CPU architecture for the `universal` macOS platform tag (`#361 `__)\n* Add some missing type hints to `packaging.requirements` (issue:`350`)\n\n20.5 - 2020-11-27\n~~~~~~~~~~~~~~~~~\n\n* Officially support Python 3.9 (`#343 `__)\n* Deprecate the ``LegacyVersion`` and ``LegacySpecifier`` classes (`#321 `__)\n* Handle ``OSError`` on non-dynamic executables when attempting to resolve\n the glibc version string.\n\n20.4 - 2020-05-19\n~~~~~~~~~~~~~~~~~\n\n* Canonicalize version before comparing specifiers. (`#282 `__)\n* Change type hint for ``canonicalize_name`` to return\n ``packaging.utils.NormalizedName``.\n This enables the use of static typing tools (like mypy) to detect mixing of\n normalized and un-normalized names.\n\n20.3 - 2020-03-05\n~~~~~~~~~~~~~~~~~\n\n* Fix changelog for 20.2.\n\n20.2 - 2020-03-05\n~~~~~~~~~~~~~~~~~\n\n* Fix a bug that caused a 32-bit OS that runs on a 64-bit ARM CPU (e.g. ARM-v8,\n aarch64), to report the wrong bitness.\n\n20.1 - 2020-01-24\n~~~~~~~~~~~~~~~~~~~\n\n* Fix a bug caused by reuse of an exhausted iterator. (`#257 `__)\n\n20.0 - 2020-01-06\n~~~~~~~~~~~~~~~~~\n\n* Add type hints (`#191 `__)\n\n* Add proper trove classifiers for PyPy support (`#198 `__)\n\n* Scale back depending on ``ctypes`` for manylinux support detection (`#171 `__)\n\n* Use ``sys.implementation.name`` where appropriate for ``packaging.tags`` (`#193 `__)\n\n* Expand upon the API provided by ``packaging.tags``: ``interpreter_name()``, ``mac_platforms()``, ``compatible_tags()``, ``cpython_tags()``, ``generic_tags()`` (`#187 `__)\n\n* Officially support Python 3.8 (`#232 `__)\n\n* Add ``major``, ``minor``, and ``micro`` aliases to ``packaging.version.Version`` (`#226 `__)\n\n* Properly mark ``packaging`` has being fully typed by adding a `py.typed` file (`#226 `__)\n\n19.2 - 2019-09-18\n~~~~~~~~~~~~~~~~~\n\n* Remove dependency on ``attrs`` (`#178 `__, `#179 `__)\n\n* Use appropriate fallbacks for CPython ABI tag (`#181 `__, `#185 `__)\n\n* Add manylinux2014 support (`#186 `__)\n\n* Improve ABI detection (`#181 `__)\n\n* Properly handle debug wheels for Python 3.8 (`#172 `__)\n\n* Improve detection of debug builds on Windows (`#194 `__)\n\n19.1 - 2019-07-30\n~~~~~~~~~~~~~~~~~\n\n* Add the ``packaging.tags`` module. (`#156 `__)\n\n* Correctly handle two-digit versions in ``python_version`` (`#119 `__)\n\n\n19.0 - 2019-01-20\n~~~~~~~~~~~~~~~~~\n\n* Fix string representation of PEP 508 direct URL requirements with markers.\n\n* Better handling of file URLs\n\n This allows for using ``file:///absolute/path``, which was previously\n prevented due to the missing ``netloc``.\n\n This allows for all file URLs that ``urlunparse`` turns back into the\n original URL to be valid.\n\n\n18.0 - 2018-09-26\n~~~~~~~~~~~~~~~~~\n\n* Improve error messages when invalid requirements are given. (`#129 `__)\n\n\n17.1 - 2017-02-28\n~~~~~~~~~~~~~~~~~\n\n* Fix ``utils.canonicalize_version`` when supplying non PEP 440 versions.\n\n\n17.0 - 2017-02-28\n~~~~~~~~~~~~~~~~~\n\n* Drop support for python 2.6, 3.2, and 3.3.\n\n* Define minimal pyparsing version to 2.0.2 (`#91 `__).\n\n* Add ``epoch``, ``release``, ``pre``, ``dev``, and ``post`` attributes to\n ``Version`` and ``LegacyVersion`` (`#34 `__).\n\n* Add ``Version().is_devrelease`` and ``LegacyVersion().is_devrelease`` to\n make it easy to determine if a release is a development release.\n\n* Add ``utils.canonicalize_version`` to canonicalize version strings or\n ``Version`` instances (`#121 `__).\n\n\n16.8 - 2016-10-29\n~~~~~~~~~~~~~~~~~\n\n* Fix markers that utilize ``in`` so that they render correctly.\n\n* Fix an erroneous test on Python RC releases.\n\n\n16.7 - 2016-04-23\n~~~~~~~~~~~~~~~~~\n\n* Add support for the deprecated ``python_implementation`` marker which was\n an undocumented setuptools marker in addition to the newer markers.\n\n\n16.6 - 2016-03-29\n~~~~~~~~~~~~~~~~~\n\n* Add support for the deprecated, PEP 345 environment markers in addition to\n the newer markers.\n\n\n16.5 - 2016-02-26\n~~~~~~~~~~~~~~~~~\n\n* Fix a regression in parsing requirements with whitespaces between the comma\n separators.\n\n\n16.4 - 2016-02-22\n~~~~~~~~~~~~~~~~~\n\n* Fix a regression in parsing requirements like ``foo (==4)``.\n\n\n16.3 - 2016-02-21\n~~~~~~~~~~~~~~~~~\n\n* Fix a bug where ``packaging.requirements:Requirement`` was overly strict when\n matching legacy requirements.\n\n\n16.2 - 2016-02-09\n~~~~~~~~~~~~~~~~~\n\n* Add a function that implements the name canonicalization from PEP 503.\n\n\n16.1 - 2016-02-07\n~~~~~~~~~~~~~~~~~\n\n* Implement requirement specifiers from PEP 508.\n\n\n16.0 - 2016-01-19\n~~~~~~~~~~~~~~~~~\n\n* Relicense so that packaging is available under *either* the Apache License,\n Version 2.0 or a 2 Clause BSD license.\n\n* Support installation of packaging when only distutils is available.\n\n* Fix ``==`` comparison when there is a prefix and a local version in play.\n (`#41 `__).\n\n* Implement environment markers from PEP 508.\n\n\n15.3 - 2015-08-01\n~~~~~~~~~~~~~~~~~\n\n* Normalize post-release spellings for rev/r prefixes. `#35 `__\n\n\n15.2 - 2015-05-13\n~~~~~~~~~~~~~~~~~\n\n* Fix an error where the arbitrary specifier (``===``) was not correctly\n allowing pre-releases when it was being used.\n\n* Expose the specifier and version parts through properties on the\n ``Specifier`` classes.\n\n* Allow iterating over the ``SpecifierSet`` to get access to all of the\n ``Specifier`` instances.\n\n* Allow testing if a version is contained within a specifier via the ``in``\n operator.\n\n\n15.1 - 2015-04-13\n~~~~~~~~~~~~~~~~~\n\n* Fix a logic error that was causing inconsistent answers about whether or not\n a pre-release was contained within a ``SpecifierSet`` or not.\n\n\n15.0 - 2015-01-02\n~~~~~~~~~~~~~~~~~\n\n* Add ``Version().is_postrelease`` and ``LegacyVersion().is_postrelease`` to\n make it easy to determine if a release is a post release.\n\n* Add ``Version().base_version`` and ``LegacyVersion().base_version`` to make\n it easy to get the public version without any pre or post release markers.\n\n* Support the update to PEP 440 which removed the implied ``!=V.*`` when using\n either ``>V`` or ``V`` or ````) operator.\n\n\n14.3 - 2014-11-19\n~~~~~~~~~~~~~~~~~\n\n* **BACKWARDS INCOMPATIBLE** Refactor specifier support so that it can sanely\n handle legacy specifiers as well as PEP 440 specifiers.\n\n* **BACKWARDS INCOMPATIBLE** Move the specifier support out of\n ``packaging.version`` into ``packaging.specifiers``.\n\n\n14.2 - 2014-09-10\n~~~~~~~~~~~~~~~~~\n\n* Add prerelease support to ``Specifier``.\n* Remove the ability to do ``item in Specifier()`` and replace it with\n ``Specifier().contains(item)`` in order to allow flags that signal if a\n prerelease should be accepted or not.\n* Add a method ``Specifier().filter()`` which will take an iterable and returns\n an iterable with items that do not match the specifier filtered out.\n\n\n14.1 - 2014-09-08\n~~~~~~~~~~~~~~~~~\n\n* Allow ``LegacyVersion`` and ``Version`` to be sorted together.\n* Add ``packaging.version.parse()`` to enable easily parsing a version string\n as either a ``Version`` or a ``LegacyVersion`` depending on it's PEP 440\n validity.\n\n\n14.0 - 2014-09-05\n~~~~~~~~~~~~~~~~~\n\n* Initial release.\n\n\n.. _`master`: https://github.com/pypa/packaging/\n\n\n", + "release_date": null, + "parties": [], + "keywords": null, + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "bsd-simplified OR apache-2.0", + "declared_license_expression_spdx": "BSD-2-Clause OR Apache-2.0", + "license_detections": [ + { + "license_expression": "bsd-simplified OR apache-2.0", + "license_expression_spdx": "BSD-2-Clause OR Apache-2.0", + "matches": [ + { + "license_expression": "bsd-simplified OR apache-2.0", + "spdx_license_expression": "BSD-2-Clause OR Apache-2.0", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 7, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-bsd_simplified_or_apache_2_0-4e6ba7864502b4956354d47c70173db3283d1005", + "rule_url": null, + "matched_text": "BSD-2-Clause or Apache-2.0" + } + ], + "identifier": "bsd_simplified_or_apache_2_0-dd30dee1-b8d2-187f-c9f9-69fd2ff5e39a" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "BSD-2-Clause or Apache-2.0", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:pypi/pyparsing", + "extracted_requirement": "pyparsing>=2.0.2", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/packaging@21.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pip@24.1", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "pip", + "version": "24.1", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "pip - The Python Package Installer\n==================================\n\n.. |pypi-version| image:: https://img.shields.io/pypi/v/pip.svg\n :target: https://pypi.org/project/pip/\n :alt: PyPI\n\n.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pip\n :target: https://pypi.org/project/pip\n :alt: PyPI - Python Version\n\n.. |docs-badge| image:: https://readthedocs.org/projects/pip/badge/?version=latest\n :target: https://pip.pypa.io/en/latest\n :alt: Documentation\n\n|pypi-version| |python-versions| |docs-badge|\n\npip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.\n\nPlease take a look at our documentation for how to install and use pip:\n\n* `Installation`_\n* `Usage`_\n\nWe release updates regularly, with a new version every 3 months. Find more details in our documentation:\n\n* `Release notes`_\n* `Release process`_\n\nIf you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:\n\n* `Issue tracking`_\n* `Discourse channel`_\n* `User IRC`_\n\nIf you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms:\n\n* `GitHub page`_\n* `Development documentation`_\n* `Development IRC`_\n\nCode of Conduct\n---------------\n\nEveryone interacting in the pip project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _package installer: https://packaging.python.org/guides/tool-recommendations/\n.. _Python Package Index: https://pypi.org\n.. _Installation: https://pip.pypa.io/en/stable/installation/\n.. _Usage: https://pip.pypa.io/en/stable/\n.. _Release notes: https://pip.pypa.io/en/stable/news.html\n.. _Release process: https://pip.pypa.io/en/latest/development/release-process/\n.. _GitHub page: https://github.com/pypa/pip\n.. _Development documentation: https://pip.pypa.io/en/latest/development\n.. _Issue tracking: https://github.com/pypa/pip/issues\n.. _Discourse channel: https://discuss.python.org/c/packaging\n.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa\n.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n", + "release_date": null, + "parties": [], + "keywords": null, + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "spdx_license_expression": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 1, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-mit-5da48780aba670b0860c46d899ed42a0f243ff06", + "rule_url": null, + "matched_text": "MIT" + } + ], + "identifier": "mit-a822f434-d61f-f2b1-c792-8b8cb9e7b9bf" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/pip@24.1" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyparsing@2.4.7", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "pyparsing", + "version": "2.4.7", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "PyParsing -- A Python Parsing Module\n====================================\n\n|Build Status|\n\nIntroduction\n============\n\nThe pyparsing module is an alternative approach to creating and\nexecuting simple grammars, vs. the traditional lex/yacc approach, or the\nuse of regular expressions. The pyparsing module provides a library of\nclasses that client code uses to construct the grammar directly in\nPython code.\n\n*[Since first writing this description of pyparsing in late 2003, this\ntechnique for developing parsers has become more widespread, under the\nname Parsing Expression Grammars - PEGs. See more information on PEGs at*\nhttps://en.wikipedia.org/wiki/Parsing_expression_grammar *.]*\n\nHere is a program to parse ``\"Hello, World!\"`` (or any greeting of the form\n``\"salutation, addressee!\"``):\n\n.. code:: python\n\n from pyparsing import Word, alphas\n greet = Word(alphas) + \",\" + Word(alphas) + \"!\"\n hello = \"Hello, World!\"\n print(hello, \"->\", greet.parseString(hello))\n\nThe program outputs the following::\n\n Hello, World! -> ['Hello', ',', 'World', '!']\n\nThe Python representation of the grammar is quite readable, owing to the\nself-explanatory class names, and the use of '+', '|' and '^' operator\ndefinitions.\n\nThe parsed results returned from ``parseString()`` can be accessed as a\nnested list, a dictionary, or an object with named attributes.\n\nThe pyparsing module handles some of the problems that are typically\nvexing when writing text parsers:\n\n- extra or missing whitespace (the above program will also handle ``\"Hello,World!\"``, ``\"Hello , World !\"``, etc.)\n- quoted strings\n- embedded comments\n\nThe examples directory includes a simple SQL parser, simple CORBA IDL\nparser, a config file parser, a chemical formula parser, and a four-\nfunction algebraic notation parser, among many others.\n\nDocumentation\n=============\n\nThere are many examples in the online docstrings of the classes\nand methods in pyparsing. You can find them compiled into online docs\nat https://pyparsing-docs.readthedocs.io/en/latest/. Additional\ndocumentation resources and project info are listed in the online\nGitHub wiki, at https://github.com/pyparsing/pyparsing/wiki. An\nentire directory of examples is at\nhttps://github.com/pyparsing/pyparsing/tree/master/examples.\n\nLicense\n=======\n\nMIT License. See header of pyparsing.py\n\nHistory\n=======\n\nSee CHANGES file.\n\n.. |Build Status| image:: https://travis-ci.org/pyparsing/pyparsing.svg?branch=master\n :target: https://travis-ci.org/pyparsing/pyparsing\n\n\n", + "release_date": null, + "parties": [], + "keywords": null, + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "spdx_license_expression": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 2, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "mit_14.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mit_14.RULE", + "matched_text": "MIT License" + } + ], + "identifier": "mit-9967e727-165e-9bb5-f090-7de5e47a3929" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "MIT License", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/pyparsing@2.4.7" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/semantic-version@2.8.5", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "semantic-version", + "version": "2.8.5", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "python-semanticversion\n======================\n\nThis small python library provides a few tools to handle `SemVer`_ in Python.\nIt follows strictly the 2.0.0 version of the SemVer scheme.\n\n.. image:: https://secure.travis-ci.org/rbarrois/python-semanticversion.png?branch=master\n :target: http://travis-ci.org/rbarrois/python-semanticversion/\n\n.. image:: https://img.shields.io/pypi/v/semantic_version.svg\n :target: https://python-semanticversion.readthedocs.io/en/latest/changelog.html\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: Supported Python versions\n\n.. image:: https://img.shields.io/pypi/wheel/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: Wheel status\n\n.. image:: https://img.shields.io/pypi/l/semantic_version.svg\n :target: https://pypi.python.org/pypi/semantic_version/\n :alt: License\n\nLinks\n-----\n\n- Package on `PyPI`_: http://pypi.python.org/pypi/semantic_version/\n- Doc on `ReadTheDocs `_: https://python-semanticversion.readthedocs.io/\n- Source on `GitHub `_: http://github.com/rbarrois/python-semanticversion/\n- Build on `Travis CI `_: http://travis-ci.org/rbarrois/python-semanticversion/\n- Semantic Version specification: `SemVer`_\n\n\nGetting started\n===============\n\nInstall the package from `PyPI`_, using pip:\n\n.. code-block:: sh\n\n pip install semantic_version\n\nOr from GitHub:\n\n.. code-block:: sh\n\n $ git clone git://github.com/rbarrois/python-semanticversion.git\n\n\nImport it in your code:\n\n\n.. code-block:: python\n\n import semantic_version\n\n\n\nThis module provides classes to handle semantic versions:\n\n- ``Version`` represents a version number (``0.1.1-alpha+build.2012-05-15``)\n- ``BaseSpec``-derived classes represent requirement specifications (``>=0.1.1,<0.3.0``):\n\n - ``SimpleSpec`` describes a natural description syntax\n - ``NpmSpec`` is used for NPM-style range descriptions.\n\nVersions\n--------\n\nDefining a ``Version`` is quite simple:\n\n\n.. code-block:: pycon\n\n >>> import semantic_version\n >>> v = semantic_version.Version('0.1.1')\n >>> v.major\n 0\n >>> v.minor\n 1\n >>> v.patch\n 1\n >>> v.prerelease\n []\n >>> v.build\n []\n >>> list(v)\n [0, 1, 1, [], []]\n\nIf the provided version string is invalid, a ``ValueError`` will be raised:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version('0.1')\n Traceback (most recent call last):\n File \"\", line 1, in \n File \"/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py\", line 64, in __init__\n major, minor, patch, prerelease, build = self.parse(version_string, partial)\n File \"/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py\", line 86, in parse\n raise ValueError('Invalid version string: %r' % version_string)\n ValueError: Invalid version string: '0.1'\n\n\nObviously, ``Versions`` can be compared:\n\n\n.. code-block:: pycon\n\n >>> semantic_version.Version('0.1.1') < semantic_version.Version('0.1.2')\n True\n >>> semantic_version.Version('0.1.1') > semantic_version.Version('0.1.1-alpha')\n True\n >>> semantic_version.Version('0.1.1') <= semantic_version.Version('0.1.1-alpha')\n False\n\nYou can also get a new version that represents a bump in one of the version levels:\n\n.. code-block:: pycon\n\n >>> v = semantic_version.Version('0.1.1+build')\n >>> new_v = v.next_major()\n >>> str(new_v)\n '1.0.0'\n >>> v = semantic_version.Version('1.1.1+build')\n >>> new_v = v.next_minor()\n >>> str(new_v)\n '1.2.0'\n >>> v = semantic_version.Version('1.1.1+build')\n >>> new_v = v.next_patch()\n >>> str(new_v)\n '1.1.2'\n\nIt is also possible to check whether a given string is a proper semantic version string:\n\n\n.. code-block:: pycon\n\n >>> semantic_version.validate('0.1.3')\n True\n >>> semantic_version.validate('0a2')\n False\n\n\nFinally, one may create a ``Version`` with named components instead:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version(major=0, minor=1, patch=2)\n Version('0.1.2')\n\nIn that case, ``major``, ``minor`` and ``patch`` are mandatory, and must be integers.\n``prerelease`` and ``patch``, if provided, must be tuples of strings:\n\n.. code-block:: pycon\n\n >>> semantic_version.Version(major=0, minor=1, patch=2, prerelease=('alpha', '2'))\n Version('0.1.2-alpha.2')\n\n\nRequirement specification\n-------------------------\n\nThe ``SimpleSpec`` object describes a range of accepted versions:\n\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.1') # At least 0.1.1\n >>> s.match(Version('0.1.1'))\n True\n >>> s.match(Version('0.1.1-alpha1')) # pre-release doesn't satisfy version spec\n False\n >>> s.match(Version('0.1.0'))\n False\n\nSimpler test syntax is also available using the ``in`` keyword:\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('==0.1.1')\n >>> Version('0.1.1-alpha1') in s\n True\n >>> Version('0.1.2') in s\n False\n\n\nCombining specifications can be expressed as follows:\n\n .. code-block:: pycon\n\n >>> SimpleSpec('>=0.1.1,<0.3.0')\n\n\nUsing a specification\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThe ``SimpleSpec.filter`` method filters an iterable of ``Version``:\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.0,<0.4.0')\n >>> versions = (Version('0.%d.0' % i) for i in range(6))\n >>> for v in s.filter(versions):\n ... print v\n 0.1.0\n 0.2.0\n 0.3.0\n\nIt is also possible to select the 'best' version from such iterables:\n\n\n.. code-block:: pycon\n\n >>> s = SimpleSpec('>=0.1.0,<0.4.0')\n >>> versions = (Version('0.%d.0' % i) for i in range(6))\n >>> s.select(versions)\n Version('0.3.0')\n\n\nCoercing an arbitrary version string\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nSome user-supplied input might not match the semantic version scheme.\nFor such cases, the ``Version.coerce`` method will try to convert any\nversion-like string into a valid semver version:\n\n.. code-block:: pycon\n\n >>> Version.coerce('0')\n Version('0.0.0')\n >>> Version.coerce('0.1.2.3.4')\n Version('0.1.2+3.4')\n >>> Version.coerce('0.1.2a3')\n Version('0.1.2-a3')\n\n\nIncluding pre-release identifiers in specifications\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nWhen testing a ``Version`` against a ``SimpleSpec``, comparisons are\nadjusted for common user expectations; thus, a pre-release version (``1.0.0-alpha``)\nwill not satisfy the ``==1.0.0`` ``SimpleSpec``.\n\nPre-release identifiers will only be compared if included in the ``BaseSpec``\ndefinition or (for the empty pre-release number) if a single dash is appended\n(``1.0.0-``):\n\n\n.. code-block:: pycon\n\n >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0') # No pre-release identifier\n False\n >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0-') # Include pre-release in checks\n True\n\n\nIncluding build metadata in specifications\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nBuild metadata has no ordering; thus, the only meaningful comparison including\nbuild metadata is equality.\n\n\n.. code-block:: pycon\n\n >>> Version('1.0.0+build2') in SimpleSpec('<=1.0.0') # Build metadata ignored\n True\n >>> Version('1.0.0+build1') in SimpleSpec('==1.0.0+build2') # Include build in checks\n False\n\n\nNPM-based ranges\n----------------\n\nThe ``NpmSpec`` class handles NPM-style ranges:\n\n.. code-block:: pycon\n\n >>> Version('1.2.3') in NpmSpec('1.2.2 - 1.4')\n True\n >>> Version('1.2.3') in NpmSpec('<1.x || >=1.2.3')\n True\n\nRefer to https://docs.npmjs.com/misc/semver.html for a detailed description of NPM\nrange syntax.\n\n\nUsing with Django\n=================\n\nThe ``semantic_version.django_fields`` module provides django fields to\nstore ``Version`` or ``BaseSpec`` objects.\n\nMore documentation is available in the ``django`` section.\n\n\nContributing\n============\n\nIn order to contribute to the source code:\n\n- Open an issue on `GitHub`_: https://github.com/rbarrois/python-semanticversion/issues\n- Fork the `repository `_\n and submit a pull request on `GitHub`_\n- Or send me a patch (mailto:raphael.barrois+semver@polytechnique.org)\n\nWhen submitting patches or pull requests, you should respect the following rules:\n\n- Coding conventions are based on ``8``\n- The whole test suite must pass after adding the changes\n- The test coverage for a new feature must be 100%\n- New features and methods should be documented in the ``reference`` section\n and included in the ``changelog``\n- Include your name in the ``contributors`` section\n\n.. note:: All files should contain the following header::\n\n # -*- encoding: utf-8 -*-\n # Copyright (c) The python-semanticversion project\n\n\nContents\n========\n\n :maxdepth: 2\n\n reference\n django\n changelog\n credits\n\n\n.. _SemVer: http://semver.org/\n.. _PyPI: http://pypi.python.org/\n\nIndices and tables\n==================\n\n* ``genindex``\n* ``modindex``\n* ``search``\n\n\n\n", + "release_date": null, + "parties": [], + "keywords": [ + "semantic version", + "versioning", + "version" + ], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "bsd-new", + "declared_license_expression_spdx": "BSD-3-Clause", + "license_detections": [ + { + "license_expression": "bsd-new", + "license_expression_spdx": "BSD-3-Clause", + "matches": [ + { + "license_expression": "bsd-new", + "spdx_license_expression": "BSD-3-Clause", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 99.0, + "matched_length": 2, + "match_coverage": 100.0, + "rule_relevance": 99, + "rule_identifier": "bsd-new_89.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/bsd-new_89.RULE", + "matched_text": "license BSD" + } + ], + "identifier": "bsd_new-261898a0-0118-87c4-7092-14e4ff134882" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "BSD", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/semantic-version@2.8.5" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/semver@2.13.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "semver", + "version": "2.13.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "Quickstart\n==========\n\n.. teaser-begin\n\nA Python module for `semantic versioning`_. Simplifies comparing versions.\n\n|build-status| |python-support| |downloads| |license| |docs| |black|\n\n.. teaser-end\n\n.. warning::\n\n As anything comes to an end, this project will focus on Python 3.x only.\n New features and bugfixes will be integrated into the 3.x.y branch only.\n\n Major version 3 of semver will contain some incompatible changes:\n\n * removes support for Python 2.7 and 3.3\n * removes deprecated functions.\n\n The last version of semver which supports Python 2.7 and 3.4 will be\n 2.10.x. However, keep in mind, version 2.10.x is frozen: no new\n features nor backports will be integrated.\n\n We recommend to upgrade your workflow to Python 3.x to gain support,\n bugfixes, and new features.\n\nThe module follows the ``MAJOR.MINOR.PATCH`` style:\n\n* ``MAJOR`` version when you make incompatible API changes,\n* ``MINOR`` version when you add functionality in a backwards compatible manner, and\n* ``PATCH`` version when you make backwards compatible bug fixes.\n\nAdditional labels for pre-release and build metadata are supported.\n\nTo import this library, use:\n\n.. code-block:: python\n\n >>> import semver\n\nWorking with the library is quite straightforward. To turn a version string into the\ndifferent parts, use the ``semver.VersionInfo.parse`` function:\n\n.. code-block:: python\n\n >>> ver = semver.VersionInfo.parse('1.2.3-pre.2+build.4')\n >>> ver.major\n 1\n >>> ver.minor\n 2\n >>> ver.patch\n 3\n >>> ver.prerelease\n 'pre.2'\n >>> ver.build\n 'build.4'\n\nTo raise parts of a version, there are a couple of functions available for\nyou. The function ``semver.VersionInfo.bump_major`` leaves the original object untouched, but\nreturns a new ``semver.VersionInfo`` instance with the raised major part:\n\n.. code-block:: python\n\n >>> ver = semver.VersionInfo.parse(\"3.4.5\")\n >>> ver.bump_major()\n VersionInfo(major=4, minor=0, patch=0, prerelease=None, build=None)\n\nIt is allowed to concatenate different \"bump functions\":\n\n.. code-block:: python\n\n >>> ver.bump_major().bump_minor()\n VersionInfo(major=4, minor=1, patch=0, prerelease=None, build=None)\n\nTo compare two versions, semver provides the ``semver.compare`` function.\nThe return value indicates the relationship between the first and second\nversion:\n\n.. code-block:: python\n\n >>> semver.compare(\"1.0.0\", \"2.0.0\")\n -1\n >>> semver.compare(\"2.0.0\", \"1.0.0\")\n 1\n >>> semver.compare(\"2.0.0\", \"2.0.0\")\n 0\n\n\nThere are other functions to discover. Read on!\n\n\n.. |latest-version| image:: https://img.shields.io/pypi/v/semver.svg\n :alt: Latest version on PyPI\n :target: https://pypi.org/project/semver\n.. |build-status| image:: https://travis-ci.com/python-semver/python-semver.svg?branch=master\n :alt: Build status\n :target: https://travis-ci.com/python-semver/python-semver\n.. |python-support| image:: https://img.shields.io/pypi/pyversions/semver.svg\n :target: https://pypi.org/project/semver\n :alt: Python versions\n.. |downloads| image:: https://img.shields.io/pypi/dm/semver.svg\n :alt: Monthly downloads from PyPI\n :target: https://pypi.org/project/semver\n.. |license| image:: https://img.shields.io/pypi/l/semver.svg\n :alt: Software license\n :target: https://github.com/python-semver/python-semver/blob/master/LICENSE.txt\n.. |docs| image:: https://readthedocs.org/projects/python-semver/badge/?version=latest\n :target: http://python-semver.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n.. _semantic versioning: http://semver.org/\n.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Black Formatter\n\n\n", + "release_date": null, + "parties": [], + "keywords": null, + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "bsd-new", + "declared_license_expression_spdx": "BSD-3-Clause", + "license_detections": [ + { + "license_expression": "bsd-new", + "license_expression_spdx": "BSD-3-Clause", + "matches": [ + { + "license_expression": "bsd-new", + "spdx_license_expression": "BSD-3-Clause", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 99.0, + "matched_length": 2, + "match_coverage": 100.0, + "rule_relevance": 99, + "rule_identifier": "bsd-new_89.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/bsd-new_89.RULE", + "matched_text": "license BSD" + } + ], + "identifier": "bsd_new-261898a0-0118-87c4-7092-14e4ff134882" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "BSD", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/semver@2.13.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/setuptools@70.1.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "setuptools", + "version": "70.1.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": ".. |pypi-version| image:: https://img.shields.io/pypi/v/setuptools.svg\n :target: https://pypi.org/project/setuptools\n\n.. |py-version| image:: https://img.shields.io/pypi/pyversions/setuptools.svg\n\n.. |test-badge| image:: https://github.com/pypa/setuptools/actions/workflows/main.yml/badge.svg\n :target: https://github.com/pypa/setuptools/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. |ruff-badge| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. |docs-badge| image:: https://img.shields.io/readthedocs/setuptools/latest.svg\n :target: https://setuptools.pypa.io\n\n.. |skeleton-badge| image:: https://img.shields.io/badge/skeleton-2024-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. |codecov-badge| image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white\n :target: https://codecov.io/gh/pypa/setuptools\n\n.. |tidelift-badge| image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat\n :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme\n\n.. |discord-badge| image:: https://img.shields.io/discord/803025117553754132\n :target: https://discord.com/channels/803025117553754132/815945031150993468\n :alt: Discord\n\n|pypi-version| |py-version| |test-badge| |ruff-badge| |docs-badge| |skeleton-badge| |codecov-badge| |discord-badge|\n\nSee the `Quickstart `_\nand the `User's Guide `_ for\ninstructions on how to use Setuptools.\n\nQuestions and comments should be directed to `GitHub Discussions\n`_.\nBug reports and especially tested patches may be\nsubmitted directly to the `bug tracker\n`_.\n\n\nCode of Conduct\n===============\n\nEveryone interacting in the setuptools project's codebases, issue trackers,\nchat rooms, and fora is expected to follow the\n`PSF Code of Conduct `_.\n\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nSetuptools and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n", + "release_date": null, + "parties": [], + "keywords": [ + "CPAN", + "PyPI", + "distutils", + "eggs", + "package", + "management" + ], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:pypi/sphinx", + "extracted_requirement": "sphinx>=3.5; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-packaging", + "extracted_requirement": "jaraco.packaging>=9.3; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/rst-linker", + "extracted_requirement": "rst.linker>=1.9; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/furo", + "extracted_requirement": "furo; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-lint", + "extracted_requirement": "sphinx-lint; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-tidelift", + "extracted_requirement": "jaraco.tidelift>=1.4; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pygments-github-lexers@0.0.5", + "extracted_requirement": "pygments-github-lexers==0.0.5; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-favicon", + "extracted_requirement": "sphinx-favicon; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-inline-tabs", + "extracted_requirement": "sphinx-inline-tabs; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-reredirects", + "extracted_requirement": "sphinx-reredirects; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinxcontrib-towncrier", + "extracted_requirement": "sphinxcontrib-towncrier; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-notfound-page", + "extracted_requirement": "sphinx-notfound-page<2,>=1; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyproject-hooks", + "extracted_requirement": "pyproject-hooks!=1.1; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest!=8.1.1,>=6; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-checkdocs", + "extracted_requirement": "pytest-checkdocs>=2.4; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-mypy", + "extracted_requirement": "pytest-mypy; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-enabler", + "extracted_requirement": "pytest-enabler>=2.2; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/virtualenv", + "extracted_requirement": "virtualenv>=13.0.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/wheel", + "extracted_requirement": "wheel; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pip", + "extracted_requirement": "pip>=19.1; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/packaging", + "extracted_requirement": "packaging>=23.2; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-envs", + "extracted_requirement": "jaraco.envs>=2.2; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-xdist", + "extracted_requirement": "pytest-xdist>=3; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-path", + "extracted_requirement": "jaraco.path>=3.2.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/build", + "extracted_requirement": "build[virtualenv]>=1.0.3; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/filelock", + "extracted_requirement": "filelock>=3.4.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/ini2toml", + "extracted_requirement": "ini2toml[lite]>=0.14; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/tomli-w", + "extracted_requirement": "tomli-w>=1.0.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-timeout", + "extracted_requirement": "pytest-timeout; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-home", + "extracted_requirement": "pytest-home>=0.5; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/mypy@1.10.0", + "extracted_requirement": "mypy==1.10.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": true, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/tomli", + "extracted_requirement": "tomli; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/importlib-metadata", + "extracted_requirement": "importlib-metadata; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-subprocess", + "extracted_requirement": "pytest-subprocess; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pyproject-hooks", + "extracted_requirement": "pyproject-hooks!=1.1; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-test", + "extracted_requirement": "jaraco.test; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-cov", + "extracted_requirement": "pytest-cov; platform_python_implementation != \"PyPy\" and extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/jaraco-develop", + "extracted_requirement": "jaraco.develop>=7.21; (python_version >= \"3.9\" and sys_platform != \"cygwin\") and extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-ruff", + "extracted_requirement": "pytest-ruff>=0.3.2; sys_platform != \"cygwin\" and extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-perf", + "extracted_requirement": "pytest-perf; sys_platform != \"cygwin\" and extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/setuptools@70.1.0" + }, + "extra_data": {} + }, + { + "purl": "pkg:pypi/attrs", + "extracted_requirement": "attrs", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/packaging", + "extracted_requirement": "packaging", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/semantic-version", + "extracted_requirement": "semantic-version", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/semver", + "extracted_requirement": "semver", + "scope": "install", + "is_runtime": true, + "is_optional": false, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx", + "extracted_requirement": "Sphinx>=5.0.2; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-rtd-theme", + "extracted_requirement": "sphinx-rtd-theme>=1.0.0; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/sphinx-reredirects", + "extracted_requirement": "sphinx-reredirects>=0.1.2; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/doc8", + "extracted_requirement": "doc8>=0.11.2; extra == \"docs\"", + "scope": "docs", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest!=7.0.0,>=6; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pytest-xdist", + "extracted_requirement": "pytest-xdist>=2; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/aboutcode-toolkit", + "extracted_requirement": "aboutcode-toolkit>=7.0.2; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/pycodestyle", + "extracted_requirement": "pycodestyle>=2.8.0; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/twine", + "extracted_requirement": "twine; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/black", + "extracted_requirement": "black; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/commoncode", + "extracted_requirement": "commoncode; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/isort", + "extracted_requirement": "isort>=5.10.1; extra == \"testing\"", + "scope": "testing", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/wheel@0.43.0", + "extracted_requirement": null, + "scope": null, + "is_runtime": true, + "is_optional": false, + "is_resolved": true, + "is_direct": false, + "resolved_package": { + "type": "pypi", + "namespace": null, + "name": "wheel", + "version": "0.43.0", + "qualifiers": {}, + "subpath": null, + "primary_language": "Python", + "description": "wheel\n=====\n\nThis library is the reference implementation of the Python wheel packaging\nstandard, as defined in `PEP 427`_.\n\nIt has two different roles:\n\n#. A setuptools_ extension for building wheels that provides the\n ``bdist_wheel`` setuptools command\n#. A command line tool for working with wheel files\n\nIt should be noted that wheel is **not** intended to be used as a library, and\nas such there is no stable, public API.\n\n.. _PEP 427: https://www.python.org/dev/peps/pep-0427/\n.. _setuptools: https://pypi.org/project/setuptools/\n\nDocumentation\n-------------\n\nThe documentation_ can be found on Read The Docs.\n\n.. _documentation: https://wheel.readthedocs.io/\n\nCode of Conduct\n---------------\n\nEveryone interacting in the wheel project's codebases, issue trackers, chat\nrooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.\n\n.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md\n\n", + "release_date": null, + "parties": [], + "keywords": [ + "wheel", + "packaging" + ], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": true, + "extra_data": {}, + "dependencies": [ + { + "purl": "pkg:pypi/pytest", + "extracted_requirement": "pytest>=6.0.0; extra == \"test\"", + "scope": "test", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + }, + { + "purl": "pkg:pypi/setuptools", + "extracted_requirement": "setuptools>=65; extra == \"test\"", + "scope": "test", + "is_runtime": true, + "is_optional": true, + "is_resolved": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/wheel@0.43.0" + }, + "extra_data": {} + } + ], + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null, + "datasource_id": "pypi_inspect_deplock", + "purl": "pkg:pypi/univers@0.0.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/test_pypi.py b/tests/packagedcode/test_pypi.py index 1bf786b11fc..a315dd19e1d 100644 --- a/tests/packagedcode/test_pypi.py +++ b/tests/packagedcode/test_pypi.py @@ -349,6 +349,20 @@ def test_parse_pyproject_toml_poetry_gino(self): self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) +class TestPipInspectDeplockHandler(PackageTester): + test_data_dir = os.path.join(os.path.dirname(__file__), 'data') + + def test_is_pip_inspect_deplock(self): + test_file = self.get_test_loc('pypi/deplock/univers/pip-inspect.deplock') + assert pypi.PipInspectDeplockHandler.is_datafile(test_file) + + def test_parse_pip_inspect_deplock_univers(self): + test_file = self.get_test_loc('pypi/deplock/univers/pip-inspect.deplock') + package = pypi.PipInspectDeplockHandler.parse(test_file) + expected_loc = self.get_test_loc('pypi/deplock/univers/pip-inspect.deplock-expected.json') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + class TestPipRequirementsFileHandler(PackageTester): test_data_dir = os.path.join(os.path.dirname(__file__), 'data')