spdx_tools.spdx.parser.rdf.license_expression_parser

 1# SPDX-FileCopyrightText: 2023 spdx contributors
 2#
 3# SPDX-License-Identifier: Apache-2.0
 4from beartype.typing import Optional, Union
 5from license_expression import LicenseExpression
 6from rdflib import RDF, Graph
 7from rdflib.term import BNode, Identifier, Node, URIRef
 8
 9from spdx_tools.common.spdx_licensing import spdx_licensing
10from spdx_tools.spdx.parser.logger import Logger
11from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix
12from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE
13
14
15def parse_license_expression(
16    license_expression_node: Union[URIRef, BNode, Node],
17    graph: Graph,
18    doc_namespace: str,
19    logger: Optional[Logger] = None,
20) -> LicenseExpression:
21    if not logger:
22        logger = Logger()
23
24    expression = ""
25    if license_expression_node.startswith(LICENSE_NAMESPACE):
26        expression = remove_prefix(license_expression_node, LICENSE_NAMESPACE)
27        return spdx_licensing.parse(expression)
28    if license_expression_node.startswith(doc_namespace):
29        expression = license_expression_node.fragment
30        return spdx_licensing.parse(expression)
31
32    node_type = graph.value(license_expression_node, RDF.type)
33    if node_type == SPDX_NAMESPACE.ConjunctiveLicenseSet:
34        members = []
35        for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)):
36            members.append(parse_license_expression(member_node, graph, doc_namespace, logger))
37        expression = " AND ".join([str(member) for member in members])
38    if node_type == SPDX_NAMESPACE.DisjunctiveLicenseSet:
39        members = []
40        for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)):
41            members.append(parse_license_expression(member_node, graph, doc_namespace, logger))
42        expression = " OR ".join([str(member) for member in members])
43    if node_type == SPDX_NAMESPACE.WithExceptionOperator:
44        license_expression = parse_license_expression(
45            graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace, logger
46        )
47        exception = parse_license_exception(
48            get_value_from_graph(logger, graph, license_expression_node, SPDX_NAMESPACE.licenseException),
49            graph,
50            logger,
51        )
52        expression = f"{license_expression} WITH {exception}"
53
54    return spdx_licensing.parse(expression)
55
56
57def parse_license_exception(exception_node: Identifier, graph: Graph, logger) -> str:
58    if exception_node.startswith(LICENSE_NAMESPACE):
59        exception = remove_prefix(exception_node, LICENSE_NAMESPACE)
60    else:
61        exception = get_value_from_graph(logger, graph, exception_node, SPDX_NAMESPACE.licenseExceptionId).toPython()
62    return exception
def parse_license_expression( license_expression_node: Union[rdflib.term.URIRef, rdflib.term.BNode, rdflib.term.Node], graph: rdflib.graph.Graph, doc_namespace: str, logger: Optional[spdx_tools.spdx.parser.logger.Logger] = None) -> boolean.boolean.Expression:
16def parse_license_expression(
17    license_expression_node: Union[URIRef, BNode, Node],
18    graph: Graph,
19    doc_namespace: str,
20    logger: Optional[Logger] = None,
21) -> LicenseExpression:
22    if not logger:
23        logger = Logger()
24
25    expression = ""
26    if license_expression_node.startswith(LICENSE_NAMESPACE):
27        expression = remove_prefix(license_expression_node, LICENSE_NAMESPACE)
28        return spdx_licensing.parse(expression)
29    if license_expression_node.startswith(doc_namespace):
30        expression = license_expression_node.fragment
31        return spdx_licensing.parse(expression)
32
33    node_type = graph.value(license_expression_node, RDF.type)
34    if node_type == SPDX_NAMESPACE.ConjunctiveLicenseSet:
35        members = []
36        for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)):
37            members.append(parse_license_expression(member_node, graph, doc_namespace, logger))
38        expression = " AND ".join([str(member) for member in members])
39    if node_type == SPDX_NAMESPACE.DisjunctiveLicenseSet:
40        members = []
41        for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)):
42            members.append(parse_license_expression(member_node, graph, doc_namespace, logger))
43        expression = " OR ".join([str(member) for member in members])
44    if node_type == SPDX_NAMESPACE.WithExceptionOperator:
45        license_expression = parse_license_expression(
46            graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace, logger
47        )
48        exception = parse_license_exception(
49            get_value_from_graph(logger, graph, license_expression_node, SPDX_NAMESPACE.licenseException),
50            graph,
51            logger,
52        )
53        expression = f"{license_expression} WITH {exception}"
54
55    return spdx_licensing.parse(expression)
def parse_license_exception( exception_node: rdflib.term.Identifier, graph: rdflib.graph.Graph, logger) -> str:
58def parse_license_exception(exception_node: Identifier, graph: Graph, logger) -> str:
59    if exception_node.startswith(LICENSE_NAMESPACE):
60        exception = remove_prefix(exception_node, LICENSE_NAMESPACE)
61    else:
62        exception = get_value_from_graph(logger, graph, exception_node, SPDX_NAMESPACE.licenseExceptionId).toPython()
63    return exception