Skip to content

Commit b86a31c

Browse files
committed
Address pylint warnings on tests for the new code
Address or disable pylint warnings raised on all test files inside tests/ testing the code of the new implementation. Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
1 parent 64bb4ef commit b86a31c

8 files changed

+109
-69
lines changed

tests/repository_simulator.py

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
Timestamp,
7373
)
7474
from tuf.api.serialization.json import JSONSerializer
75-
from tuf.exceptions import FetcherHTTPError, RepositoryError
75+
from tuf.exceptions import FetcherHTTPError
7676
from tuf.ngclient.fetcher import FetcherInterface
7777

7878
logger = logging.getLogger(__name__)
@@ -89,6 +89,9 @@ class RepositoryTarget:
8989

9090

9191
class RepositorySimulator(FetcherInterface):
92+
"""Simulates a repository that can be used for testing"""
93+
94+
# pylint: disable=too-many-instance-attributes
9295
def __init__(self):
9396
self.md_root: Metadata[Root] = None
9497
self.md_timestamp: Metadata[Timestamp] = None
@@ -134,11 +137,14 @@ def targets(self) -> Targets:
134137
return self.md_targets.signed
135138

136139
def all_targets(self) -> Iterator[Tuple[str, Targets]]:
140+
"""Yield role name and signed portion of targets one by one"""
137141
yield "targets", self.md_targets.signed
138142
for role, md in self.md_delegates.items():
139143
yield role, md.signed
140144

145+
# pylint: disable-next=no-self-use
141146
def create_key(self) -> Tuple[Key, SSlibSigner]:
147+
"""Create ed25519 key"""
142148
sslib_key = generate_ed25519_key()
143149
return Key.from_securesystemslib_key(sslib_key), SSlibSigner(sslib_key)
144150

@@ -178,6 +184,7 @@ def publish_root(self):
178184
logger.debug("Published root v%d", self.root.version)
179185

180186
def fetch(self, url: str) -> Iterator[bytes]:
187+
"""Fetches data from the given url and yeilds an Iterator"""
181188
if not self.root.consistent_snapshot:
182189
raise NotImplementedError("non-consistent snapshot not supported")
183190
path = parse.urlparse(url).path
@@ -188,20 +195,24 @@ def fetch(self, url: str) -> Iterator[bytes]:
188195
version = None
189196
role = "timestamp"
190197
else:
198+
# pylint: disable-next=invalid-name
191199
version, _, role = ver_and_name.partition(".")
192200
version = int(version)
193201
yield self._fetch_metadata(role, version)
194202
elif path.startswith("/targets/"):
195203
# figure out target path and hash prefix
196204
target_path = path[len("/targets/") :]
197205
dir_parts, sep, prefixed_filename = target_path.rpartition("/")
206+
# pylint: disable-next=invalid-name
198207
prefix, _, filename = prefixed_filename.partition(".")
199208
target_path = f"{dir_parts}{sep}{filename}"
200209

201210
yield self._fetch_target(target_path, prefix)
202211
else:
203212
raise FetcherHTTPError(f"Unknown path '{path}'", 404)
204213

214+
# Disable the redefined-builtin warning raised because of the hash func.
215+
# pylint: disable-next=redefined-builtin
205216
def _fetch_target(self, target_path: str, hash: Optional[str]) -> bytes:
206217
"""Return data for 'target_path', checking 'hash' if it is given.
207218
@@ -227,35 +238,32 @@ def _fetch_metadata(
227238
# return a version previously serialized in publish_root()
228239
if version is None or version > len(self.signed_roots):
229240
raise FetcherHTTPError(f"Unknown root version {version}", 404)
230-
logger.debug("fetched root version %d", role, version)
241+
logger.debug("fetched root version %d", version)
231242
return self.signed_roots[version - 1]
243+
244+
# sign and serialize the requested metadata
245+
if role == "timestamp":
246+
md: Metadata = self.md_timestamp
247+
elif role == "snapshot":
248+
md = self.md_snapshot
249+
elif role == "targets":
250+
md = self.md_targets
232251
else:
233-
# sign and serialize the requested metadata
234-
if role == "timestamp":
235-
md: Metadata = self.md_timestamp
236-
elif role == "snapshot":
237-
md = self.md_snapshot
238-
elif role == "targets":
239-
md = self.md_targets
240-
else:
241-
md = self.md_delegates[role]
242-
243-
if md is None:
244-
raise FetcherHTTPError(f"Unknown role {role}", 404)
245-
if version is not None and version != md.signed.version:
246-
raise FetcherHTTPError(f"Unknown {role} version {version}", 404)
247-
248-
md.signatures.clear()
249-
for signer in self.signers[role]:
250-
md.sign(signer, append=True)
251-
252-
logger.debug(
253-
"fetched %s v%d with %d sigs",
254-
role,
255-
md.signed.version,
256-
len(self.signers[role]),
257-
)
258-
return md.to_bytes(JSONSerializer())
252+
md = self.md_delegates[role]
253+
254+
if md is None:
255+
raise FetcherHTTPError(f"Unknown role {role}", 404)
256+
if version is not None and version != md.signed.version:
257+
raise FetcherHTTPError(f"Unknown {role} version {version}", 404)
258+
259+
md.signatures.clear()
260+
for signer in self.signers[role]:
261+
md.sign(signer, append=True)
262+
263+
num_signers = len(self.signers[role])
264+
msg = f"fetched {role} {md.signed.version} with {num_signers} sigs"
265+
logger.debug(msg)
266+
return md.to_bytes(JSONSerializer())
259267

260268
def _compute_hashes_and_length(
261269
self, role: str
@@ -267,6 +275,7 @@ def _compute_hashes_and_length(
267275
return hashes, len(data)
268276

269277
def update_timestamp(self):
278+
"""Update timestamp and assign snapshot ver to snapshot_meta ver"""
270279
self.timestamp.snapshot_meta.version = self.snapshot.version
271280

272281
if self.compute_metafile_hashes_length:
@@ -277,6 +286,7 @@ def update_timestamp(self):
277286
self.timestamp.version += 1
278287

279288
def update_snapshot(self):
289+
"""Update snapshot, assign targets versions and update timestamp"""
280290
for role, delegate in self.all_targets():
281291
hashes = None
282292
length = None
@@ -291,6 +301,7 @@ def update_snapshot(self):
291301
self.update_timestamp()
292302

293303
def add_target(self, role: str, data: bytes, path: str):
304+
"""Create a target from data and add it to the target_files"""
294305
if role == "targets":
295306
targets = self.targets
296307
else:
@@ -309,6 +320,7 @@ def add_delegation(
309320
paths: Optional[List[str]],
310321
hash_prefixes: Optional[List[str]],
311322
):
323+
"""Add delegated target role to the repository"""
312324
if delegator_name == "targets":
313325
delegator = self.targets
314326
else:
@@ -342,17 +354,18 @@ def write(self):
342354
print(f"Repository Simulator dumps in {self.dump_dir}")
343355

344356
self.dump_version += 1
345-
dir = os.path.join(self.dump_dir, str(self.dump_version))
346-
os.makedirs(dir)
357+
dest_dir = os.path.join(self.dump_dir, str(self.dump_version))
358+
os.makedirs(dest_dir)
347359

348360
for ver in range(1, len(self.signed_roots) + 1):
349-
with open(os.path.join(dir, f"{ver}.root.json"), "wb") as f:
361+
with open(os.path.join(dest_dir, f"{ver}.root.json"), "wb") as f:
350362
f.write(self._fetch_metadata("root", ver))
351363

352364
for role in ["timestamp", "snapshot", "targets"]:
353-
with open(os.path.join(dir, f"{role}.json"), "wb") as f:
365+
with open(os.path.join(dest_dir, f"{role}.json"), "wb") as f:
354366
f.write(self._fetch_metadata(role))
355367

368+
# pylint: disable-next=consider-iterating-dictionary
356369
for role in self.md_delegates.keys():
357-
with open(os.path.join(dir, f"{role}.json"), "wb") as f:
370+
with open(os.path.join(dest_dir, f"{role}.json"), "wb") as f:
358371
f.write(self._fetch_metadata(role))

tests/test_api.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545

4646
class TestMetadata(unittest.TestCase):
47+
"""Tests for public API of all classes in tuf/api/metadata.py"""
48+
4749
@classmethod
4850
def setUpClass(cls):
4951
# Create a temporary directory to store the repository, metadata, and
@@ -155,8 +157,8 @@ def test_to_from_bytes(self):
155157
self.assertEqual(metadata_obj_2.to_bytes(), obj_bytes)
156158

157159
def test_sign_verify(self):
158-
root_path = os.path.join(self.repo_dir, "metadata", "root.json")
159-
root = Metadata[Root].from_file(root_path).signed
160+
path = os.path.join(self.repo_dir, "metadata", "root.json")
161+
root = Metadata[Root].from_file(path).signed
160162

161163
# Locate the public keys we need from root
162164
targets_keyid = next(iter(root.roles["targets"].keyids))
@@ -203,7 +205,8 @@ def test_sign_verify(self):
203205
with self.assertRaises(exceptions.UnsignedMetadataError):
204206
targets_key.verify_signature(md_obj)
205207

206-
# Test failure on unknown scheme (securesystemslib UnsupportedAlgorithmError)
208+
# Test failure on unknown scheme (securesystemslib
209+
# UnsupportedAlgorithmError)
207210
scheme = timestamp_key.scheme
208211
timestamp_key.scheme = "foo"
209212
with self.assertRaises(exceptions.UnsignedMetadataError):
@@ -231,8 +234,8 @@ def test_sign_verify(self):
231234
sig.signature = correct_sig
232235

233236
def test_metadata_base(self):
234-
# Use of Snapshot is arbitrary, we're just testing the base class features
235-
# with real data
237+
# Use of Snapshot is arbitrary, we're just testing the base class
238+
# features with real data
236239
snapshot_path = os.path.join(self.repo_dir, "metadata", "snapshot.json")
237240
md = Metadata.from_file(snapshot_path)
238241

@@ -279,7 +282,7 @@ def test_metadata_snapshot(self):
279282
# Create a MetaFile instance representing what we expect
280283
# the updated data to be.
281284
hashes = {
282-
"sha256": "c2986576f5fdfd43944e2b19e775453b96748ec4fe2638a6d2f32f1310967095"
285+
"sha256": "c2986576f5fdfd43944e2b19e775453b96748ec4fe2638a6d2f32f1310967095" # pylint: disable=line-too-long
283286
}
284287
fileinfo = MetaFile(2, 123, hashes)
285288

@@ -319,7 +322,7 @@ def test_metadata_timestamp(self):
319322
# Create a MetaFile instance representing what we expect
320323
# the updated data to be.
321324
hashes = {
322-
"sha256": "0ae9664468150a9aa1e7f11feecb32341658eb84292851367fea2da88e8a58dc"
325+
"sha256": "0ae9664468150a9aa1e7f11feecb32341658eb84292851367fea2da88e8a58dc" # pylint: disable=line-too-long
323326
}
324327
fileinfo = MetaFile(2, 520, hashes)
325328

@@ -472,6 +475,7 @@ def test_is_target_in_pathpattern(self):
472475
]
473476
for targetpath, pathpattern in supported_use_cases:
474477
self.assertTrue(
478+
# pylint: disable-next=protected-access
475479
DelegatedRole._is_target_in_pathpattern(targetpath, pathpattern)
476480
)
477481

@@ -485,18 +489,19 @@ def test_is_target_in_pathpattern(self):
485489
]
486490
for targetpath, pathpattern in invalid_use_cases:
487491
self.assertFalse(
492+
# pylint: disable-next=protected-access
488493
DelegatedRole._is_target_in_pathpattern(targetpath, pathpattern)
489494
)
490495

491496
def test_metadata_targets(self):
492497
targets_path = os.path.join(self.repo_dir, "metadata", "targets.json")
493498
targets = Metadata[Targets].from_file(targets_path)
494499

495-
# Create a fileinfo dict representing what we expect the updated data to be
500+
# Create a fileinfo dict representing the expected updated data.
496501
filename = "file2.txt"
497502
hashes = {
498-
"sha256": "141f740f53781d1ca54b8a50af22cbf74e44c21a998fa2a8a05aaac2c002886b",
499-
"sha512": "ef5beafa16041bcdd2937140afebd485296cd54f7348ecd5a4d035c09759608de467a7ac0eb58753d0242df873c305e8bffad2454aa48f44480f15efae1cacd0",
503+
"sha256": "141f740f53781d1ca54b8a50af22cbf74e44c21a998fa2a8a05aaac2c002886b", # pylint: disable=line-too-long
504+
"sha512": "ef5beafa16041bcdd2937140afebd485296cd54f7348ecd5a4d035c09759608de467a7ac0eb58753d0242df873c305e8bffad2454aa48f44480f15efae1cacd0", # pylint: disable=line-too-long
500505
}
501506

502507
fileinfo = TargetFile(length=28, hashes=hashes, path=filename)
@@ -531,7 +536,7 @@ def test_targets_key_api(self):
531536
key_dict = {
532537
"keytype": "ed25519",
533538
"keyval": {
534-
"public": "edcd0a32a07dce33f7c7873aaffbff36d20ea30787574ead335eefd337e4dacd"
539+
"public": "edcd0a32a07dce33f7c7873aaffbff36d20ea30787574ead335eefd337e4dacd" # pylint: disable=line-too-long
535540
},
536541
"scheme": "ed25519",
537542
}
@@ -628,7 +633,7 @@ def test_length_and_hash_validation(self):
628633
)
629634

630635
snapshot_metafile.hashes = {
631-
"unsupported-alg": "8f88e2ba48b412c3843e9bb26e1b6f8fc9e98aceb0fbaa97ba37b4c98717d7ab"
636+
"unsupported-alg": "8f88e2ba48b412c3843e9bb26e1b6f8fc9e98aceb0fbaa97ba37b4c98717d7ab" # pylint: disable=line-too-long
632637
}
633638
self.assertRaises(
634639
exceptions.LengthOrHashMismatchError,
@@ -638,7 +643,7 @@ def test_length_and_hash_validation(self):
638643

639644
# Test wrong algorithm format (sslib.FormatError)
640645
snapshot_metafile.hashes = {
641-
256: "8f88e2ba48b412c3843e9bb26e1b6f8fc9e98aceb0fbaa97ba37b4c98717d7ab"
646+
256: "8f88e2ba48b412c3843e9bb26e1b6f8fc9e98aceb0fbaa97ba37b4c98717d7ab" # pylint: disable=line-too-long
642647
}
643648
self.assertRaises(
644649
exceptions.LengthOrHashMismatchError,

tests/test_fetcher.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
import tuf
1818
import tuf.exceptions
1919
import tuf.requests_fetcher
20-
import tuf.unittest_toolbox as unittest_toolbox
2120
from tests import utils
21+
from tuf import unittest_toolbox
2222

2323
logger = logging.getLogger(__name__)
2424

2525

2626
class TestFetcher(unittest_toolbox.Modified_TestCase):
27+
"""Unit tests for RequestFetcher"""
28+
2729
def setUp(self):
2830
"""
2931
Create a temporary file and launch a simple server in the
@@ -35,7 +37,8 @@ def setUp(self):
3537
# Making a temporary file.
3638
current_dir = os.getcwd()
3739
target_filepath = self.make_temp_data_file(directory=current_dir)
38-
self.target_fileobj = open(target_filepath, "r")
40+
# pylint: disable-next=consider-using-with
41+
self.target_fileobj = open(target_filepath, "r", encoding="utf8")
3942
self.file_contents = self.target_fileobj.read()
4043
self.file_length = len(self.file_contents)
4144

