mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00
47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
![]() |
import itertools
|
||
|
import sys
|
||
|
from typing import Any, Callable, Iterable
|
||
|
|
||
|
|
||
|
def classvar_matrix(**kwargs: Iterable[Any]) -> Callable[[type], None]:
|
||
|
"""
|
||
|
Create a new class for each variation of input, allowing to generate a TestCase matrix / parametrization that
|
||
|
supports multi-threading and has better reporting for ``unittest --durations=...`` and ``pytest --durations=...``
|
||
|
than subtests.
|
||
|
|
||
|
The kwargs will be set as ClassVars in the newly created classes. Use as ::
|
||
|
|
||
|
@classvar_matrix(var_name=[value1, value2])
|
||
|
class MyTestCase(unittest.TestCase):
|
||
|
var_name: typing.ClassVar[...]
|
||
|
|
||
|
:param kwargs: A dict of ClassVars to set, where key is the variable name and value is a list of all values.
|
||
|
:return: A decorator to be applied to a class.
|
||
|
"""
|
||
|
keys: tuple[str]
|
||
|
values: Iterable[Iterable[Any]]
|
||
|
keys, values = zip(*kwargs.items())
|
||
|
values = map(lambda v: sorted(v) if isinstance(v, (set, frozenset)) else v, values)
|
||
|
permutations_dicts = [dict(zip(keys, v)) for v in itertools.product(*values)]
|
||
|
|
||
|
def decorator(cls: type) -> None:
|
||
|
mod = sys.modules[cls.__module__]
|
||
|
|
||
|
for permutation in permutations_dicts:
|
||
|
|
||
|
class Unrolled(cls): # type: ignore
|
||
|
pass
|
||
|
|
||
|
for k, v in permutation.items():
|
||
|
setattr(Unrolled, k, v)
|
||
|
params = ", ".join([f"{k}={repr(v)}" for k, v in permutation.items()])
|
||
|
params = f"{{{params}}}"
|
||
|
|
||
|
Unrolled.__module__ = cls.__module__
|
||
|
Unrolled.__qualname__ = f"{cls.__qualname__}{params}"
|
||
|
setattr(mod, f"{cls.__name__}{params}", Unrolled)
|
||
|
|
||
|
return None
|
||
|
|
||
|
return decorator
|