Skip to content

Commit

Permalink
refactor: generalize builder types
Browse files Browse the repository at this point in the history
  • Loading branch information
gmega committed Jan 17, 2025
1 parent 60fd274 commit 82f1f9a
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 20 deletions.
6 changes: 3 additions & 3 deletions benchmarks/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -22,7 +22,7 @@
split_logs_in_source,
)

config_parser = ConfigParser()
config_parser = ConfigParser[ExperimentBuilder]()
config_parser.register(DelugeExperimentConfig)

log_parser = basic_log_parser()
Expand Down
28 changes: 16 additions & 12 deletions benchmarks/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions benchmarks/core/experiments/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from typing_extensions import Generic, TypeVar

from benchmarks.core.config import Builder

logger = logging.getLogger(__name__)


Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/deluge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 0 additions & 4 deletions benchmarks/deluge/deluge_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 82f1f9a

Please sign in to comment.