@@ -54,6 +57,7 @@ def setUp(self):
5457

5558
# Create a temporary file where the target file chunks are written
5659
# during fetching
60+
# pylint: disable-next=consider-using-with
5761
self.temp_file = tempfile.TemporaryFile()
5862
self.fetcher = tuf.requests_fetcher.RequestsFetcher()
5963

tests/test_fetcher_ng.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727

2828
class TestFetcher(unittest_toolbox.Modified_TestCase):
29+
"""Test RequestsFetcher class"""
30+
2931
@classmethod
3032
def setUpClass(cls):
3133
# Launch a SimpleHTTPServer (serves files in the current dir).
@@ -48,11 +50,16 @@ def setUp(self):
4850
current_dir = os.getcwd()
4951
target_filepath = self.make_temp_data_file(directory=current_dir)
5052

51-
self.target_fileobj = open(target_filepath, "r")
53+
# pylint: disable-next=consider-using-with
54+
self.target_fileobj = open(target_filepath, "r", encoding="utf8")
5255
self.file_contents = self.target_fileobj.read()
5356
self.file_length = len(self.file_contents)
5457
self.rel_target_filepath = os.path.basename(target_filepath)
55-
self.url = f"http://{utils.TEST_HOST_ADDRESS}:{str(self.server_process_handler.port)}/{self.rel_target_filepath}"
58+
self.url_prefix = (
59+
f"http://{utils.TEST_HOST_ADDRESS}:"
60+
f"{str(self.server_process_handler.port)}"
61+
)
62+
self.url = f"{self.url_prefix}/{self.rel_target_filepath}"
5663

5764
# Instantiate a concrete instance of FetcherInterface
5865
self.fetcher = RequestsFetcher()
@@ -106,7 +113,7 @@ def test_url_parsing(self):
106113
# File not found error
107114
def test_http_error(self):
108115
with self.assertRaises(exceptions.FetcherHTTPError) as cm:
109-
self.url = f"http://{utils.TEST_HOST_ADDRESS}:{str(self.server_process_handler.port)}/non-existing-path"
116+
self.url = f"{self.url_prefix}/non-existing-path"
110117
self.fetcher.fetch(self.url)
111118
self.assertEqual(cm.exception.status_code, 404)
112119

tests/test_metadata_serialization.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636

3737
class TestSerialization(unittest.TestCase):
38+
"""Test serialization for all classes in tuf/api/metadata.py"""
3839

3940
# Snapshot instances with meta = {} are valid, but for a full valid
4041
# repository it's required that meta has at least one element inside it.

0 commit comments

Comments
 (0)