Merge ~adam-collard/maas-ci/+git/system-tests:strict-mypy into ~maas-committers/maas-ci/+git/system-tests:master
- Git
- lp:~adam-collard/maas-ci/+git/system-tests
- strict-mypy
- Merge into master
Proposed by
Adam Collard
Status: | Merged |
---|---|
Approved by: | Adam Collard |
Approved revision: | a91b80b938d188ca9c0eab2bd2b6d22b5b728540 |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~adam-collard/maas-ci/+git/system-tests:strict-mypy |
Merge into: | ~maas-committers/maas-ci/+git/system-tests:master |
Diff against target: |
558 lines (+132/-78) 10 files modified
pyproject.toml (+1/-3) systemtests/api.py (+94/-49) systemtests/fixtures.py (+5/-5) systemtests/lxd.py (+6/-5) systemtests/region.py (+8/-4) systemtests/subprocess.py (+4/-2) systemtests/tests/conftest.py (+4/-4) systemtests/tests/test_basic.py (+3/-1) systemtests/tests/test_crud.py (+3/-3) systemtests/utils.py (+4/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alberto Donato (community) | Approve | ||
MAAS Lander | Approve | ||
Review via email: mp+408010@code.launchpad.net |
Commit message
Add strict mypy validation.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/pyproject.toml b/pyproject.toml |
2 | index 0c84d1d..cf33498 100644 |
3 | --- a/pyproject.toml |
4 | +++ b/pyproject.toml |
5 | @@ -13,8 +13,6 @@ log_file_date_format = "%Y-%m-%d %H:%M:%S" |
6 | |
7 | |
8 | [tool.mypy] |
9 | -disallow_untyped_calls = true |
10 | -disallow_untyped_defs = true |
11 | -warn_unused_configs = true |
12 | install_types = true |
13 | non_interactive = true |
14 | +strict = true |
15 | diff --git a/systemtests/api.py b/systemtests/api.py |
16 | index 4aac548..a82fde4 100644 |
17 | --- a/systemtests/api.py |
18 | +++ b/systemtests/api.py |
19 | @@ -29,10 +29,10 @@ class MAASAPIClient: |
20 | self.pull_file = partial(lxd.pull_file, maas_container) |
21 | self.push_file = partial(lxd.push_file, maas_container) |
22 | |
23 | - def execute(self, cmd: list[str]) -> CompletedProcess: |
24 | + def execute(self, cmd: list[str]) -> CompletedProcess[str]: |
25 | return self.lxd.execute(self.maas_container, ["maas"] + cmd) |
26 | |
27 | - def log_in(self, session: str, token: str) -> CompletedProcess: |
28 | + def log_in(self, session: str, token: str) -> CompletedProcess[str]: |
29 | return self.execute(["login", session, self.url, token]) |
30 | |
31 | |
32 | @@ -44,7 +44,7 @@ class AuthenticatedAPIClient: |
33 | def execute( |
34 | self, |
35 | cmd: list[str], |
36 | - extra_params: dict[str, str] = None, |
37 | + extra_params: Optional[dict[str, str]] = None, |
38 | json_output: bool = True, |
39 | ) -> Any: |
40 | if extra_params: |
41 | @@ -52,31 +52,47 @@ class AuthenticatedAPIClient: |
42 | result = self.api_client.execute([self.session] + cmd) |
43 | return json.loads(result.stdout) if json_output else result.stdout |
44 | |
45 | - def list_subnets(self) -> list[dict]: |
46 | - return self.execute(["subnets", "read"]) |
47 | + def list_subnets(self) -> list[dict[str, Any]]: |
48 | + subnets: list[dict[str, Any]] = self.execute(["subnets", "read"]) |
49 | + return subnets |
50 | |
51 | - def create_subnet(self, name: str, cidr: str) -> dict: |
52 | - return self.execute(["subnets", "create", "name=" + name, "cidr=" + cidr]) |
53 | + def create_subnet(self, name: str, cidr: str) -> dict[str, Any]: |
54 | + subnet: dict[str, Any] = self.execute( |
55 | + ["subnets", "create", "name=" + name, "cidr=" + cidr] |
56 | + ) |
57 | + return subnet |
58 | |
59 | def delete_subnet(self, name: str) -> str: |
60 | - return self.execute(["subnet", "delete", name], json_output=False) |
61 | + result: str = self.execute(["subnet", "delete", name], json_output=False) |
62 | + return result |
63 | |
64 | - def list_rack_controllers(self) -> list[dict]: |
65 | - return self.execute(["rack-controllers", "read"]) |
66 | + def list_rack_controllers(self) -> list[dict[str, Any]]: |
67 | + rack_controllers: list[dict[str, Any]] = self.execute( |
68 | + ["rack-controllers", "read"] |
69 | + ) |
70 | + return rack_controllers |
71 | |
72 | - def list_ip_ranges(self) -> list[dict]: |
73 | - return self.execute(["ipranges", "read"]) |
74 | + def list_ip_ranges(self) -> list[dict[str, Any]]: |
75 | + ip_ranges: list[dict[str, Any]] = self.execute(["ipranges", "read"]) |
76 | + return ip_ranges |
77 | |
78 | def delete_ip_range(self, range_id: Union[str, int]) -> str: |
79 | - return self.execute(["iprange", "delete", str(range_id)], json_output=False) |
80 | + result: str = self.execute( |
81 | + ["iprange", "delete", str(range_id)], json_output=False |
82 | + ) |
83 | + return result |
84 | |
85 | - def create_ip_range(self, start: str, end: str, range_type: str) -> dict: |
86 | - return self.execute( |
87 | + def create_ip_range(self, start: str, end: str, range_type: str) -> dict[str, Any]: |
88 | + ip_range: dict[str, Any] = self.execute( |
89 | ["ipranges", "create", "type=dynamic", f"start_ip={start}", f"end_ip={end}"] |
90 | ) |
91 | + return ip_range |
92 | |
93 | - def enable_dhcp(self, fabric: str, vlan: str, primary_rack: dict[str, str]) -> dict: |
94 | - return self.execute( |
95 | + def enable_dhcp( |
96 | + self, fabric: str, vlan: str, primary_rack: dict[str, str] |
97 | + ) -> dict[str, Any]: |
98 | + |
99 | + vlan_obj: dict[str, Any] = self.execute( |
100 | [ |
101 | "vlan", |
102 | "update", |
103 | @@ -86,9 +102,13 @@ class AuthenticatedAPIClient: |
104 | f"primary_rack={primary_rack['system_id']}", |
105 | ] |
106 | ) |
107 | + return vlan_obj |
108 | |
109 | - def disable_dhcp(self, fabric: str, vlan: str) -> Any: |
110 | - return self.execute(["vlan", "update", fabric, vlan, "dhcp_on=False"]) |
111 | + def disable_dhcp(self, fabric: str, vlan: str) -> dict[str, Any]: |
112 | + vlan_obj: dict[str, Any] = self.execute( |
113 | + ["vlan", "update", fabric, vlan, "dhcp_on=False"] |
114 | + ) |
115 | + return vlan_obj |
116 | |
117 | def import_boot_resources(self) -> str: |
118 | LOG.debug("Getting latest debug event for watermark") |
119 | @@ -124,46 +144,55 @@ class AuthenticatedAPIClient: |
120 | return result |
121 | |
122 | def is_importing_boot_resources(self) -> str: |
123 | - return self.execute(["boot-resources", "is-importing"]) |
124 | + result: str = self.execute(["boot-resources", "is-importing"]) |
125 | + return result |
126 | |
127 | def list_machines(self, **kwargs: str) -> list[dict[str, Any]]: |
128 | """ |
129 | machines read -h to know parameters available for kwargs |
130 | """ |
131 | - cmd = ["machines", "read"] |
132 | - return self.execute(cmd, extra_params=kwargs) |
133 | + machines: list[dict[str, Any]] = self.execute( |
134 | + ["machines", "read"], extra_params=kwargs |
135 | + ) |
136 | + return machines |
137 | |
138 | def list_boot_images(self, rack_controller: dict[str, str]) -> dict[str, str]: |
139 | - return self.execute( |
140 | + boot_images: dict[str, str] = self.execute( |
141 | ["rack-controller", "list-boot-images", rack_controller["system_id"]] |
142 | ) |
143 | + return boot_images |
144 | |
145 | def import_boot_resources_in_rack(self, rack_controller: dict[str, str]) -> str: |
146 | - return self.execute( |
147 | + result: str = self.execute( |
148 | ["rack-controller", "import-boot-images", rack_controller["system_id"]], |
149 | json_output=False, |
150 | ) |
151 | + return result |
152 | |
153 | def commission_machine(self, machine: dict[str, str]) -> dict[str, str]: |
154 | - result = self.execute(["machine", "commission", machine["system_id"]]) |
155 | + result: dict[str, str] = self.execute( |
156 | + ["machine", "commission", machine["system_id"]] |
157 | + ) |
158 | assert result["status_name"] == "Commissioning" |
159 | return result |
160 | |
161 | def deploy_machine(self, machine: dict[str, str], **kwargs: str) -> dict[str, str]: |
162 | - result = self.execute( |
163 | + result: dict[str, str] = self.execute( |
164 | ["machine", "deploy", machine["system_id"]], extra_params=kwargs |
165 | ) |
166 | assert result["status_name"] == "Deploying" |
167 | return result |
168 | |
169 | def create_ssh_key(self, public_key: str) -> None: |
170 | - result = self.execute(["sshkeys", "create", f"key={public_key}"]) |
171 | + result: dict[str, str] = self.execute( |
172 | + ["sshkeys", "create", f"key={public_key}"] |
173 | + ) |
174 | assert result["key"] == public_key |
175 | return |
176 | |
177 | def release_machine(self, machine: dict[str, str]) -> None: |
178 | system_id: str = machine["system_id"] |
179 | - result: dict = self.execute(["machine", "release", system_id]) |
180 | + result: dict[str, Any] = self.execute(["machine", "release", system_id]) |
181 | assert result["status_name"] == "Releasing" |
182 | wait_for_machines( |
183 | self, |
184 | @@ -238,11 +267,13 @@ class AuthenticatedAPIClient: |
185 | ["zones", "create", f"name={name}", f"description={description}"] |
186 | ) |
187 | |
188 | - def list_zones(self) -> list[dict]: |
189 | - return self.execute(["zones", "read"]) |
190 | + def list_zones(self) -> list[dict[str, Any]]: |
191 | + zones: list[dict[str, Any]] = self.execute(["zones", "read"]) |
192 | + return zones |
193 | |
194 | def read_zone(self, zone_name: str) -> Any: |
195 | - return self.execute(["zone", "read", zone_name]) |
196 | + zone: dict[str, Any] = self.execute(["zone", "read", zone_name]) |
197 | + return zone |
198 | |
199 | def update_zone( |
200 | self, |
201 | @@ -256,41 +287,49 @@ class AuthenticatedAPIClient: |
202 | if new_description is not None: |
203 | cmd.append(f"description={new_description}") |
204 | |
205 | - return self.execute(cmd) |
206 | + zone: dict[str, Any] = self.execute(cmd) |
207 | + return zone |
208 | |
209 | def delete_zone(self, zone_name: str) -> str: |
210 | try: |
211 | - return self.execute(["zone", "delete", zone_name], json_output=False) |
212 | + result: str = self.execute(["zone", "delete", zone_name], json_output=False) |
213 | except CalledProcessError as err: |
214 | if "cannot be deleted" in err.stdout: |
215 | raise CannotDeleteError(err.stdout) |
216 | else: |
217 | raise |
218 | + else: |
219 | + return result |
220 | |
221 | def create_pool(self, name: str, description: str) -> Any: |
222 | return self.execute( |
223 | ["resource-pools", "create", f"name={name}", f"description={description}"] |
224 | ) |
225 | |
226 | - def list_pools(self) -> list[dict]: |
227 | - return self.execute(["resource-pools", "read"]) |
228 | + def list_pools(self) -> list[dict[str, Any]]: |
229 | + resource_pools: list[dict[str, Any]] = self.execute(["resource-pools", "read"]) |
230 | + return resource_pools |
231 | |
232 | - def read_pool(self, pool: dict[str, Any]) -> dict: |
233 | - return self.execute(["resource-pool", "read", str(pool["id"])]) |
234 | + def read_pool(self, pool: dict[str, Any]) -> dict[str, Any]: |
235 | + resource_pool: dict[str, Any] = self.execute( |
236 | + ["resource-pool", "read", str(pool["id"])] |
237 | + ) |
238 | + return resource_pool |
239 | |
240 | def update_pool( |
241 | self, |
242 | pool: dict[str, Any], |
243 | new_name: Optional[str] = None, |
244 | new_description: Optional[str] = None, |
245 | - ) -> Any: |
246 | + ) -> dict[str, Any]: |
247 | cmd = ["resource-pool", "update", str(pool["id"])] |
248 | if new_name is not None: |
249 | cmd.append(f"name={new_name}") |
250 | if new_description is not None: |
251 | cmd.append(f"description={new_description}") |
252 | |
253 | - return self.execute(cmd) |
254 | + pool_obj: dict[str, Any] = self.execute(cmd) |
255 | + return pool_obj |
256 | |
257 | def delete_pool(self, pool: dict[str, Any]) -> Any: |
258 | try: |
259 | @@ -303,27 +342,31 @@ class AuthenticatedAPIClient: |
260 | else: |
261 | raise |
262 | |
263 | - def create_space(self, name: str) -> Any: |
264 | - return self.execute(["spaces", "create", f"name={name}"]) |
265 | + def create_space(self, name: str) -> dict[str, Any]: |
266 | + space: dict[str, Any] = self.execute(["spaces", "create", f"name={name}"]) |
267 | + return space |
268 | |
269 | - def list_spaces(self) -> list[dict]: |
270 | - return self.execute(["spaces", "read"]) |
271 | + def list_spaces(self) -> list[dict[str, Any]]: |
272 | + spaces: list[dict[str, Any]] = self.execute(["spaces", "read"]) |
273 | + return spaces |
274 | |
275 | - def read_space(self, space: dict[str, Any]) -> Any: |
276 | - return self.execute(["space", "read", str(space["id"])]) |
277 | + def read_space(self, space: dict[str, Any]) -> dict[str, Any]: |
278 | + space_obj: dict[str, Any] = self.execute(["space", "read", str(space["id"])]) |
279 | + return space_obj |
280 | |
281 | def update_space( |
282 | self, space: dict[str, Any], new_name: Optional[str] = None |
283 | - ) -> Any: |
284 | + ) -> dict[str, Any]: |
285 | cmd = ["space", "update", str(space["id"])] |
286 | if new_name is not None: |
287 | cmd.append(f"name={new_name}") |
288 | |
289 | - return self.execute(cmd) |
290 | + space_obj: dict[str, Any] = self.execute(cmd) |
291 | + return space_obj |
292 | |
293 | - def delete_space(self, space: dict[str, Any]) -> Any: |
294 | + def delete_space(self, space: dict[str, Any]) -> str: |
295 | try: |
296 | - return self.execute( |
297 | + result: str = self.execute( |
298 | ["space", "delete", str(space["id"])], json_output=False |
299 | ) |
300 | except CalledProcessError as err: |
301 | @@ -331,3 +374,5 @@ class AuthenticatedAPIClient: |
302 | raise CannotDeleteError(err.stdout) |
303 | else: |
304 | raise |
305 | + else: |
306 | + return result |
307 | diff --git a/systemtests/fixtures.py b/systemtests/fixtures.py |
308 | index fa50527..70278a7 100644 |
309 | --- a/systemtests/fixtures.py |
310 | +++ b/systemtests/fixtures.py |
311 | @@ -8,7 +8,7 @@ import tempfile |
312 | from logging import StreamHandler, getLogger |
313 | from pathlib import Path |
314 | from textwrap import dedent |
315 | -from typing import IO, TYPE_CHECKING, Any, Iterator, Optional |
316 | +from typing import TYPE_CHECKING, Any, Iterator, Optional, TextIO |
317 | |
318 | import paramiko |
319 | import pytest |
320 | @@ -137,7 +137,7 @@ def maas_deb_repo( |
321 | |
322 | |
323 | def get_user_data( |
324 | - devices: dict[str, dict[str, Any]], cloud_config: Optional[dict] = None |
325 | + devices: dict[str, dict[str, Any]], cloud_config: Optional[dict[str, Any]] = None |
326 | ) -> str: |
327 | ethernets = {} |
328 | for name, device in sorted(devices.items()): |
329 | @@ -160,7 +160,7 @@ def get_user_data( |
330 | } |
331 | ) |
332 | |
333 | - user_data = "#cloud-config\n" + yaml.dump(cloud_config, default_style="|") |
334 | + user_data: str = "#cloud-config\n" + yaml.dump(cloud_config, default_style="|") |
335 | return user_data |
336 | |
337 | |
338 | @@ -325,12 +325,12 @@ def maas_api_client(maas_region: MAASRegion) -> Iterator[MAASAPIClient]: |
339 | |
340 | |
341 | @pytest.fixture |
342 | -def logstream() -> Iterator[IO]: |
343 | +def logstream() -> Iterator[TextIO]: |
344 | yield io.StringIO() |
345 | |
346 | |
347 | @pytest.fixture(autouse=True) |
348 | -def testlog(logstream: IO) -> Iterator[Logger]: |
349 | +def testlog(logstream: TextIO) -> Iterator[Logger]: |
350 | current_test = os.environ.get("PYTEST_CURRENT_TEST") |
351 | logger = getLogger(f"systemtests.{current_test}") |
352 | handler = StreamHandler(logstream) |
353 | diff --git a/systemtests/lxd.py b/systemtests/lxd.py |
354 | index a783f95..2c49809 100644 |
355 | --- a/systemtests/lxd.py |
356 | +++ b/systemtests/lxd.py |
357 | @@ -35,7 +35,7 @@ class CLILXD: |
358 | except subprocess.CalledProcessError: |
359 | return False |
360 | |
361 | - def _run(self, cmd: Union[str, list[str]]) -> subprocess.CompletedProcess: |
362 | + def _run(self, cmd: Union[str, list[str]]) -> subprocess.CompletedProcess[str]: |
363 | return run_with_logging(cmd, self.logger) |
364 | |
365 | def create_container( |
366 | @@ -89,7 +89,7 @@ class CLILXD: |
367 | |
368 | def pull_file( |
369 | self, container: str, file_path: str, local_path: str |
370 | - ) -> subprocess.CompletedProcess: |
371 | + ) -> subprocess.CompletedProcess[str]: |
372 | return self._run( |
373 | [ |
374 | "lxc", |
375 | @@ -122,9 +122,9 @@ class CLILXD: |
376 | def execute( |
377 | self, |
378 | container: str, |
379 | - command: list, |
380 | + command: list[str], |
381 | environment: Optional[dict[str, str]] = None, |
382 | - ) -> subprocess.CompletedProcess: |
383 | + ) -> subprocess.CompletedProcess[str]: |
384 | lxc_command = ["lxc", "exec", "--force-noninteractive", container] |
385 | if environment is not None: |
386 | for key, value in environment.items(): |
387 | @@ -146,7 +146,8 @@ class CLILXD: |
388 | for address in entry["state"]["network"]["eth0"]["addresses"]: |
389 | self.logger.info(f"Considering address: {address}") |
390 | if address["family"] == "inet": |
391 | - return address["address"] |
392 | + ip: str = address["address"] |
393 | + return ip |
394 | else: |
395 | raise RuntimeError("Couldn't find an IP address") |
396 | |
397 | diff --git a/systemtests/region.py b/systemtests/region.py |
398 | index 4e96f81..5ca3901 100644 |
399 | --- a/systemtests/region.py |
400 | +++ b/systemtests/region.py |
401 | @@ -21,7 +21,7 @@ class MAASRegion: |
402 | self.maas_container = maas_container |
403 | self.installed_from_snap = installed_from_snap |
404 | |
405 | - def execute(self, command: list[str]) -> subprocess.CompletedProcess: |
406 | + def execute(self, command: list[str]) -> subprocess.CompletedProcess[str]: |
407 | lxd = get_lxd(LOG) |
408 | return lxd.execute(self.maas_container, command) |
409 | |
410 | @@ -61,7 +61,9 @@ class MAASRegion: |
411 | "enable_http_proxy": enable_http_proxy, |
412 | } |
413 | |
414 | - def enable_dhcp(self, config: dict, client: api.AuthenticatedAPIClient) -> None: |
415 | + def enable_dhcp( |
416 | + self, config: dict[str, Any], client: api.AuthenticatedAPIClient |
417 | + ) -> None: |
418 | rack_controllers = get_rack_controllers(client) |
419 | for network in config["networks"].values(): |
420 | primary_controller, link = get_dhcp_controller( |
421 | @@ -134,7 +136,9 @@ class MAASRegion: |
422 | return self.set_config("debug", "True") |
423 | |
424 | |
425 | -def get_dhcp_controller(rack_controllers: list[dict], cidr: str) -> tuple[dict, dict]: |
426 | +def get_dhcp_controller( |
427 | + rack_controllers: list[dict[str, Any]], cidr: str |
428 | +) -> tuple[dict[str, Any], dict[str, Any]]: |
429 | for rack_controller in rack_controllers: |
430 | for interface in rack_controller["interface_set"]: |
431 | for link in interface["links"]: |
432 | @@ -143,7 +147,7 @@ def get_dhcp_controller(rack_controllers: list[dict], cidr: str) -> tuple[dict, |
433 | raise AssertionError(f"Couldn't find rack controller managing DHCP for {cidr}") |
434 | |
435 | |
436 | -def get_rack_controllers(client: api.AuthenticatedAPIClient) -> list[dict]: |
437 | +def get_rack_controllers(client: api.AuthenticatedAPIClient) -> list[dict[str, Any]]: |
438 | """Repeatedly attempt to get rack controllers""" |
439 | attempts = count(1) |
440 | for elapsed, _ in retries(timeout=300, delay=10): |
441 | diff --git a/systemtests/subprocess.py b/systemtests/subprocess.py |
442 | index 2c34389..8e4219f 100644 |
443 | --- a/systemtests/subprocess.py |
444 | +++ b/systemtests/subprocess.py |
445 | @@ -8,8 +8,10 @@ if TYPE_CHECKING: |
446 | |
447 | |
448 | def run_with_logging( |
449 | - cmd: Union[str, list[str]], logger: logging.Logger, env: Optional[dict] = None |
450 | -) -> subprocess.CompletedProcess: |
451 | + cmd: Union[str, list[str]], |
452 | + logger: logging.Logger, |
453 | + env: Optional[dict[str, str]] = None, |
454 | +) -> subprocess.CompletedProcess[str]: |
455 | logger.info("Running command: " + " ".join(cmd)) |
456 | process = subprocess.Popen( |
457 | cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env |
458 | diff --git a/systemtests/tests/conftest.py b/systemtests/tests/conftest.py |
459 | index 7fa063d..7b8163a 100644 |
460 | --- a/systemtests/tests/conftest.py |
461 | +++ b/systemtests/tests/conftest.py |
462 | @@ -1,7 +1,7 @@ |
463 | from __future__ import annotations |
464 | |
465 | import argparse |
466 | -from typing import TYPE_CHECKING, Any, Iterator |
467 | +from typing import TYPE_CHECKING, Any, Iterator, cast |
468 | |
469 | import pytest |
470 | import yaml |
471 | @@ -52,14 +52,14 @@ def pytest_addoption(parser: Parser) -> None: |
472 | |
473 | |
474 | @pytest.fixture(scope="session") |
475 | -def config(request: pytest.FixtureRequest) -> dict: |
476 | +def config(request: pytest.FixtureRequest) -> dict[str, Any]: |
477 | config_file = request.config.getoption("--ss-config") |
478 | if not config_file: |
479 | config_file = open("config.yaml", "r") |
480 | - return yaml.safe_load(config_file) if config_file else {} |
481 | + return cast(dict[str, Any], yaml.safe_load(config_file)) if config_file else {} |
482 | |
483 | |
484 | -@pytest.hookimpl(tryfirst=True, hookwrapper=True) |
485 | +@pytest.hookimpl(tryfirst=True, hookwrapper=True) # type: ignore |
486 | def pytest_runtest_makereport(item: Any, call: Any) -> Iterator[Any]: |
487 | # execute all other hooks to obtain the report object |
488 | outcome: _Result |
489 | diff --git a/systemtests/tests/test_basic.py b/systemtests/tests/test_basic.py |
490 | index a94c69a..a653921 100644 |
491 | --- a/systemtests/tests/test_basic.py |
492 | +++ b/systemtests/tests/test_basic.py |
493 | @@ -19,7 +19,9 @@ if TYPE_CHECKING: |
494 | |
495 | class TestSetup: |
496 | @pytest.mark.skip_if_installed_from_snap("Prometheus is installed in the snap") |
497 | - def test_setup_prometheus(self, maas_region: MAASRegion, config: dict) -> None: |
498 | + def test_setup_prometheus( |
499 | + self, maas_region: MAASRegion, config: dict[str, str] |
500 | + ) -> None: |
501 | result = maas_region.execute( |
502 | ["apt", "install", "python3-prometheus-client", "-y"] |
503 | ) |
504 | diff --git a/systemtests/tests/test_crud.py b/systemtests/tests/test_crud.py |
505 | index 366f815..0cb76f8 100644 |
506 | --- a/systemtests/tests/test_crud.py |
507 | +++ b/systemtests/tests/test_crud.py |
508 | @@ -11,7 +11,7 @@ if TYPE_CHECKING: |
509 | from ..api import AuthenticatedAPIClient |
510 | |
511 | |
512 | -@test_steps("create", "update", "delete") |
513 | +@test_steps("create", "update", "delete") # type: ignore |
514 | def test_zone(authenticated_admin: AuthenticatedAPIClient) -> Iterator[None]: |
515 | authenticated_admin.create_zone( |
516 | name="test-zone", description="A zone created by system-tests" |
517 | @@ -48,7 +48,7 @@ def test_zone(authenticated_admin: AuthenticatedAPIClient) -> Iterator[None]: |
518 | yield |
519 | |
520 | |
521 | -@test_steps("create", "update", "delete") |
522 | +@test_steps("create", "update", "delete") # type: ignore |
523 | def test_resource_pool(authenticated_admin: AuthenticatedAPIClient) -> Iterator[None]: |
524 | authenticated_admin.create_pool( |
525 | name="test-pool", description="A resource pool created by system-tests" |
526 | @@ -87,7 +87,7 @@ def test_resource_pool(authenticated_admin: AuthenticatedAPIClient) -> Iterator[ |
527 | yield |
528 | |
529 | |
530 | -@test_steps("create", "update", "delete") |
531 | +@test_steps("create", "update", "delete") # type: ignore |
532 | def test_spaces(authenticated_admin: AuthenticatedAPIClient) -> Iterator[None]: |
533 | authenticated_admin.create_space(name="test-space") |
534 | spaces = authenticated_admin.list_spaces() |
535 | diff --git a/systemtests/utils.py b/systemtests/utils.py |
536 | index 68e17e9..7959492 100644 |
537 | --- a/systemtests/utils.py |
538 | +++ b/systemtests/utils.py |
539 | @@ -3,7 +3,7 @@ from __future__ import annotations |
540 | import random |
541 | import string |
542 | import time |
543 | -from typing import TYPE_CHECKING, Any, Callable, Generator, Union |
544 | +from typing import TYPE_CHECKING, Any, Callable, Iterator, Union |
545 | |
546 | import paramiko |
547 | from retry.api import retry_call |
548 | @@ -42,7 +42,9 @@ def randomstring(length: int = 10) -> str: |
549 | return "".join(random.choice(string.ascii_lowercase) for _ in range(length)) |
550 | |
551 | |
552 | -def retries(timeout: Union[int, float] = 30, delay: Union[int, float] = 1) -> Generator: |
553 | +def retries( |
554 | + timeout: Union[int, float] = 30, delay: Union[int, float] = 1 |
555 | +) -> Iterator[tuple[float, float]]: |
556 | """Helper for retrying something, sleeping between attempts. |
557 | |
558 | Yields ``(elapsed, remaining)`` tuples, giving times in seconds. |
UNIT TESTS
-b strict-mypy lp:~adam-collard/maas-ci/+git/system-tests into -b master lp:~maas-committers/maas-ci/+git/system-tests
STATUS: SUCCESS a9c0eab2bd2b6d2 2b5b728540
COMMIT: a91b80b938d188c