@@ -301,31 +301,31 @@ def __init__(
301301 raise ValueError (f'version must be < 0, got { version } ' )
302302 self .version = version
303303
304+ @staticmethod
305+ def _common_fields_from_dict (signed_dict : Mapping [str , Any ]) -> list :
306+ """Returns common fields of 'Signed' instances from the passed dict
307+ representation, and returns an ordered list to be passed as leading
308+ positional arguments to a subclass constructor.
304309
305- # Deserialization (factories).
306- @classmethod
307- def from_dict (cls , signed_dict : Mapping [str , Any ]) -> 'Signed' :
308- """Creates Signed object from its dict representation. """
310+ See '{Root, Timestamp, Snapshot, Targets}.from_dict' methods for usage.
311+
312+ """
313+ _type = signed_dict .pop ('_type' )
314+ version = signed_dict .pop ('version' )
315+ spec_version = signed_dict .pop ('spec_version' )
316+ expires_str = signed_dict .pop ('expires' )
309317 # Convert 'expires' TUF metadata string to a datetime object, which is
310318 # what the constructor expects and what we store. The inverse operation
311- # is implemented in 'to_dict'.
312- signed_dict ['expires' ] = tuf .formats .expiry_string_to_datetime (
313- signed_dict ['expires' ])
314- # NOTE: We write the converted 'expires' back into 'signed_dict' above
315- # so that we can pass it to the constructor as '**signed_dict' below,
316- # along with other fields that belong to Signed subclasses.
317- # Any 'from_dict'(-like) conversions of fields that correspond to a
318- # subclass should be performed in the 'from_dict' method of that
319- # subclass and also be written back into 'signed_dict' before calling
320- # super().from_dict.
321-
322- # NOTE: cls might be a subclass of Signed, if 'from_dict' was called on
323- # that subclass (see e.g. Metadata.from_dict).
324- return cls (** signed_dict )
319+ # is implemented in '_common_fields_to_dict'.
320+ expires = tuf .formats .expiry_string_to_datetime (expires_str )
321+ return [_type , version , spec_version , expires ]
325322
323+ def _common_fields_to_dict (self ) -> Dict [str , Any ]:
324+ """Returns dict representation of common fields of 'Signed' instances.
326325
327- def to_dict (self ) -> Dict [str , Any ]:
328- """Returns the dict representation of self. """
326+ See '{Root, Timestamp, Snapshot, Targets}.to_dict' methods for usage.
327+
328+ """
329329 return {
330330 '_type' : self ._type ,
331331 'version' : self .version ,
@@ -393,10 +393,18 @@ def __init__(
393393 self .keys = keys
394394 self .roles = roles
395395
396+ @classmethod
397+ def from_dict (cls , root_dict : Mapping [str , Any ]) -> 'Root' :
398+ """Creates Root object from its dict representation. """
399+ common_args = super ()._common_fields_from_dict (root_dict )
400+ consistent_snapshot = root_dict .pop ('consistent_snapshot' )
401+ keys = root_dict .pop ('keys' )
402+ roles = root_dict .pop ('roles' )
403+ return cls (* common_args , consistent_snapshot , keys , roles )
396404
397405 def to_dict (self ) -> Dict [str , Any ]:
398406 """Returns the dict representation of self. """
399- root_dict = super ().to_dict ()
407+ root_dict = super ()._common_fields_to_dict ()
400408 root_dict .update ({
401409 'consistent_snapshot' : self .consistent_snapshot ,
402410 'keys' : self .keys ,
@@ -453,9 +461,16 @@ def __init__(
453461 # TODO: Add class for meta
454462 self .meta = meta
455463
464+ @classmethod
465+ def from_dict (cls , timestamp_dict : Mapping [str , Any ]) -> 'Timestamp' :
466+ """Creates Timestamp object from its dict representation. """
467+ common_args = super ()._common_fields_from_dict (timestamp_dict )
468+ meta = timestamp_dict .pop ('meta' )
469+ return cls (* common_args , meta )
470+
456471 def to_dict (self ) -> Dict [str , Any ]:
457472 """Returns the dict representation of self. """
458- timestamp_dict = super ().to_dict ()
473+ timestamp_dict = super ()._common_fields_to_dict ()
459474 timestamp_dict .update ({
460475 'meta' : self .meta
461476 })
@@ -505,9 +520,16 @@ def __init__(
505520 # TODO: Add class for meta
506521 self .meta = meta
507522
523+ @classmethod
524+ def from_dict (cls , snapshot_dict : Mapping [str , Any ]) -> 'Snapshot' :
525+ """Creates Snapshot object from its dict representation. """
526+ common_args = super ()._common_fields_from_dict (snapshot_dict )
527+ meta = snapshot_dict .pop ('meta' )
528+ return cls (* common_args , meta )
529+
508530 def to_dict (self ) -> Dict [str , Any ]:
509531 """Returns the dict representation of self. """
510- snapshot_dict = super ().to_dict ()
532+ snapshot_dict = super ()._common_fields_to_dict ()
511533 snapshot_dict .update ({
512534 'meta' : self .meta
513535 })
@@ -595,9 +617,17 @@ def __init__(
595617 self .targets = targets
596618 self .delegations = delegations
597619
620+ @classmethod
621+ def from_dict (cls , targets_dict : Mapping [str , Any ]) -> 'Targets' :
622+ """Creates Targets object from its dict representation. """
623+ common_args = super ()._common_fields_from_dict (targets_dict )
624+ targets = targets_dict .pop ('targets' )
625+ delegations = targets_dict .pop ('delegations' )
626+ return cls (* common_args , targets , delegations )
627+
598628 def to_dict (self ) -> Dict [str , Any ]:
599629 """Returns the dict representation of self. """
600- targets_dict = super ().to_dict ()
630+ targets_dict = super ()._common_fields_to_dict ()
601631 targets_dict .update ({
602632 'targets' : self .targets ,
603633 'delegations' : self .delegations ,
0 commit comments