Skip to content

Commit e394758

Browse files
committed
callable_marker: add type hints
Signed-off-by: Gaëtan Lehmann <[email protected]>
1 parent afedb11 commit e394758

File tree

2 files changed

+13
-10
lines changed

2 files changed

+13
-10
lines changed

lib/common.py

Lines changed: 7 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, 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
@@ -69,7 +69,6 @@ def expand_scope_relative_nodeid(scoped_nodeid, scope, ref_nodeid):
6969
logging.debug("scope: %r base: %r relative: %r", scope, base, scoped_nodeid)
7070
return "::".join(itertools.chain(base, (scoped_nodeid,)))
7171

72-
def callable_marker(value, request):
7372
T = TypeVar("T")
7473

7574
_ensure_type_cache: Dict[type, TypeAdapter] = {}
@@ -97,6 +96,7 @@ def ensure_type(typ: Type[T], value: Any) -> T:
9796
raise TypeError(f"'{type(value).__name__}' object is not of the expected type '{typ.__name__}'")
9897
return value
9998

99+
def callable_marker(value: Union[T, Callable[[], T]], request: pytest.FixtureRequest) -> T:
100100
"""
101101
Process value optionally generated by fixture-dependent callable.
102102
@@ -112,8 +112,11 @@ def ensure_type(typ: Type[T], value: Any) -> T:
112112
for arg_name in inspect.getfullargspec(value).args}
113113
except pytest.FixtureLookupError as e:
114114
raise RuntimeError("fixture in mapping not found on test") from e
115-
value = value(**params)
116-
return value
115+
# callable ensures the value is of type Callable[..., object], which is not enough in that case
116+
# we can trust the static checker though, and thus use cast
117+
return cast(Callable[[], T], value)(**params)
118+
else:
119+
return value
117120

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

tests/install/conftest.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import logging
22
import os
3-
from typing import Sequence
3+
from typing import Callable, Sequence, Union
44
import pytest
55
import pytest_dependency # type: ignore
66
import tempfile
77
import xml.etree.ElementTree as ET
88

99
from lib import installer, pxe
10-
from lib.common import callable_marker, url_download, wait_for
10+
from lib.common import callable_marker, ensure_type, url_download, wait_for
1111
from lib.installer import AnswerFile
1212
from lib.commands import local_cmd
1313

@@ -66,8 +66,8 @@ def answerfile(request):
6666
return
6767

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

7272
answerfile_def.top_append(
7373
dict(TAG="admin-interface",
@@ -329,8 +329,8 @@ def xcpng_chained(request):
329329
# take test name from mark
330330
marker = request.node.get_closest_marker("continuation_of")
331331
assert marker is not None, "xcpng_chained fixture requires 'continuation_of' marker"
332-
continuation_of = callable_marker(marker.args[0], request)
333-
assert isinstance(continuation_of, Sequence)
332+
marker_args = ensure_type(Sequence[Union[Sequence[dict], Callable[[], Sequence[dict]]]], marker.args)
333+
continuation_of = callable_marker(marker_args[0], request)
334334

335335
vm_defs = [dict(name=vm_spec['vm'],
336336
image_test=vm_spec['image_test'],

0 commit comments

Comments
 (0)