Skip to content

Commit

Permalink
[issue-185] squash review commits
Browse files Browse the repository at this point in the history
Signed-off-by: Meret Behrens <meret.behrens@tngtech.com>
  • Loading branch information
meretp committed Nov 28, 2022
1 parent 94d5716 commit 72780a4
Show file tree
Hide file tree
Showing 27 changed files with 303 additions and 237 deletions.
8 changes: 4 additions & 4 deletions examples/write_tv.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from spdx.review import Review
from spdx.package import Package
from spdx.file import File, FileType
from spdx.checksum import Algorithm
from spdx.checksum import Checksum
from spdx.utils import SPDXNone, NoAssert, UnKnown

doc = Document()
Expand All @@ -36,7 +36,7 @@
testfile1.type = FileType.BINARY
testfile1.spdx_id = "TestFilet#SPDXRef-FILE"
testfile1.comment = "This is a test file."
testfile1.chksum = Algorithm("SHA1", "c537c5d99eca5333f23491d47ededd083fefb7ad")
testfile1.chksum = Checksum("SHA1", "c537c5d99eca5333f23491d47ededd083fefb7ad")
testfile1.conc_lics = License.from_identifier("BSD-2-Clause")
testfile1.add_lics(License.from_identifier("BSD-2-Clause"))
testfile1.copyright = SPDXNone()
Expand All @@ -48,7 +48,7 @@
testfile2.type = FileType.SOURCE
testfile2.spdx_id = "TestFile2#SPDXRef-FILE"
testfile2.comment = "This is a test file."
testfile2.chksum = Algorithm("SHA1", "bb154f28d1cf0646ae21bb0bec6c669a2b90e113")
testfile2.chksum = Checksum("SHA1", "bb154f28d1cf0646ae21bb0bec6c669a2b90e113")
testfile2.conc_lics = License.from_identifier("Apache-2.0")
testfile2.add_lics(License.from_identifier("Apache-2.0"))
testfile2.copyright = NoAssert()
Expand All @@ -62,7 +62,7 @@
package.file_name = "twt.jar"
package.spdx_id = 'TestPackage#SPDXRef-PACKAGE'
package.download_location = "http://www.tagwritetest.test/download"
package.checksum = Algorithm("SHA1", "c537c5d99eca5333f23491d47ededd083fefb7ad")
package.checksum = Checksum("SHA1", "c537c5d99eca5333f23491d47ededd083fefb7ad")
package.homepage = SPDXNone()
package.verif_code = "4e3211c67a2d28fced849ee1bb76e7391b93feba"
license_set = LicenseConjunction(
Expand Down
46 changes: 33 additions & 13 deletions spdx/checksum.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
# limitations under the License.
import re
from enum import Enum, auto
from typing import Optional



class ChecksumAlgorithmIdentifier(Enum):
class ChecksumAlgorithm(Enum):
SHA1 = auto()
SHA224 = auto()
SHA256 = auto()
Expand All @@ -32,27 +32,47 @@ class ChecksumAlgorithmIdentifier(Enum):
MD6 = auto()
ADLER32 = auto()

def checksum_to_rdf(self):
return "checksumAlgorithm_" + self.name.lower()
def algorithm_to_rdf_representation(self) -> str:
if self.name.startswith("BLAKE2B"):
return "checksumAlgorithm_" + self.name.replace("_", "").lower()
else:
return "checksumAlgorithm_" + self.name.lower()

@classmethod
def checksum_from_rdf(cls, identifier: str) -> str:
def checksum_from_rdf(cls, identifier: str) -> 'ChecksumAlgorithm':
identifier = identifier.split('_', 1)[-1].upper()
blake_checksum = re.compile(r"(BLAKE2B)\s*(256|384|512)", re.UNICODE)
blake_checksum = re.compile(r"^(BLAKE2B)(256|384|512)$", re.UNICODE)
match = blake_checksum.match(identifier)
if match:
return match[1] + '_' + match[2]
return identifier
identifier = match[1] + '_' + match[2]
if identifier not in ChecksumAlgorithm.__members__:
raise ValueError(f"Invalid algorithm for checksum: {identifier}")
return ChecksumAlgorithm[identifier]

@classmethod
def checksum_algorithm_from_string(cls, identifier: str) -> 'ChecksumAlgorithm':
identifier.replace("-", "_").upper()
if identifier not in ChecksumAlgorithm.__members__:
raise ValueError(f"Invalid algorithm for checksum: {identifier}")
return ChecksumAlgorithm[identifier]


class Algorithm(object):
class Checksum(object):
"""Generic checksum algorithm."""

def __init__(self, identifier: str, value):
if identifier.upper().replace('-', '_') not in ChecksumAlgorithmIdentifier.__members__:
raise ValueError('Invalid algorithm for Checksum: {}'.format(identifier))
def __init__(self, identifier: ChecksumAlgorithm, value: str):
self.identifier = identifier
self.value = value

@classmethod
def checksum_from_string(cls, value: str) -> 'Checksum':
CHECKSUM_RE = re.compile("(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|" \
"SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\\s*([a-fA-F0-9]*)")
match = CHECKSUM_RE.match(value)
if match is None or match.group(1) is None or match.group(2) is None:
raise ValueError(f"Invalid checksum: {value}")
identifier = ChecksumAlgorithm.checksum_algorithm_from_string(match.group(1))
return Checksum(identifier=identifier, value=match.group(2))

def to_tv(self):
return "{0}: {1}".format(self.identifier, self.value)
return "{0}: {1}".format(self.identifier.name, self.value)
6 changes: 3 additions & 3 deletions spdx/cli_tools/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def main(file, force):
)
print("Package Homepage: {0}".format(package.homepage))
for checksum in doc.package.checksums.values():
print("Package Checksum: {0} {1}".format(checksum.identifier, checksum.value))
print("Package Checksum: {0} {1}".format(checksum.identifier.name, checksum.value))
print("Package Attribution Text: {0}".format(package.attribution_text))
print("Package verification code: {0}".format(package.verif_code))
print(
Expand Down Expand Up @@ -82,8 +82,8 @@ def main(file, force):
print("\tFile name: {0}".format(f.name))
for file_type in f.file_types:
print("\tFile type: {0}".format(file_type.name))
for file_checksum in f.checksums:
print("\tFile Checksum: {0} {1}".format(file_checksum.identifier, file_checksum.value))
for file_checksum in f.checksums.values():
print("\tFile Checksum: {0} {1}".format(file_checksum.identifier.name, file_checksum.value))
print("\tFile license concluded: {0}".format(f.conc_lics))
print(
"\tFile license info in file: {0}".format(
Expand Down
12 changes: 6 additions & 6 deletions spdx/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,25 @@ class ExternalDocumentRef(object):
"""

def __init__(
self, external_document_id=None, spdx_document_uri=None, check_sum=None
self, external_document_id=None, spdx_document_uri=None, checksum=None
):
self.external_document_id = external_document_id
self.spdx_document_uri = spdx_document_uri
self.check_sum = check_sum
self.checksum = checksum

def __eq__(self, other):
return (
isinstance(other, ExternalDocumentRef)
and self.external_document_id == other.external_document_id
and self.spdx_document_uri == other.spdx_document_uri
and self.check_sum == other.check_sum
and self.checksum == other.checksum
)

def __lt__(self, other):
return (self.external_document_id, self.spdx_document_uri, self.check_sum) < (
return (self.external_document_id, self.spdx_document_uri, self.checksum) < (
other.external_document_id,
other.spdx_document_uri,
other.check_sum,
other.checksum,
)

def validate(self, messages: ErrorMessages) -> ErrorMessages:
Expand All @@ -74,7 +74,7 @@ def validate_spdx_doc_uri(self, messages):
messages.append("ExternalDocumentRef has no SPDX Document URI.")

def validate_checksum(self, messages):
if not self.check_sum:
if not self.checksum:
messages.append("ExternalDocumentRef has no Checksum.")


Expand Down
43 changes: 23 additions & 20 deletions spdx/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
from functools import total_ordering
import hashlib

from spdx.checksum import Algorithm, ChecksumAlgorithmIdentifier
from spdx import utils
from spdx.license import License
from spdx import utils
from spdx.checksum import Checksum, ChecksumAlgorithm
from spdx.parsers.builderexceptions import SPDXValueError
from spdx.parsers.loggers import ErrorMessages


class FileType(Enum):
Expand Down Expand Up @@ -59,7 +60,7 @@ class File(object):
referenced by other elements. Mandatory, one. Type: str.
- comment: File comment str, Optional zero or one.
- file_types: list of file types. Cardinality 0..*
- checksums: Dict with identifier of spdx.checksum.Algorithm as key and spdx.checksum.Algorithm as value,
- checksums: Dict with checksum.ChecksumAlgorithm as key and checksum.Checksum as value,
there must be a SHA1 hash, at least.
- conc_lics: Mandatory one. license.License or utils.NoAssert or utils.SPDXNone.
- licenses_in_file: list of licenses found in file, mandatory one or more.
Expand Down Expand Up @@ -101,22 +102,22 @@ def __lt__(self, other):
return self.name < other.name

@property
def chk_sum(self):
def checksum(self):
"""
Backwards compatibility, return SHA1 checksum.
"""
warnings.warn("This property is deprecated. Use get_checksum instead.")
return self.get_checksum(ChecksumAlgorithmIdentifier.SHA1)
return self.get_checksum(ChecksumAlgorithm.SHA1)

@chk_sum.setter
def chk_sum(self, value):
@checksum.setter
def checksum(self, value):
"""
Backwards compatibility, set checksum.
"""
warnings.warn("This property is deprecated. Use set_checksum instead.")
if isinstance(value, str):
self.set_checksum(Algorithm("SHA1", value))
elif isinstance(value, Algorithm):
self.set_checksum(Checksum("SHA1", value))
elif isinstance(value, Checksum):
self.set_checksum(value)

def add_lics(self, lics):
Expand Down Expand Up @@ -144,7 +145,7 @@ def validate(self, messages):
messages.push_context(self.name)
self.validate_concluded_license(messages)
self.validate_file_types(messages)
self.validate_checksum(messages)
self.validate_checksums(messages)
self.validate_licenses_in_file(messages)
self.validate_copyright(messages)
self.validate_artifacts(messages)
Expand Down Expand Up @@ -211,13 +212,16 @@ def validate_file_types(self, messages):
messages.append(f"{file_type} is not of type FileType.")
return messages

def validate_checksum(self, messages):
if self.get_checksum(ChecksumAlgorithmIdentifier.SHA1) is None:
def validate_checksums(self, messages: ErrorMessages):
for checksum in self.checksums.values():
if not isinstance(checksum, Checksum):
messages.append("File checksum must be instance of spdx.checksum.Checksum.")

if self.get_checksum(ChecksumAlgorithm.SHA1) is None:
messages.append("At least one file checksum algorithm must be SHA1")
return messages

def calculate_checksum(self, hash_algorithm='SHA1'):
if hash_algorithm not in ChecksumAlgorithmIdentifier.__members__:
if hash_algorithm not in ChecksumAlgorithm.__members__:
raise ValueError
BUFFER_SIZE = 65536

Expand All @@ -231,14 +235,13 @@ def calculate_checksum(self, hash_algorithm='SHA1'):

return file_hash.hexdigest()

def get_checksum(self, hash_algorithm: ChecksumAlgorithmIdentifier = ChecksumAlgorithmIdentifier.SHA1) -> Algorithm:
return self.checksums[hash_algorithm.name]
def get_checksum(self, hash_algorithm: ChecksumAlgorithm = ChecksumAlgorithm.SHA1) -> Checksum:
return self.checksums[hash_algorithm]

def set_checksum(self, new_checksum: Algorithm):
if not isinstance(new_checksum, Algorithm):
def set_checksum(self, new_checksum: Checksum):
if not isinstance(new_checksum, Checksum):
raise SPDXValueError
if new_checksum.identifier in self.checksums:
return

self.checksums[new_checksum.identifier] = new_checksum

def has_optional_field(self, field):
Expand Down
45 changes: 21 additions & 24 deletions spdx/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from spdx import creationinfo
from spdx import license
from spdx import utils
from spdx.checksum import Algorithm, ChecksumAlgorithmIdentifier
from spdx.checksum import Checksum, ChecksumAlgorithm
from spdx.parsers.builderexceptions import SPDXValueError
from spdx.parsers.loggers import ErrorMessages

Expand Down Expand Up @@ -60,7 +60,7 @@ class Package(object):
whenever files_analyzed is True or None (omitted) and Must be None (omitted)
if files_analyzed is False. However, as a convenience within this library,
we allow this to be Optional even when files_analyzed is True/None.
- checksums: Optional, Dict with identifier of spdx.checksum.Algorithm as key and spdx.checksum.Algorithm as value.
- checksums: Optional, Dict with checksum.ChecksumAlgorithm as key and checksum.Checksum as value.
- source_info: Optional string.
- conc_lics: Mandatory license.License or utils.SPDXNone or
utils.NoAssert.
Expand Down Expand Up @@ -120,22 +120,22 @@ def __init__(
self.valid_until_date: Optional[datetime] = None

@property
def check_sum(self):
def checksum(self):
"""
Backwards compatibility, return SHA1 checksum.
"""
warnings.warn("This property is deprecated. Use get_checksum instead.")
return self.get_checksum(ChecksumAlgorithmIdentifier.SHA1)
return self.get_checksum(ChecksumAlgorithm.SHA1)

@check_sum.setter
def check_sum(self, value):
@checksum.setter
def checksum(self, value):
"""
Backwards compatibility, set SHA1 checksum.
"""
warnings.warn("This property is deprecated. Use set_checksum instead.")
if isinstance(value, str):
self.set_checksum(Algorithm("SHA1", value))
elif isinstance(value, Algorithm):
self.set_checksum(Checksum("SHA1", value))
elif isinstance(value, Checksum):
self.set_checksum(value)

@property
Expand All @@ -160,7 +160,7 @@ def validate(self, messages):
"""
messages.push_context(self.name)
self.validate_files_analyzed(messages)
self.validate_checksum(messages)
self.validate_checksums(messages)
self.validate_optional_str_fields(messages)
self.validate_mandatory_str_fields(messages)
self.validate_pkg_ext_refs(messages)
Expand Down Expand Up @@ -291,23 +291,20 @@ def validate_str_fields(self, fields, optional, messages):

return messages

def validate_checksum(self, messages):
def validate_checksums(self, messages: ErrorMessages):
if not self.checksums:
return messages
try:
self.get_checksum(ChecksumAlgorithmIdentifier.SHA1)
except KeyError:
messages.append("At least one package checksum algorithm must be SHA1")
return messages

def get_checksum(self, hash_algorithm: ChecksumAlgorithmIdentifier = ChecksumAlgorithmIdentifier.SHA1) -> Algorithm:
return self.checksums[hash_algorithm.name]

def set_checksum(self, new_checksum: Algorithm):
if not isinstance(new_checksum, Algorithm):
raise SPDXValueError("Package::Checksum")
if new_checksum.identifier in self.checksums:
return
for checksum in self.checksums.values():
if not isinstance(checksum, Checksum):
messages.append("Package checksum must be instance of spdx.checksum.Checksum")

def get_checksum(self, hash_algorithm: ChecksumAlgorithm = ChecksumAlgorithm.SHA1) -> Checksum:
return self.checksums[hash_algorithm]

def set_checksum(self, new_checksum: Checksum):
if not isinstance(new_checksum, Checksum):
raise SPDXValueError("Package::Checksum")

self.checksums[new_checksum.identifier] = new_checksum

def has_optional_field(self, field):
Expand Down
12 changes: 6 additions & 6 deletions spdx/parsers/jsonyamlxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# limitations under the License.
from datetime import datetime
from enum import Enum, auto
from typing import List, Dict, Tuple, Callable
from typing import List, Dict, Tuple, Callable, Optional

from spdx import document
from spdx import utils
Expand Down Expand Up @@ -1093,10 +1093,10 @@ def _handle_file_dependency(self, file_dependency):
return None
return None

def parse_file_checksums(self, file_checksums):
def parse_file_checksums(self, file_checksums: List[Dict]) -> Optional[bool]:
"""
Parse File checksums
- file_checksum: Python List
- file_checksums: Python List
"""
if isinstance(file_checksums, list):
for checksum in file_checksums:
Expand Down Expand Up @@ -1593,10 +1593,10 @@ def parse_pkg_files(self, pkg_has_files: List[str], method_to_parse_relationship
elif pkg_has_files is not None:
self.value_error("PKG_HAS_FILES", pkg_has_files)

def parse_pkg_checksums(self, pkg_checksums):
def parse_pkg_checksums(self, pkg_checksums: List[Dict]) -> Optional[bool]:
"""
Parse Package checksum
- pkg_chksum: Python str/unicode
Parse Package checksums
- pkg_chksums: Python List
"""
if isinstance(pkg_checksums, list):
for checksum in pkg_checksums:
Expand Down

0 comments on commit 72780a4

Please sign in to comment.