diff --git a/tests/test_api.py b/tests/test_api.py index f3dbd62013..ca45f8ed92 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -89,13 +89,25 @@ def test_generic_read(self): ('timestamp', Timestamp), ('targets', Targets)]: + # Load JSON-formatted metdata of each supported type from file + # and from out-of-band read JSON string path = os.path.join(self.repo_dir, 'metadata', metadata + '.json') metadata_obj = Metadata.from_json_file(path) + with open(path, 'rb') as f: + metadata_str = f.read() + metadata_obj2 = Metadata.from_json(metadata_str) - # Assert that generic method instantiates the right inner class for - # each metadata type + # Assert that both methods instantiate the right inner class for + # each metadata type and ... self.assertTrue( isinstance(metadata_obj.signed, inner_metadata_cls)) + self.assertTrue( + isinstance(metadata_obj2.signed, inner_metadata_cls)) + + # ... and return the same object (compared by dict representation) + self.assertDictEqual( + metadata_obj.to_dict(), metadata_obj2.to_dict()) + # Assert that it chokes correctly on an unknown metadata type bad_metadata_path = 'bad-metadata.json' diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 7df43b2862..171930834f 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -29,7 +29,11 @@ import tempfile from securesystemslib.formats import encode_canonical -from securesystemslib.util import load_json_file, persist_temp_file +from securesystemslib.util import ( + load_json_file, + load_json_string, + persist_temp_file +) from securesystemslib.storage import StorageBackendInterface from securesystemslib.keys import create_signature, verify_signature from tuf.repository_lib import ( @@ -80,6 +84,24 @@ def to_dict(self) -> JsonDict: 'signed': self.signed.to_dict() } + @classmethod + def from_json(cls, metadata_json: str) -> 'Metadata': + """Loads JSON-formatted TUF metadata from a string. + + Arguments: + metadata_json: TUF metadata in JSON-string representation. + + Raises: + securesystemslib.exceptions.Error, ValueError, KeyError: The + metadata cannot be parsed. + + Returns: + A TUF Metadata object. + + """ + return cls.from_dict(load_json_string(metadata_json)) + + def to_json(self, compact: bool = False) -> None: """Returns the optionally compacted JSON representation of self. """ return json.dumps(