Skip to content

Commit 7815f05

Browse files
authored
Merge pull request #1455 from jku/mypy-tweaks
Harden mypy configuration
2 parents e61055a + f3d2655 commit 7815f05

File tree

3 files changed

+42
-36
lines changed

3 files changed

+42
-36
lines changed

setup.cfg

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ ignore =
99

1010
[mypy]
1111
warn_unused_configs = True
12-
files = tuf/api/
12+
warn_redundant_casts = True
13+
warn_unused_ignores = True
14+
warn_unreachable = True
15+
strict_equality = True
16+
disallow_untyped_defs = True
17+
disallow_untyped_calls = True
18+
files = tuf/api/, tuf/exceptions.py
1319

1420
[mypy-securesystemslib.*]
1521
ignore_missing_imports = True

tuf/api/metadata.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,11 @@ class Signed(metaclass=abc.ABCMeta):
288288

289289
# _type and type are identical: 1st replicates file format, 2nd passes lint
290290
@property
291-
def _type(self):
291+
def _type(self) -> str:
292292
return self._signed_type
293293

294294
@property
295-
def type(self):
295+
def type(self) -> str:
296296
return self._signed_type
297297

298298
# NOTE: Signed is a stupid name, because this might not be signed yet, but
@@ -372,7 +372,7 @@ def _common_fields_to_dict(self) -> Dict[str, Any]:
372372
**self.unrecognized_fields,
373373
}
374374

375-
def is_expired(self, reference_time: datetime = None) -> bool:
375+
def is_expired(self, reference_time: Optional[datetime] = None) -> bool:
376376
"""Checks metadata expiration against a reference time.
377377
378378
Args:
@@ -464,7 +464,7 @@ def verify_signature(
464464
self,
465465
metadata: Metadata,
466466
signed_serializer: Optional[SignedSerializer] = None,
467-
):
467+
) -> None:
468468
"""Verifies that the 'metadata.signatures' contains a signature made
469469
with this key, correctly signing 'metadata.signed'.
470470
@@ -765,7 +765,7 @@ def to_dict(self) -> Dict[str, Any]:
765765

766766
return res_dict
767767

768-
def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]):
768+
def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]) -> None:
769769
"""Verifies that the length and hashes of "data" match expected values.
770770
771771
Args:
@@ -1024,9 +1024,7 @@ def __init__(
10241024
self.unrecognized_fields = unrecognized_fields or {}
10251025

10261026
@property
1027-
def custom(self):
1028-
if self.unrecognized_fields is None:
1029-
return None
1027+
def custom(self) -> Any:
10301028
return self.unrecognized_fields.get("custom", None)
10311029

10321030
@classmethod
@@ -1046,7 +1044,7 @@ def to_dict(self) -> Dict[str, Any]:
10461044
**self.unrecognized_fields,
10471045
}
10481046

1049-
def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]):
1047+
def verify_length_and_hashes(self, data: Union[bytes, BinaryIO]) -> None:
10501048
"""Verifies that length and hashes of "data" match expected values.
10511049
10521050
Args:

tuf/exceptions.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
from urllib import parse
2626

27+
from typing import Any, Dict
28+
2729
import logging
2830
logger = logging.getLogger(__name__)
2931

@@ -45,16 +47,16 @@ class FormatError(Error):
4547
class InvalidMetadataJSONError(FormatError):
4648
"""Indicate that a metadata file is not valid JSON."""
4749

48-
def __init__(self, exception):
50+
def __init__(self, exception: BaseException):
4951
super(InvalidMetadataJSONError, self).__init__()
5052

5153
# Store the original exception.
5254
self.exception = exception
5355

54-
def __str__(self):
56+
def __str__(self) -> str:
5557
return repr(self)
5658

57-
def __repr__(self):
59+
def __repr__(self) -> str:
5860
# Show the original exception.
5961
return self.__class__.__name__ + ' : wraps error: ' + repr(self.exception)
6062

@@ -71,18 +73,18 @@ class LengthOrHashMismatchError(Error):
7173
class BadHashError(Error):
7274
"""Indicate an error while checking the value of a hash object."""
7375

74-
def __init__(self, expected_hash, observed_hash):
76+
def __init__(self, expected_hash: str, observed_hash: str):
7577
super(BadHashError, self).__init__()
7678

7779
self.expected_hash = expected_hash
7880
self.observed_hash = observed_hash
7981

80-
def __str__(self):
82+
def __str__(self) -> str:
8183
return (
8284
'Observed hash (' + repr(self.observed_hash) + ') != expected hash (' +
8385
repr(self.expected_hash) + ')')
8486

85-
def __repr__(self):
87+
def __repr__(self) -> str:
8688
return self.__class__.__name__ + ' : ' + str(self)
8789

8890
# # Directly instance-reproducing:
@@ -125,21 +127,20 @@ class ExpiredMetadataError(Error):
125127
class ReplayedMetadataError(RepositoryError):
126128
"""Indicate that some metadata has been replayed to the client."""
127129

128-
def __init__(self, metadata_role, previous_version, current_version):
130+
def __init__(self, metadata_role: str, previous_version: int, current_version: int):
129131
super(ReplayedMetadataError, self).__init__()
130132

