Skip to content

Instantly share code, notes, and snippets.

@bact
Last active August 22, 2025 12:06
Show Gist options
  • Save bact/7227ad858500c2097a25344a4af015d6 to your computer and use it in GitHub Desktop.
Save bact/7227ad858500c2097a25344a4af015d6 to your computer and use it in GitHub Desktop.
spdx-python-model-tutorial.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"authorship_tag": "ABX9TyM2iDXKVuDVSs6ugr/e4y1j",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/bact/7227ad858500c2097a25344a4af015d6/spdx-python-model-tutorial.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"source": [
"# SPDX-FileCopyrightText: 2025-present Arthit Suriyawongkul <[email protected]>\n",
"# SPDX-FileType: SOURCE\n",
"# SPDX-License-Identifier: Apache-2.0"
],
"metadata": {
"id": "fTKOUcN_esq8"
},
"execution_count": 1,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# Using SPDX 3 in Python with spdx-python-model\n",
"\n",
"This tutorial demonstrates how to read software bill of materials (SBOM) data in the [System Package Data Exchange (SPDX)][spdx] format from an [SPDX 3 JSON][spdx-3-json] file.\n",
"\n",
"- It will use the [spdx-python-model][] library to access SPDX objects and their relationships.\n",
"- The SBOM 3 JSON file example is taken from [AI Example 2][ai-example-2] of the spdx-examples repository.\n",
"- This documentation is a contribution to the [NTIA Conformance Checker][ntia-conformance-checker] as part of the [Google Summer of Code 2025 program][gsoc-2025].\n",
"\n",
"[@bact][bact] Arthit Suriyawongkul \n",
"7 July 2025\n",
"\n",
"[spdx]: https://spdx.dev/use/specifications/\n",
"[spdx-python-model]: https://github.com/spdx/spdx-python-model\n",
"[spdx-3-json]: https://github.com/spdx/spdx-spec/blob/develop/docs/serializations.md#serialization-in-spdx-3-json\n",
"[ai-example-2]: https://github.com/spdx/spdx-examples/tree/master/ai/example02/spdx3.0\n",
"[ntia-conformance-checker]: https://github.com/spdx/ntia-conformance-checker\n",
"[gsoc-2025]: https://summerofcode.withgoogle.com/programs/2025/projects/CeR3hQTq\n",
"[bact]: https://github.com/bact/"
],
"metadata": {
"id": "09M0uv5_Bk7B"
}
},
{
"cell_type": "markdown",
"source": [
"## Install the spdx-python-model library"
],
"metadata": {
"id": "_ZRVMOBvQDuO"
}
},
{
"cell_type": "code",
"source": [
"!pip install spdx-python-model"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "JsENPjgwHlHc",
"outputId": "8af2b962-3809-4c79-ce1e-5587256e69ac"
},
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Collecting spdx-python-model\n",
" Downloading spdx_python_model-0.0.2-py3-none-any.whl.metadata (3.2 kB)\n",
"Downloading spdx_python_model-0.0.2-py3-none-any.whl (48 kB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m48.5/48.5 kB\u001b[0m \u001b[31m1.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hInstalling collected packages: spdx-python-model\n",
"Successfully installed spdx-python-model-0.0.2\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## Import and check library version"
],
"metadata": {
"id": "0rhToD4DQQ0-"
}
},
{
"cell_type": "code",
"source": [
"from spdx_python_model import VERSION, bindings\n",
"\n",
"print(f\"spdx-python-model library version: {VERSION}\")\n",
"\n",
"print(\"Available SPDX bindings in spdx_python_model module:\")\n",
"for name in dir(bindings):\n",
" if not name.startswith(\"__\"):\n",
" print(name)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "977gguFuH1Nt",
"outputId": "0b42d7f5-1ff2-4088-d194-e31ee1e12b2f"
},
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"spdx-python-model library version: 0.0.2\n",
"Available SPDX bindings in spdx_python_model module:\n",
"v3_0_1\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"To use a Python binding, import a specific version of the model.\n",
"\n",
"For example, to import a binding for SPDX model version 3.0.1, import `v3_0_1`."
],
"metadata": {
"id": "yuweD-jan0A8"
}
},
{
"cell_type": "code",
"source": [
"from spdx_python_model import v3_0_1"
],
"metadata": {
"id": "MW10UJY2n7Ot"
},
"execution_count": 4,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Or you may like to assign it to a versionless alias,\n",
"so you can update the version easily later.\n",
"\n",
"For example, this will set the import alias as `spdx3`."
],
"metadata": {
"id": "v7E3Ys6BoBKQ"
}
},
{
"cell_type": "code",
"source": [
"from spdx_python_model import v3_0_1 as spdx3"
],
"metadata": {
"id": "bgKEojPtn_yC"
},
"execution_count": 5,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"If a new version (e.g., v3_0_2) is released, you only need to update the import line and can keep the rest of your code intact.\n",
"\n",
"For example, `from spdx_python_model import v3_0_2 as spdx3`."
],
"metadata": {
"id": "PC_h1XmSpIF3"
}
},
{
"cell_type": "markdown",
"source": [
"Once imported, we can now access SPDX 3 model.\n",
"\n",
"Let's print some \"named individuals\" from the model."
],
"metadata": {
"id": "9bWRkIYvpkzO"
}
},
{
"cell_type": "code",
"source": [
"list(spdx3.NAMED_INDIVIDUALS)[:8]"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "jh4qYAep0d-L",
"outputId": "27d02223-4ea0-4ba2-da64-41e9bf656193"
},
"execution_count": 6,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['https://spdx.org/rdf/3.0.1/terms/Core/PresenceType/noAssertion',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Core/HashAlgorithm/blake2b512',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Core/RelationshipType/reportedBy',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Software/SoftwarePurpose/manifest',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Core/HashAlgorithm/crystalsKyber',\n",
" 'https://spdx.org/rdf/3.0.1/terms/AI/SafetyRiskAssessmentType/medium',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Core/RelationshipType/modifiedBy',\n",
" 'https://spdx.org/rdf/3.0.1/terms/Core/ProfileIdentifierType/security']"
]
},
"metadata": {},
"execution_count": 6
}
]
},
{
"cell_type": "markdown",
"source": [
"Some of these could be entries in SPDX 3 vocabularies (enum)."
],
"metadata": {
"id": "x6C0wvWRqDIP"
}
},
{
"cell_type": "markdown",
"source": [
"## Read SPDX data from SPDX 3 JSON file"
],
"metadata": {
"id": "LeTPh0lsQZBw"
}
},
{
"cell_type": "markdown",
"source": [
"The library offers a built-in JSON-LD deserializer.\n",
"To use it, provide the path to your SPDX 3 JSON file and an instance of SHACLObjectSet.\n",
"The deserializer will read the JSON file and populate the SHACLObjectSet.\n",
"\n",
"SHACLObjectSet holds SHACLObjects, which are the primary data structures for\n",
"interaction within this library. It also includes helpful utilities, such as\n",
"a generator (iterator) for accessing objects by their type.\n",
"\n",
"In this example, we will first download the JSON file from the `spdx-examples` repository."
],
"metadata": {
"id": "wak3vYKObfXI"
}
},
{
"cell_type": "code",
"source": [
"from urllib.request import urlretrieve\n",
"\n",
"url = \"https://raw.githubusercontent.com/spdx/spdx-examples/refs/heads/master/ai/example02/spdx3.0/sbom.spdx.json\"\n",
"filename = \"sbom.spdx.json\"\n",
"filepath, _ = urlretrieve(url, filename) # download from url; get the filepath\n",
"\n",
"object_set = spdx3.SHACLObjectSet()\n",
"\n",
"with open(filepath, \"r\", encoding=\"utf-8\") as f:\n",
" spdx3.JSONLDDeserializer().read(f, object_set)\n",
"\n",
"print(object_set)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "JQ9lTkNdIckN",
"outputId": "839d4ff4-0a0f-4aa3-9e58-72080d0110da"
},
"execution_count": 7,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"<spdx_python_model.bindings.v3_0_1.SHACLObjectSet object at 0x7c98d9f36ae0>\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## Some internal works of SHACLObjectSet"
],
"metadata": {
"id": "8llGik8aQdct"
}
},
{
"cell_type": "markdown",
"source": [
"Internally SHACLObjectSet keeps objects in its `objects` set."
],
"metadata": {
"id": "jbEuuu53b0Eb"
}
},
{
"cell_type": "code",
"source": [
"# see what is inside\n",
"print(list(object_set.objects)[:3])"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "y1z84-MK6cnx",
"outputId": "b303b2a0-79e5-4b02-a583-d3a74c312e00"
},
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[<spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f74830>, <spdx_python_model.bindings.v3_0_1.software_File object at 0x7c98d8f308c0>, <spdx_python_model.bindings.v3_0_1.software_File object at 0x7c98d9c8b0e0>]\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Internally, for faster lookup, SHACLObjectSet maintains two indexes:\n",
"`obj_by_id` and `obj_by_type`.\n",
"\n",
"`obj_by_id` is a dictionary where:\n",
"- Keys are the `spdxId` property values of the objects.\n",
"- Values are the corresponding SHACLObject instances.\n",
"\n",
"`obj_by_type` is a dictionary where:\n",
"- Keys are the `type` property values of the objects.\n",
" (e.g., \"SpdxDocument\", \"software_Package\", \"simplelicensing_LicenseExpression\").\n",
" Note: Core Profile types do not require a prefix, while other Profiles do (e.g., \"software_\").\n",
"- Values are sets of tuples. Each tuple contains:\n",
" 1. A boolean indicating if the SHACLObject in this tuple is an exact type match (True)\n",
" or a subclass match (False); and\n",
" 2. The SHACLObject instance itself."
],
"metadata": {
"id": "4sqtE2vVcDnx"
}
},
{
"cell_type": "code",
"source": [
"any_license_infos = object_set.obj_by_type[\"simplelicensing_AnyLicenseInfo\"]\n",
"print(any_license_infos)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xb-edy3n4eRh",
"outputId": "4d6f398d-47d6-4862-ffb3-21ab2adb11a3"
},
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"{(False, <spdx_python_model.bindings.v3_0_1.simplelicensing_LicenseExpression object at 0x7c98d9b16150>)}\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Let's begin with a quick check.\n",
"\n",
"For example, we can see how many SpdxDocument objects are present\n",
"and if it is according to the specification.\n",
"\n",
"See: https://spdx.github.io/spdx-spec/v3.0.1/serializations/#serialization-information"
],
"metadata": {
"id": "S17Cuqt5cgiY"
}
},
{
"cell_type": "code",
"source": [
"spdx_documents = list(object_set.obj_by_type[\"SpdxDocument\"])\n",
"\n",
"if len(spdx_documents) > 1:\n",
" print(\"Warning: A serialization must not contain more than one SpdxDocument.\")\n",
"else:\n",
" print(\"Looks good.\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "S-Q78uecJ-m9",
"outputId": "7693e602-bf2a-47ca-d798-f23bae99c238"
},
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Looks good.\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# Get all objects of type \"Relationship\", including its subclasses\n",
"relationships = object_set.obj_by_type[\"Relationship\"]\n",
"print(\"Relationship found:\", len(relationships))\n",
"for o in relationships:\n",
" print(o)\n",
"print()\n",
"\n",
"# Get all objects of type \"LifecycleScopedRelationship\", including its subclasses\n",
"lifecycle_scoped_relationships = object_set.obj_by_type[\"LifecycleScopedRelationship\"]\n",
"print(\"LifecycleScopedRelationship found:\", len(lifecycle_scoped_relationships))\n",
"for o in lifecycle_scoped_relationships:\n",
" print(o)\n",
"print()\n",
"\n",
"# Get all objects of type \"Softare/Package\", including its subclasses\n",
"packages = object_set.obj_by_type[\"software_Package\"]\n",
"print(\"software_Package found:\", len(packages))\n",
"for o in packages:\n",
" print(o)\n",
"\n",
"print()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "1tiaPV-FKmZh",
"outputId": "6ea12c09-986b-49c7-a97a-a501544d87f9"
},
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Relationship found: 15\n",
"(False, <spdx_python_model.bindings.v3_0_1.LifecycleScopedRelationship object at 0x7c98d8f75190>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f74830>)\n",
"(False, <spdx_python_model.bindings.v3_0_1.LifecycleScopedRelationship object at 0x7c98d8f74950>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f75610>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f742c0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f74a70>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f33c20>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f753d0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f745f0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d9b97920>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f743b0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f754f0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f74710>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f752b0>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.Relationship object at 0x7c98d8f744d0>)\n",
"\n",
"LifecycleScopedRelationship found: 2\n",
"(True, <spdx_python_model.bindings.v3_0_1.LifecycleScopedRelationship object at 0x7c98d8f75190>)\n",
"(True, <spdx_python_model.bindings.v3_0_1.LifecycleScopedRelationship object at 0x7c98d8f74950>)\n",
"\n",
"software_Package found: 2\n",
"(False, <spdx_python_model.bindings.v3_0_1.ai_AIPackage object at 0x7c98d9c59310>)\n",
"(False, <spdx_python_model.bindings.v3_0_1.dataset_DatasetPackage object at 0x7c98d8f30dd0>)\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## A proper way to get access to SPDX objects"
],
"metadata": {
"id": "qY3_-XIGQoKT"
}
},
{
"cell_type": "markdown",
"source": [
"While direct access to `obj_by_id` and `obj_by_type` is possible,\n",
"it is generally recommended to use the provided access methods for better\n",
"encapsulation. These methods include `find_by_id` and `foreach_type`.\n",
"\n",
"SHACLObjectSet offers the `find_by_id` method to retrieve a specific object\n",
"using its unique `spdxId`."
],
"metadata": {
"id": "uqNOwXXAczeW"
}
},
{
"cell_type": "code",
"source": [
"obj = object_set.find_by_id(\"https://spdx.org/spdxdocs/Sbom1-b1b4ff24-5ada-4c22-a9c9-7bd7121978ff\")\n",
"print(obj)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "c-28HXbkudie",
"outputId": "a841dc1e-7a8c-4333-f418-b11d33523e10"
},
"execution_count": 12,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"software_Sbom(@id='https://spdx.org/spdxdocs/Sbom1-b1b4ff24-5ada-4c22-a9c9-7bd7121978ff')\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"SHACLObjectSet also provides `foreach_type`, a generator method that\n",
"iterates over all objects of a specified type.\n",
"\n",
"By default, `foreach_type` will also return instances of subclasses."
],
"metadata": {
"id": "wyvA-i5fdB80"
}
},
{
"cell_type": "code",
"source": [
"for obj in object_set.foreach_type(\"Relationship\"):\n",
" print(obj)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Qjz-D9iz_p8n",
"outputId": "2da78892-6810-4d50-d626-7d569fd3dec4"
},
"execution_count": 13,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"LifecycleScopedRelationship(@id='https://spdx.org/spdxdocs/Relationship/generates2-02ec04c7-b248-4472-b017-da7c04145ec2')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains9-c09ce78c-fa22-4110-9232-e246ea989999')\n",
"LifecycleScopedRelationship(@id='https://spdx.org/spdxdocs/Relationship/generates1-01bd0839-cb33-4446-9cae-b01c9148d221')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/testedOn1-01efd83b-b615-4099-a9b7-e0c7db47fdd8')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDeclaredLicense3-d3e53884-69b0-404d-b297-e2180d2724be')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDataFile1-016903ab-f618-4aaf-87f7-f260e37874f1')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasConcludedLicense1-c18ca8f8-32f1-4682-a136-51c32a5d555a')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDocumentation1-1dcbd2c2-f6aa-4059-95b6-8574e598e619')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains3-c03bf106-fc40-4bd3-93a6-bac2235bb71b')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDeclaredLicense1-d1741c4c-4c18-459a-b9f9-e24f018e39f1')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasConcludedLicense3-c3e6ff66-b9da-4529-bd8b-dc75a13baad3')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/trainedOn1-01b4b32c-7854-4c31-9bf0-95f2e5805b66')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains8-c087fb75-9ca8-4952-974d-87cb207375a6')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDependencyManifest1-1deb949d-5874-4b8e-a779-188e3ce4c420')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains1-c01b64da-fda5-4338-9425-da853192e79a')\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Notice the presence of `LifecycleScopedRelationship`, which is a subclass of `Relationship`."
],
"metadata": {
"id": "24pEngfddGw1"
}
},
{
"cell_type": "markdown",
"source": [
"Set `match_subclass` argument to False, to exclude subclasses.\n"
],
"metadata": {
"id": "6YbhPUpqdSZ9"
}
},
{
"cell_type": "code",
"source": [
"for obj in object_set.foreach_type(\"Relationship\", match_subclass=False):\n",
" print(obj)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "CLSKgtC7yRmt",
"outputId": "fe1bab8b-05fe-4ad2-b7bf-70ca3c636925"
},
"execution_count": 14,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains9-c09ce78c-fa22-4110-9232-e246ea989999')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/testedOn1-01efd83b-b615-4099-a9b7-e0c7db47fdd8')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDeclaredLicense3-d3e53884-69b0-404d-b297-e2180d2724be')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDataFile1-016903ab-f618-4aaf-87f7-f260e37874f1')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasConcludedLicense1-c18ca8f8-32f1-4682-a136-51c32a5d555a')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDocumentation1-1dcbd2c2-f6aa-4059-95b6-8574e598e619')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains3-c03bf106-fc40-4bd3-93a6-bac2235bb71b')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDeclaredLicense1-d1741c4c-4c18-459a-b9f9-e24f018e39f1')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasConcludedLicense3-c3e6ff66-b9da-4529-bd8b-dc75a13baad3')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/trainedOn1-01b4b32c-7854-4c31-9bf0-95f2e5805b66')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains8-c087fb75-9ca8-4952-974d-87cb207375a6')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/hasDependencyManifest1-1deb949d-5874-4b8e-a779-188e3ce4c420')\n",
"Relationship(@id='https://spdx.org/spdxdocs/Relationship/contains1-c01b64da-fda5-4338-9425-da853192e79a')\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Notice the absence of `LifecycleScopedRelationship` this time."
],
"metadata": {
"id": "_uwUlUordW9R"
}
},
{
"cell_type": "markdown",
"source": [
"Because `foreach_type` is a generator, you can use it like this as well:\n",
"\n",
"\n"
],
"metadata": {
"id": "pDSVRsAXdcqM"
}
},
{
"cell_type": "code",
"source": [
"objs = set(object_set.foreach_type(\"Relationship\", match_subclass=False))\n",
"print(len(objs))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "1uVFmeYQAcSC",
"outputId": "d4320574-8540-4f0a-d82c-170d4e0bc386"
},
"execution_count": 15,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"13\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## Accessing SPDX properties"
],
"metadata": {
"id": "0GpZV9m1QzI1"
}
},
{
"cell_type": "markdown",
"source": [
"SPDX objects and their properties can be accessed directly from Python attributes.\n",
"\n",
"For example, this SpdxDocument `doc` has an attribute `creationInfo`\n",
"and the value of `creationInfo` is a CreationInfo object.\n",
"We can directly access `specVersion` attribute of the CreationInfo object like this."
],
"metadata": {
"id": "vnpIoFf1dli8"
}
},
{
"cell_type": "code",
"source": [
"doc = list(object_set.foreach_type(\"SpdxDocument\", match_subclass=False))[0]\n",
"print(\"SPDX Spec Version:\", doc.creationInfo.specVersion)\n",
"\n",
"root_element = doc.rootElement[0] # assume we have only one root element\n",
"print(\"Root element ID:\", root_element.spdxId)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "pXl50kABJXnw",
"outputId": "fb92b1ef-16eb-488a-bd83-8b8cd9ae9d43"
},
"execution_count": 16,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"SPDX Spec Version: 3.0.1\n",
"Root element ID: https://spdx.org/spdxdocs/Sbom1-b1b4ff24-5ada-4c22-a9c9-7bd7121978ff\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"The SPDX specification defines the classes and properties of SPDX models.\n",
"\n",
"For example, the SpdxDocument class is detailed at: https://spdx.github.io/spdx-spec/v3.0.1/model/Core/Classes/SpdxDocument/"
],
"metadata": {
"id": "VgA7RhdiPZjl"
}
},
{
"cell_type": "markdown",
"source": [
"## Put things together\n",
"\n",
"We can now perform basic object access.\n",
"Let's try to visualize an SPDX SBOM.\n",
"\n",
"The example below will iterate through all relationships and print relationship types between SPDX objects."
],
"metadata": {
"id": "rNdl2dqiPht8"
}
},
{
"cell_type": "code",
"source": [
"for rel in object_set.foreach_type(\"Relationship\"):\n",
" from_ = getattr(rel, \"from_\") # spdx-python-model uses \"from_\" instead of \"from\" to avoid the Python keyword\n",
" to = getattr(rel, \"to\")\n",
" rel_type = getattr(rel, \"relationshipType\").split(\"/\")[-1] # print only the type name, not the full URL\n",
"\n",
" print( \"┏\" + \"━\"*50 + \"┅\")\n",
" print(f\"┃ {from_.__class__.__name__}\")\n",
" print(f\"┃ - name: {from_.name}\")\n",
" print(f\"┃ - spdxId: {from_.spdxId}\")\n",
" print( \"┗\" + \"━\"*50 + \"┅\")\n",
"\n",
" print( \" │\")\n",
" print(f\" {rel_type}\")\n",
" print( \" ↓\")\n",
"\n",
" for o in to:\n",
" print( \" ┏\" + \"━\"*50 + \"┅\")\n",
" print(f\" ┃ {o.__class__.__name__}\")\n",
" print(f\" ┃ - name: {o.name}\")\n",
" print(f\" ┃ - spdxId: {o.spdxId}\")\n",
" print( \" ┗\" + \"━\"*50 + \"┅\")\n",
"\n",
" print()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "pAgJZnDJU4Jf",
"outputId": "9901f529-3df2-44fb-f012-c399d4c3b0c5"
},
"execution_count": 17,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: train.py\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File15-f15b29a6-9634-4813-aa99-9986891a0711\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" generates\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: model.bin\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File10-f10f9f75-3a23-465e-a80d-3a4fec75b220\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: techdocs\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File3-d36bc4df-b88e-4e0c-8aeb-ec446dbae90f\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" contains\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: dataprepare.md\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File31-f31f6dc0-f9ce-4efa-9ccd-47dee50041d3\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: instructions.md\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File32-f32f0784-038e-488d-a7bf-7d172dfe8b8a\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: preprocess.py\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File12-f12effed-9289-4fc3-986a-5fd83ff6724c\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" generates\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: test.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File16-f16c17ad-d95d-40d6-860f-1bacde2dbfd9\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: train.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File17-f17f40d2-0540-4d2b-9f23-1b58d7ab4652\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: valid.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File18-f18be0d7-d16f-4658-91f3-5e5cf364edfa\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: model.bin\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File10-f10f9f75-3a23-465e-a80d-3a4fec75b220\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" testedOn\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: test.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File16-f16c17ad-d95d-40d6-860f-1bacde2dbfd9\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ ai_AIPackage\n",
"┃ - name: Sentiment Demo: A Simple AI Application and its AI BOM Example\n",
"┃ - spdxId: https://spdx.org/spdxdocs/AIPackage1-a1fae2b4-2c1a-4f21-9001-1bdc5ac9e481\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasDeclaredLicense\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ simplelicensing_LicenseExpression\n",
" ┃ - name: None\n",
" ┃ - spdxId: https://spdx.org/licenses/CC0-1.0\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: predict.py\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File11-f11e140e-67ef-48db-bb4a-7fcb3775406f\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasDataFile\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: model.bin\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File10-f10f9f75-3a23-465e-a80d-3a4fec75b220\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ dataset_DatasetPackage\n",
"┃ - name: Data after preprocessing\n",
"┃ - spdxId: https://spdx.org/spdxdocs/DatasetPackage1-d1f693d0-b420-4b6a-b9f2-ec2097bac863\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasConcludedLicense\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ simplelicensing_LicenseExpression\n",
" ┃ - name: None\n",
" ┃ - spdxId: https://spdx.org/licenses/CC0-1.0\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ ai_AIPackage\n",
"┃ - name: Sentiment Demo: A Simple AI Application and its AI BOM Example\n",
"┃ - spdxId: https://spdx.org/spdxdocs/AIPackage1-a1fae2b4-2c1a-4f21-9001-1bdc5ac9e481\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasDocumentation\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: techdocs\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File3-d36bc4df-b88e-4e0c-8aeb-ec446dbae90f\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: LICENSE\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File9-f09b8718-e9ab-4d89-97b5-940988fdf050\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: README.md\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File13-f13b1a21-3183-4eb8-a4c2-c4c0e2f55d50\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: data\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File1-d1f75466-39c8-4d2b-8ec9-79f67e8a20d7\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" contains\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: test.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File16-f16c17ad-d95d-40d6-860f-1bacde2dbfd9\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: train.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File17-f17f40d2-0540-4d2b-9f23-1b58d7ab4652\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: valid.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File18-f18be0d7-d16f-4658-91f3-5e5cf364edfa\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ dataset_DatasetPackage\n",
"┃ - name: Data after preprocessing\n",
"┃ - spdxId: https://spdx.org/spdxdocs/DatasetPackage1-d1f693d0-b420-4b6a-b9f2-ec2097bac863\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasDeclaredLicense\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ simplelicensing_LicenseExpression\n",
" ┃ - name: None\n",
" ┃ - spdxId: https://spdx.org/licenses/CC0-1.0\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ ai_AIPackage\n",
"┃ - name: Sentiment Demo: A Simple AI Application and its AI BOM Example\n",
"┃ - spdxId: https://spdx.org/spdxdocs/AIPackage1-a1fae2b4-2c1a-4f21-9001-1bdc5ac9e481\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasConcludedLicense\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ simplelicensing_LicenseExpression\n",
" ┃ - name: None\n",
" ┃ - spdxId: https://spdx.org/licenses/CC0-1.0\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ software_File\n",
"┃ - name: model.bin\n",
"┃ - spdxId: https://spdx.org/spdxdocs/File10-f10f9f75-3a23-465e-a80d-3a4fec75b220\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" trainedOn\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: train.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File17-f17f40d2-0540-4d2b-9f23-1b58d7ab4652\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: valid.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File18-f18be0d7-d16f-4658-91f3-5e5cf364edfa\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ ai_AIPackage\n",
"┃ - name: Sentiment Demo: A Simple AI Application and its AI BOM Example\n",
"┃ - spdxId: https://spdx.org/spdxdocs/AIPackage1-a1fae2b4-2c1a-4f21-9001-1bdc5ac9e481\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" contains\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: techdocs\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File3-d36bc4df-b88e-4e0c-8aeb-ec446dbae90f\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: evaluate.py\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File8-f08b4fa4-2658-421b-80e9-e9ab116102de\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: LICENSE\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File9-f09b8718-e9ab-4d89-97b5-940988fdf050\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: model.bin\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File10-f10f9f75-3a23-465e-a80d-3a4fec75b220\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: predict.py\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File11-f11e140e-67ef-48db-bb4a-7fcb3775406f\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: preprocess.py\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File12-f12effed-9289-4fc3-986a-5fd83ff6724c\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: README.md\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File13-f13b1a21-3183-4eb8-a4c2-c4c0e2f55d50\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: requirements.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File14-f14b0f00-1396-4986-8ca9-5d59b9362826\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: train.py\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File15-f15b29a6-9634-4813-aa99-9986891a0711\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ ai_AIPackage\n",
"┃ - name: Sentiment Demo: A Simple AI Application and its AI BOM Example\n",
"┃ - spdxId: https://spdx.org/spdxdocs/AIPackage1-a1fae2b4-2c1a-4f21-9001-1bdc5ac9e481\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" hasDependencyManifest\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: requirements.txt\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File14-f14b0f00-1396-4986-8ca9-5d59b9362826\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n",
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"┃ dataset_DatasetPackage\n",
"┃ - name: Data after preprocessing\n",
"┃ - spdxId: https://spdx.org/spdxdocs/DatasetPackage1-d1f693d0-b420-4b6a-b9f2-ec2097bac863\n",
"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" │\n",
" contains\n",
" ↓\n",
" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
" ┃ software_File\n",
" ┃ - name: data\n",
" ┃ - spdxId: https://spdx.org/spdxdocs/File1-d1f75466-39c8-4d2b-8ec9-79f67e8a20d7\n",
" ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┅\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## That's it\n",
"\n",
"That's it for now! Hope you enjoyed the tutorial.\n",
"\n",
"Special thanks to Joshua Watt for the spdx-python-model library, making SPDX 3 more accessible for Python developers.\n",
"\n",
"Find more examples of how to use the library:\n",
"\n",
"- `spdx-python-model` tests: https://github.com/spdx/spdx-python-model/blob/main/tests/test_import.py\n",
"- `shacl2code` (which generates spdx-python-model's Python binding) tests: https://github.com/JPEWdev/shacl2code/blob/main/tests/test_python.py\n"
],
"metadata": {
"id": "lqg60qPeLaI3"
}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment