@@ -300,18 +300,24 @@ class Signed:
300300 spec_version: The TUF specification version number (semver) the
301301 metadata format adheres to.
302302 expires: The metadata expiration datetime object.
303- known_fields: A dictionary containing the known fields(attributes). Used
304- when filtering the known fields from all fields in order to retrieve
305- and store the unrecognized fields. See ADR 0008 for context.
303+ unrecognized_fields: An optional dictionary storing all unrecognized
304+ fields. Used for backward compatibility.
306305
307306 """
308307
308+ # This list is used when filtering the known fields from all fields
309+ # in order to retrieve and store the unrecognized fields.
309310 known_fields = ["_type" , "spec_version" , "expires" , "version" ]
310311 # NOTE: Signed is a stupid name, because this might not be signed yet, but
311312 # we keep it to match spec terminology (I often refer to this as "payload",
312313 # or "inner metadata")
313314 def __init__ (
314- self , _type : str , version : int , spec_version : str , expires : datetime
315+ self ,
316+ _type : str ,
317+ version : int ,
318+ spec_version : str ,
319+ expires : datetime ,
320+ unrecognized_fields : Optional [Mapping [str , Any ]] = {},
315321 ) -> None :
316322
317323 self ._type = _type
@@ -322,19 +328,29 @@ def __init__(
322328 if version < 0 :
323329 raise ValueError (f"version must be >= 0, got { version } " )
324330 self .version = version
331+ self .unrecognized_fields = unrecognized_fields
325332
326333 @classmethod
327- def _store_unrecognized_fields (
334+ def _get_unrecognized_fields (
328335 cls , all_fields : Mapping [str , Any ]
329336 ) -> Mapping [str , Any ]:
330337 """Utility function filtering the known fields from all in order to
331- retrieve and store the unrecognized fields."""
338+ get the unrecognized fields."""
339+
340+ _type = all_fields ["_type" ]
341+ if _type == "root" :
342+ cls .known_fields += ["consistent_snapshot" , "keys" , "roles" ]
343+ elif _type == "snapshot" or _type == "timestamp" :
344+ cls .known_fields += ["meta" ]
345+ elif _type == "targets" :
346+ cls .known_fields += ["targets" , "delegations" ]
347+
332348 unrecognized_fields = {}
333349 for key , value in all_fields .items ():
334350 if key not in cls .known_fields :
335351 unrecognized_fields [key ] = value
336352
337- cls . unrecognized_fields = unrecognized_fields
353+ return unrecognized_fields
338354
339355 @staticmethod
340356 def _common_fields_from_dict (signed_dict : Mapping [str , Any ]) -> list :
@@ -366,6 +382,7 @@ def _common_fields_to_dict(self) -> Dict[str, Any]:
366382 "version" : self .version ,
367383 "spec_version" : self .spec_version ,
368384 "expires" : self .expires .isoformat () + "Z" ,
385+ ** self .unrecognized_fields ,
369386 }
370387
371388 # Modification.
@@ -426,8 +443,11 @@ def __init__(
426443 consistent_snapshot : bool ,
427444 keys : Mapping [str , Any ],
428445 roles : Mapping [str , Any ],
446+ unrecognized_fields : Optional [Mapping [str , Any ]] = {},
429447 ) -> None :
430- super ().__init__ (_type , version , spec_version , expires )
448+ super ().__init__ (
449+ _type , version , spec_version , expires , unrecognized_fields
450+ )
431451 # TODO: Add classes for keys and roles
432452 self .consistent_snapshot = consistent_snapshot
433453 self .keys = keys
@@ -436,13 +456,14 @@ def __init__(
436456 @classmethod
437457 def from_dict (cls , root_dict : Mapping [str , Any ]) -> "Root" :
438458 """Creates Root object from its dict representation. """
459+ unrecognized_fields = cls ._get_unrecognized_fields (root_dict )
439460 common_args = cls ._common_fields_from_dict (root_dict )
440461 consistent_snapshot = root_dict .pop ("consistent_snapshot" )
441462 keys = root_dict .pop ("keys" )
442463 roles = root_dict .pop ("roles" )
443- cls . known_fields += [ "consistent_snapshot" , "keys" , "roles" ]
444- cls . _store_unrecognized_fields ( root_dict )
445- return cls ( * common_args , consistent_snapshot , keys , roles )
464+ return cls (
465+ * common_args , consistent_snapshot , keys , roles , unrecognized_fields
466+ )
446467
447468 def to_dict (self ) -> Dict [str , Any ]:
448469 """Returns the dict representation of self. """
@@ -452,7 +473,6 @@ def to_dict(self) -> Dict[str, Any]:
452473 "consistent_snapshot" : self .consistent_snapshot ,
453474 "keys" : self .keys ,
454475 "roles" : self .roles ,
455- ** self .unrecognized_fields ,
456476 }
457477 )
458478 return root_dict
@@ -505,24 +525,26 @@ def __init__(
505525 spec_version : str ,
506526 expires : datetime ,
507527 meta : Mapping [str , Any ],
528+ unrecognized_fields : Optional [Mapping [str , Any ]] = {},
508529 ) -> None :
509- super ().__init__ (_type , version , spec_version , expires )
530+ super ().__init__ (
531+ _type , version , spec_version , expires , unrecognized_fields
532+ )
510533 # TODO: Add class for meta
511534 self .meta = meta
512535
513536 @classmethod
514537 def from_dict (cls , timestamp_dict : Mapping [str , Any ]) -> "Timestamp" :
515538 """Creates Timestamp object from its dict representation. """
539+ unrecognized_fields = cls ._get_unrecognized_fields (timestamp_dict )
516540 common_args = cls ._common_fields_from_dict (timestamp_dict )
517541 meta = timestamp_dict .pop ("meta" )
518- cls .known_fields += ["meta" ]
519- cls ._store_unrecognized_fields (timestamp_dict )
520- return cls (* common_args , meta )
542+ return cls (* common_args , meta , unrecognized_fields )
521543
522544 def to_dict (self ) -> Dict [str , Any ]:
523545 """Returns the dict representation of self. """
524546 timestamp_dict = self ._common_fields_to_dict ()
525- timestamp_dict .update ({"meta" : self .meta , ** self . unrecognized_fields })
547+ timestamp_dict .update ({"meta" : self .meta })
526548 return timestamp_dict
527549
528550 # Modification.
@@ -571,24 +593,27 @@ def __init__(
571593 spec_version : str ,
572594 expires : datetime ,
573595 meta : Mapping [str , Any ],
596+ unrecognized_fields : Optional [Mapping [str , Any ]] = {},
574597 ) -> None :
575- super ().__init__ (_type , version , spec_version , expires )
598+ super ().__init__ (
599+ _type , version , spec_version , expires , unrecognized_fields
600+ )
576601 # TODO: Add class for meta
577602 self .meta = meta
578603
579604 @classmethod
580605 def from_dict (cls , snapshot_dict : Mapping [str , Any ]) -> "Snapshot" :
581606 """Creates Snapshot object from its dict representation. """
607+ unrecognized_fields = cls ._get_unrecognized_fields (snapshot_dict )
582608 common_args = cls ._common_fields_from_dict (snapshot_dict )
583609 meta = snapshot_dict .pop ("meta" )
584610 cls .known_fields += ["meta" ]
585- cls ._store_unrecognized_fields (snapshot_dict )
586- return cls (* common_args , meta )
611+ return cls (* common_args , meta , unrecognized_fields )
587612
588613 def to_dict (self ) -> Dict [str , Any ]:
589614 """Returns the dict representation of self. """
590615 snapshot_dict = self ._common_fields_to_dict ()
591- snapshot_dict .update ({"meta" : self .meta , ** self . unrecognized_fields })
616+ snapshot_dict .update ({"meta" : self .meta })
592617 return snapshot_dict
593618
594619 # Modification.
@@ -676,21 +701,23 @@ def __init__(
676701 expires : datetime ,
677702 targets : Mapping [str , Any ],
678703 delegations : Mapping [str , Any ],
704+ unrecognized_fields : Optional [Mapping [str , Any ]] = {},
679705 ) -> None :
680- super ().__init__ (_type , version , spec_version , expires )
706+ super ().__init__ (
707+ _type , version , spec_version , expires , unrecognized_fields
708+ )
681709 # TODO: Add class for meta
682710 self .targets = targets
683711 self .delegations = delegations
684712
685713 @classmethod
686714 def from_dict (cls , targets_dict : Mapping [str , Any ]) -> "Targets" :
687715 """Creates Targets object from its dict representation. """
716+ unrecognized_fields = cls ._get_unrecognized_fields (targets_dict )
688717 common_args = cls ._common_fields_from_dict (targets_dict )
689718 targets = targets_dict .pop ("targets" )
690719 delegations = targets_dict .pop ("delegations" )
691- cls .known_fields += ["meta" , "targets" , "delegations" ]
692- cls ._store_unrecognized_fields (targets_dict )
693- return cls (* common_args , targets , delegations )
720+ return cls (* common_args , targets , delegations , unrecognized_fields )
694721
695722 def to_dict (self ) -> Dict [str , Any ]:
696723 """Returns the dict representation of self. """
@@ -699,7 +726,6 @@ def to_dict(self) -> Dict[str, Any]:
699726 {
700727 "targets" : self .targets ,
701728 "delegations" : self .delegations ,
702- ** self .unrecognized_fields ,
703729 }
704730 )
705731 return targets_dict
0 commit comments