Skip to content

Commit d8b20bd

Browse files
authored
fix: behavior of and typing for crypto setters with optional values (#694)
fixes #690 --------- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
1 parent cc09c42 commit d8b20bd

File tree

3 files changed

+154
-22
lines changed

3 files changed

+154
-22
lines changed

cyclonedx/model/crypto.py

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def primitive(self) -> Optional[CryptoPrimitive]:
322322
return self._primitive
323323

324324
@primitive.setter
325-
def primitive(self, primitive: CryptoPrimitive) -> None:
325+
def primitive(self, primitive: Optional[CryptoPrimitive]) -> None:
326326
self._primitive = primitive
327327

328328
@property
@@ -339,7 +339,7 @@ def parameter_set_identifier(self) -> Optional[str]:
339339
return self._parameter_set_identifier
340340

341341
@parameter_set_identifier.setter
342-
def parameter_set_identifier(self, parameter_set_identifier: str) -> None:
342+
def parameter_set_identifier(self, parameter_set_identifier: Optional[str]) -> None:
343343
self._parameter_set_identifier = parameter_set_identifier
344344

345345
@property
@@ -357,7 +357,7 @@ def curve(self) -> Optional[str]:
357357
return self._curve
358358

359359
@curve.setter
360-
def curve(self, curve: str) -> None:
360+
def curve(self, curve: Optional[str]) -> None:
361361
self._curve = curve
362362

363363
@property
@@ -372,7 +372,7 @@ def execution_environment(self) -> Optional[CryptoExecutionEnvironment]:
372372
return self._execution_environment
373373

374374
@execution_environment.setter
375-
def execution_environment(self, execution_environment: CryptoExecutionEnvironment) -> None:
375+
def execution_environment(self, execution_environment: Optional[CryptoExecutionEnvironment]) -> None:
376376
self._execution_environment = execution_environment
377377

378378
@property
@@ -388,7 +388,7 @@ def implementation_platform(self) -> Optional[CryptoImplementationPlatform]:
388388
return self._implementation_platform
389389

390390
@implementation_platform.setter
391-
def implementation_platform(self, implementation_platform: CryptoImplementationPlatform) -> None:
391+
def implementation_platform(self, implementation_platform: Optional[CryptoImplementationPlatform]) -> None:
392392
self._implementation_platform = implementation_platform
393393

394394
@property
@@ -422,7 +422,7 @@ def mode(self) -> Optional[CryptoMode]:
422422
return self._mode
423423

424424
@mode.setter
425-
def mode(self, mode: CryptoMode) -> None:
425+
def mode(self, mode: Optional[CryptoMode]) -> None:
426426
self._mode = mode
427427

428428
@property
@@ -437,7 +437,7 @@ def padding(self) -> Optional[CryptoPadding]:
437437
return self._padding
438438

439439
@padding.setter
440-
def padding(self, padding: CryptoPadding) -> None:
440+
def padding(self, padding: Optional[CryptoPadding]) -> None:
441441
self._padding = padding
442442

443443
@property
@@ -468,7 +468,7 @@ def classical_security_level(self) -> Optional[int]:
468468
return self._classical_security_level
469469

470470
@classical_security_level.setter
471-
def classical_security_level(self, classical_security_level: int) -> None:
471+
def classical_security_level(self, classical_security_level: Optional[int]) -> None:
472472
self._classical_security_level = classical_security_level
473473

474474
@property
@@ -485,12 +485,14 @@ def nist_quantum_security_level(self) -> Optional[int]:
485485
return self._nist_quantum_security_level
486486

487487
@nist_quantum_security_level.setter
488-
def nist_quantum_security_level(self, nist_quantum_security_level: int) -> None:
489-
if nist_quantum_security_level < 0 or nist_quantum_security_level > 6:
488+
def nist_quantum_security_level(self, nist_quantum_security_level: Optional[int]) -> None:
489+
if nist_quantum_security_level is not None and (
490+
nist_quantum_security_level < 0
491+
or nist_quantum_security_level > 6
492+
):
490493
raise InvalidNistQuantumSecurityLevelException(
491494
'NIST Quantum Security Level must be (0 <= value <= 6)'
492495
)
493-
494496
self._nist_quantum_security_level = nist_quantum_security_level
495497

496498
def __eq__(self, other: object) -> bool:
@@ -553,7 +555,7 @@ def subject_name(self) -> Optional[str]:
553555
return self._subject_name
554556

555557
@subject_name.setter
556-
def subject_name(self, subject_name: str) -> None:
558+
def subject_name(self, subject_name: Optional[str]) -> None:
557559
self._subject_name = subject_name
558560

559561
@property
@@ -584,7 +586,7 @@ def not_valid_before(self) -> Optional[datetime]:
584586
return self._not_valid_before
585587

586588
@not_valid_before.setter
587-
def not_valid_before(self, not_valid_before: datetime) -> None:
589+
def not_valid_before(self, not_valid_before: Optional[datetime]) -> None:
588590
self._not_valid_before = not_valid_before
589591

590592
@property
@@ -600,7 +602,7 @@ def not_valid_after(self) -> Optional[datetime]:
600602
return self._not_valid_after
601603

602604
@not_valid_after.setter
603-
def not_valid_after(self, not_valid_after: datetime) -> None:
605+
def not_valid_after(self, not_valid_after: Optional[datetime]) -> None:
604606
self._not_valid_after = not_valid_after
605607

606608
@property
@@ -616,7 +618,7 @@ def signature_algorithm_ref(self) -> Optional[BomRef]:
616618
return self._signature_algorithm_ref
617619

618620
@signature_algorithm_ref.setter
619-
def signature_algorithm_ref(self, signature_algorithm_ref: BomRef) -> None:
621+
def signature_algorithm_ref(self, signature_algorithm_ref: Optional[BomRef]) -> None:
620622
self._signature_algorithm_ref = signature_algorithm_ref
621623

622624
@property
@@ -632,7 +634,7 @@ def subject_public_key_ref(self) -> Optional[BomRef]:
632634
return self._subject_public_key_ref
633635

634636
@subject_public_key_ref.setter
635-
def subject_public_key_ref(self, subject_public_key_ref: BomRef) -> None:
637+
def subject_public_key_ref(self, subject_public_key_ref: Optional[BomRef]) -> None:
636638
self._subject_public_key_ref = subject_public_key_ref
637639

638640
@property
@@ -647,7 +649,7 @@ def certificate_format(self) -> Optional[str]:
647649
return self._certificate_format
648650

649651
@certificate_format.setter
650-
def certificate_format(self, certificate_format: str) -> None:
652+
def certificate_format(self, certificate_format: Optional[str]) -> None:
651653
self._certificate_format = certificate_format
652654

653655
@property
@@ -662,7 +664,7 @@ def certificate_extension(self) -> Optional[str]:
662664
return self._certificate_extension
663665

664666
@certificate_extension.setter
665-
def certificate_extension(self, certificate_extension: str) -> None:
667+
def certificate_extension(self, certificate_extension: Optional[str]) -> None:
666668
self._certificate_extension = certificate_extension
667669

668670
def __eq__(self, other: object) -> bool:
@@ -898,7 +900,7 @@ def algorithm_ref(self) -> Optional[BomRef]:
898900
return self._algorithm_ref
899901

900902
@algorithm_ref.setter
901-
def algorithm_ref(self, algorithm_ref: BomRef) -> None:
903+
def algorithm_ref(self, algorithm_ref: Optional[BomRef]) -> None:
902904
self._algorithm_ref = algorithm_ref
903905

904906
@property
@@ -1476,9 +1478,10 @@ def related_crypto_material_properties(self) -> Optional[RelatedCryptoMaterialPr
14761478
return self._related_crypto_material_properties
14771479

14781480
@related_crypto_material_properties.setter
1479-
def related_crypto_material_properties(self,
1480-
related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties]
1481-
) -> None:
1481+
def related_crypto_material_properties(
1482+
self,
1483+
related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties]
1484+
) -> None:
14821485
self._related_crypto_material_properties = related_crypto_material_properties
14831486

