Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

only instantiate get_spdx_licensing() once in the project #749

Merged
merged 1 commit into from Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 7 additions & 8 deletions examples/spdx2_document_from_scratch.py
Expand Up @@ -5,8 +5,7 @@
from datetime import datetime
from typing import List

from license_expression import get_spdx_licensing

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import (
Actor,
ActorType,
Expand Down Expand Up @@ -65,9 +64,9 @@
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"),
Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"),
],
license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"),
license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")],
license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"),
license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"),
license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")],
license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"),
license_comment="license comment",
copyright_text="Copyright 2022 Jane Doe",
description="package description",
Expand Down Expand Up @@ -100,8 +99,8 @@
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"),
Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"),
],
license_concluded=get_spdx_licensing().parse("MIT"),
license_info_in_file=[get_spdx_licensing().parse("MIT")],
license_concluded=spdx_licensing.parse("MIT"),
license_info_in_file=[spdx_licensing.parse("MIT")],
copyright_text="Copyright 2022 Jane Doe",
)
file2 = File(
Expand All @@ -110,7 +109,7 @@
checksums=[
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"),
],
license_concluded=get_spdx_licensing().parse("GPL-2.0-only"),
license_concluded=spdx_licensing.parse("GPL-2.0-only"),
)

# Assuming the package contains those two files, we create two CONTAINS relationships.
Expand Down
7 changes: 7 additions & 0 deletions src/spdx_tools/common/spdx_licensing.py
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
from license_expression import get_spdx_licensing

# this getter takes quite long so we only call it once in this singleton module
spdx_licensing = get_spdx_licensing()
5 changes: 3 additions & 2 deletions src/spdx_tools/spdx/parser/rdf/license_expression_parser.py
Expand Up @@ -2,10 +2,11 @@
#
# SPDX-License-Identifier: Apache-2.0
from beartype.typing import Optional, Union
from license_expression import LicenseExpression, get_spdx_licensing
from license_expression import LicenseExpression
from rdflib import RDF, Graph
from rdflib.term import BNode, Identifier, Node, URIRef

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.parser.logger import Logger
from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix
from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE
Expand All @@ -19,7 +20,7 @@ def parse_license_expression(
) -> LicenseExpression:
if not logger:
logger = Logger()
spdx_licensing = get_spdx_licensing()

expression = ""
if license_expression_node.startswith(LICENSE_NAMESPACE):
expression = remove_prefix(license_expression_node, LICENSE_NAMESPACE)
Expand Down
Expand Up @@ -3,8 +3,9 @@
# SPDX-License-Identifier: Apache-2.0

from beartype.typing import List, Optional, Union
from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing
from license_expression import ExpressionError, ExpressionParseError, LicenseExpression

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone
from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage

Expand Down Expand Up @@ -40,7 +41,7 @@ def validate_license_expression(
validation_messages = []
license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info]

