@@ -301,31 +301,31 @@ def __init__(
301
301
raise ValueError (f'version must be < 0, got { version } ' )
302
302
self .version = version
303
303
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.
304
309
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' )
309
317
# Convert 'expires' TUF metadata string to a datetime object, which is
310
318
# 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 ]
325
322
323
+ def _common_fields_to_dict (self ) -> Dict [str , Any ]:
324
+ """Returns dict representation of common fields of 'Signed' instances.
326
325
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
+ """
329
329
return {
330
330
'_type' : self ._type ,
331
331
'version' : self .version ,
@@ -393,10 +393,18 @@ def __init__(
393
393
self .keys = keys
394
394
self .roles = roles
395
395
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 )
396
404
397
405
def to_dict (self ) -> Dict [str , Any ]:
398
406
"""Returns the dict representation of self. """
399
- root_dict = super ().to_dict ()
407
+ root_dict = super ()._common_fields_to_dict ()
400
408
root_dict .update ({
401
409
'consistent_snapshot' : self .consistent_snapshot ,
402
410
'keys' : self .keys ,
@@ -453,9 +461,16 @@ def __init__(
453
461
# TODO: Add class for meta
454
462
self .meta = meta
455
463
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
+
456
471
def to_dict (self ) -> Dict [str , Any ]:
457
472
"""Returns the dict representation of self. """
458
- timestamp_dict = super ().to_dict ()
473
+ timestamp_dict = super ()._common_fields_to_dict ()
459
474
timestamp_dict .update ({
460
475
'meta' : self .meta
461
476
})
@@ -505,9 +520,16 @@ def __init__(
505
520
# TODO: Add class for meta
506
521
self .meta = meta
507
522
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
+
508
530
def to_dict (self ) -> Dict [str , Any ]:
509
531
"""Returns the dict representation of self. """
510
- snapshot_dict = super ().to_dict ()
532
+ snapshot_dict = super ()._common_fields_to_dict ()
511
533
snapshot_dict .update ({
512
534
'meta' : self .meta
513
535
})
@@ -595,9 +617,17 @@ def __init__(
595
617
self .targets = targets
596
618
self .delegations = delegations
597
619
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
+
598
628
def to_dict (self ) -> Dict [str , Any ]:
599
629
"""Returns the dict representation of self. """
600
- targets_dict = super ().to_dict ()
630
+ targets_dict = super ()._common_fields_to_dict ()
601
631
targets_dict .update ({
602
632
'targets' : self .targets ,
603
633
'delegations' : self .delegations ,
0 commit comments