{"id":18176469,"url":"https://github.com/aboutcode-org/license-expression","last_synced_at":"2025-12-11T23:12:42.793Z","repository":{"id":10626341,"uuid":"66389094","full_name":"aboutcode-org/license-expression","owner":"aboutcode-org","description":"Utility library  to parse, normalize and compare License expressions for Python using a boolean logic engine. For expressions using SPDX or any other license id scheme.","archived":false,"fork":false,"pushed_at":"2025-04-03T10:49:16.000Z","size":37049,"stargazers_count":66,"open_issues_count":28,"forks_count":27,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-10T02:51:52.730Z","etag":null,"topics":["boolean-expression","license-expression","licensing","python","spdx","spdx-license"],"latest_commit_sha":null,"homepage":"http://aboutcode.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","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":"license-expression.ABOUT","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":"2016-08-23T17:39:00.000Z","updated_at":"2025-04-23T09:07:05.000Z","dependencies_parsed_at":"2024-02-27T14:52:29.954Z","dependency_job_id":"45e82c58-a8df-427b-8e08-1eb9007ce4df","html_url":"https://github.com/aboutcode-org/license-expression","commit_stats":{"total_commits":511,"total_committers":29,"mean_commits":"17.620689655172413","dds":"0.34442270058708413","last_synced_commit":"265415a2651c682157bd688a251093c1e7a2ee15"},"previous_names":["aboutcode-org/license-expression"],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Flicense-expression","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Flicense-expression/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Flicense-expression/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcode-org%2Flicense-expression/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aboutcode-org","download_url":"https://codeload.github.com/aboutcode-org/license-expression/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"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":["boolean-expression","license-expression","licensing","python","spdx","spdx-license"],"created_at":"2024-11-02T17:01:13.869Z","updated_at":"2025-12-11T23:12:42.743Z","avatar_url":"https://github.com/aboutcode-org.png","language":"Python","readme":"==================\nlicense-expression\n==================\n\n``license-expression`` is a comprehensive utility library to parse, compare,\nsimplify and normalize license expressions (such as SPDX license expressions)\nusing boolean logic.\n\n- License: Apache-2.0\n- Python: 3.9+\n- Homepage: https://github.com/aboutcode-org/license-expression/\n- Install: `pip install license-expression` also available in most Linux distro.\n\nSoftware project licenses are often a combination of several free and open\nsource software licenses. License expressions -- as specified by SPDX -- provide\na concise and human readable way to express these licenses without having to\nread long license texts, while still being machine-readable.\n\nLicense expressions are used by key FOSS projects such as Linux; several\npackages ecosystem use them to document package licensing metadata such as\nnpm and Rubygems; they are important when exchanging software data (such as with\nSPDX and SBOM in general) as a way to express licensing precisely.\n\n``license-expression`` is a comprehensive utility library to parse, compare,\nsimplify and normalize these license expressions (such as SPDX license expressions)\nusing boolean logic like in: `GPL-2.0-or-later WITH Classpath-exception-2.0 AND MIT`.\n\nIt includes the license keys from SPDX https://spdx.org/licenses/ (version 3.26)\nand ScanCode LicenseDB (from scancode-toolkit version 32.3.1, last published on 2025-01-10).\nSee https://scancode-licensedb.aboutcode.org/ to get started quickly.\n\n``license-expression`` is both powerful and simple to use and is a used as the\nlicense expression engine in several projects and products such as:\n\n- AboutCode-toolkit https://github.com/aboutcode-org/aboutcode-toolkit\n- AlekSIS (School Information System) https://edugit.org/AlekSIS/official/AlekSIS-Core\n- Barista https://github.com/Optum/barista\n- Conda forge tools https://github.com/conda-forge/conda-smithy\n- DejaCode https://dejacode.com\n- DeltaCode https://github.com/nexB/deltacode\n- FenixscanX https://github.com/SmartsYoung/FenixscanX\n- FetchCode https://github.com/aboutcode-org/fetchcode\n- Flict https://github.com/vinland-technology/flict and https://github.com/vinland-technology\n- license.sh https://github.com/webscopeio/license.sh\n- liferay_inbound_checker https://github.com/carmenbianca/liferay_inbound_checker\n- REUSE https://reuse.software/ and https://github.com/fsfe/reuse-tool\n- ScanCode-io https://github.com/aboutcode-org/scancode.io\n- ScanCode-toolkit https://github.com/aboutcode-org/scancode-toolkit\n- SecObserve https://github.com/MaibornWolff/SecObserve\n\nSee also for details:\n- https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/\n\n``license-expression`` is also packaged for most Linux distributions. See below.\n\nAlternative:\n\nThere is no known alternative library for Python, but there are several similar\nlibraries in other languages (but not as powerful of course!):\n\n- JavaScript https://github.com/jslicense/spdx-expression-parse.js\n- Rust https://github.com/ehuss/license-exprs\n- Haskell https://github.com/phadej/spdx\n- Go https://github.com/kyoh86/go-spdx\n- Ada https://github.com/Fabien-Chouteau/spdx_ada\n- Java https://github.com/spdx/tools and https://github.com/aschet/spdx-license-expression-tools\n\nBuild and tests status\n======================\n\n+--------------------------+------------------------+----------------------------------+\n|**Linux \u0026 macOS (Travis)**| **Windows (AppVeyor)** |**Linux, Windows \u0026 macOS (Azure)**|\n+==========================+========================+==================================+\n|                          |                        |                                  |\n| |travis-badge-icon|      | |appveyor-badge-icon|  |   |azure-badge-icon|             |\n|                          |                        |                                  |\n+--------------------------+------------------------+----------------------------------+\n\nSource code and download\n========================\n\n- GitHub https://github.com/aboutcode-org/license-expression.git\n- PyPI https://pypi.python.org/pypi/license-expression\n\nAlso available in several Linux distros:\n\n- Arch Linux https://archlinux.org/packages/extra/any/python-license-expression/\n- Debian https://packages.debian.org/unstable/source/license-expression\n- DragonFly BSD https://github.com/DragonFlyBSD/DPorts/tree/master/textproc/py-license-expression\n- Fedora https://src.fedoraproject.org/rpms/python-license-expression/\n- FreeBSD https://www.freshports.org/textproc/py-license-expression\n- NixOS https://github.com/NixOS/nixpkgs/blob/release-21.05/pkgs/development/python-modules/license-expression/default.nix\n- openSUSE https://build.opensuse.org/package/show/openSUSE:Factory/python-license-expression\n\n\nSupport\n=======\n\n- Submit bugs and questions at: https://github.com/aboutcode-org/license-expression/issues\n- Join the chat at: https://gitter.im/aboutcode-org/discuss\n\nDescription\n===========\n\nThis module defines a mini language to parse, validate, simplify, normalize and\ncompare license expressions using a boolean logic engine.\n\nThis supports SPDX license expressions and also accepts other license naming\nconventions and license identifiers aliases to resolve and normalize any license\nexpressions.\n\nUsing boolean logic, license expressions can be tested for equality, containment,\nequivalence and can be normalized or simplified.\n\nIt also bundles the SPDX License list (3.26 as of now) and the ScanCode license\nDB (based on latest ScanCode) to easily parse and validate expressions using\nthe license symbols.\n\n\nUsage examples\n==============\n\nThe main entry point is the ``Licensing`` object that you can use to parse,\nvalidate, compare, simplify and normalize license expressions.\n\nCreate an SPDX Licensing and parse expressions::\n\n\t\u003e\u003e\u003e from license_expression import get_spdx_licensing\n\t\u003e\u003e\u003e licensing = get_spdx_licensing()\n\t\u003e\u003e\u003e expression = ' GPL-2.0 or LGPL-2.1 and mit '\n\t\u003e\u003e\u003e parsed = licensing.parse(expression)\n\t\u003e\u003e\u003e print(parsed.pretty())\n\tOR(\n\t  LicenseSymbol('GPL-2.0-only'),\n\t  AND(\n\t    LicenseSymbol('LGPL-2.1-only'),\n\t    LicenseSymbol('MIT')\n\t  )\n\t)\n\n\t\u003e\u003e\u003e str(parsed)\n\t'GPL-2.0-only OR (LGPL-2.1-only AND MIT)'\n\n\t\u003e\u003e\u003e licensing.parse('unknwon with foo', validate=True, strict=True)\n\tlicense_expression.ExpressionParseError: A plain license symbol cannot be used\n\tas an exception in a \"WITH symbol\" statement. for token: \"foo\" at position: 13\n\n\t\u003e\u003e\u003e licensing.parse('unknwon with foo', validate=True)\n\tlicense_expression.ExpressionError: Unknown license key(s): unknwon, foo\n\n\t\u003e\u003e\u003e licensing.validate('foo and MIT and GPL-2.0+')\n\tExpressionInfo(\n\t    original_expression='foo and MIT and GPL-2.0+',\n\t    normalized_expression=None,\n\t    errors=['Unknown license key(s): foo'],\n\t    invalid_symbols=['foo']\n\t)\n\n\nCreate a simple Licensing and parse expressions::\n\n    \u003e\u003e\u003e from license_expression import Licensing, LicenseSymbol\n    \u003e\u003e\u003e licensing = Licensing()\n    \u003e\u003e\u003e expression = ' GPL-2.0 or LGPL-2.1 and mit '\n    \u003e\u003e\u003e parsed = licensing.parse(expression)\n    \u003e\u003e\u003e expression = ' GPL-2.0 or LGPL-2.1 and mit '\n    \u003e\u003e\u003e expected = 'GPL-2.0-only OR (LGPL-2.1-only AND mit)'\n    \u003e\u003e\u003e assert str(parsed) == expected\n    \u003e\u003e\u003e assert parsed.render('{symbol.key}') == expected\n\n\nCreate a Licensing with your own license symbols::\n\n    \u003e\u003e\u003e expected = [\n    ...   LicenseSymbol('GPL-2.0'),\n    ...   LicenseSymbol('LGPL-2.1'),\n    ...   LicenseSymbol('mit')\n    ... ]\n    \u003e\u003e\u003e assert licensing.license_symbols(expression) == expected\n    \u003e\u003e\u003e assert licensing.license_symbols(parsed) == expected\n\n    \u003e\u003e\u003e symbols = ['GPL-2.0+', 'Classpath', 'BSD']\n    \u003e\u003e\u003e licensing = Licensing(symbols)\n    \u003e\u003e\u003e expression = 'GPL-2.0+ with Classpath or (bsd)'\n    \u003e\u003e\u003e parsed = licensing.parse(expression)\n    \u003e\u003e\u003e expected = 'GPL-2.0+ WITH Classpath OR BSD'\n    \u003e\u003e\u003e assert parsed.render('{symbol.key}') == expected\n\n    \u003e\u003e\u003e expected = [\n    ...   LicenseSymbol('GPL-2.0+'),\n    ...   LicenseSymbol('Classpath'),\n    ...   LicenseSymbol('BSD')\n    ... ]\n    \u003e\u003e\u003e assert licensing.license_symbols(parsed) == expected\n    \u003e\u003e\u003e assert licensing.license_symbols(expression) == expected\n\nAnd expression can be deduplicated, to remove duplicate license subexpressions\nwithout changing the order and without consider license choices as simplifiable::\n\n    \u003e\u003e\u003e expression2 = ' GPL-2.0 or (mit and LGPL 2.1) or bsd Or GPL-2.0  or (mit and LGPL 2.1)'\n    \u003e\u003e\u003e parsed2 = licensing.parse(expression2)\n    \u003e\u003e\u003e str(parsed2)\n    'GPL-2.0 OR (mit AND LGPL 2.1) OR BSD OR GPL-2.0 OR (mit AND LGPL 2.1)'\n    \u003e\u003e\u003e assert str(parsed2.simplify()) == 'BSD OR GPL-2.0 OR (LGPL 2.1 AND mit)'\n\nExpression can be simplified, treating them as boolean expressions::\n\n    \u003e\u003e\u003e expression2 = ' GPL-2.0 or (mit and LGPL 2.1) or bsd Or GPL-2.0  or (mit and LGPL 2.1)'\n    \u003e\u003e\u003e parsed2 = licensing.parse(expression2)\n    \u003e\u003e\u003e str(parsed2)\n    'GPL-2.0 OR (mit AND LGPL 2.1) OR BSD OR GPL-2.0 OR (mit AND LGPL 2.1)'\n    \u003e\u003e\u003e assert str(parsed2.simplify()) == 'BSD OR GPL-2.0 OR (LGPL 2.1 AND mit)'\n\nTwo expressions can be compared for equivalence and containment:\n\n    \u003e\u003e\u003e expr1 = licensing.parse(' GPL-2.0 or (LGPL 2.1 and mit) ')\n    \u003e\u003e\u003e expr2 = licensing.parse(' (mit and LGPL 2.1)  or GPL-2.0 ')\n    \u003e\u003e\u003e licensing.is_equivalent(expr1, expr2)\n    True\n    \u003e\u003e\u003e licensing.is_equivalent(' GPL-2.0 or (LGPL 2.1 and mit) ',\n    ...                         ' (mit and LGPL 2.1)  or GPL-2.0 ')\n    True\n    \u003e\u003e\u003e expr1.simplify() == expr2.simplify()\n    True\n    \u003e\u003e\u003e expr3 = licensing.parse(' GPL-2.0 or mit or LGPL 2.1')\n    \u003e\u003e\u003e licensing.is_equivalent(expr2, expr3)\n    False\n    \u003e\u003e\u003e expr4 = licensing.parse('mit and LGPL 2.1')\n    \u003e\u003e\u003e expr4.simplify() in expr2.simplify()\n    True\n    \u003e\u003e\u003e licensing.contains(expr2, expr4)\n    True\n\nDevelopment\n===========\n\n- Checkout a clone from https://github.com/aboutcode-org/license-expression.git\n\n- Then run ``./configure --dev`` and then ``source tmp/bin/activate`` on Linux and POSIX.\n  This will install all dependencies in a local virtualenv, including\n  development deps.\n\n- On Windows run  ``configure.bat --dev`` and then ``Scripts\\bin\\activate`` instead.\n\n- To run the tests, run ``pytest -vvs``\n\n\n.. |travis-badge-icon| image:: https://api.travis-ci.org/nexB/license-expression.png?branch=master\n    :target: https://travis-ci.org/nexB/license-expression\n    :alt: Travis tests status\n    :align: middle\n\n.. |appveyor-badge-icon| image:: https://ci.appveyor.com/api/projects/status/github/nexB/license-expression?svg=true\n    :target: https://ci.appveyor.com/project/nexB/license-expression\n    :alt: Appveyor tests status\n    :align: middle\n\n.. |azure-badge-icon| image:: https://dev.azure.com/nexB/license-expression/_apis/build/status/nexB.license-expression?branchName=master\n    :target: https://dev.azure.com/nexB/license-expression/_build/latest?definitionId=2\u0026branchName=master\n    :alt: Azure pipelines tests status\n    :align: middle\n\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcode-org%2Flicense-expression","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faboutcode-org%2Flicense-expression","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcode-org%2Flicense-expression/lists"}