|
43 | 43 | List,
|
44 | 44 | Mapping,
|
45 | 45 | Optional,
|
| 46 | + OrderedDict as OrderedDictT, |
46 | 47 | Tuple,
|
47 | 48 | Type,
|
48 | 49 | TypeVar,
|
49 | 50 | Union,
|
50 | 51 | cast,
|
51 | 52 | )
|
| 53 | +from collections import OrderedDict |
52 | 54 |
|
53 | 55 | from securesystemslib import exceptions as sslib_exceptions
|
54 | 56 | from securesystemslib import hash as sslib_hash
|
@@ -293,16 +295,20 @@ def to_bytes(
|
293 | 295 |
|
294 | 296 | return serializer.serialize(self)
|
295 | 297 |
|
296 |
| - def to_dict(self) -> Dict[str, Any]: |
| 298 | + def to_dict(self) -> OrderedDictT[str, Any]: |
297 | 299 | """Returns the dict representation of self."""
|
298 | 300 |
|
299 | 301 | signatures = [sig.to_dict() for sig in self.signatures.values()]
|
300 | 302 |
|
301 |
| - return { |
302 |
| - "signatures": signatures, |
303 |
| - "signed": self.signed.to_dict(), |
304 |
| - **self.unrecognized_fields, |
305 |
| - } |
| 303 | + return OrderedDict( |
| 304 | + ( |
| 305 | + ("signatures", signatures), |
| 306 | + ("signed", self.signed.to_dict()), |
| 307 | + ) |
| 308 | + + tuple( |
| 309 | + sorted(self.unrecognized_fields.items(), key=lambda x: x[0]) |
| 310 | + ) |
| 311 | + ) |
306 | 312 |
|
307 | 313 | def to_file(
|
308 | 314 | self,
|
@@ -582,19 +588,21 @@ def _common_fields_from_dict(
|
582 | 588 |
|
583 | 589 | return version, spec_version, expires
|
584 | 590 |
|
585 |
| - def _common_fields_to_dict(self) -> Dict[str, Any]: |
| 591 | + def _common_fields_to_dict(self) -> OrderedDictT[str, Any]: |
586 | 592 | """Returns dict representation of common fields of ``Signed`` instances.
|
587 | 593 |
|
588 | 594 | See ``{Root, Timestamp, Snapshot, Targets}.to_dict`` methods for usage.
|
589 | 595 |
|
590 | 596 | """
|
591 |
| - return { |
592 |
| - "_type": self._type, |
593 |
| - "version": self.version, |
594 |
| - "spec_version": self.spec_version, |
595 |
| - "expires": self.expires.isoformat() + "Z", |
596 |
| - **self.unrecognized_fields, |
597 |
| - } |
| 597 | + return OrderedDict( |
| 598 | + { |
| 599 | + "_type": self._type, |
| 600 | + "version": self.version, |
| 601 | + "spec_version": self.spec_version, |
| 602 | + "expires": self.expires.isoformat() + "Z", |
| 603 | + **self.unrecognized_fields, |
| 604 | + } |
| 605 | + ) |
598 | 606 |
|
599 | 607 | def is_expired(self, reference_time: Optional[datetime] = None) -> bool:
|
600 | 608 | """Checks metadata expiration against a reference time.
|
@@ -682,14 +690,16 @@ def from_dict(cls, keyid: str, key_dict: Dict[str, Any]) -> "Key":
|
682 | 690 | # All fields left in the key_dict are unrecognized.
|
683 | 691 | return cls(keyid, keytype, scheme, keyval, key_dict)
|
684 | 692 |
|
685 |
| - def to_dict(self) -> Dict[str, Any]: |
| 693 | + def to_dict(self) -> OrderedDictT[str, Any]: |
686 | 694 | """Returns the dictionary representation of self."""
|
687 |
| - return { |
688 |
| - "keytype": self.keytype, |
689 |
| - "scheme": self.scheme, |
690 |
| - "keyval": self.keyval, |
691 |
| - **self.unrecognized_fields, |
692 |
| - } |
| 695 | + return OrderedDict( |
| 696 | + { |
| 697 | + "keytype": self.keytype, |
| 698 | + "scheme": self.scheme, |
| 699 | + "keyval": self.keyval, |
| 700 | + **self.unrecognized_fields, |
| 701 | + } |
| 702 | + ) |
693 | 703 |
|
694 | 704 | def to_securesystemslib_key(self) -> Dict[str, Any]:
|
695 | 705 | """Returns a ``Securesystemslib`` compatible representation of self."""
|
@@ -840,13 +850,17 @@ def from_dict(cls, role_dict: Dict[str, Any]) -> "Role":
|
840 | 850 | # All fields left in the role_dict are unrecognized.
|
841 | 851 | return cls(keyids, threshold, role_dict)
|
842 | 852 |
|
843 |
| - def to_dict(self) -> Dict[str, Any]: |
| 853 | + def to_dict(self) -> OrderedDictT[str, Any]: |
844 | 854 | """Returns the dictionary representation of self."""
|
845 |
| - return { |
846 |
| - "keyids": self.keyids, |
847 |
| - "threshold": self.threshold, |
848 |
| - **self.unrecognized_fields, |
849 |
| - } |
| 855 | + return OrderedDict( |
| 856 | + ( |
| 857 | + ("keyids", self.keyids), |
| 858 | + ("threshold", self.threshold), |
| 859 | + ) |
| 860 | + + tuple( |
| 861 | + sorted(self.unrecognized_fields.items(), key=lambda x: x[0]) |
| 862 | + ) |
| 863 | + ) |
850 | 864 |
|
851 | 865 |
|
852 | 866 | class Root(Signed):
|
@@ -927,12 +941,15 @@ def from_dict(cls, signed_dict: Dict[str, Any]) -> "Root":
|
927 | 941 | # All fields left in the signed_dict are unrecognized.
|
928 | 942 | return cls(*common_args, keys, roles, consistent_snapshot, signed_dict)
|
929 | 943 |
|
930 |
| - def to_dict(self) -> Dict[str, Any]: |
| 944 | + def to_dict(self) -> OrderedDictT[str, Any]: |
931 | 945 | """Returns the dict representation of self."""
|
932 | 946 | root_dict = self._common_fields_to_dict()
|
933 |
| - keys = {keyid: key.to_dict() for (keyid, key) in self.keys.items()} |
934 |
| - roles = {} |
935 |
| - for role_name, role in self.roles.items(): |
| 947 | + keys = OrderedDict( |
| 948 | + (keyid, key.to_dict()) |
| 949 | + for (keyid, key) in sorted(self.keys.items(), key=lambda x: x[0]) |
| 950 | + ) |
| 951 | + roles = OrderedDict() |
| 952 | + for role_name, role in sorted(self.roles.items(), key=lambda x: x[0]): |
936 | 953 | roles[role_name] = role.to_dict()
|
937 | 954 | if self.consistent_snapshot is not None:
|
938 | 955 | root_dict["consistent_snapshot"] = self.consistent_snapshot
|
@@ -1274,11 +1291,13 @@ def from_dict(cls, signed_dict: Dict[str, Any]) -> "Snapshot":
|
1274 | 1291 | # All fields left in the snapshot_dict are unrecognized.
|
1275 | 1292 | return cls(*common_args, meta, signed_dict)
|
1276 | 1293 |
|
1277 |
| - def to_dict(self) -> Dict[str, Any]: |
| 1294 | + def to_dict(self) -> OrderedDictT[str, Any]: |
1278 | 1295 | """Returns the dict representation of self."""
|
1279 | 1296 | snapshot_dict = self._common_fields_to_dict()
|
1280 |
| - meta_dict = {} |
1281 |
| - for meta_path, meta_info in self.meta.items(): |
| 1297 | + meta_dict = OrderedDict() |
| 1298 | + for meta_path, meta_info in sorted( |
| 1299 | + self.meta.items(), key=lambda x: x[0] |
| 1300 | + ): |
1282 | 1301 | meta_dict[meta_path] = meta_info.to_dict()
|
1283 | 1302 |
|
1284 | 1303 | snapshot_dict["meta"] = meta_dict
|
@@ -1695,13 +1714,18 @@ def from_dict(cls, delegations_dict: Dict[str, Any]) -> "Delegations":
|
1695 | 1714 | # All fields left in the delegations_dict are unrecognized.
|
1696 | 1715 | return cls(keys_res, roles_res, succinct_roles_info, delegations_dict)
|
1697 | 1716 |
|
1698 |
| - def to_dict(self) -> Dict[str, Any]: |
| 1717 | + def to_dict(self) -> OrderedDictT[str, Any]: |
1699 | 1718 | """Returns the dict representation of self."""
|
1700 |
| - keys = {keyid: key.to_dict() for keyid, key in self.keys.items()} |
1701 |
| - res_dict: Dict[str, Any] = { |
1702 |
| - "keys": keys, |
1703 |
| - **self.unrecognized_fields, |
1704 |
| - } |
| 1719 | + keys = OrderedDict( |
| 1720 | + (keyid, key.to_dict()) |
| 1721 | + for keyid, key in sorted(self.keys.items(), key=lambda x: x[0]) |
| 1722 | + ) |
| 1723 | + res_dict: Dict[str, Any] = OrderedDict( |
| 1724 | + { |
| 1725 | + "keys": keys, |
| 1726 | + **self.unrecognized_fields, |
| 1727 | + } |
| 1728 | + ) |
1705 | 1729 | if self.roles is not None:
|
1706 | 1730 | roles = [role_obj.to_dict() for role_obj in self.roles.values()]
|
1707 | 1731 | res_dict["roles"] = roles
|
@@ -1967,11 +1991,13 @@ def from_dict(cls, signed_dict: Dict[str, Any]) -> "Targets":
|
1967 | 1991 | # All fields left in the targets_dict are unrecognized.
|
1968 | 1992 | return cls(*common_args, res_targets, delegations, signed_dict)
|
1969 | 1993 |
|
1970 |
| - def to_dict(self) -> Dict[str, Any]: |
| 1994 | + def to_dict(self) -> OrderedDictT[str, Any]: |
1971 | 1995 | """Returns the dict representation of self."""
|
1972 | 1996 | targets_dict = self._common_fields_to_dict()
|
1973 |
| - targets = {} |
1974 |
| - for target_path, target_file_obj in self.targets.items(): |
| 1997 | + targets = OrderedDict() |
| 1998 | + for target_path, target_file_obj in sorted( |
| 1999 | + self.targets.items(), key=lambda x: x[0] |
| 2000 | + ): |
1975 | 2001 | targets[target_path] = target_file_obj.to_dict()
|
1976 | 2002 | targets_dict[_TARGETS] = targets
|
1977 | 2003 | if self.delegations is not None:
|
|
0 commit comments