131133
self.metadata_role = metadata_role
132134
self.previous_version = previous_version
133135
self.current_version = current_version
134136

135-
136-
def __str__(self):
137+
def __str__(self) -> str:
137138
return (
138139
'Downloaded ' + repr(self.metadata_role) + ' is older (' +
139140
repr(self.previous_version) + ') than the version currently '
140141
'installed (' + repr(self.current_version) + ').')
141142

142-
def __repr__(self):
143+
def __repr__(self) -> str:
143144
return self.__class__.__name__ + ' : ' + str(self)
144145

145146
# # Directly instance-reproducing:
@@ -156,15 +157,15 @@ class CryptoError(Error):
156157
class BadSignatureError(CryptoError):
157158
"""Indicate that some metadata file has a bad signature."""
158159

159-
def __init__(self, metadata_role_name):
160+
def __init__(self, metadata_role_name: str):
160161
super(BadSignatureError, self).__init__()
161162

162163
self.metadata_role_name = metadata_role_name
163164

164-
def __str__(self):
165+
def __str__(self) -> str:
165166
return repr(self.metadata_role_name) + ' metadata has a bad signature.'
166167

167-
def __repr__(self):
168+
def __repr__(self) -> str:
168169
return self.__class__.__name__ + ' : ' + str(self)
169170

170171
# # Directly instance-reproducing:
@@ -187,18 +188,18 @@ class DownloadError(Error):
187188
class DownloadLengthMismatchError(DownloadError):
188189
"""Indicate that a mismatch of lengths was seen while downloading a file."""
189190

190-
def __init__(self, expected_length, observed_length):
191+
def __init__(self, expected_length: int, observed_length: int):
191192
super(DownloadLengthMismatchError, self).__init__()
192193

193194
self.expected_length = expected_length #bytes
194195
self.observed_length = observed_length #bytes
195196

196-
def __str__(self):
197+
def __str__(self) -> str:
197198
return (
198199
'Observed length (' + repr(self.observed_length) +
199200
') < expected length (' + repr(self.expected_length) + ').')
200201

201-
def __repr__(self):
202+
def __repr__(self) -> str:
202203
return self.__class__.__name__ + ' : ' + str(self)
203204

204205
# # Directly instance-reproducing:
@@ -211,17 +212,17 @@ def __repr__(self):
211212
class SlowRetrievalError(DownloadError):
212213
""""Indicate that downloading a file took an unreasonably long time."""
213214

214-
def __init__(self, average_download_speed):
215+
def __init__(self, average_download_speed: int):
215216
super(SlowRetrievalError, self).__init__()
216217

217218
self.__average_download_speed = average_download_speed #bytes/second
218219

219-
def __str__(self):
220+
def __str__(self) -> str:
220221
return (
221222
'Download was too slow. Average speed: ' +
222223
repr(self.__average_download_speed) + ' bytes per second.')
223224

224-
def __repr__(self):
225+
def __repr__(self) -> str:
225226
return self.__class__.__name__ + ' : ' + str(self)
226227

227228
# # Directly instance-reproducing:
@@ -252,16 +253,17 @@ class InvalidNameError(Error):
252253
class UnsignedMetadataError(Error):
253254
"""Indicate metadata object with insufficient threshold of signatures."""
254255

255-
def __init__(self, message, signable):
256+
# signable is not used but kept in method signature for backwards compat
257+
def __init__(self, message: str, signable: Any = None):
256258
super(UnsignedMetadataError, self).__init__()
257259

258260
self.exception_message = message
259261
self.signable = signable
260262

261-
def __str__(self):
263+
def __str__(self) -> str:
262264
return self.exception_message
263265

264-
def __repr__(self):
266+
def __repr__(self) -> str:
265267
return self.__class__.__name__ + ' : ' + str(self)
266268

267269
# # Directly instance-reproducing:
@@ -278,13 +280,13 @@ class NoWorkingMirrorError(Error):
278280
provided.
279281
"""
280282

281-
def __init__(self, mirror_errors):
283+
def __init__(self, mirror_errors: Dict[str, BaseException]):
282284
super(NoWorkingMirrorError, self).__init__()
283285

284286
# Dictionary of URL strings to Exception instances
285287
self.mirror_errors = mirror_errors
286288

287-
def __str__(self):
289+
def __str__(self) -> str:
288290
all_errors = 'No working mirror was found:'
289291

290292
for mirror_url, mirror_error in self.mirror_errors.items():
@@ -303,7 +305,7 @@ def __str__(self):
303305

304306
return all_errors
305307

306-
def __repr__(self):
308+
def __repr__(self) -> str:
307309
return self.__class__.__name__ + ' : ' + str(self)
308310

309311
# # Directly instance-reproducing:
@@ -334,6 +336,6 @@ class FetcherHTTPError(Exception):
334336
message (str): The HTTP error messsage
335337
status_code (int): The HTTP status code
336338
"""
337-
def __init__(self, message, status_code):
339+
def __init__(self, message: str, status_code: int):
338340
super(FetcherHTTPError, self).__init__(message)
339341
self.status_code = status_code

0 commit comments

Comments
 (0)