License-Expression
license-expression is a comprehensive Python utility library designed to parse, compare, simplify, and normalize license expressions, particularly SPDX license expressions, using boolean logic. It actively maintains and updates its bundled license keys from the SPDX License List and ScanCode LicenseDB, with frequent patch releases for these updates and minor releases for broader changes.
Warnings
- breaking Support for Python 3.8 was dropped in version 30.4.0. Users on Python 3.8 or older must upgrade their Python environment to Python 3.9 or newer to use the latest versions of license-expression.
- breaking Support for Python 3.7 was dropped in version 30.3.0. Users on Python 3.7 or older must upgrade their Python environment to Python 3.8 or newer (preferably 3.9+) to use these versions.
- gotcha Version 30.4.2 was released with missing wheels, which could lead to installation issues. This was corrected in version 30.4.3.
- gotcha The `get_spdx_licensing()` function, which initializes the license parsing engine, can be slow to execute due to loading license data. It is recommended to call this function once and reuse the returned `licensing` object throughout your application for performance.
- gotcha The library's GitHub organization moved from 'nexB' to 'aboutcode-org' around version 30.3.1. While the `pypi` package name remains `license-expression`, any direct references to the GitHub repository in CI/CD or other tools should be updated.
Install
-
pip install license-expression
Imports
- get_spdx_licensing
from license_expression import get_spdx_licensing
Quickstart
from license_expression import get_spdx_licensing
# Get a licensing object. This can be slow and should be reused.
licensing = get_spdx_licensing()
# Parse a license expression
expression_str = 'GPL-2.0-only OR LGPL-2.1-only AND MIT'
parsed_expression = licensing.parse(expression_str)
print(f"Original: {expression_str}")
print(f"Parsed (pretty): {parsed_expression.pretty()}")
# Check for equivalence
expression_str_2 = 'MIT AND (GPL-2.0-only OR LGPL-2.1-only)'
parsed_expression_2 = licensing.parse(expression_str_2)
print(f"Is '{expression_str}' equivalent to '{expression_str_2}'? {licensing.is_equivalent(parsed_expression, parsed_expression_2)}")
# Validate an expression
valid = licensing.validate(expression_str)
print(f"Is '{expression_str}' a valid expression? {valid.errors if valid.errors else True}")
invalid_expression = 'Invalid-License AND Other-License'
invalid_valid = licensing.validate(invalid_expression)
print(f"Is '{invalid_expression}' a valid expression? {invalid_valid.errors if invalid_valid.errors else True}")