1515available in the class model.
1616
1717"""
18+ import abc
1819import tempfile
1920from datetime import datetime , timedelta
20- from typing import Any , Dict , List , Mapping , Optional
21+ from typing import Any , ClassVar , Dict , List , Mapping , Optional , Tuple , Type
2122
2223from securesystemslib .keys import verify_signature
2324from securesystemslib .signer import Signature , Signer
@@ -78,7 +79,7 @@ def from_dict(cls, metadata: Dict[str, Any]) -> "Metadata":
7879 _type = metadata ["signed" ]["_type" ]
7980
8081 if _type == "targets" :
81- inner_cls = Targets
82+ inner_cls : Type [ Signed ] = Targets
8283 elif _type == "snapshot" :
8384 inner_cls = Snapshot
8485 elif _type == "timestamp" :
@@ -304,7 +305,7 @@ def verify(
304305 )
305306
306307
307- class Signed :
308+ class Signed ( metaclass = abc . ABCMeta ) :
308309 """A base class for the signed part of TUF metadata.
309310
310311 Objects with base class Signed are usually included in a Metadata object
@@ -321,7 +322,7 @@ class Signed:
321322 """
322323
323324 # Signed implementations are expected to override this
324- _signed_type = None
325+ _signed_type : ClassVar [ str ] = "signed"
325326
326327 # _type and type are identical: 1st replicates file format, 2nd passes lint
327328 @property
@@ -351,8 +352,21 @@ def __init__(
351352 self .version = version
352353 self .unrecognized_fields : Mapping [str , Any ] = unrecognized_fields or {}
353354
355+ @abc .abstractmethod
356+ def to_dict (self ) -> Dict [str , Any ]:
357+ """Serialization helper that returns dict representation of self"""
358+ raise NotImplementedError
359+
360+ @classmethod
361+ @abc .abstractmethod
362+ def from_dict (cls , signed_dict : Dict [str , Any ]) -> "Signed" :
363+ """Deserialization helper, creates object from dict representation"""
364+ raise NotImplementedError
365+
354366 @classmethod
355- def _common_fields_from_dict (cls , signed_dict : Dict [str , Any ]) -> List [Any ]:
367+ def _common_fields_from_dict (
368+ cls , signed_dict : Dict [str , Any ]
369+ ) -> Tuple [int , str , datetime ]:
356370 """Returns common fields of 'Signed' instances from the passed dict
357371 representation, and returns an ordered list to be passed as leading
358372 positional arguments to a subclass constructor.
@@ -371,7 +385,7 @@ def _common_fields_from_dict(cls, signed_dict: Dict[str, Any]) -> List[Any]:
371385 # what the constructor expects and what we store. The inverse operation
372386 # is implemented in '_common_fields_to_dict'.
373387 expires = formats .expiry_string_to_datetime (expires_str )
374- return [ version , spec_version , expires ]
388+ return version , spec_version , expires
375389
376390 def _common_fields_to_dict (self ) -> Dict [str , Any ]:
377391 """Returns dict representation of common fields of 'Signed' instances.
@@ -550,20 +564,20 @@ def __init__(
550564 self .roles = roles
551565
552566 @classmethod
553- def from_dict (cls , root_dict : Dict [str , Any ]) -> "Root" :
567+ def from_dict (cls , signed_dict : Dict [str , Any ]) -> "Root" :
554568 """Creates Root object from its dict representation."""
555- common_args = cls ._common_fields_from_dict (root_dict )
556- consistent_snapshot = root_dict .pop ("consistent_snapshot" , None )
557- keys = root_dict .pop ("keys" )
558- roles = root_dict .pop ("roles" )
569+ common_args = cls ._common_fields_from_dict (signed_dict )
570+ consistent_snapshot = signed_dict .pop ("consistent_snapshot" , None )
571+ keys = signed_dict .pop ("keys" )
572+ roles = signed_dict .pop ("roles" )
559573
560574 for keyid , key_dict in keys .items ():
561575 keys [keyid ] = Key .from_dict (key_dict )
562576 for role_name , role_dict in roles .items ():
563577 roles [role_name ] = Role .from_dict (role_dict )
564578
565- # All fields left in the root_dict are unrecognized.
566- return cls (* common_args , keys , roles , consistent_snapshot , root_dict )
579+ # All fields left in the signed_dict are unrecognized.
580+ return cls (* common_args , keys , roles , consistent_snapshot , signed_dict )
567581
568582 def to_dict (self ) -> Dict [str , Any ]:
569583 """Returns the dict representation of self."""
@@ -646,7 +660,10 @@ def from_dict(cls, meta_dict: Dict[str, Any]) -> "MetaFile":
646660
647661 def to_dict (self ) -> Dict [str , Any ]:
648662 """Returns the dictionary representation of self."""
649- res_dict = {"version" : self .version , ** self .unrecognized_fields }
663+ res_dict : Dict [str , Any ] = {
664+ "version" : self .version ,
665+ ** self .unrecognized_fields ,
666+ }
650667
651668 if self .length is not None :
652669 res_dict ["length" ] = self .length
@@ -683,13 +700,13 @@ def __init__(
683700 self .meta = meta
684701
685702 @classmethod
686- def from_dict (cls , timestamp_dict : Dict [str , Any ]) -> "Timestamp" :
703+ def from_dict (cls , signed_dict : Dict [str , Any ]) -> "Timestamp" :
687704 """Creates Timestamp object from its dict representation."""
688- common_args = cls ._common_fields_from_dict (timestamp_dict )
689- meta_dict = timestamp_dict .pop ("meta" )
705+ common_args = cls ._common_fields_from_dict (signed_dict )
706+ meta_dict = signed_dict .pop ("meta" )
690707 meta = {"snapshot.json" : MetaFile .from_dict (meta_dict ["snapshot.json" ])}
691708 # All fields left in the timestamp_dict are unrecognized.
692- return cls (* common_args , meta , timestamp_dict )
709+ return cls (* common_args , meta , signed_dict )
693710
694711 def to_dict (self ) -> Dict [str , Any ]:
695712 """Returns the dict representation of self."""
@@ -733,15 +750,15 @@ def __init__(
733750 self .meta = meta
734751
735752 @classmethod
736- def from_dict (cls , snapshot_dict : Dict [str , Any ]) -> "Snapshot" :
753+ def from_dict (cls , signed_dict : Dict [str , Any ]) -> "Snapshot" :
737754 """Creates Snapshot object from its dict representation."""
738- common_args = cls ._common_fields_from_dict (snapshot_dict )
739- meta_dicts = snapshot_dict .pop ("meta" )
755+ common_args = cls ._common_fields_from_dict (signed_dict )
756+ meta_dicts = signed_dict .pop ("meta" )
740757 meta = {}
741758 for meta_path , meta_dict in meta_dicts .items ():
742759 meta [meta_path ] = MetaFile .from_dict (meta_dict )
743760 # All fields left in the snapshot_dict are unrecognized.
744- return cls (* common_args , meta , snapshot_dict )
761+ return cls (* common_args , meta , signed_dict )
745762
746763 def to_dict (self ) -> Dict [str , Any ]:
747764 """Returns the dict representation of self."""
@@ -801,7 +818,7 @@ def __init__(
801818 self .path_hash_prefixes = path_hash_prefixes
802819
803820 @classmethod
804- def from_dict (cls , role_dict : Mapping [str , Any ]) -> "Role " :
821+ def from_dict (cls , role_dict : Dict [str , Any ]) -> "DelegatedRole " :
805822 """Creates DelegatedRole object from its dict representation."""
806823 name = role_dict .pop ("name" )
807824 keyids = role_dict .pop ("keyids" )
@@ -971,12 +988,12 @@ def __init__(
971988 self .delegations = delegations
972989
973990 @classmethod
974- def from_dict (cls , targets_dict : Dict [str , Any ]) -> "Targets" :
991+ def from_dict (cls , signed_dict : Dict [str , Any ]) -> "Targets" :
975992 """Creates Targets object from its dict representation."""
976- common_args = cls ._common_fields_from_dict (targets_dict )
977- targets = targets_dict .pop ("targets" )
993+ common_args = cls ._common_fields_from_dict (signed_dict )
994+ targets = signed_dict .pop ("targets" )
978995 try :
979- delegations_dict = targets_dict .pop ("delegations" )
996+ delegations_dict = signed_dict .pop ("delegations" )
980997 except KeyError :
981998 delegations = None
982999 else :
@@ -985,7 +1002,7 @@ def from_dict(cls, targets_dict: Dict[str, Any]) -> "Targets":
9851002 for target_path , target_info in targets .items ():
9861003 res_targets [target_path ] = TargetFile .from_dict (target_info )
9871004 # All fields left in the targets_dict are unrecognized.
988- return cls (* common_args , res_targets , delegations , targets_dict )
1005+ return cls (* common_args , res_targets , delegations , signed_dict )
9891006
9901007 def to_dict (self ) -> Dict [str , Any ]:
9911008 """Returns the dict representation of self."""
0 commit comments