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 external references 85 externalReferences: list = field(default_factory=list) 86 87 # the Package's declared license 88 declaredLicense: str = "NOASSERTION" 89 90 # the Package's copyright text 91 copyrightText: str = "NOASSERTION" 92 93 # absolute path of the "root" directory on disk, to be used as the 94 # base directory from which this Package's Files will calculate their 95 # relative paths 96 # may want to note this in a Package comment field 97 relativeBaseDir: str = "" 98 99 100# Package contains the data assembled by the SBOM builder, to be used to 101# create the actual SPDX Package. 102class Package: 103 # initialize with: 104 # 1) PackageConfig 105 # 2) the Document that owns this Package 106 def __init__(self, cfg, doc): 107 super().__init__() 108 109 # configuration - PackageConfig 110 self.cfg = cfg 111 112 # Document that owns this Package 113 self.doc = doc 114 115 # verification code, calculated per section 7.9 of SPDX spec v2.3 116 self.verificationCode = "" 117 118 # concluded license for this Package, if 119 # cfg.shouldConcludePackageLicense == True; NOASSERTION otherwise 120 self.concludedLicense = "NOASSERTION" 121 122 # list of licenses found in this Package's Files 123 self.licenseInfoFromFiles = [] 124 125 # Files in this Package 126 # dict of SPDX ID => File 127 self.files = {} 128 129 # Relationships "owned" by this Package (e.g., this Package is left 130 # side) 131 self.rlns = [] 132 133 # If this Package was a target, which File was its main build product? 134 self.targetBuildFile = None 135 136 137# RelationshipDataElementType defines whether a RelationshipData element 138# (e.g., the "owner" or the "other" element) is a File, a target Package, 139# a Package's ID (as other only, and only where owner type is DOCUMENT), 140# or the SPDX document itself (as owner only). 141class RelationshipDataElementType(Enum): 142 UNKNOWN = 0 143 FILENAME = 1 144 TARGETNAME = 2 145 PACKAGEID = 3 146 DOCUMENT = 4 147 148 149# RelationshipData contains the pre-analysis data about a relationship between 150# Files and/or Packages/targets. It is eventually parsed into a corresponding 151# Relationship after we have organized the SPDX Package and File data. 152@dataclass(eq=True) 153class RelationshipData: 154 # for the "owner" element (e.g., the left side of the Relationship), 155 # is it a filename or a target name (e.g., a Package in the build doc) 156 ownerType: RelationshipDataElementType = RelationshipDataElementType.UNKNOWN 157 158 # owner file absolute path (if ownerType is FILENAME) 159 ownerFileAbspath: str = "" 160 161 # owner target name (if ownerType is TARGETNAME) 162 ownerTargetName: str = "" 163 164 # owner SPDX Document (if ownerType is DOCUMENT) 165 ownerDocument: Optional['Document'] = None 166 167 # for the "other" element (e.g., the right side of the Relationship), 168 # is it a filename or a target name (e.g., a Package in the build doc) 169 otherType: RelationshipDataElementType = RelationshipDataElementType.UNKNOWN 170 171 # other file absolute path (if otherType is FILENAME) 172 otherFileAbspath: str = "" 173 174 # other target name (if otherType is TARGETNAME) 175 otherTargetName: str = "" 176 177 # other package ID (if ownerType is DOCUMENT and otherType is PACKAGEID) 178 otherPackageID: str = "" 179 180 # text string with Relationship type 181 # from table 68 in section 11.1 of SPDX spec v2.3 182 rlnType: str = "" 183 184 185# Relationship contains the post-analysis, processed data about a relationship 186# in a form suitable for creating the actual SPDX Relationship in a particular 187# Document's context. 188@dataclass(eq=True) 189class Relationship: 190 # SPDX ID for left side of relationship 191 # including "SPDXRef-" as well as "DocumentRef-" if needed 192 refA: str = "" 193 194 # SPDX ID for right side of relationship 195 # including "SPDXRef-" as well as "DocumentRef-" if needed 196 refB: str = "" 197 198 # text string with Relationship type 199 # from table 68 in section 11.1 of SPDX spec v2.3 200 rlnType: str = "" 201 202 203# File contains the data needed to create a File element in the context of a 204# particular SPDX Document and Package. 205class File: 206 # initialize with: 207 # 1) Document containing this File 208 # 2) Package containing this File 209 def __init__(self, doc, pkg): 210 super().__init__() 211 212 # absolute path to this file on disk 213 self.abspath = "" 214 215 # relative path for this file, measured from the owning Package's 216 # cfg.relativeBaseDir 217 self.relpath = "" 218 219 # SPDX ID for this file, including "SPDXRef-" 220 self.spdxID = "" 221 222 # SHA1 hash 223 self.sha1 = "" 224 225 # SHA256 hash, if pkg.cfg.doSHA256 == True; empty string otherwise 226 self.sha256 = "" 227 228 # MD5 hash, if pkg.cfg.doMD5 == True; empty string otherwise 229 self.md5 = "" 230 231 # concluded license, if pkg.cfg.shouldConcludeFileLicenses == True; 232 # "NOASSERTION" otherwise 233 self.concludedLicense = "NOASSERTION" 234 235 # license info in file 236 self.licenseInfoInFile = [] 237 238 # copyright text 239 self.copyrightText = "NOASSERTION" 240 241 # Relationships "owned" by this File (e.g., this File is left side) 242 self.rlns = [] 243 244 # Package that owns this File 245 self.pkg = pkg 246 247 # Document that owns this File 248 self.doc = doc 249