Skip to content

Commit e530af3

Browse files
committed
Add more docstrings (WIP)
1 parent 68e8c89 commit e530af3

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

tests/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Copyright 2020, New York University and the TUF contributors
44
# SPDX-License-Identifier: MIT OR Apache-2.0
5-
""" Unit tests for api/metdata.py
5+
""" Unit tests for api/metadata.py
66
77
Skipped on Python < 3.6.
88

tuf/api/metadata.py

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,14 @@ def __init__(
7777
self.signatures = signatures
7878

7979
def as_dict(self) -> JsonDict:
80-
"""Returns the JSON-compatible dictionary representation. """
80+
"""Returns the JSON-serializable dictionary representation of self. """
8181
return {
8282
'signatures': self.signatures,
8383
'signed': self.signed.as_dict()
8484
}
8585

8686
def as_json(self, compact: bool = False) -> None:
87-
"""Returns the optionally compacted JSON representation. """
87+
"""Returns the optionally compacted JSON representation of self. """
8888
return json.dumps(
8989
self.as_dict(),
9090
indent=(None if compact else 1),
@@ -141,7 +141,7 @@ def read_from_json(
141141
cls, filename: str,
142142
storage_backend: Optional[StorageBackendInterface] = None
143143
) -> 'Metadata':
144-
"""Loads JSON-formatted TUF metadata from a file storage.
144+
"""Loads JSON-formatted TUF metadata from file storage.
145145
146146
Arguments:
147147
filename: The path to read the file from.
@@ -183,7 +183,7 @@ def read_from_json(
183183
def write_to_json(
184184
self, filename: str, compact: bool = False,
185185
storage_backend: StorageBackendInterface = None) -> None:
186-
"""Writes the JSON representation of the instance to file storage.
186+
"""Writes the JSON representation of self to file storage.
187187
188188
Arguments:
189189
filename: The path to write the file to.
@@ -203,6 +203,21 @@ def write_to_json(
203203

204204

205205
class Signed:
206+
"""A base class for the signed part of TUF metadata.
207+
208+
Objects with base class Signed are usually included in a Metablock object
209+
on the signed attribute. This class provides attributes and methods that
210+
are common for all TUF metadata types (roles).
211+
212+
Attributes:
213+
_type: The metadata type string.
214+
version: The metadata version number.
215+
spec_version: The TUF specification version number (semver) the
216+
metadata format adheres to.
217+
expires: The metadata expiration date in 'YYYY-MM-DDTHH:MM:SSZ' format.
218+
signed_bytes: The UTF-8 encoded canonical JSON representation of self.
219+
220+
"""
206221
# NOTE: Signed is a stupid name, because this might not be signed yet, but
207222
# we keep it to match spec terminology (I often refer to this as "payload",
208223
# or "inner metadata")
@@ -237,19 +252,18 @@ def signed_bytes(self) -> bytes:
237252

238253
@property
239254
def expires(self) -> str:
240-
"""The expiration property in TUF metadata format."""
241255
return self.__expiration.isoformat() + 'Z'
242256

243257
def bump_expiration(self, delta: timedelta = timedelta(days=1)) -> None:
258+
"""Increments the expires attribute by the passed timedelta. """
244259
self.__expiration = self.__expiration + delta
245260

246261
def bump_version(self) -> None:
262+
"""Increments the metadata version number by 1."""
247263
self.version += 1
248264

249265
def as_dict(self) -> JsonDict:
250-
# NOTE: The classes should be the single source of truth about metadata
251-
# let's define the dict representation here and not in some dubious
252-
# build_dict_conforming_to_schema
266+
"""Returns the JSON-serializable dictionary representation of self. """
253267
return {
254268
'_type': self._type,
255269
'version': self.version,
@@ -263,7 +277,24 @@ def read_from_json(
263277
storage_backend: Optional[StorageBackendInterface] = None
264278
) -> Metadata:
265279
signable = load_json_file(filename, storage_backend)
280+
"""Loads corresponding JSON-formatted metadata from file storage.
281+
282+
Arguments:
283+
filename: The path to read the file from.
284+
storage_backend: An object that implements
285+
securesystemslib.storage.StorageBackendInterface. Per default
286+
a (local) FilesystemBackend is used.
287+
288+
Raises:
289+
securesystemslib.exceptions.StorageError: The file cannot be read.
290+
securesystemslib.exceptions.Error, ValueError: The metadata cannot
291+
be parsed.
292+
293+
Returns:
294+
A TUF Metadata object whose signed attribute contains an object
295+
of this class.
266296
297+
"""
267298
# FIXME: It feels dirty to access signable["signed"]["version"] here in
268299
# order to do this check, and also a bit random (there are likely other
269300
# things to check), but later we don't have the filename anymore. If we
@@ -281,21 +312,37 @@ def read_from_json(
281312

282313

283314
class Timestamp(Signed):
315+
"""A container for the signed part of timestamp metadata.
316+
317+
Attributes:
318+
meta: A dictionary that contains information about snapshot metadata::
319+
320+
{
321+
"snapshot.json": {
322+
"version" : <snapshot metadata version number>,
323+
"length" : <snapshot metadata file size> // optional
324+
"hashes" : <snapshot metadata file hash dict> // optional
325+
}
326+
}
327+
328+
"""
284329
def __init__(self, meta: JsonDict = None, **kwargs) -> None:
285330
super().__init__(**kwargs)
286331
# TODO: How much init magic do we want?
287332
# TODO: Is there merit in creating classes for dict fields?
288333
self.meta = meta
289334

290335
def as_dict(self) -> JsonDict:
336+
"""Returns the JSON-serializable dictionary representation of self. """
291337
json_dict = super().as_dict()
292338
json_dict.update({
293339
'meta': self.meta
294340
})
295341
return json_dict
296342

297-
# Update metadata about the snapshot metadata.
298343
def update(self, version: int, length: int, hashes: JsonDict) -> None:
344+
"""Assigns passed info about snapshot metadata to meta dictionary. """
345+
# TODO: Should we assign it
299346
fileinfo = self.meta.get('snapshot.json', {})
300347
fileinfo['version'] = version
301348
fileinfo['length'] = length
@@ -304,13 +351,35 @@ def update(self, version: int, length: int, hashes: JsonDict) -> None:
304351

305352

306353
class Snapshot(Signed):
354+
"""A container for the signed part of snapshot metadata.
355+
356+
Attributes:
357+
meta: A dictionary that contains information about targets metadata::
358+
359+
{
360+
"targets.json": {
361+
"version" : <targets metadata version number>,
362+
"length" : <targets metadata file size> // optional
363+
"hashes" : <targets metadata file hash dict> // optional
364+
},
365+
"<delegated targets role 1>.json>: {
366+
...
367+
},
368+
"<delegated targets role 2>.json>: {
369+
...
370+
},
371+
...
372+
}
373+
374+
"""
307375
def __init__(self, meta: JsonDict = None, **kwargs) -> None:
308376
# TODO: How much init magic do we want?
309377
# TODO: Is there merit in creating classes for dict fields?
310378
super().__init__(**kwargs)
311379
self.meta = meta
312380

313381
def as_dict(self) -> JsonDict:
382+
"""Returns the JSON-serializable dictionary representation of self. """
314383
json_dict = super().as_dict()
315384
json_dict.update({
316385
'meta': self.meta
@@ -321,6 +390,7 @@ def as_dict(self) -> JsonDict:
321390
def update(
322391
self, rolename: str, version: int, length: Optional[int] = None,
323392
hashes: Optional[JsonDict] = None) -> None:
393+
"""Add or update the meta dictionary for a given targets role. """
324394
metadata_fn = f'{rolename}.json'
325395

326396
self.meta[metadata_fn] = {'version': version}

0 commit comments

Comments
 (0)