Skip to content

Commit 10fa5d6

Browse files
glehmannydirson
andcommitted
callable_marker: add type hints
Signed-off-by: Gaëtan Lehmann <[email protected]> Co-Authored-By: Yann Dirson <[email protected]>
1 parent 1d93cc8 commit 10fa5d6

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

lib/common.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import traceback
1010
from enum import Enum
1111
from pydantic import TypeAdapter, ValidationError
12-
from typing import Any, Dict, Literal, Optional, Type, TypeVar, cast, overload, TYPE_CHECKING, Union
12+
from typing import Any, Callable, Dict, Literal, Optional, Type, TypeVar, cast, overload, TYPE_CHECKING, Union
1313
from uuid import UUID
1414

1515
import pytest
@@ -90,7 +90,7 @@ def ensure_type(typ: Type[T], value: Any) -> T:
9090
return ta.validate_python(value)
9191
raise TypeError(f"'{type(value).__name__}' object is not of the expected type '{typ.__name__}'")
9292

93-
def callable_marker(value, request):
93+
def callable_marker(value: Union[T, Callable[..., T]], request: pytest.FixtureRequest) -> T:
9494
"""
9595
Process value optionally generated by fixture-dependent callable.
9696
@@ -106,8 +106,12 @@ def callable_marker(value, request):
106106
for arg_name in inspect.getfullargspec(value).args}
107107
except pytest.FixtureLookupError as e:
108108
raise RuntimeError("fixture in mapping not found on test") from e
109-
value = value(**params)
110-
return value
109+
# callable ensures the value is of type Callable[..., object], which is not enough in that case
110+
# we can trust the static checker though, and thus use cast
111+
fn = cast(Callable[..., T], value)
112+
return fn(**params)
113+
else:
114+
return value
111115

112116
def wait_for(fn, msg=None, timeout_secs=2 * 60, retry_delay_secs=2, invert=False):
113117
if msg is not None:

tests/install/conftest.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
from __future__ import annotations
2+
13
import logging
24
import os
3-
from typing import Sequence
5+
from typing import Callable, Generator, Sequence, Union
46
import pytest
57
import pytest_dependency # type: ignore
68
import tempfile
79
import xml.etree.ElementTree as ET
810

911
from lib import installer, pxe
10-
from lib.common import callable_marker, url_download, wait_for
12+
from lib.common import callable_marker, ensure_type, url_download, wait_for
1113
from lib.installer import AnswerFile
1214
from lib.commands import local_cmd
1315

@@ -39,7 +41,7 @@ def skip_package_source(version, package_source):
3941
return True, "unknown source type {}".format(package_source)
4042

4143
@pytest.fixture(scope='function')
42-
def answerfile(request):
44+
def answerfile(request: pytest.FixtureRequest) -> Generator[Union[AnswerFile, None], None, None]:
4345
"""
4446
Makes an AnswerFile object available to test and other fixtures.
4547
@@ -66,8 +68,8 @@ def answerfile(request):
6668
return
6769

6870
# construct answerfile definition from option "base", and explicit bits
69-
answerfile_def = callable_marker(marker.args[0], request)
70-
assert isinstance(answerfile_def, AnswerFile)
71+
marker_args = ensure_type(tuple[Union[AnswerFile, Callable[..., AnswerFile]]], marker.args)
72+
answerfile_def = callable_marker(marker_args[0], request)
7173

7274
yield answerfile_def
7375

@@ -322,8 +324,8 @@ def xcpng_chained(request):
322324
# take test name from mark
323325
marker = request.node.get_closest_marker("continuation_of")
324326
assert marker is not None, "xcpng_chained fixture requires 'continuation_of' marker"
325-
continuation_of = callable_marker(marker.args[0], request)
326-
assert isinstance(continuation_of, Sequence)
327+
marker_args = ensure_type(tuple[Union[Sequence[dict], Callable[..., Sequence[dict]]]], marker.args)
328+
continuation_of = callable_marker(marker_args[0], request)
327329

328330
vm_defs = [dict(name=vm_spec['vm'],
329331
image_test=vm_spec['image_test'],

0 commit comments

Comments
 (0)