Skip to content

Commit

Permalink
actually simplify license expressions. So far, this has only been run…
Browse files Browse the repository at this point in the history
… on multiple licenses per SBOM component
  • Loading branch information
mxmehl committed Aug 12, 2024
1 parent e18a140 commit b1c1659
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 12 deletions.
17 changes: 15 additions & 2 deletions complassist/_flict.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,24 @@ def _run_flict(

def flict_simplify(expression: str, output_format: str) -> str:
"""Simplify a license expression using flict"""
return _run_flict("simplify", expression, options=["-of", output_format])
simplified = _run_flict("simplify", expression, options=["-of", output_format])

logging.debug("Simplified '%s' to '%s' using flict", expression, simplified)

return simplified


def flict_simplify_list(expressions: list[str]) -> list[str]:
"""Simplify a list of license expressions"""
simplified = []
for lic in expressions:
simplified.append(flict_simplify(lic, output_format="text"))

return list(set(simplified))


def flict_outbound_candidate(expression: str, output_format: str) -> str:
"""Get possible outbound license candidates using flict"""
# TODO: `-el` would make this command more helpful but it has an error:
# https://github.com/vinland-technology/flict/issues/391
return _run_flict("outbound-candidate", expression, options=["-of", output_format])
return _run_flict("outbound-candidate", expression, options=["-nr", "-of", output_format])
13 changes: 11 additions & 2 deletions complassist/_licensing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from license_expression import ExpressionError, Licensing, get_spdx_licensing

from ._flict import flict_outbound_candidate, flict_simplify
from ._flict import flict_outbound_candidate, flict_simplify, flict_simplify_list
from ._sbom_parse import extract_items_from_cdx_sbom


Expand All @@ -33,7 +33,16 @@ def _extract_license_expression_and_names_from_sbom(
if lic_name := lic_dict.get("name", ""):
lic_names.append(lic_name)

return sorted(list(set(lic_expressions))), sorted(list(set(lic_names)))
# Make expressions and names unique, and sort them
expressions = sorted(list(set(lic_expressions)))
# If using flict, simplify these found licenses. Will reduce possible
# duplicates and fix problematic SPDX expressions (e.g. MPL-2.0+)
# That's far more performant than doing that for each license in the SBOM
if use_flict:
expressions = flict_simplify_list(expressions)
names = sorted(list(set(lic_names)))

return expressions, names


def list_all_licenses(sbom_path: str, use_flict: bool = False) -> list[str]:
Expand Down
13 changes: 7 additions & 6 deletions complassist/_sbom_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from ._helpers import read_json_file


def _simplify_licenses_data(licenses_data: list[dict], use_flict: bool = True) -> list[dict]:
"""Simplify a list of license ids/expressions/names to a single string,
def _unify_licenses_data(licenses_data: list[dict], use_flict: bool = True) -> list[dict]:
"""Convert a list of license ids/expressions/names to a single string,
either an expression or a name"""

# Case 1: no data
Expand Down Expand Up @@ -92,15 +92,16 @@ def _shorten_cdx_licenses_item(licenses: list, use_flict: bool = True) -> list:
licdata,
)

simplified_license_data = _simplify_licenses_data(collection, use_flict=use_flict)
simplified_license_data = _unify_licenses_data(collection, use_flict=use_flict)
return _license_short_to_valid_cdx_item(simplified_license_data)


def extract_items_from_component(component: dict, items: list, use_flict: bool) -> dict:
"""Extract certain items from a single component of a CycloneDX SBOM"""
logging.debug(
"Handling component: purl = %s, name = %s", component.get("purl"), component.get("name")
)
# Very noisy logging, disabled
# logging.debug(
# "Handling component: purl = %s, name = %s", component.get("purl"), component.get("name")
# )
extraction = {}
# Loop requested data points for extraction
for item in items:
Expand Down
4 changes: 2 additions & 2 deletions complassist/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def configure_logger(args) -> logging.Logger:
return log


def main(): # pylint: disable=too-many-branches
def main(): # pylint: disable=too-many-branches, too-many-statements
"""Main function"""

args = parser.parse_args()
Expand Down Expand Up @@ -262,7 +262,7 @@ def main(): # pylint: disable=too-many-branches
pass

# Suggest possible outbound licenses based on detected licenses in an SBOM
if args.licensing_command == "outbound":
elif args.licensing_command == "outbound":
outbound_candidates = get_outbound_candidate(
sbom_path=args.file, simplify=not args.no_simplify
)
Expand Down

0 comments on commit b1c1659

Please sign in to comment.