跳转到主要内容

许可证表达式是一个综合性的实用程序库,用于使用布尔逻辑解析、比较、简化和规范化许可证表达式(如SPDX许可证表达式)。

项目描述

license-expression 是一个综合性的实用库,用于解析、比较、简化和标准化许可证表达式(如SPDX许可证表达式),使用布尔逻辑。

软件项目的许可证通常是几个免费和开源软件许可证的组合。许可证表达式(如SPDX指定)提供了一种简洁且易于阅读的方式来表达这些许可证,无需阅读冗长的许可证文本,同时仍然具有机器可读性。

许可证表达式被Linux等关键FOSS项目使用;几个软件包生态系统使用它们来记录包许可元数据,如npm和Rubygems;在交换软件数据(如SPDX和SBOM)时,它们是精确表达许可的一种方式。

license-expression 是一个综合性的实用库,用于解析、比较、简化和标准化这些许可证表达式(如SPDX许可证表达式),使用布尔逻辑,例如:GPL-2.0-or-later WITH Classpath-exception-2.0 AND MIT

它包括来自SPDX https://spdx.org/licenses/(版本3.23)和ScanCode许可证数据库(版本32.0.8,最后发布于2023-02-27)的许可证键。请访问 https://scancode-licensedb.aboutcode.org/ 以快速开始。

license-expression 功能强大且易于使用,被用作多个项目和产品的许可证表达式引擎,例如

有关详细信息,请参阅:- https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/

license-expression 也已打包到大多数Linux发行版中。请参阅以下内容。

替代方案

目前没有已知适用于Python的替代库,但其他语言中有几个类似的库(但当然没有这么强大!)

构建和测试状态

Linux & macOS (Travis)

Windows (AppVeyor)

Linux、Windows 和 macOS (Azure)

Travis tests status

Appveyor tests status

Azure pipelines tests status

源代码和下载

也适用于多个 Linux 发行版

支持

描述

此模块定义了一种小语言,使用布尔逻辑引擎解析、验证、简化、归一化和比较许可证表达式。

它支持 SPDX 许可证表达式,并接受其他许可证命名约定和许可证标识符别名,以解析和归一化任何许可证表达式。

使用布尔逻辑,可以测试许可证表达式是否相等、包含、等价,并且可以进行归一化或简化。

它还捆绑了 SPDX 许可证列表(目前为 3.20 版本)和 ScanCode 许可证数据库(基于最新的 ScanCode),以便易于使用许可证符号解析和验证表达式。

使用示例

主要入口点是 Licensing 对象,您可以使用它来解析、验证、比较、简化和归一化许可证表达式。

创建 SPDX 许可证并解析表达式

>>> from license_expression import get_spdx_licensing
>>> licensing = get_spdx_licensing()
>>> expression = ' GPL-2.0 or LGPL-2.1 and mit '
>>> parsed = licensing.parse(expression)
>>> print(parsed.pretty())
OR(
  LicenseSymbol('GPL-2.0-only'),
  AND(
    LicenseSymbol('LGPL-2.1-only'),
    LicenseSymbol('MIT')
  )
)

>>> str(parsed)
'GPL-2.0-only OR (LGPL-2.1-only AND MIT)'

>>> licensing.parse('unknwon with foo', validate=True, strict=True)
license_expression.ExpressionParseError: A plain license symbol cannot be used
as an exception in a "WITH symbol" statement. for token: "foo" at position: 13

>>> licensing.parse('unknwon with foo', validate=True)
license_expression.ExpressionError: Unknown license key(s): unknwon, foo

>>> licensing.validate('foo and MIT and GPL-2.0+')
ExpressionInfo(
    original_expression='foo and MIT and GPL-2.0+',
    normalized_expression=None,
    errors=['Unknown license key(s): foo'],
    invalid_symbols=['foo']
)

创建简单许可证并解析表达式

>>> from license_expression import Licensing, LicenseSymbol
>>> licensing = Licensing()
>>> expression = ' GPL-2.0 or LGPL-2.1 and mit '
>>> parsed = licensing.parse(expression)
>>> expression = ' GPL-2.0 or LGPL-2.1 and mit '
>>> expected = 'GPL-2.0-only OR (LGPL-2.1-only AND mit)'
>>> assert str(parsed) == expected
>>> assert parsed.render('{symbol.key}') == expected

