diff --git a/parsl/config.py b/parsl/config.py index 0f56c5b9cb..4f3b7be23a 100644 --- a/parsl/config.py +++ b/parsl/config.py @@ -1,7 +1,7 @@ import logging import typeguard -from typing import Callable, List, Optional, Sequence, Union +from typing import Callable, Iterable, Optional, Sequence, Union from typing_extensions import Literal from parsl.utils import RepresentationMixin @@ -20,9 +20,9 @@ class Config(RepresentationMixin): Parameters ---------- - executors : list of ParslExecutor, optional - List of `ParslExecutor` instances to use for executing tasks. - Default is [:class:`~parsl.executors.threads.ThreadPoolExecutor()`]. + executors : sequence of ParslExecutor, optional + List (or other iterable) of `ParslExecutor` instances to use for executing tasks. + Default is (:class:`~parsl.executors.threads.ThreadPoolExecutor()`,). app_cache : bool, optional Enable app caching. Default is True. checkpoint_files : sequence of str, optional @@ -73,7 +73,7 @@ class Config(RepresentationMixin): @typeguard.typechecked def __init__(self, - executors: Optional[List[ParslExecutor]] = None, + executors: Optional[Iterable[ParslExecutor]] = None, app_cache: bool = True, checkpoint_files: Optional[Sequence[str]] = None, checkpoint_mode: Union[None, @@ -92,9 +92,14 @@ def __init__(self, monitoring: Optional[MonitoringHub] = None, usage_tracking: bool = False, initialize_logging: bool = True) -> None: - if executors is None: - executors = [ThreadPoolExecutor()] - self.executors = executors + + executors = tuple(executors or []) + if not executors: + executors = (ThreadPoolExecutor(),) + + self._executors: Sequence[ParslExecutor] = executors + self._validate_executors() + self.app_cache = app_cache self.checkpoint_files = checkpoint_files self.checkpoint_mode = checkpoint_mode @@ -125,11 +130,13 @@ def __init__(self, def executors(self) -> Sequence[ParslExecutor]: return self._executors - @executors.setter - def executors(self, executors: Sequence[ParslExecutor]): - labels = [e.label for e in executors] + def _validate_executors(self) -> None: + + if len(self.executors) == 0: + raise ConfigurationError('At least one executor must be specified') + + labels = [e.label for e in self.executors] duplicates = [e for n, e in enumerate(labels) if e in labels[:n]] if len(duplicates) > 0: raise ConfigurationError('Executors must have unique labels ({})'.format( ', '.join(['label={}'.format(repr(d)) for d in duplicates]))) - self._executors = executors