for non_spdx_token in get_spdx_licensing().validate(license_expression).invalid_symbols:
for non_spdx_token in spdx_licensing.validate(license_expression).invalid_symbols:
if non_spdx_token not in license_ref_ids:
validation_messages.append(
ValidationMessage(
Expand All @@ -51,14 +52,14 @@ def validate_license_expression(
)

try:
get_spdx_licensing().parse(str(license_expression), validate=True, strict=True)
spdx_licensing.parse(str(license_expression), validate=True, strict=True)
except ExpressionParseError as err:
# This error is raised when an exception symbol is used as a license symbol and vice versa.
# So far, it only catches the first such error in the provided string.
validation_messages.append(ValidationMessage(f"{err}. for license_expression: {license_expression}", context))
except ExpressionError:
# This error is raised for invalid symbols within the license_expression, but it provides only a string of
# these. On the other hand, get_spdx_licensing().validate() gives an actual list of invalid symbols, so this is
# these. On the other hand, spdx_licensing.validate() gives an actual list of invalid symbols, so this is
# handled above.
pass

Expand Down
13 changes: 3 additions & 10 deletions src/spdx_tools/spdx/writer/rdf/license_expression_writer.py
Expand Up @@ -3,18 +3,11 @@
# SPDX-License-Identifier: Apache-2.0
from beartype.typing import List, Union
from boolean import Expression
from license_expression import (
AND,
OR,
ExpressionInfo,
LicenseExpression,
LicenseSymbol,
LicenseWithExceptionSymbol,
get_spdx_licensing,
)
from license_expression import AND, OR, ExpressionInfo, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol
from rdflib import RDF, BNode, Graph, URIRef
from rdflib.term import Literal, Node

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone
from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE

Expand Down Expand Up @@ -75,7 +68,7 @@ def add_license_expression_to_graph(


def license_or_exception_is_on_spdx_licensing_list(license_symbol: LicenseSymbol) -> bool:
symbol_info: ExpressionInfo = get_spdx_licensing().validate(license_symbol)
symbol_info: ExpressionInfo = spdx_licensing.validate(license_symbol)
return not symbol_info.errors


Expand Down
14 changes: 4 additions & 10 deletions src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py
Expand Up @@ -2,15 +2,9 @@
#
# SPDX-License-Identifier: Apache-2.0
from beartype.typing import List, Union
from license_expression import (
AND,
OR,
LicenseExpression,
LicenseSymbol,
LicenseWithExceptionSymbol,
get_spdx_licensing,
)
from license_expression import AND, OR, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx3.model.licensing import (
AnyLicenseInfo,
ConjunctiveLicenseSet,
Expand Down Expand Up @@ -61,7 +55,7 @@ def bump_license_expression(
subject_addition=bump_license_exception(license_expression.exception_symbol, extracted_licensing_info),
)
if isinstance(license_expression, LicenseSymbol):
if not get_spdx_licensing().validate(license_expression).invalid_symbols:
if not spdx_licensing.validate(license_expression).invalid_symbols:
return ListedLicense(license_expression.key, license_expression.obj, "blank")
else:
for licensing_info in extracted_licensing_info:
Expand All @@ -80,7 +74,7 @@ def bump_license_expression(
def bump_license_exception(
license_exception: LicenseSymbol, extracted_licensing_info: List[ExtractedLicensingInfo]
) -> LicenseAddition:
if not get_spdx_licensing().validate(license_exception).invalid_symbols:
if not spdx_licensing.validate(license_exception).invalid_symbols:
return ListedLicenseException(license_exception.key, "", "")
else:
for licensing_info in extracted_licensing_info:
Expand Down
15 changes: 7 additions & 8 deletions tests/spdx/examples/test_spdx2_document_from_scratch.py
Expand Up @@ -5,8 +5,7 @@
from datetime import datetime
from typing import List

from license_expression import get_spdx_licensing

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import (
Actor,
ActorType,
Expand Down Expand Up @@ -67,9 +66,9 @@ def test_spdx2_document_from_scratch():
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"),
Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"),
],
license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"),
license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")],
license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"),
license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"),
license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")],
license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"),
license_comment="license comment",
copyright_text="Copyright 2022 Jane Doe",
description="package description",
Expand Down Expand Up @@ -102,8 +101,8 @@ def test_spdx2_document_from_scratch():
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"),
Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"),
],
license_concluded=get_spdx_licensing().parse("MIT"),
license_info_in_file=[get_spdx_licensing().parse("MIT")],
license_concluded=spdx_licensing.parse("MIT"),
license_info_in_file=[spdx_licensing.parse("MIT")],
copyright_text="Copyright 2022 Jane Doe",
)
file2 = File(
Expand All @@ -112,7 +111,7 @@ def test_spdx2_document_from_scratch():
checksums=[
Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"),
],
license_concluded=get_spdx_licensing().parse("GPL-2.0-only"),
license_concluded=spdx_licensing.parse("GPL-2.0-only"),
)

# Assuming the package contains those two files, we create two CONTAINS relationships.
Expand Down
17 changes: 8 additions & 9 deletions tests/spdx/fixtures.py
Expand Up @@ -3,8 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
from datetime import datetime

from license_expression import get_spdx_licensing

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID
from spdx_tools.spdx.model import (
Actor,
Expand Down Expand Up @@ -88,7 +87,7 @@ def file_fixture(
spdx_id="SPDXRef-File",
checksums=None,
file_types=None,
license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"),
license_concluded=spdx_licensing.parse("MIT and GPL-2.0"),
license_info_in_file=None,
license_comment="licenseComment",
copyright_text="copyrightText",
Expand All @@ -100,7 +99,7 @@ def file_fixture(
checksums = [checksum_fixture()] if checksums is None else checksums
file_types = [FileType.TEXT] if file_types is None else file_types
license_info_in_file = (
[get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()]
[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()]
if license_info_in_file is None
else license_info_in_file
)
Expand Down Expand Up @@ -135,9 +134,9 @@ def package_fixture(
checksums=None,
homepage="https://homepage.com",
source_info="sourceInfo",
license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"),
license_concluded=spdx_licensing.parse("MIT and GPL-2.0"),
license_info_from_files=None,
license_declared=get_spdx_licensing().parse("MIT and GPL-2.0"),
license_declared=spdx_licensing.parse("MIT and GPL-2.0"),
license_comment="packageLicenseComment",
copyright_text="packageCopyrightText",
summary="packageSummary",
Expand All @@ -152,7 +151,7 @@ def package_fixture(
) -> Package:
checksums = [checksum_fixture()] if checksums is None else checksums
license_info_from_files = (
[get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()]
[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()]
if license_info_from_files is None
else license_info_from_files
)
Expand Down Expand Up @@ -208,7 +207,7 @@ def snippet_fixture(
file_spdx_id="SPDXRef-File",
byte_range=(1, 2),
line_range=(3, 4),
license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"),
license_concluded=spdx_licensing.parse("MIT and GPL-2.0"),
license_info_in_snippet=None,
license_comment="snippetLicenseComment",
copyright_text="licenseCopyrightText",
Expand All @@ -217,7 +216,7 @@ def snippet_fixture(
attribution_texts=None,
) -> Snippet:
license_info_in_snippet = (
[get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNone()]
[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNone()]
if license_info_in_snippet is None
else license_info_in_snippet
)
Expand Down
Expand Up @@ -4,8 +4,8 @@
from unittest import TestCase

import pytest
from license_expression import get_spdx_licensing

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone
from spdx_tools.spdx.parser.error import SPDXParsingError
from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser
Expand All @@ -14,8 +14,8 @@
@pytest.mark.parametrize(
"license_expression_str, expected_license",
[
("First License", get_spdx_licensing().parse("First License")),
("Second License", get_spdx_licensing().parse("Second License")),
("First License", spdx_licensing.parse("First License")),
("Second License", spdx_licensing.parse("Second License")),
("NOASSERTION", SpdxNoAssertion()),
("NONE", SpdxNone()),
],
Expand Down
6 changes: 3 additions & 3 deletions tests/spdx/parser/rdf/test_file_parser.py
Expand Up @@ -5,9 +5,9 @@
from unittest import TestCase

import pytest
from license_expression import get_spdx_licensing
from rdflib import RDF, BNode, Graph, URIRef

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion
from spdx_tools.spdx.parser.error import SPDXParsingError
from spdx_tools.spdx.parser.rdf.file_parser import parse_file
Expand All @@ -29,10 +29,10 @@ def test_parse_file():
assert file.comment == "fileComment"
assert file.copyright_text == "copyrightText"
assert file.contributors == ["fileContributor"]
assert file.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0")
assert file.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0")
TestCase().assertCountEqual(
file.license_info_in_file,
[get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()],
[spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()],
)
assert file.license_comment == "licenseComment"
assert file.notice == "fileNotice"
Expand Down
16 changes: 8 additions & 8 deletions tests/spdx/parser/rdf/test_license_expression_parser.py
Expand Up @@ -4,9 +4,9 @@
import os
from unittest import TestCase

from license_expression import get_spdx_licensing
from rdflib import RDF, Graph

from spdx_tools.common.spdx_licensing import spdx_licensing
from spdx_tools.spdx.parser.rdf import rdf_parser
from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression
from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
Expand All @@ -19,7 +19,7 @@ def test_license_expression_parser():

license_expression = parse_license_expression(license_expression_node, graph, "https://some.namespace#")

assert license_expression == get_spdx_licensing().parse("GPL-2.0 AND MIT")
assert license_expression == spdx_licensing.parse("GPL-2.0 AND MIT")


def test_license_expression_parser_with_coupled_licenses():
Expand All @@ -30,19 +30,19 @@ def test_license_expression_parser_with_coupled_licenses():
packages_by_spdx_id = {package.spdx_id: package for package in doc.packages}
files_by_spdx_id = {file.spdx_id: file for file in doc.files}

assert packages_by_spdx_id["SPDXRef-Package"].license_declared == get_spdx_licensing().parse(
assert packages_by_spdx_id["SPDXRef-Package"].license_declared == spdx_licensing.parse(
"LGPL-2.0-only AND LicenseRef-3"
)
assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == get_spdx_licensing().parse(
assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == spdx_licensing.parse(
"LGPL-2.0-only OR LicenseRef-3"
)
TestCase().assertCountEqual(
packages_by_spdx_id["SPDXRef-Package"].license_info_from_files,
[
get_spdx_licensing().parse("GPL-2.0"),
get_spdx_licensing().parse("LicenseRef-1"),
get_spdx_licensing().parse("LicenseRef-2"),
spdx_licensing.parse("GPL-2.0"),
spdx_licensing.parse("LicenseRef-1"),
spdx_licensing.parse("LicenseRef-2"),
],
)

assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == get_spdx_licensing().parse("LicenseRef-1")
assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == spdx_licensing.parse("LicenseRef-1")