Skip to content

Commit e1d1588

Browse files
committed
ngclient: Remove "Optional" from helper props
The properties in TrustedMetadataSet are a bit difficult to use with static typing since they return Optional but in many cases we know the "None"-case is impossible. Remove None from annotation: the idea is that calling the property getter too early is a programming error: it will result in KeyError which is consistent: * trusted_set["timestamp"] raises KeyError if timestamp is not set * trusted_set.timestamp raises KeyError if timestamp is not set Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
1 parent 26e872a commit e1d1588

2 files changed

Lines changed: 17 additions & 23 deletions

File tree

tuf/ngclient/_internal/trusted_metadata_set.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,19 @@ def root(self) -> Metadata[Root]:
117117
return self._trusted_set[Root.type]
118118

119119
@property
120-
def timestamp(self) -> Optional[Metadata[Timestamp]]:
121-
"""Get current timestamp ``Metadata`` or ``None``"""
122-
return self._trusted_set.get(Timestamp.type)
120+
def timestamp(self) -> Metadata[Timestamp]:
121+
"""Get current timestamp ``Metadata``"""
122+
return self._trusted_set[Timestamp.type]
123123

124124
@property
125-
def snapshot(self) -> Optional[Metadata[Snapshot]]:
126-
"""Get current snapshot ``Metadata`` or ``None``"""
127-
return self._trusted_set.get(Snapshot.type)
125+
def snapshot(self) -> Metadata[Snapshot]:
126+
"""Get current snapshot ``Metadata``"""
127+
return self._trusted_set[Snapshot.type]
128128

129129
@property
130-
def targets(self) -> Optional[Metadata[Targets]]:
131-
"""Get current targets ``Metadata`` or ``None``"""
132-
return self._trusted_set.get(Targets.type)
130+
def targets(self) -> Metadata[Targets]:
131+
"""Get current top-level targets ``Metadata``"""
132+
return self._trusted_set[Targets.type]
133133

134134
# Methods for updating metadata
135135
def update_root(self, data: bytes) -> Metadata[Root]:
@@ -149,7 +149,7 @@ def update_root(self, data: bytes) -> Metadata[Root]:
149149
Returns:
150150
Deserialized and verified root ``Metadata`` object
151151
"""
152-
if self.timestamp is not None:
152+
if Timestamp.type in self._trusted_set:
153153
raise RuntimeError("Cannot update root after timestamp")
154154
logger.debug("Updating root")
155155

@@ -199,7 +199,7 @@ def update_timestamp(self, data: bytes) -> Metadata[Timestamp]:
199199
Returns:
200200
Deserialized and verified timestamp ``Metadata`` object
201201
"""
202-
if self.snapshot is not None:
202+
if Snapshot.type in self._trusted_set:
203203
raise RuntimeError("Cannot update timestamp after snapshot")
204204

205205
# client workflow 5.3.10: Make sure final root is not expired.
@@ -219,7 +219,7 @@ def update_timestamp(self, data: bytes) -> Metadata[Timestamp]:
219219

220220
# If an existing trusted timestamp is updated,
221221
# check for a rollback attack
222-
if self.timestamp is not None:
222+
if Timestamp.type in self._trusted_set:
223223
# Prevent rolling back timestamp version
224224
if new_timestamp.signed.version < self.timestamp.signed.version:
225225
raise exceptions.BadVersionNumberError(
@@ -253,7 +253,6 @@ def update_timestamp(self, data: bytes) -> Metadata[Timestamp]:
253253
def _check_final_timestamp(self) -> None:
254254
"""Raise if timestamp is expired"""
255255

256-
assert self.timestamp is not None # nosec
257256
if self.timestamp.signed.is_expired(self.reference_time):
258257
raise exceptions.ExpiredMetadataError("timestamp.json is expired")
259258

@@ -288,9 +287,9 @@ def update_snapshot(
288287
Deserialized and verified snapshot ``Metadata`` object
289288
"""
290289

291-
if self.timestamp is None:
290+
if Timestamp.type not in self._trusted_set:
292291
raise RuntimeError("Cannot update snapshot before timestamp")
293-
if self.targets is not None:
292+
if Targets.type in self._trusted_set:
294293
raise RuntimeError("Cannot update snapshot after targets")
295294
logger.debug("Updating snapshot")
296295

@@ -317,7 +316,7 @@ def update_snapshot(
317316
# used in rollback protection: it is checked when targets is updated
318317

319318
# If an existing trusted snapshot is updated, check for rollback attack
320-
if self.snapshot is not None:
319+
if Snapshot.type in self._trusted_set:
321320
for filename, fileinfo in self.snapshot.signed.meta.items():
322321
new_fileinfo = new_snapshot.signed.meta.get(filename)
323322

@@ -348,8 +347,6 @@ def update_snapshot(
348347
def _check_final_snapshot(self) -> None:
349348
"""Raise if snapshot is expired or meta version does not match"""
350349

351-
assert self.snapshot is not None # nosec
352-
assert self.timestamp is not None # nosec
353350
if self.snapshot.signed.is_expired(self.reference_time):
354351
raise exceptions.ExpiredMetadataError("snapshot.json is expired")
355352
snapshot_meta = self.timestamp.signed.snapshot_meta
@@ -392,7 +389,7 @@ def update_delegated_targets(
392389
Returns:
393390
Deserialized and verified targets ``Metadata`` object
394391
"""
395-
if self.snapshot is None:
392+
if Snapshot.type not in self._trusted_set:
396393
raise RuntimeError("Cannot load targets before snapshot")
397394

398395
# Targets cannot be loaded if final snapshot is expired or its version

tuf/ngclient/updater.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def get_targetinfo(self, target_path: str) -> Optional[TargetFile]:
168168
``TargetFile`` instance or ``None``.
169169
"""
170170

171-
if self._trusted_set.targets is None:
171+
if Targets.type not in self._trusted_set:
172172
self.refresh()
173173
return self._preorder_depth_first_walk(target_path)
174174

@@ -361,7 +361,6 @@ def _load_snapshot(self) -> None:
361361
# Local snapshot does not exist or is invalid: update from remote
362362
logger.debug("Local snapshot not valid as final: %s", e)
363363

364-
assert self._trusted_set.timestamp is not None # nosec
365364
snapshot_meta = self._trusted_set.timestamp.signed.snapshot_meta
366365
length = snapshot_meta.length or self.config.snapshot_max_length
367366
version = None
@@ -390,8 +389,6 @@ def _load_targets(self, role: str, parent_role: str) -> Metadata[Targets]:
390389
# Local 'role' does not exist or is invalid: update from remote
391390
logger.debug("Failed to load local %s: %s", role, e)
392391

393-
assert self._trusted_set.snapshot is not None # nosec
394-
395392
snapshot = self._trusted_set.snapshot.signed
396393
metainfo = snapshot.meta.get(f"{role}.json")
397394
if metainfo is None:

0 commit comments

Comments
 (0)