Skip to content

Commit

Permalink
instantiate get_spdx_licensing() in a singleton module
Browse files Browse the repository at this point in the history
this getter takes quite some time and should be called as few times as possible

Signed-off-by: Armin Tänzer <[email protected]>
  • Loading branch information
armintaenzertng committed Aug 23, 2023
1 parent 1ecc6f6 commit ca72624
Show file tree
Hide file tree
Showing 19 changed files with 95 additions and 100 deletions.
15 changes: 7 additions & 8 deletions examples/spdx2_document_from_scratch.py
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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")
Loading

0 comments on commit ca72624

Please sign in to comment.