Home

Awesome

Python library to parse, validate and create SPDX documents

CI status (Linux, macOS and Windows): Install and Test

Breaking changes v0.7 -> v0.8

Please be aware that the upcoming 0.8 release has undergone a significant refactoring in preparation for the upcoming SPDX v3.0 release, leading to breaking changes in the API. Please refer to the migration guide to update your existing code.

The main features of v0.8 are:

Information

This library implements SPDX parsers, convertors, validators and handlers in Python.

Important updates regarding this library are shared via the SPDX tech mailing list: https://lists.spdx.org/g/Spdx-tech.

License

Apache-2.0

Features

Experimental support for SPDX 3.0

See Quickstart to SPDX 3.0 below.
The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5372a3c145dbdfc1381fc1f791c68889aafc7ff).

Installation

As always you should work in a virtualenv (venv). You can install a local clone of this repo with yourenv/bin/pip install . or install it from PyPI (check for the newest release and install it like yourenv/bin/pip install spdx-tools==0.8.0a2). Note that on Windows it would be Scripts instead of bin.

How to use

Command-line usage

  1. PARSING/VALIDATING (for parsing any format):
  1. CONVERTING (for converting one format to another):
  1. GRAPH GENERATION (optional feature)

Library usage

  1. DATA MODEL
  1. PARSING
  1. VALIDATING
  1. WRITING

Example

Here are some examples of possible use cases to quickly get you started with the spdx-tools. If you want more examples, like how to create an SPDX document from scratch, have a look at the examples folder.

import logging

from license_expression import get_spdx_licensing

from spdx_tools.spdx.model import (Checksum, ChecksumAlgorithm, File, 
                                   FileType, Relationship, RelationshipType)
from spdx_tools.spdx.parser.parse_anything import parse_file
from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document
from spdx_tools.spdx.writer.write_anything import write_file

# read in an SPDX document from a file
document = parse_file("spdx_document.json")

# change the document's name
document.creation_info.name = "new document name"

# define a file and a DESCRIBES relationship between the file and the document
checksum = Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")

file = File(name="./fileName.py", spdx_id="SPDXRef-File", checksums=[checksum], 
            file_types=[FileType.TEXT], 
            license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"),
            license_comment="licenseComment", copyright_text="copyrightText")

relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File")

# add the file and the relationship to the document 
# (note that we do not use "document.files.append(file)" as that would circumvent the type checking)
document.files = document.files + [file]
document.relationships = document.relationships + [relationship]

# validate the edited document and log the validation messages
# (depending on your use case, you might also want to utilize the validation_message.context)
validation_messages = validate_full_spdx_document(document)
for validation_message in validation_messages:
    logging.warning(validation_message.validation_message)

# if there are no validation messages, the document is valid 
# and we can safely serialize it without validating again
if not validation_messages:
    write_file(document, "new_spdx_document.rdf", validate=False)

Quickstart to SPDX 3.0

In contrast to SPDX v2, all elements are now subclasses of the central Element class. This includes packages, files, snippets, relationships, annotations, but also SBOMs, SpdxDocuments, and more.
For serialization purposes, all Elements that are to be serialized into the same file are collected in a Payload. This is just a dictionary that maps each Element's SpdxId to itself. Use the write_payload() functions to serialize a payload. There currently are two options:

You can convert an SPDX v2 document to v3 via the spdx_tools.spdx3.bump_from_spdx2.spdx_document module. The bump_spdx_document() function will return a payload containing an SpdxDocument Element and one Element for each package, file, snippet, relationship, or annotation contained in the v2 document.

Dependencies

Support

Contributing

Contributions are very welcome! See CONTRIBUTING.md for instructions on how to contribute to the codebase.

History

This is the result of an initial GSoC contribution by @ah450 (or https://github.com/a-h-i) and is maintained by a community of SPDX adopters and enthusiasts. In order to prepare for the release of SPDX v3.0, the repository has undergone a major refactoring during the time from 11/2022 to 07/2023.