{"id":15893115,"url":"https://github.com/aboutcode-org/univers","last_synced_at":"2025-04-04T11:17:03.178Z","repository":{"id":40248160,"uuid":"348246373","full_name":"aboutcode-org/univers","owner":"aboutcode-org","description":"Parse and compare all the package versions and all the ranges. From debian, npm, pypi, ruby and more. Process all the version range specs and expressions. This project is sponsored by an NLnet project https://nlnet.nl/project/vulnerabilitydatabase/ , the Google Summer of Code, nexB and others generous sponsors!","archived":false,"fork":false,"pushed_at":"2024-10-15T16:50:00.000Z","size":3920,"stargazers_count":34,"open_issues_count":53,"forks_count":16,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-28T09:02:22.710Z","etag":null,"topics":["dependencies","dependency-resolver","osv","package-manager","package-url","purl","version","versioning","vulnerabilities","vulnerablecode"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aboutcode-org.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.rst","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-16T07:03:43.000Z","updated_at":"2025-03-08T00:02:31.000Z","dependencies_parsed_at":"2024-06-19T09:38:34.864Z","dependency_job_id":"3a91a4a6-05ad-4846-80cf-713c7f37302d","html_url":"https://github.com/aboutcode-org/univers","commit_stats":{"total_commits":2119,"total_committers":197,"mean_commits":"10.756345177664974","dds":0.7706465313827278,"last_synced_commit":"b17189a03079d97e2afe49bf460abc443019925a"},"previous_names":["aboutcode-org/univers"],"tags_count":24,"template":false,"template_full_name":"aboutcode-org/skeleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Funivers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Funivers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Funivers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Funivers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aboutcode-org","download_url":"https://codeload.github.com/aboutcode-org/univers/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247149488,"owners_count":20891954,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependencies","dependency-resolver","osv","package-manager","package-url","purl","version","versioning","vulnerabilities","vulnerablecode"],"created_at":"2024-10-06T08:07:37.380Z","updated_at":"2025-04-04T11:17:03.158Z","avatar_url":"https://github.com/aboutcode-org.png","language":"Python","readme":"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\u0026status=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) \u003chttps://github.com/package-url\u003e`_.\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 \"\u003e=1.2.3\" as used in a Python package into ``vers:pypi/\u003e=1.2.3``,\n\n- or converting \"^1.0.2\" as used in an npm package dependency declaration into\n  ``vers:npm/\u003e=1.0.2|\u003c2.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  \u003chttps://github.com/rbarrois/python-semanticversion\u003e`_ 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 \"~\u003e\"\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  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/debian.py.ABOUT\u003e`_\n\n- debian: handled by the  `debian-inspector library\n  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/debian.py.ABOUT\u003e`_.\n\n- maven: handled by the embedded `pymaven library\n  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/pymaven.py.ABOUT\u003e`_.\n\n- rpm: handled by the embedded `rpm_vercmp library\n  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/rpm.py.ABOUT\u003e`_.\n\n- golang (using semver)\n\n- PHP composer\n\n- ebuild/gentoo: handled by the embedded `gentoo_vercmp module\n  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/gentoo.py.ABOUT\u003e`_.\n\n- arch linux: handled by the embedded `arch utility module borrowed from msys2\n  \u003chttps://github.com/aboutcode-org/univers/blob/main/src/univers/arch.py.ABOUT\u003e`_.\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\u003chttps://github.com/repology/libversion\u003e`_. ``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\") \u003c 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/\u003e=1.0.2|\u003c2.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/\u003e=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/aboutcode-org/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/aboutcode-org/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\n\nAcknowledgements, Funding, Support and Sponsoring\n--------------------------------------------------------\n\nThis project is funded, supported and sponsored by:\n\n- Generous support and contributions from users like you!\n- the European Commission NGI programme\n- the NLnet Foundation \n- the Swiss State Secretariat for Education, Research and Innovation (SERI)\n- Google, including the Google Summer of Code and the Google Seasons of Doc programmes\n- Mercedes-Benz Group\n- Microsoft and Microsoft Azure\n- AboutCode ASBL\n- nexB Inc. \n\n\n\n|europa|   |dgconnect| \n\n|ngi|   |nlnet|   \n\n|aboutcode|  |nexb|\n\n\n\nThis project was funded through the NGI0 PET Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 825310.\n\n|ngizeropet|  https://nlnet.nl/project/VulnerableCode/\n\n\nThis project was funded through the NGI0 Discovery Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 825322.\n\n|ngidiscovery| https://nlnet.nl/project/vulnerabilitydatabase/\n\n\nThis project was funded through the NGI0 Core Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 101092990.\n\n|ngizerocore| https://nlnet.nl/project/VulnerableCode-enhancements/\n\n\nThis project is funded through the NGI0 Entrust Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 101069594.\n\n|ngizeroentrust| https://nlnet.nl/project/FederatedSoftwareMetadata/\n\n\nThis project was funded through the NGI0 Commons Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 101135429. Additional\nfunding is made available by the Swiss State Secretariat for Education, Research and Innovation\n(SERI). \n\n|ngizerocommons| |swiss| https://nlnet.nl/project/FederatedCodeNext/\n\n\nThis project was funded through the NGI0 Entrust Fund, a fund established by NLnet with financial\nsupport from the European Commission's Next Generation Internet programme, under the aegis of DG\nCommunications Networks, Content and Technology under grant agreement No 101069594. \n\n|ngizeroentrust| https://nlnet.nl/project/CRAVEX/\n\n\n\n.. |nlnet| image:: https://nlnet.nl/logo/banner.png\n    :target: https://nlnet.nl\n    :height: 50\n    :alt: NLnet foundation logo\n\n.. |ngi| image:: https://ngi.eu/wp-content/uploads/thegem-logos/logo_8269bc6efcf731d34b6385775d76511d_1x.png\n    :target: https://ngi.eu35\n    :height: 50\n    :alt: NGI logo\n\n.. |nexb| image:: https://nexb.com/wp-content/uploads/2022/04/nexB.svg\n    :target: https://nexb.com\n    :height: 30\n    :alt: nexB logo\n\n.. |europa| image:: https://ngi.eu/wp-content/uploads/sites/77/2017/10/bandiera_stelle.png\n    :target: http://ec.europa.eu/index_en.htm\n    :height: 40\n    :alt: Europa logo\n\n.. |aboutcode| image:: https://aboutcode.org/wp-content/uploads/2023/10/AboutCode.svg\n    :target: https://aboutcode.org/\n    :height: 30\n    :alt: AboutCode logo\n\n.. |swiss| image:: https://www.sbfi.admin.ch/sbfi/en/_jcr_content/logo/image.imagespooler.png/1493119032540/logo.png\n    :target: https://www.sbfi.admin.ch/sbfi/en/home/seri/seri.html\n    :height: 40\n    :alt: Swiss logo\n\n.. |dgconnect| image:: https://commission.europa.eu/themes/contrib/oe_theme/dist/ec/images/logo/positive/logo-ec--en.svg\n    :target: https://commission.europa.eu/about-european-commission/departments-and-executive-agencies/communications-networks-content-and-technology_en\n    :height: 40\n    :alt: EC DG Connect logo\n\n.. |ngizerocore| image:: https://nlnet.nl/image/logos/NGI0_tag.svg\n    :target: https://nlnet.nl/core\n    :height: 40\n    :alt: NGI Zero Core Logo\n\n.. |ngizerocommons| image:: https://nlnet.nl/image/logos/NGI0_tag.svg\n    :target: https://nlnet.nl/commonsfund/\n    :height: 40\n    :alt: NGI Zero Commons Logo\n\n.. |ngizeropet| image:: https://nlnet.nl/image/logos/NGI0PET_tag.svg\n    :target: https://nlnet.nl/PET\n    :height: 40\n    :alt: NGI Zero PET logo\n\n.. |ngizeroentrust| image:: https://nlnet.nl/image/logos/NGI0Entrust_tag.svg\n    :target: https://nlnet.nl/entrust\n    :height: 38\n    :alt: NGI Zero Entrust logo\n\n.. |ngiassure| image:: https://nlnet.nl/image/logos/NGIAssure_tag.svg\n    :target: https://nlnet.nl/image/logos/NGIAssure_tag.svg\n    :height: 32\n    :alt: NGI Assure logo\n\n.. |ngidiscovery| image:: https://nlnet.nl/image/logos/NGI0Discovery_tag.svg\n    :target: https://nlnet.nl/discovery/\n    :height: 40\n    :alt: NGI Discovery logo\n\n\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcode-org%2Funivers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faboutcode-org%2Funivers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcode-org%2Funivers/lists"}