1# Copyright (c) 2021 The Linux Foundation 2# 3# SPDX-License-Identifier: Apache-2.0 4 5from dataclasses import dataclass, field 6from enum import Enum 7from typing import Optional 8 9 10# DocumentConfig contains settings used to configure how the SPDX Document 11# should be built. 12@dataclass(eq=True) 13class DocumentConfig: 14 # name of document 15 name: str = "" 16 17 # namespace for this document 18 namespace: str = "" 19 20 # standardized DocumentRef- (including that prefix) that the other 21 # docs will use to refer to this one 22 docRefID: str = "" 23 24 25# Document contains the data assembled by the SBOM builder, to be used to 26# create the actual SPDX Document. 27class Document: 28 # initialize with a DocumentConfig 29 def __init__(self, cfg): 30 super().__init__() 31 32 # configuration - DocumentConfig 33 self.cfg = cfg 34 35 # dict of SPDX ID => Package 36 self.pkgs = {} 37 38 # relationships "owned" by this Document, _not_ those "owned" by its 39 # Packages or Files; will likely be just DESCRIBES 40 self.relationships = [] 41 42 # dict of filename (ignoring its directory) => number of times it has 43 # been seen while adding files to this Document; used to calculate 44 # useful SPDX IDs 45 self.timesSeen = {} 46 47 # dict of absolute path on disk => File 48 self.fileLinks = {} 49 50 # set of other Documents that our elements' Relationships refer to 51 self.externalDocuments = set() 52 53 # set of LicenseRef- custom licenses to be declared 54 # may or may not include "LicenseRef-" license prefix 55 self.customLicenseIDs = set() 56 57 # this Document's SHA1 hash, filled in _after_ the Document has been 58 # written to disk, so that others can refer to it 59 self.myDocSHA1 = "" 60 61 62# PackageConfig contains settings used to configure how an SPDX Package should 63# be built. 64@dataclass(eq=True) 65class PackageConfig: 66 # package name 67 name: str = "" 68 69 # SPDX ID, including "SPDXRef-" 70 spdxID: str = "" 71 72 # primary package purpose (ex. "LIBRARY", "APPLICATION", etc.) 73 primaryPurpose: str = "" 74 75 # package URL 76 url: str = "" 77 78 # package version 79 version: str = "" 80 81 # package revision 82 revision: str = "" 83 84 # package supplier or vendor 85 supplier: str = "" 86 87 # package external references 88 externalReferences: list = field(default_factory=list) 89 90 # the Package's declared license 91 declaredLicense: str = "NOASSERTION" 92 93 # the Package's copyright text 94 copyrightText: str = "NOASSERTION" 95 96 # absolute path of the "root" directory on disk, to be used as the 97 # base directory from which this Package's Files will calculate their 98 # relative paths 99 # may want to note this in a Package comment field 100 relativeBaseDir: str = "" 101 102 103# Package contains the data assembled by the SBOM builder, to be used to 104# create the actual SPDX Package. 105class Package: 106 # initialize with: 107 # 1) PackageConfig 108 # 2) the Document that owns this Package 109 def __init__(self, cfg, doc): 110 super().__init__() 111 112 # configuration - PackageConfig 113 self.cfg = cfg 114 115 # Document that owns this Package 116 self.doc = doc 117 118 # verification code, calculated per section 7.9 of SPDX spec v2.3 119 self.verificationCode = "" 120 121 # concluded license for this Package, if 122 # cfg.shouldConcludePackageLicense == True; NOASSERTION otherwise 123 self.concludedLicense = "NOASSERTION" 124 125 # list of licenses found in this Package's Files 126 self.licenseInfoFromFiles = [] 127 128 # Files in this Package 129 # dict of SPDX ID => File 130 self.files = {} 131 132 # Relationships "owned" by this Package (e.g., this Package is left 133 # side) 134 self.rlns = [] 135 136 # If this Package was a target, which File was its main build product? 137 self.targetBuildFile = None 138 139 140# RelationshipDataElementType defines whether a RelationshipData element 141# (e.g., the "owner" or the "other" element) is a File, a target Package, 142# a Package's ID (as other only, and only where owner type is DOCUMENT), 143# or the SPDX document itself (as owner only). 144class RelationshipDataElementType(Enum): 145 UNKNOWN = 0 146 FILENAME = 1 147 TARGETNAME = 2 148 PACKAGEID = 3 149 DOCUMENT = 4 150 151 152# RelationshipData contains the pre-analysis data about a relationship between 153# Files and/or Packages/targets. It is eventually parsed into a corresponding 154# Relationship after we have organized the SPDX Package and File data. 155@dataclass(eq=True) 156class RelationshipData: 157 # for the "owner" element (e.g., the left side of the Relationship), 158 # is it a filename or a target name (e.g., a Package in the build doc) 159 ownerType: RelationshipDataElementType = RelationshipDataElementType.UNKNOWN 160 161 # owner file absolute path (if ownerType is FILENAME) 162 ownerFileAbspath: str = "" 163 164 # owner target name (if ownerType is TARGETNAME) 165 ownerTargetName: str = "" 166 167 # owner SPDX Document (if ownerType is DOCUMENT) 168 ownerDocument: Optional['Document'] = None 169 170 # for the "other" element (e.g., the right side of the Relationship), 171 # is it a filename or a target name (e.g., a Package in the build doc) 172 otherType: RelationshipDataElementType = RelationshipDataElementType.UNKNOWN 173 174 # other file absolute path (if otherType is FILENAME) 175 otherFileAbspath: str = "" 176 177 # other target name (if otherType is TARGETNAME) 178 otherTargetName: str = "" 179 180 # other package ID (if ownerType is DOCUMENT and otherType is PACKAGEID) 181 otherPackageID: str = "" 182 183 # text string with Relationship type 184 # from table 68 in section 11.1 of SPDX spec v2.3 185 rlnType: str = "" 186 187 188# Relationship contains the post-analysis, processed data about a relationship 189# in a form suitable for creating the actual SPDX Relationship in a particular 190# Document's context. 191@dataclass(eq=True) 192class Relationship: 193 # SPDX ID for left side of relationship 194 # including "SPDXRef-" as well as "DocumentRef-" if needed 195 refA: str = "" 196 197 # SPDX ID for right side of relationship 198 # including "SPDXRef-" as well as "DocumentRef-" if needed 199 refB: str = "" 200 201 # text string with Relationship type 202 # from table 68 in section 11.1 of SPDX spec v2.3 203 rlnType: str = "" 204 205 206# File contains the data needed to create a File element in the context of a 207# particular SPDX Document and Package. 208class File: 209 # initialize with: 210 # 1) Document containing this File 211 # 2) Package containing this File 212 def __init__(self, doc, pkg): 213 super().__init__() 214 215 # absolute path to this file on disk 216 self.abspath = "" 217 218 # relative path for this file, measured from the owning Package's 219 # cfg.relativeBaseDir 220 self.relpath = "" 221 222 # SPDX ID for this file, including "SPDXRef-" 223 self.spdxID = "" 224 225 # SHA1 hash 226 self.sha1 = "" 227 228 # SHA256 hash, if pkg.cfg.doSHA256 == True; empty string otherwise 229 self.sha256 = "" 230 231 # MD5 hash, if pkg.cfg.doMD5 == True; empty string otherwise 232 self.md5 = "" 233 234 # concluded license, if pkg.cfg.shouldConcludeFileLicenses == True; 235 # "NOASSERTION" otherwise 236 self.concludedLicense = "NOASSERTION" 237 238 # license info in file 239 self.licenseInfoInFile = [] 240 241 # copyright text 242 self.copyrightText = "NOASSERTION" 243 244 # Relationships "owned" by this File (e.g., this File is left side) 245 self.rlns = [] 246 247 # Package that owns this File 248 self.pkg = pkg 249 250 # Document that owns this File 251 self.doc = doc 252