创建具有您自己的许可证符号的许可证

>>> expected = [
...   LicenseSymbol('GPL-2.0'),
...   LicenseSymbol('LGPL-2.1'),
...   LicenseSymbol('mit')
... ]
>>> assert licensing.license_symbols(expression) == expected
>>> assert licensing.license_symbols(parsed) == expected

>>> symbols = ['GPL-2.0+', 'Classpath', 'BSD']
>>> licensing = Licensing(symbols)
>>> expression = 'GPL-2.0+ with Classpath or (bsd)'
>>> parsed = licensing.parse(expression)
>>> expected = 'GPL-2.0+ WITH Classpath OR BSD'
>>> assert parsed.render('{symbol.key}') == expected

>>> expected = [
...   LicenseSymbol('GPL-2.0+'),
...   LicenseSymbol('Classpath'),
...   LicenseSymbol('BSD')
... ]
>>> assert licensing.license_symbols(parsed) == expected
>>> assert licensing.license_symbols(expression) == expected

表达式可以进行去重,以删除重复的许可证子表达式,同时不改变顺序,不考虑许可证选择是否可简化

>>> expression2 = ' GPL-2.0 or (mit and LGPL 2.1) or bsd Or GPL-2.0  or (mit and LGPL 2.1)'
>>> parsed2 = licensing.parse(expression2)
>>> str(parsed2)
'GPL-2.0 OR (mit AND LGPL 2.1) OR BSD OR GPL-2.0 OR (mit AND LGPL 2.1)'
>>> assert str(parsed2.simplify()) == 'BSD OR GPL-2.0 OR (LGPL 2.1 AND mit)'

表达式可以进行简化,将其视为布尔表达式

>>> expression2 = ' GPL-2.0 or (mit and LGPL 2.1) or bsd Or GPL-2.0  or (mit and LGPL 2.1)'
>>> parsed2 = licensing.parse(expression2)
>>> str(parsed2)
'GPL-2.0 OR (mit AND LGPL 2.1) OR BSD OR GPL-2.0 OR (mit AND LGPL 2.1)'
>>> assert str(parsed2.simplify()) == 'BSD OR GPL-2.0 OR (LGPL 2.1 AND mit)'

两个表达式可以进行比较以确定它们是否等价或包含

>>> expr1 = licensing.parse(' GPL-2.0 or (LGPL 2.1 and mit) ')
>>> expr2 = licensing.parse(' (mit and LGPL 2.1)  or GPL-2.0 ')
>>> licensing.is_equivalent(expr1, expr2)
True
>>> licensing.is_equivalent(' GPL-2.0 or (LGPL 2.1 and mit) ',
...                         ' (mit and LGPL 2.1)  or GPL-2.0 ')
True
>>> expr1.simplify() == expr2.simplify()
True
>>> expr3 = licensing.parse(' GPL-2.0 or mit or LGPL 2.1')
>>> licensing.is_equivalent(expr2, expr3)
False
>>> expr4 = licensing.parse('mit and LGPL 2.1')
>>> expr4.simplify() in expr2.simplify()
True
>>> licensing.contains(expr2, expr4)
True

开发

  • https://github.com/aboutcode-org/license-expression.git 检出克隆

  • 然后在 Linux 和 POSIX 上运行 ./configure --dev,然后运行 source tmp/bin/activate。这将在一个局部虚拟环境中安装所有依赖项,包括开发依赖项。

  • 在 Windows 上运行 configure.bat --dev,然后运行 Scripts\bin\activate

  • 要运行测试,请运行 pytest -vvs

项目详细信息


下载文件

下载适用于您平台的文件。如果您不确定该选择哪一个,请了解有关安装包的更多信息。

源分布

license_expression-30.3.1.tar.gz (174.6 kB 查看哈希值)

上传时间

构建分布

license_expression-30.3.1-py3-none-any.whl (109.0 kB 查看哈希值)

上传时间 Python 3

由以下支持