@@ -300,14 +300,22 @@ 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+ unrecognized_fields: An optional dictionary storing all unrecognized
304+ fields. Used for backward compatibility. If None is provided, an
305+ empty dictionary will be created.
303306
304307 """
305308
306309 # NOTE: Signed is a stupid name, because this might not be signed yet, but
307310 # we keep it to match spec terminology (I often refer to this as "payload",
308311 # or "inner metadata")
309312 def __init__ (
310- self , _type : str , version : int , spec_version : str , expires : datetime
313+ self ,
314+ _type : str ,
315+ version : int ,
316+ spec_version : str ,
317+ expires : datetime ,
318+ unrecognized_fields : Optional [Mapping [str , Any ]] = None ,
311319 ) -> None :
312320
313321 self ._type = _type
@@ -318,6 +326,9 @@ def __init__(
318326 if version < 0 :
319327 raise ValueError (f"version must be >= 0, got { version } " )
320328 self .version = version
329+ if unrecognized_fields is None :
330+ unrecognized_fields = {}
331+ self .unrecognized_fields = unrecognized_fields
321332
322333 @staticmethod
323334 def _common_fields_from_dict (signed_dict : Mapping [str , Any ]) -> list :
@@ -349,6 +360,7 @@ def _common_fields_to_dict(self) -> Dict[str, Any]:
349360 "version" : self .version ,
350361 "spec_version" : self .spec_version ,
351362 "expires" : self .expires .isoformat () + "Z" ,
363+ ** self .unrecognized_fields ,
352364 }
353365
354366 # Modification.
@@ -409,8 +421,11 @@ def __init__(
409421 consistent_snapshot : bool ,
410422 keys : Mapping [str , Any ],
411423 roles : Mapping [str , Any ],
424+ unrecognized_fields : Optional [Mapping [str , Any ]] = None ,
412425 ) -> None :
413- super ().__init__ (_type , version , spec_version , expires )
426+ super ().__init__ (
427+ _type , version , spec_version , expires , unrecognized_fields
428+ )
414429 # TODO: Add classes for keys and roles
415430 self .consistent_snapshot = consistent_snapshot
416431 self .keys = keys
@@ -423,7 +438,11 @@ def from_dict(cls, root_dict: Mapping[str, Any]) -> "Root":
423438 consistent_snapshot = root_dict .pop ("consistent_snapshot" )
424439 keys = root_dict .pop ("keys" )
425440 roles = root_dict .pop ("roles" )
426- return cls (* common_args , consistent_snapshot , keys , roles )
441+ # All fields left in the root_dict and unrecognized.
442+ unrecognized_fields = root_dict
443+ return cls (
444+ * common_args , consistent_snapshot , keys , roles , unrecognized_fields
445+ )
427446
428447 def to_dict (self ) -> Dict [str , Any ]:
429448 """Returns the dict representation of self. """
@@ -485,8 +504,11 @@ def __init__(
485504 spec_version : str ,
486505 expires : datetime ,
487506 meta : Mapping [str , Any ],
507+ unrecognized_fields : Optional [Mapping [str , Any ]] = None ,
488508 ) -> None :
489- super ().__init__ (_type , version , spec_version , expires )
509+ super ().__init__ (
510+ _type , version , spec_version , expires , unrecognized_fields
511+ )
490512 # TODO: Add class for meta
491513 self .meta = meta
492514
@@ -495,7 +517,9 @@ def from_dict(cls, timestamp_dict: Mapping[str, Any]) -> "Timestamp":
495517 """Creates Timestamp object from its dict representation. """
496518 common_args = cls ._common_fields_from_dict (timestamp_dict )
497519 meta = timestamp_dict .pop ("meta" )
498- return cls (* common_args , meta )
520+ # All fields left in the timestamp_dict and unrecognized.
521+ unrecognized_fields = timestamp_dict
522+ return cls (* common_args , meta , unrecognized_fields )
499523
500524 def to_dict (self ) -> Dict [str , Any ]:
501525 """Returns the dict representation of self. """
@@ -549,8 +573,11 @@ def __init__(
549573 spec_version : str ,
550574 expires : datetime ,
551575 meta : Mapping [str , Any ],
576+ unrecognized_fields : Optional [Mapping [str , Any ]] = None ,
552577 ) -> None :
553- super ().__init__ (_type , version , spec_version , expires )
578+ super ().__init__ (
579+ _type , version , spec_version , expires , unrecognized_fields
580+ )
554581 # TODO: Add class for meta
555582 self .meta = meta
556583
@@ -559,7 +586,9 @@ def from_dict(cls, snapshot_dict: Mapping[str, Any]) -> "Snapshot":
559586 """Creates Snapshot object from its dict representation. """
560587 common_args = cls ._common_fields_from_dict (snapshot_dict )
561588 meta = snapshot_dict .pop ("meta" )
562- return cls (* common_args , meta )
589+ # All fields left in the snapshot_dict and unrecognized.
590+ unrecognized_fields = snapshot_dict
591+ return cls (* common_args , meta , unrecognized_fields )
563592
564593 def to_dict (self ) -> Dict [str , Any ]:
565594 """Returns the dict representation of self. """
@@ -652,8 +681,11 @@ def __init__(
652681 expires : datetime ,
653682 targets : Mapping [str , Any ],
654683 delegations : Mapping [str , Any ],
684+ unrecognized_fields : Optional [Mapping [str , Any ]] = None ,
655685 ) -> None :
656- super ().__init__ (_type , version , spec_version , expires )
686+ super ().__init__ (
687+ _type , version , spec_version , expires , unrecognized_fields
688+ )
657689 # TODO: Add class for meta
658690 self .targets = targets
659691 self .delegations = delegations
@@ -664,7 +696,9 @@ def from_dict(cls, targets_dict: Mapping[str, Any]) -> "Targets":
664696 common_args = cls ._common_fields_from_dict (targets_dict )
665697 targets = targets_dict .pop ("targets" )
666698 delegations = targets_dict .pop ("delegations" )
667- return cls (* common_args , targets , delegations )
699+ # All fields left in the targets_dict and unrecognized.
700+ unrecognized_fields = targets_dict
701+ return cls (* common_args , targets , delegations , unrecognized_fields )
668702
669703 def to_dict (self ) -> Dict [str , Any ]:
670704 """Returns the dict representation of self. """
0 commit comments