Skip to content

Commit 4f37de1

Browse files
author
Martin Vrachev
committed
Metadata API: add Metadata.to_bytes()
Metadata.to_bytes() is missing from the API and that is now becoming annoying when writing the tests. I think it makes sense to add: it'll complete the serializing counterparts to from_bytes()/from_file(). We can also reuse to_bytes() in to_file() and that way ensure we don't import the JSONSerializer locally twice. Signed-off-by: Martin Vrachev <[email protected]>
1 parent 23e4f5c commit 4f37de1

2 files changed

Lines changed: 47 additions & 7 deletions

File tree

tests/test_api.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ def test_read_write_read_compare(self):
159159
os.remove(path_2)
160160

161161

162+
def test_to_from_bytes(self):
163+
for metadata in ["root", "snapshot", "timestamp", "targets"]:
164+
path = os.path.join(self.repo_dir, 'metadata', metadata + '.json')
165+
with open(path, 'rb') as f:
166+
metadata_bytes = f.read()
167+
metadata_obj = Metadata.from_bytes(metadata_bytes)
168+
# Comparate that from_bytes/to_bytes doesn't change the content
169+
# for two cases for the serializer: noncompact and compact.
170+
171+
# Case 1: test noncompact by overriding the default serializer.
172+
self.assertEqual(
173+
metadata_obj.to_bytes(JSONSerializer()), metadata_bytes
174+
)
175+
176+
# Case 2: test compact by using the default serializer.
177+
obj_bytes = metadata_obj.to_bytes()
178+
metadata_obj_2 = Metadata.from_bytes(obj_bytes)
179+
self.assertEqual(
180+
metadata_obj_2.to_bytes(), obj_bytes
181+
)
182+
183+
162184
def test_sign_verify(self):
163185
root_path = os.path.join(self.repo_dir, 'metadata', 'root.json')
164186
root:Root = Metadata.from_file(root_path).signed

tuf/api/metadata.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,29 @@ def from_bytes(
185185

186186
return deserializer.deserialize(data)
187187

188+
def to_bytes(
189+
self, serializer: Optional[MetadataSerializer] = None
190+
) -> bytes:
191+
"""Return the serialized TUF file format as bytes.
192+
193+
Arguments:
194+
serializer: A MetadataSerializer instance that implements the
195+
desired serialization format. Default is JSONSerializer.
196+
197+
Raises:
198+
tuf.api.serialization.SerializationError:
199+
The metadata object cannot be serialized.
200+
"""
201+
202+
if serializer is None:
203+
# Use local scope import to avoid circular import errors
204+
# pylint: disable=import-outside-toplevel
205+
from tuf.api.serialization.json import JSONSerializer
206+
207+
serializer = JSONSerializer(compact=True)
208+
209+
return serializer.serialize(self)
210+
188211
def to_dict(self) -> Dict[str, Any]:
189212
"""Returns the dict representation of self."""
190213

@@ -214,15 +237,10 @@ def to_file(
214237
The file cannot be written.
215238
"""
216239

217-
if serializer is None:
218-
# Use local scope import to avoid circular import errors
219-
# pylint: disable=import-outside-toplevel
220-
from tuf.api.serialization.json import JSONSerializer
221-
222-
serializer = JSONSerializer(compact=True)
240+
bytes_data = self.to_bytes(serializer)
223241

224242
with tempfile.TemporaryFile() as temp_file:
225-
temp_file.write(serializer.serialize(self))
243+
temp_file.write(bytes_data)
226244
persist_temp_file(temp_file, filename, storage_backend)
227245

228246
# Signatures.

0 commit comments

Comments
 (0)