diff --git a/benchmarks/cli.py b/benchmarks/cli.py index 7030f3d..cbcd8f5 100644 --- a/benchmarks/cli.py +++ b/benchmarks/cli.py @@ -6,8 +6,8 @@ from pydantic_core import ValidationError -from benchmarks.core.config import ConfigParser, ExperimentBuilder -from benchmarks.core.experiments.experiments import Experiment +from benchmarks.core.config import ConfigParser +from benchmarks.core.experiments.experiments import Experiment, ExperimentBuilder from benchmarks.logging.logging import ( basic_log_parser, LogSplitter, @@ -22,7 +22,7 @@ split_logs_in_source, ) -config_parser = ConfigParser() +config_parser = ConfigParser[ExperimentBuilder]() config_parser.register(DelugeExperimentConfig) log_parser = basic_log_parser() diff --git a/benchmarks/core/config.py b/benchmarks/core/config.py index 9e17abd..fde9fb8 100644 --- a/benchmarks/core/config.py +++ b/benchmarks/core/config.py @@ -6,39 +6,43 @@ from typing import Type, Dict, TextIO import yaml -from typing_extensions import Generic, overload +from typing_extensions import Generic, overload, TypeVar -from benchmarks.core.experiments.experiments import TExperiment from benchmarks.core.pydantic import SnakeCaseModel +T = TypeVar("T") -class ExperimentBuilder(SnakeCaseModel, Generic[TExperiment]): - """:class:`ExperimentBuilders` can build real :class:`Experiment`s out of :class:`ConfigModel`s.""" + +class Builder(SnakeCaseModel, Generic[T]): + """:class:`Builder` is a configuration model that can build useful objects.""" @abstractmethod - def build(self) -> TExperiment: + def build(self) -> T: pass -class ConfigParser: +TBuilder = TypeVar("TBuilder", bound=Builder) + + +class ConfigParser(Generic[TBuilder]): """ - :class:`ConfigParser` is a utility class to parse configuration files into :class:`ExperimentBuilder`s. - Currently, each :class:`ExperimentBuilder` can appear at most once in the config file. + :class:`ConfigParser` is a utility class to parse configuration files into :class:`Builder`s. + Currently, each :class:`Builder` type can appear at most once in the config file. """ def __init__(self): self.experiment_types = {} - def register(self, root: Type[ExperimentBuilder[TExperiment]]): + def register(self, root: Type[TBuilder]): self.experiment_types[root.alias()] = root @overload - def parse(self, data: dict) -> Dict[str, ExperimentBuilder[TExperiment]]: ... + def parse(self, data: dict) -> Dict[str, TBuilder]: ... @overload - def parse(self, data: TextIO) -> Dict[str, ExperimentBuilder[TExperiment]]: ... + def parse(self, data: TextIO) -> Dict[str, TBuilder]: ... - def parse(self, data: dict | TextIO) -> Dict[str, ExperimentBuilder[TExperiment]]: + def parse(self, data: dict | TextIO) -> Dict[str, TBuilder]: if isinstance(data, TextIOBase): entries = yaml.safe_load(os.path.expandvars(data.read())) else: diff --git a/benchmarks/core/experiments/experiments.py b/benchmarks/core/experiments/experiments.py index fefac2f..83e267d 100644 --- a/benchmarks/core/experiments/experiments.py +++ b/benchmarks/core/experiments/experiments.py @@ -8,6 +8,8 @@ from typing_extensions import Generic, TypeVar +from benchmarks.core.config import Builder + logger = logging.getLogger(__name__) @@ -22,6 +24,8 @@ def run(self): TExperiment = TypeVar("TExperiment", bound=Experiment) +ExperimentBuilder = Builder[TExperiment] + class ExperimentWithLifecycle(Experiment): """An :class:`ExperimentWithLifecycle` is a basic implementation of an :class:`Experiment` with overridable diff --git a/benchmarks/deluge/config.py b/benchmarks/deluge/config.py index 04f8c9d..85b1bd3 100644 --- a/benchmarks/deluge/config.py +++ b/benchmarks/deluge/config.py @@ -6,11 +6,11 @@ from torrentool.torrent import Torrent from urllib3.util import parse_url -from benchmarks.core.config import ExperimentBuilder from benchmarks.core.experiments.experiments import ( IteratedExperiment, ExperimentEnvironment, BoundExperiment, + ExperimentBuilder, ) from benchmarks.core.experiments.static_experiment import StaticDisseminationExperiment from benchmarks.core.pydantic import Host diff --git a/benchmarks/deluge/deluge_node.py b/benchmarks/deluge/deluge_node.py index 1da4c21..4f40b81 100644 --- a/benchmarks/deluge/deluge_node.py +++ b/benchmarks/deluge/deluge_node.py @@ -13,7 +13,6 @@ from tenacity.stop import stop_base from tenacity.wait import wait_base from torrentool.torrent import Torrent -from typing_extensions import TypeVar from urllib3.util import Url from benchmarks.core.experiments.experiments import ExperimentComponent @@ -168,9 +167,6 @@ def __str__(self): return f"DelugeNode({self.name}, {self.daemon_args['host']}:{self.daemon_args['port']})" -T = TypeVar("T") - - class ResilientCallWrapper: def __init__(self, node: Any, wait_policy: wait_base, stop_policy: stop_base): self.node = node