Skip to content

LLGPL appears to be treated as a plain license, not as a license exception #91

@dvzrv

Description

@dvzrv

Hi! 👋

As background: I have added this project as backend for namcap, a validation tool for packages and build scripts, that is used on Arch Linux. From what I can tell after integrating is, that it works pretty well for our use-case and helps us a great deal in being more compliant with SPDX license identifiers (see https://rfc.archlinux.page/0016-spdx-license-identifiers/). Thanks for that! 🎉

However, there appear to be edge cases and maybe you are able to help me in figuring this particular one out.

When trying to package an upstream that uses the LLGPL preamble my assumption would be, after reading

Exceptions are added to a license using the License Expression operator, "WITH".

on https://spdx.org/licenses/exceptions-index.html that an expression such as LGPL-2.1-only WITH LLGPL would be valid. This does not seem to be the case though:

Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from license_expression import get_spdx_licensing
>>> licensing = get_spdx_licensing()
>>> licensing.parse("LGPL-2.1-or-later WITH LLGPL", strict=True)
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/license_expression/__init__.py", line 540, in parse
    tokens = list(self.tokenize(
             ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/license_expression/__init__.py", line 604, in tokenize
    for token in tokens:
  File "/usr/lib/python3.11/site-packages/license_expression/__init__.py", line 1090, in replace_with_subexpression_by_license_symbol
    raise ParseError(
boolean.boolean.ParseError: A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "LLGPL" at position: 23

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/site-packages/license_expression/__init__.py", line 548, in parse
    raise ExpressionParseError(
license_expression.ExpressionParseError: A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "LLGPL" at position: 23
>>> licensing.parse("LGPL-2.1-or-later WITH LLGPL")
LicenseWithExceptionSymbol(license_symbol=LicenseSymbol('LGPL-2.1-or-later', aliases=('LGPL-2.1+',), is_exception=False), exception_symbol=LicenseSymbol('LLGPL', aliases=('LicenseRef-scancode-llgpl',), is_exception=False))
>>>

When looking at above output, it becomes clear, that the expression fails parsing when applying strict rules, because LLGPL is treated as a "plain license". This is evidenced by it being represented by a LicenseSymbol where is_exception=False when not applying strict rules during parsing.

Relatedly, we apply strict parsing by default, because we want to have SPDX compliant expressions and we want to have them to be correctly distinguished between plain licenses and exceptions for packaging reasons. In the case of LLGPL this does not seem to work correctly and namcap fails parsing the license expression.

Furthermore (and to make things somewhat more complicated, but also more specific and useful for us as a distribution), when it comes to packaging, on Arch Linux we rely on a system-wide package (see https://gitlab.archlinux.org/archlinux/packaging/packages/licenses) to provide "common" license and exception files in well-known locations. Those "common" license files are of licenses and exceptions that are frequently used verbatim and do not contain or require individually identifying information (e.g. specific list of authors) or an ever-changing date identifier. We also provide full lists of all known license and exception identifiers separately. The package allows us to centrally share common license files and not repackage them in every package.
Namcap in turn relies on this information to identify and correlate known identifiers and the ones that are common (and thus do not need to be packaged).

This unfortunately does not work with LLGPL though, since license-expression treats it as a plain license, not an exception identifier. As such namcap fails when adding it in a WITH expression (e.g. LGPL-2.1-or-later WITH LLGPL) and would if provided plainly (e.g. LLGPL) require the user to prefix it with LicenseRef-, because LLGPL is not found in the list of "known" licenses (as it is in the list of "known" license exceptions).
From my understanding, the expression LGPL-2.1-or-later WITH LLGPL should be valid though and LLGPL should be treated as a license exception, not a plain license.

This leads me to the question: Is there a specific reason why LLGPL is treated as a plain license and not as a license exception?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions