A comprehensive utility library to parse, compare, simplify and normalize license expressions using boolean logic
npx @tessl/cli install tessl/pypi-license-expression@30.4.0A comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic. This library supports complex boolean operations on license expressions, provides validation and normalization capabilities, and includes complete license databases with SPDX and ScanCode license identifiers.
pip install license-expressionfrom license_expression import Licensing, LicenseSymbolFor SPDX-compliant licensing:
from license_expression import get_spdx_licensingFor ScanCode licensing database:
from license_expression import get_scancode_licensingfrom license_expression import get_spdx_licensing
# Create SPDX licensing instance
licensing = get_spdx_licensing()
# Parse a license expression
expression = 'GPL-2.0 or LGPL-2.1 and MIT'
parsed = licensing.parse(expression)
# Get normalized expression
print(str(parsed)) # 'GPL-2.0-only OR (LGPL-2.1-only AND MIT)'
# Validate expressions
result = licensing.validate('MIT and Apache-2.0')
print(result.errors) # [] - no errors
# Check if expressions are equivalent
expr1 = licensing.parse('MIT or Apache-2.0')
expr2 = licensing.parse('Apache-2.0 or MIT')
print(licensing.is_equivalent(expr1, expr2)) # True
# Simplify complex expressions
complex_expr = 'MIT or (GPL-2.0 and MIT) or MIT'
simplified = licensing.parse(complex_expr).simplify()
print(str(simplified)) # 'MIT'The license-expression library is built around several key components:
The library uses boolean algebra to enable sophisticated license expression analysis, including equivalence testing, containment analysis, and expression simplification.
Main API for parsing, validating, and comparing license expressions. Provides the primary interface for working with license expressions through the Licensing class.
class Licensing:
def parse(self, expression: str, validate: bool = False, strict: bool = False) -> LicenseExpression: ...
def validate(self, expression: str) -> ExpressionInfo: ...
def is_equivalent(self, expr1, expr2) -> bool: ...
def contains(self, expr1, expr2) -> bool: ...Classes and utilities for working with individual license symbols, including standard licenses, license-like symbols, and complex WITH exception constructs.
class LicenseSymbol:
def __init__(self, key: str, aliases: list = None, is_exception: bool = False): ...
class LicenseWithExceptionSymbol:
def __init__(self, license_symbol: LicenseSymbol, exception_symbol: LicenseSymbol): ...Utility functions for expression manipulation, validation, combination, and analysis. Includes functions for combining multiple expressions and validating symbol collections.
def combine_expressions(expressions, relation: str = "AND", unique: bool = True, licensing=None) -> LicenseExpression: ...
def validate_symbols(symbols, validate_keys: bool = False) -> tuple: ...Convenience functions for creating preconfigured Licensing instances with SPDX or ScanCode license databases.
def get_spdx_licensing(license_index_location=None) -> Licensing: ...
def get_scancode_licensing(license_index_location=None) -> Licensing: ...
def get_license_index(license_index_location=None) -> dict: ...Error codes, token constants, and exception classes for robust error handling and expression parsing.
class ExpressionError(Exception): ...
class ExpressionParseError(ParseError, ExpressionError): ...
# Parse error constants
PARSE_INVALID_EXCEPTION: int
PARSE_INVALID_SYMBOL_AS_EXCEPTION: intclass ExpressionInfo:
original_expression: str
normalized_expression: str
errors: list
invalid_symbols: list
class LicenseExpression:
def pretty(self) -> str: ...
def render(self, template: str) -> str: ...
def simplify(self) -> 'LicenseExpression': ...