27
27
28
28
from .._internal .compare import ComparableTuple as _ComparableTuple
29
29
from .._internal .hash import file_sha1sum as _file_sha1sum
30
- from ..exception .model import InvalidOmniBorIdException , NoPropertiesProvidedException
30
+ from ..exception .model import InvalidOmniBorIdException , InvalidSwhidException , NoPropertiesProvidedException
31
31
from ..exception .serialization import (
32
32
CycloneDxDeserializationException ,
33
33
SerializationOfUnexpectedValueException ,
@@ -932,6 +932,65 @@ def __str__(self) -> str:
932
932
return self ._id
933
933
934
934
935
+ @serializable .serializable_class
936
+ class Swhid (serializable .helpers .BaseHelper ):
937
+ """
938
+ Helper class that allows us to perform validation on data strings that must conform to
939
+ https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html.
940
+
941
+ """
942
+
943
+ _VALID_SWHID_REGEX = re .compile (r'^swh:1:(cnp|rel|rev|dir|cnt):([0-9a-z]{40})(.*)?$' )
944
+
945
+ def __init__ (self , id : str ) -> None :
946
+ if Swhid ._VALID_SWHID_REGEX .match (id ) is None :
947
+ raise InvalidSwhidException (
948
+ f'Supplied value "{ id } does not meet format specification.'
949
+ )
950
+ self ._id = id
951
+
952
+ @property
953
+ @serializable .json_name ('.' )
954
+ @serializable .xml_name ('.' )
955
+ def id (self ) -> str :
956
+ return self ._id
957
+
958
+ @classmethod
959
+ def serialize (cls , o : Any ) -> str :
960
+ if isinstance (o , Swhid ):
961
+ return str (o )
962
+ raise SerializationOfUnexpectedValueException (
963
+ f'Attempt to serialize a non-Swhid: { o !r} ' )
964
+
965
+ @classmethod
966
+ def deserialize (cls , o : Any ) -> 'Swhid' :
967
+ try :
968
+ return Swhid (id = str (o ))
969
+ except ValueError as err :
970
+ raise CycloneDxDeserializationException (
971
+ f'Swhid string supplied does not parse: { o !r} '
972
+ ) from err
973
+
974
+ def __eq__ (self , other : Any ) -> bool :
975
+ if isinstance (other , Swhid ):
976
+ return hash (other ) == hash (self )
977
+ return False
978
+
979
+ def __lt__ (self , other : Any ) -> bool :
980
+ if isinstance (other , Swhid ):
981
+ return self ._id < other ._id
982
+ return NotImplemented
983
+
984
+ def __hash__ (self ) -> int :
985
+ return hash (self ._id )
986
+
987
+ def __repr__ (self ) -> str :
988
+ return f'<Swhid { self ._id } >'
989
+
990
+ def __str__ (self ) -> str :
991
+ return self ._id
992
+
993
+
935
994
@serializable .serializable_class
936
995
class Component (Dependable ):
937
996
"""
@@ -986,7 +1045,7 @@ def __init__(self, *,
986
1045
modified : bool = False , manufacturer : Optional [OrganizationalEntity ] = None ,
987
1046
authors : Optional [Iterable [OrganizationalContact ]] = None ,
988
1047
omnibor_ids : Optional [Iterable [OmniborId ]] = None ,
989
- # swhid : Optional[Iterable[str ]] = None,
1048
+ swhids : Optional [Iterable [Swhid ]] = None ,
990
1049
# Deprecated in v1.6
991
1050
author : Optional [str ] = None ,
992
1051
) -> None :
@@ -1011,7 +1070,7 @@ def __init__(self, *,
1011
1070
self .cpe = cpe
1012
1071
self .purl = purl
1013
1072
self .omnibor_ids = omnibor_ids or [] # type:ignore[assignment]
1014
- # self.swhid = swhid or [] # type:ignore[assignment]
1073
+ self .swhids = swhids or [] # type:ignore[assignment]
1015
1074
self .swid = swid
1016
1075
self .modified = modified
1017
1076
self .pedigree = pedigree
@@ -1380,25 +1439,26 @@ def omnibor_ids(self) -> 'SortedSet[OmniborId]':
1380
1439
def omnibor_ids (self , omnibor_ids : Iterable [OmniborId ]) -> None :
1381
1440
self ._omnibor_ids = SortedSet (omnibor_ids )
1382
1441
1383
- # @property
1384
- # @serializable.view(SchemaVersion1Dot6)
1385
- # @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, child_name='swhid')
1386
- # @serializable.xml_sequence(17)
1387
- # def swhid(self) -> SortedSet[str]:
1388
- # """
1389
- # Specifies the Software Heritage persistent identifier (SWHID). The SWHID, if specified, MUST be valid and
1390
- # conform to the specification defined at:
1391
- # https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html
1392
- #
1393
- # Returns:
1394
- # `Iterable[swhid]` if set else `None`
1395
- # """
1396
- # return self._swhid
1397
-
1398
- # @swhid.setter
1399
- # def swhid(self, swhid: Iterable[str]) -> None:
1400
- # self._swhid = SortedSet(swhid)
1401
- #
1442
+ @property
1443
+ @serializable .json_name ('swhid' )
1444
+ @serializable .view (SchemaVersion1Dot6 )
1445
+ @serializable .xml_array (serializable .XmlArraySerializationType .FLAT , child_name = 'swhid' )
1446
+ @serializable .xml_sequence (17 )
1447
+ def swhids (self ) -> 'SortedSet[Swhid]' :
1448
+ """
1449
+ Specifies the Software Heritage persistent identifier (SWHID). The SWHID, if specified, MUST be valid and
1450
+ conform to the specification defined at:
1451
+ https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html
1452
+
1453
+ Returns:
1454
+ `Iterable[Swhid]` if set else `None`
1455
+ """
1456
+ return self ._swhids
1457
+
1458
+ @swhids .setter
1459
+ def swhids (self , swhids : Iterable [Swhid ]) -> None :
1460
+ self ._swhids = SortedSet (swhids )
1461
+
1402
1462
@property
1403
1463
@serializable .view (SchemaVersion1Dot2 )
1404
1464
@serializable .view (SchemaVersion1Dot3 )
0 commit comments