Skip to content

Add more usage examples for the SPDX2 part of the library #709

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

Merged
merged 9 commits into from
Jun 27, 2023
17 changes: 17 additions & 0 deletions examples/spdx2_convert_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
from os import path

from spdx_tools.spdx.model import Document
from spdx_tools.spdx.writer.write_anything import write_file
from spdx_tools.spdx.parser.parse_anything import parse_file

# This example demonstrates how to load an existing SPDX2 file and convert it to a different SPDX2 format

# Provide a path to the input file in the originating format
input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
# Parse the original input file (format is deduced automatically from the file extension)
document: Document = parse_file(input_path)
# Write to a different file format (e.g. XML, format is deduced automatically from the file extension)
write_file(document, "converted_format.xml")
21 changes: 21 additions & 0 deletions examples/spdx2_convert_to_spdx3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
from os import path

from spdx_tools.spdx.model import Document
from spdx_tools.spdx3.payload import Payload
from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload
from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document
from spdx_tools.spdx.parser.parse_anything import parse_file

# This example demonstrates how to load an existing SPDX2 file and convert it to the SPDX3 format

# Provide a path to the input file
input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
# Parse the original SPDX2 input file
spdx2_document: Document = parse_file(input_path)
# Convert original document to an SPDX3 payload
spdx3_payload: Payload = bump_spdx_document(spdx2_document)
# Write SPDX3 payload in json-ld format
write_payload(spdx3_payload, "spdx2_to_3")
17 changes: 17 additions & 0 deletions examples/spdx2_generate_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
from os import path

from spdx_tools.spdx.graph_generation import export_graph_from_document
from spdx_tools.spdx.model import Document
from spdx_tools.spdx.parser.parse_anything import parse_file

# This example demonstrates how to generate a relationship graph for an SPDX2 document

# Provide a path to the input file
input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXJSONExample-v2.3.spdx.json")
# Parse the file
document: Document = parse_file(input_path)
# Generate the graph (note: you need to have installed the optional dependencies networkx and pygraphviz)
export_graph_from_document(document, "graph.png")
24 changes: 24 additions & 0 deletions examples/spdx2_parse_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
import logging
from os import path

from spdx_tools.spdx.model.document import Document
from spdx_tools.spdx.parser.error import SPDXParsingError
from spdx_tools.spdx.parser.parse_anything import parse_file

# This example demonstrates how to parse an existing spdx file.

# Provide a path to the input file
input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
try:
# Try to parse the input file. If successful, returns a Document, otherwise raises an SPDXParsingError
document: Document = parse_file(input_path)
except SPDXParsingError:
logging.exception("Failed to parse spdx file")

# We can now access attributes from the parsed document
print(f"Parsed document name: {document.creation_info.name}")
creators_as_str = ", ".join([creator.to_serialized_string() for creator in document.creation_info.creators])
print(f"Created on {document.creation_info.created} by {creators_as_str}")
14 changes: 9 additions & 5 deletions src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload

print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87")

namespaces, imports = zip(
*[
bump_external_document_ref(external_document_ref)
for external_document_ref in spdx2_creation_info.external_document_refs
]
namespaces, imports = (
zip(
*[
bump_external_document_ref(external_document_ref)
for external_document_ref in spdx2_creation_info.external_document_refs
]
)
if spdx2_creation_info.external_document_refs
else ([], [])
)
namespaces = list(namespaces)
imports = list(imports)
Expand Down
4 changes: 3 additions & 1 deletion src/spdx_tools/spdx3/bump_from_spdx2/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def bump_package(
elif isinstance(id_or_ref, ExternalIdentifier):
external_identifier.append(id_or_ref)

package_purpose = SoftwarePurpose[spdx2_package.primary_package_purpose.name]
package_purpose = (
SoftwarePurpose[spdx2_package.primary_package_purpose.name] if spdx2_package.primary_package_purpose else None
)

payload.add_element(
Package(
Expand Down
56 changes: 56 additions & 0 deletions tests/spdx/examples/test_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: 2023 spdx contributors
#
# SPDX-License-Identifier: Apache-2.0
import os.path
import runpy

import pytest


@pytest.fixture
def cleanup_output_files():
yield

files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml", "graph.png"]
for file in files_to_delete:
if os.path.exists(file):
os.remove(file)


def run_example(example_file: str):
file_path = os.path.join(os.path.dirname(__file__), "../../../examples/", example_file)
runpy.run_path(file_path)


def test_spdx2_parse_file():
run_example("spdx2_parse_file.py")


@pytest.mark.usefixtures("cleanup_output_files")
def test_spdx2_convert_to_spdx3():
run_example("spdx2_convert_to_spdx3.py")
assert os.path.exists("spdx2_to_3.jsonld")


@pytest.mark.usefixtures("cleanup_output_files")
def test_spdx2_document_from_scratch():
run_example("spdx2_document_from_scratch.py")
assert os.path.exists("my_spdx_document.spdx.json")


@pytest.mark.usefixtures("cleanup_output_files")
def test_spdx2_convert_format():
run_example("spdx2_convert_format.py")
assert os.path.exists("converted_format.xml")


@pytest.mark.usefixtures("cleanup_output_files")
def test_spdx2_generate_graph():
try:
import networkx # noqa F401
import pygraphviz # noqa F401
except ImportError:
pytest.skip("Missing optional dependencies")

run_example("spdx2_generate_graph.py")
assert os.path.exists("graph.png")