14841487
@property
@@ -1516,6 +1519,25 @@ def __eq__(self, other: object) -> bool:
15161519
return hash(other) == hash(self)
15171520
return False
15181521

1522+
def __lt__(self, other: Any) -> bool:
1523+
if isinstance(other, CryptoProperties):
1524+
return _ComparableTuple((
1525+
self.asset_type,
1526+
self.algorithm_properties,
1527+
self.certificate_properties,
1528+
self.related_crypto_material_properties,
1529+
self.protocol_properties,
1530+
self.oid,
1531+
)) < _ComparableTuple((
1532+
other.asset_type,
1533+
other.algorithm_properties,
1534+
other.certificate_properties,
1535+
other.related_crypto_material_properties,
1536+
other.protocol_properties,
1537+
other.oid,
1538+
))
1539+
return NotImplemented
1540+
15191541
def __hash__(self) -> int:
15201542
return hash((self.asset_type, self.algorithm_properties, self.certificate_properties,
15211543
self.related_crypto_material_properties, self.protocol_properties, self.oid))

tests/_data/own/json/1.6/issue690.json

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/test_deserialize_json.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,16 @@ def test(ls: LicenseRepository) -> None:
8282
test(bom.metadata.component.licenses)
8383
test(list(bom.components)[0].licenses)
8484
test(list(bom.services)[0].licenses)
85+
86+
def test_regression_issue690(self) -> None:
87+
"""
88+
regressio test for issue#690.
89+
see https://github.com/CycloneDX/cyclonedx-python-lib/issues/690
90+
"""
91+
json_file = join(OWN_DATA_DIRECTORY, 'json',
92+
SchemaVersion.V1_6.to_version(),
93+
'issue690.json')
94+
with open(json_file) as f:
95+
json = json_loads(f.read())
96+
bom: Bom = Bom.from_json(json) # <<< is expected to not crash
97+
self.assertIsNotNone(bom)

0 commit comments

Comments
 (0)