Skip to content

Commit

Permalink
fix: behavior of and typing for crypto setters with optional values (#…
Browse files Browse the repository at this point in the history
…694)

fixes #690

---------

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
  • Loading branch information
jkowalleck authored Oct 7, 2024
1 parent cc09c42 commit d8b20bd
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 22 deletions.
66 changes: 44 additions & 22 deletions cyclonedx/model/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def primitive(self) -> Optional[CryptoPrimitive]:
return self._primitive

@primitive.setter
def primitive(self, primitive: CryptoPrimitive) -> None:
def primitive(self, primitive: Optional[CryptoPrimitive]) -> None:
self._primitive = primitive

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

@parameter_set_identifier.setter
def parameter_set_identifier(self, parameter_set_identifier: str) -> None:
def parameter_set_identifier(self, parameter_set_identifier: Optional[str]) -> None:
self._parameter_set_identifier = parameter_set_identifier

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

@curve.setter
def curve(self, curve: str) -> None:
def curve(self, curve: Optional[str]) -> None:
self._curve = curve

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

@execution_environment.setter
def execution_environment(self, execution_environment: CryptoExecutionEnvironment) -> None:
def execution_environment(self, execution_environment: Optional[CryptoExecutionEnvironment]) -> None:
self._execution_environment = execution_environment

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

@implementation_platform.setter
def implementation_platform(self, implementation_platform: CryptoImplementationPlatform) -> None:
def implementation_platform(self, implementation_platform: Optional[CryptoImplementationPlatform]) -> None:
self._implementation_platform = implementation_platform

@property
Expand Down Expand Up @@ -422,7 +422,7 @@ def mode(self) -> Optional[CryptoMode]:
return self._mode

@mode.setter
def mode(self, mode: CryptoMode) -> None:
def mode(self, mode: Optional[CryptoMode]) -> None:
self._mode = mode

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

@padding.setter
def padding(self, padding: CryptoPadding) -> None:
def padding(self, padding: Optional[CryptoPadding]) -> None:
self._padding = padding

@property
Expand Down Expand Up @@ -468,7 +468,7 @@ def classical_security_level(self) -> Optional[int]:
return self._classical_security_level

@classical_security_level.setter
def classical_security_level(self, classical_security_level: int) -> None:
def classical_security_level(self, classical_security_level: Optional[int]) -> None:
self._classical_security_level = classical_security_level

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

@nist_quantum_security_level.setter
def nist_quantum_security_level(self, nist_quantum_security_level: int) -> None:
if nist_quantum_security_level < 0 or nist_quantum_security_level > 6:
def nist_quantum_security_level(self, nist_quantum_security_level: Optional[int]) -> None:
if nist_quantum_security_level is not None and (
nist_quantum_security_level < 0
or nist_quantum_security_level > 6
):
raise InvalidNistQuantumSecurityLevelException(
'NIST Quantum Security Level must be (0 <= value <= 6)'
)

self._nist_quantum_security_level = nist_quantum_security_level

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

@subject_name.setter
def subject_name(self, subject_name: str) -> None:
def subject_name(self, subject_name: Optional[str]) -> None:
self._subject_name = subject_name

@property
Expand Down Expand Up @@ -584,7 +586,7 @@ def not_valid_before(self) -> Optional[datetime]:
return self._not_valid_before

@not_valid_before.setter
def not_valid_before(self, not_valid_before: datetime) -> None:
def not_valid_before(self, not_valid_before: Optional[datetime]) -> None:
self._not_valid_before = not_valid_before

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

@not_valid_after.setter
def not_valid_after(self, not_valid_after: datetime) -> None:
def not_valid_after(self, not_valid_after: Optional[datetime]) -> None:
self._not_valid_after = not_valid_after

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

@signature_algorithm_ref.setter
def signature_algorithm_ref(self, signature_algorithm_ref: BomRef) -> None:
def signature_algorithm_ref(self, signature_algorithm_ref: Optional[BomRef]) -> None:
self._signature_algorithm_ref = signature_algorithm_ref

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

@subject_public_key_ref.setter
def subject_public_key_ref(self, subject_public_key_ref: BomRef) -> None:
def subject_public_key_ref(self, subject_public_key_ref: Optional[BomRef]) -> None:
self._subject_public_key_ref = subject_public_key_ref

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

@certificate_format.setter
def certificate_format(self, certificate_format: str) -> None:
def certificate_format(self, certificate_format: Optional[str]) -> None:
self._certificate_format = certificate_format

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

@certificate_extension.setter
def certificate_extension(self, certificate_extension: str) -> None:
def certificate_extension(self, certificate_extension: Optional[str]) -> None:
self._certificate_extension = certificate_extension

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

@algorithm_ref.setter
def algorithm_ref(self, algorithm_ref: BomRef) -> None:
def algorithm_ref(self, algorithm_ref: Optional[BomRef]) -> None:
self._algorithm_ref = algorithm_ref

@property
Expand Down Expand Up @@ -1476,9 +1478,10 @@ def related_crypto_material_properties(self) -> Optional[RelatedCryptoMaterialPr
return self._related_crypto_material_properties

@related_crypto_material_properties.setter
def related_crypto_material_properties(self,
related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties]
) -> None:
def related_crypto_material_properties(
self,
related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties]
) -> None:
self._related_crypto_material_properties = related_crypto_material_properties

@property
Expand Down Expand Up @@ -1516,6 +1519,25 @@ def __eq__(self, other: object) -> bool:
return hash(other) == hash(self)
return False

def __lt__(self, other: Any) -> bool:
if isinstance(other, CryptoProperties):
return _ComparableTuple((
self.asset_type,
self.algorithm_properties,
self.certificate_properties,
self.related_crypto_material_properties,
self.protocol_properties,
self.oid,
)) < _ComparableTuple((
other.asset_type,
other.algorithm_properties,
other.certificate_properties,
other.related_crypto_material_properties,
other.protocol_properties,
other.oid,
))
return NotImplemented

def __hash__(self) -> int:
return hash((self.asset_type, self.algorithm_properties, self.certificate_properties,
self.related_crypto_material_properties, self.protocol_properties, self.oid))
Expand Down
97 changes: 97 additions & 0 deletions tests/_data/own/json/1.6/issue690.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions tests/test_deserialize_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,16 @@ def test(ls: LicenseRepository) -> None:
test(bom.metadata.component.licenses)
test(list(bom.components)[0].licenses)
test(list(bom.services)[0].licenses)

def test_regression_issue690(self) -> None:
"""
regressio test for issue#690.
see https://github.com/CycloneDX/cyclonedx-python-lib/issues/690
"""
json_file = join(OWN_DATA_DIRECTORY, 'json',
SchemaVersion.V1_6.to_version(),
'issue690.json')
with open(json_file) as f:
json = json_loads(f.read())
bom: Bom = Bom.from_json(json) # <<< is expected to not crash
self.assertIsNotNone(bom)

0 comments on commit d8b20bd

Please sign in to comment.