diff --git a/smartsim/settings/arguments/batch/lsf.py b/smartsim/settings/arguments/batch/lsf.py index 23f948bd09..9a2b1362d8 100644 --- a/smartsim/settings/arguments/batch/lsf.py +++ b/smartsim/settings/arguments/batch/lsf.py @@ -57,8 +57,11 @@ def set_walltime(self, walltime: str) -> None: :param walltime: Time in hh:mm format, e.g. "10:00" for 10 hours, if time is supplied in hh:mm:ss format, seconds will be ignored and walltime will be set as ``hh:mm`` + :raises TypeError: if not type str """ # For compatibility with other launchers, as explained in docstring + if not isinstance(walltime, str): + raise TypeError("walltime argument was not of type str") if walltime: if len(walltime.split(":")) > 2: walltime = ":".join(walltime.split(":")[:2]) @@ -72,7 +75,13 @@ def set_smts(self, smts: int) -> None: takes precedence. :param smts: SMT (e.g on Summit: 1, 2, or 4) + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(smts, int): + raise TypeError("smts argument was not of type int") + if smts <= 0: + raise ValueError("smts must be a positive value") self.set("alloc_flags", str(smts)) def set_project(self, project: str) -> None: @@ -81,7 +90,10 @@ def set_project(self, project: str) -> None: This sets ``-P``. :param time: project name + :raises TypeError: if not a str """ + if not isinstance(project, str): + raise TypeError("project argument was not of type str") self.set("P", project) def set_account(self, account: str) -> None: @@ -90,7 +102,10 @@ def set_account(self, account: str) -> None: this function is an alias for `set_project`. :param account: project name + :raises TypeError: if not a str """ + if not isinstance(account, str): + raise TypeError("account argument was not of type str") return self.set_project(account) def set_nodes(self, num_nodes: int) -> None: @@ -99,7 +114,13 @@ def set_nodes(self, num_nodes: int) -> None: This sets ``-nnodes``. :param nodes: number of nodes + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(num_nodes, int): + raise TypeError("num_nodes argument was not of type int") + if num_nodes <= 0: + raise ValueError("Number of nodes must be a positive value") self.set("nnodes", str(num_nodes)) def set_hostlist(self, host_list: t.Union[str, t.List[str]]) -> None: @@ -110,10 +131,11 @@ def set_hostlist(self, host_list: t.Union[str, t.List[str]]) -> None: """ if isinstance(host_list, str): host_list = [host_list.strip()] - if not isinstance(host_list, list): + if not ( + isinstance(host_list, list) + and all(isinstance(item, str) for item in host_list) + ): raise TypeError("host_list argument must be a list of strings") - if not all(isinstance(host, str) for host in host_list): - raise TypeError("host_list argument must be list of strings") self.set("m", '"' + " ".join(host_list) + '"') def set_tasks(self, tasks: int) -> None: @@ -122,7 +144,13 @@ def set_tasks(self, tasks: int) -> None: This sets ``-n`` :param tasks: number of tasks + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(tasks, int): + raise TypeError("tasks argument was not of type int") + if tasks <= 0: + raise ValueError("Number of tasks must be a positive value") self.set("n", str(tasks)) def set_queue(self, queue: str) -> None: @@ -131,7 +159,10 @@ def set_queue(self, queue: str) -> None: This sets ``-q`` :param queue: The queue to submit the job on + :raises TypeError: if not a str """ + if not isinstance(queue, str): + raise TypeError("queue argument was not of type str") self.set("q", queue) def format_batch_args(self) -> t.List[str]: @@ -159,5 +190,7 @@ def set(self, key: str, value: str | None) -> None: :param value: A string representation of the value for the launch argument (if applicable), otherwise `None` """ + if key in self._batch_args and key != self._batch_args[key]: + logger.warning(f"Overwriting argument '{key}' with value '{value}'") # Store custom arguments in the launcher_args self._batch_args[key] = value diff --git a/smartsim/settings/arguments/batch/pbs.py b/smartsim/settings/arguments/batch/pbs.py index 1262076656..ab471c0b9b 100644 --- a/smartsim/settings/arguments/batch/pbs.py +++ b/smartsim/settings/arguments/batch/pbs.py @@ -26,6 +26,7 @@ from __future__ import annotations +import re import typing as t from copy import deepcopy @@ -61,7 +62,13 @@ def set_nodes(self, num_nodes: int) -> None: nodes here is sets the 'nodes' resource. :param num_nodes: number of nodes + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(num_nodes, int): + raise TypeError("num_nodes argument was not of type int") + if num_nodes <= 0: + raise ValueError("Number of nodes must be a positive value") self.set("nodes", str(num_nodes)) @@ -73,9 +80,10 @@ def set_hostlist(self, host_list: t.Union[str, t.List[str]]) -> None: """ if isinstance(host_list, str): host_list = [host_list.strip()] - if not isinstance(host_list, list): - raise TypeError("host_list argument must be a list of strings") - if not all(isinstance(host, str) for host in host_list): + if not ( + isinstance(host_list, list) + and all(isinstance(item, str) for item in host_list) + ): raise TypeError("host_list argument must be a list of strings") self.set("hostname", ",".join(host_list)) @@ -89,15 +97,28 @@ def set_walltime(self, walltime: str) -> None: this value will be overridden :param walltime: wall time + :raises ValueError: if walltime format is invalid + :raises TypeError: if not type str """ - self.set("walltime", walltime) + if not isinstance(walltime, str): + raise TypeError("walltime argument was not of type str") + pattern = r"^\d{2}:\d{2}:\d{2}$" + if walltime and re.match(pattern, walltime): + self.set("walltime", walltime) + else: + raise ValueError( + f"Invalid walltime: {walltime}. Please use 'HH:MM:SS' format." + ) def set_queue(self, queue: str) -> None: """Set the queue for the batch job :param queue: queue name + :raises TypeError: if not a str """ - self.set("q", str(queue)) + if not isinstance(queue, str): + raise TypeError("queue argument was not of type str") + self.set("q", queue) def set_ncpus(self, num_cpus: int) -> None: """Set the number of cpus obtained in each node. @@ -107,15 +128,24 @@ def set_ncpus(self, num_cpus: int) -> None: this value will be overridden :param num_cpus: number of cpus per node in select + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(num_cpus, int): + raise TypeError("num_cpus argument was not of type int") + if num_cpus <= 0: + raise ValueError("Number of CPUs must be a positive value") self.set("ppn", str(num_cpus)) def set_account(self, account: str) -> None: """Set the account for this batch job :param acct: account id + :raises TypeError: if not a str """ - self.set("A", str(account)) + if not isinstance(account, str): + raise TypeError("account argument was not of type str") + self.set("A", account) def format_batch_args(self) -> t.List[str]: """Get the formatted batch arguments for a preview @@ -183,4 +213,6 @@ def set(self, key: str, value: str | None) -> None: :param value: A string representation of the value for the launch argument (if applicable), otherwise `None` """ + if key in self._batch_args and key != self._batch_args[key]: + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._batch_args[key] = value diff --git a/smartsim/settings/arguments/batch/slurm.py b/smartsim/settings/arguments/batch/slurm.py index 26f9cf8549..b8768ac5a3 100644 --- a/smartsim/settings/arguments/batch/slurm.py +++ b/smartsim/settings/arguments/batch/slurm.py @@ -56,12 +56,18 @@ def set_walltime(self, walltime: str) -> None: format = "HH:MM:SS" :param walltime: wall time + :raises ValueError: if walltime format is invalid + :raises TypeError: if not str """ + if not isinstance(walltime, str): + raise TypeError("walltime argument was not of type str") pattern = r"^\d{2}:\d{2}:\d{2}$" if walltime and re.match(pattern, walltime): self.set("time", str(walltime)) else: - raise ValueError("Invalid walltime format. Please use 'HH:MM:SS' format.") + raise ValueError( + f"Invalid walltime: {walltime}. Please use 'HH:MM:SS' format." + ) def set_nodes(self, num_nodes: int) -> None: """Set the number of nodes for this batch job @@ -69,7 +75,13 @@ def set_nodes(self, num_nodes: int) -> None: This sets ``--nodes``. :param num_nodes: number of nodes + :raises TypeError: if not an int + :raises ValueError: if not positive int """ + if not isinstance(num_nodes, int): + raise TypeError("num_nodes argument was not of type int") + if num_nodes <= 0: + raise ValueError("Number of nodes must be a positive value") self.set("nodes", str(num_nodes)) def set_account(self, account: str) -> None: @@ -78,7 +90,10 @@ def set_account(self, account: str) -> None: This sets ``--account``. :param account: account id + :raises TypeError: if not a str """ + if not isinstance(account, str): + raise TypeError("account argument was not of type str") self.set("account", account) def set_partition(self, partition: str) -> None: @@ -87,8 +102,11 @@ def set_partition(self, partition: str) -> None: This sets ``--partition``. :param partition: partition name + :raises TypeError: if not a str """ - self.set("partition", str(partition)) + if not isinstance(partition, str): + raise TypeError("partition argument was not of type str") + self.set("partition", partition) def set_queue(self, queue: str) -> None: """alias for set_partition @@ -96,7 +114,10 @@ def set_queue(self, queue: str) -> None: Sets the partition for the slurm batch job :param queue: the partition to run the batch job on + :raises TypeError: if not a str """ + if not isinstance(queue, str): + raise TypeError("queue argument was not of type str") return self.set_partition(queue) def set_cpus_per_task(self, cpus_per_task: int) -> None: @@ -105,7 +126,13 @@ def set_cpus_per_task(self, cpus_per_task: int) -> None: This sets ``--cpus-per-task`` :param num_cpus: number of cpus to use per task + :raises TypeError: if not int + :raises ValueError: if not positive int """ + if not isinstance(cpus_per_task, int): + raise TypeError("cpus_per_task argument was not of type int") + if cpus_per_task <= 0: + raise ValueError("CPUs per task must be a positive value") self.set("cpus-per-task", str(cpus_per_task)) def set_hostlist(self, host_list: t.Union[str, t.List[str]]) -> None: @@ -118,10 +145,13 @@ def set_hostlist(self, host_list: t.Union[str, t.List[str]]) -> None: """ if isinstance(host_list, str): host_list = [host_list.strip()] - if not isinstance(host_list, list): + + if not ( + isinstance(host_list, list) + and all(isinstance(item, str) for item in host_list) + ): raise TypeError("host_list argument must be a list of strings") - if not all(isinstance(host, str) for host in host_list): - raise TypeError("host_list argument must be list of strings") + self.set("nodelist", ",".join(host_list)) def format_batch_args(self) -> t.List[str]: @@ -153,4 +183,6 @@ def set(self, key: str, value: str | None) -> None: argument (if applicable), otherwise `None` """ # Store custom arguments in the launcher_args + if key in self._batch_args and key != self._batch_args[key]: + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._batch_args[key] = value diff --git a/smartsim/settings/arguments/launch/alps.py b/smartsim/settings/arguments/launch/alps.py index 356a443d65..0834ae9a51 100644 --- a/smartsim/settings/arguments/launch/alps.py +++ b/smartsim/settings/arguments/launch/alps.py @@ -224,5 +224,5 @@ def set(self, key: str, value: str | None) -> None: ) return if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/arguments/launch/dragon.py b/smartsim/settings/arguments/launch/dragon.py index d8044267e6..05de782286 100644 --- a/smartsim/settings/arguments/launch/dragon.py +++ b/smartsim/settings/arguments/launch/dragon.py @@ -71,7 +71,7 @@ def set(self, key: str, value: str | None) -> None: """ set_check_input(key, value) if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value def set_node_feature(self, feature_list: t.Union[str, t.List[str]]) -> None: diff --git a/smartsim/settings/arguments/launch/local.py b/smartsim/settings/arguments/launch/local.py index 2c589cb48d..8c2224067f 100644 --- a/smartsim/settings/arguments/launch/local.py +++ b/smartsim/settings/arguments/launch/local.py @@ -83,5 +83,5 @@ def set(self, key: str, value: str | None) -> None: """ set_check_input(key, value) if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/arguments/launch/lsf.py b/smartsim/settings/arguments/launch/lsf.py index ed24271985..9b4fe01abe 100644 --- a/smartsim/settings/arguments/launch/lsf.py +++ b/smartsim/settings/arguments/launch/lsf.py @@ -148,5 +148,5 @@ def set(self, key: str, value: str | None) -> None: ) return if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/arguments/launch/mpi.py b/smartsim/settings/arguments/launch/mpi.py index ce8c43aa5c..090cb60dda 100644 --- a/smartsim/settings/arguments/launch/mpi.py +++ b/smartsim/settings/arguments/launch/mpi.py @@ -221,7 +221,7 @@ def set(self, key: str, value: str | None) -> None: ) return if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/arguments/launch/pals.py b/smartsim/settings/arguments/launch/pals.py index d48dc799b9..91ae0f9aa5 100644 --- a/smartsim/settings/arguments/launch/pals.py +++ b/smartsim/settings/arguments/launch/pals.py @@ -158,5 +158,5 @@ def set(self, key: str, value: str | None) -> None: ) return if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/arguments/launch/slurm.py b/smartsim/settings/arguments/launch/slurm.py index c5dceff628..c670b28ce7 100644 --- a/smartsim/settings/arguments/launch/slurm.py +++ b/smartsim/settings/arguments/launch/slurm.py @@ -210,7 +210,9 @@ def set_walltime(self, walltime: str) -> None: if walltime and re.match(pattern, walltime): self.set("time", str(walltime)) else: - raise ValueError("Invalid walltime format. Please use 'HH:MM:SS' format.") + raise ValueError( + f"Invalid walltime: {walltime}. Please use 'HH:MM:SS' format." + ) def set_het_group(self, het_group: t.Iterable[int]) -> None: """Set the heterogeneous group for this job @@ -349,5 +351,5 @@ def set(self, key: str, value: str | None) -> None: ) return if key in self._launch_args and key != self._launch_args[key]: - logger.warning(f"Overwritting argument '{key}' with value '{value}'") + logger.warning(f"Overwriting argument '{key}' with value '{value}'") self._launch_args[key] = value diff --git a/smartsim/settings/batch_settings.py b/smartsim/settings/batch_settings.py index 734e919ce3..7219e5e709 100644 --- a/smartsim/settings/batch_settings.py +++ b/smartsim/settings/batch_settings.py @@ -117,6 +117,18 @@ def __init__( """The scheduler type""" except ValueError: raise ValueError(f"Invalid scheduler type: {batch_scheduler}") from None + + if batch_args is not None: + if not ( + isinstance(batch_args, dict) + and all( + isinstance(key, str) and isinstance(val, (str, type(None))) + for key, val in batch_args.items() + ) + ): + raise TypeError( + "batch_args argument was not of type dict of str and str or None" + ) self._arguments = self._get_arguments(batch_args) """The BatchSettings child class based on scheduler type""" self.env_vars = env_vars or {} @@ -140,6 +152,16 @@ def env_vars(self) -> StringArgument: @env_vars.setter def env_vars(self, value: t.Dict[str, str | None]) -> None: """Set the environment variables.""" + + if not ( + isinstance(value, t.Dict) + and all( + isinstance(key, str) and isinstance(val, (str, type(None))) + for key, val in value.items() + ) + ): + raise TypeError("env_vars argument was not of type dict of str and str") + self._env_vars = copy.deepcopy(value) def _get_arguments(self, batch_args: StringArgument | None) -> BatchArguments: diff --git a/smartsim/settings/launch_settings.py b/smartsim/settings/launch_settings.py index 7b60830228..6ed7695e4a 100644 --- a/smartsim/settings/launch_settings.py +++ b/smartsim/settings/launch_settings.py @@ -126,6 +126,18 @@ def __init__( """The launcher type""" except ValueError: raise ValueError(f"Invalid launcher type: {launcher}") + + if launch_args is not None: + if not ( + isinstance(launch_args, t.Dict) + and all( + isinstance(key, str) and isinstance(val, (str, type(None))) + for key, val in launch_args.items() + ) + ): + raise TypeError( + "launch_args argument was not of type dict of str and str or None" + ) self._arguments = self._get_arguments(launch_args) """The LaunchSettings child class based on launcher type""" self.env_vars = env_vars or {} @@ -165,6 +177,15 @@ def env_vars(self, value: dict[str, str | None]) -> None: :param value: The new environment mapping """ + if not ( + isinstance(value, dict) + and all( + isinstance(key, str) and isinstance(val, (str, type(None))) + for key, val in value.items() + ) + ): + raise TypeError("env_vars argument was not of type dict of str and str") + self._env_vars = copy.deepcopy(value) def _get_arguments(self, launch_args: StringArgument | None) -> LaunchArguments: @@ -209,6 +230,7 @@ def update_env(self, env_vars: t.Dict[str, str | None]) -> None: :param env_vars: environment variables to update or add :raises TypeError: if env_vars values cannot be coerced to strings """ + # Coerce env_vars values to str as a convenience to user for env, val in env_vars.items(): if not isinstance(env, str): diff --git a/tests/temp_tests/test_settings/test_batchSettings.py b/tests/temp_tests/test_settings/test_batchSettings.py index 37fd3a33f2..67cbc15fe2 100644 --- a/tests/temp_tests/test_settings/test_batchSettings.py +++ b/tests/temp_tests/test_settings/test_batchSettings.py @@ -78,3 +78,86 @@ def test_env_vars_property(): assert bs.env_vars == {"ENV": "VAR"} ref = bs.env_vars assert ref is bs.env_vars + + +def test_type_batch_scheduler(): + batch_scheduler = "invalid" + with pytest.raises(ValueError, match="Invalid scheduler type: invalid"): + BatchSettings( + batch_scheduler=batch_scheduler, + batch_args={"launch": "var"}, + env_vars={"ENV": "VAR"}, + ) + + +@pytest.mark.parametrize( + "batch_args", + [ + pytest.param("invalid", id="invalid"), + pytest.param("", id="empty string"), + pytest.param(0, id="0"), + pytest.param([], id="empty list"), + pytest.param({"valid": 1}, id="value not str or None"), + ], +) +def test_type_batch_args(batch_args): + with pytest.raises( + TypeError, + match="batch_args argument was not of type dict of str and str or None", + ): + BatchSettings( + batch_scheduler="slurm", + batch_args=batch_args, + env_vars={"ENV": "VAR"}, + ) + + +def test_type_env_vars(): + env_vars = "invalid" + with pytest.raises( + TypeError, match="env_vars argument was not of type dict of str and str" + ): + BatchSettings(batch_scheduler="slurm", env_vars=env_vars) + + +@pytest.mark.parametrize( + "scheduler", + [ + pytest.param("slurm", id="slurm scheduler"), + pytest.param("lsf", id="bsub scheduler"), + pytest.param("pbs", id="qsub scheduler"), + ], +) +def test_batch_arguments_type_set_nodes(scheduler): + bs = BatchSettings(batch_scheduler=scheduler, env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="num_nodes argument was not of type int"): + bs.batch_args.set_nodes("invalid") + + +@pytest.mark.parametrize( + "scheduler", + [ + pytest.param("slurm", id="slurm scheduler"), + pytest.param("lsf", id="bsub scheduler"), + pytest.param("pbs", id="qsub scheduler"), + ], +) +def test_batch_arguments_type_set_account(scheduler): + bs = BatchSettings(batch_scheduler=scheduler, env_vars={"ENV": "VAR"}) + + with pytest.raises(TypeError, match="account argument was not of type str"): + bs.batch_args.set_account(27) + + +@pytest.mark.parametrize( + "scheduler", + [ + pytest.param("slurm", id="slurm scheduler"), + pytest.param("lsf", id="bsub scheduler"), + pytest.param("pbs", id="qsub scheduler"), + ], +) +def test_batch_arguments_type_set_queue(scheduler): + bs = BatchSettings(batch_scheduler=scheduler, env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="queue argument was not of type str"): + bs.batch_args.set_queue(27) diff --git a/tests/temp_tests/test_settings/test_launchSettings.py b/tests/temp_tests/test_settings/test_launchSettings.py index 3fc5e544a9..303b41eb0c 100644 --- a/tests/temp_tests/test_settings/test_launchSettings.py +++ b/tests/temp_tests/test_settings/test_launchSettings.py @@ -87,3 +87,39 @@ def test_update_env_vars_errors(): # and that the function is atomic ls.update_env({"test": "test", "test": 1}) assert ls.env_vars == {"ENV": "VAR"} + + +def test_type_launcher(): + launcher = "invalid" + with pytest.raises(ValueError, match="Invalid launcher type: invalid"): + LaunchSettings( + launcher=launcher, launch_args={"launch": "var"}, env_vars={"ENV": "VAR"} + ) + + +@pytest.mark.parametrize( + "launch_args", + [ + pytest.param("invalid", id="invalid"), + pytest.param("", id="empty string"), + pytest.param(0, id="0"), + pytest.param([], id="empty list"), + pytest.param({"valid", 2}, id="val not str or None"), + ], +) +def test_type_launch_args(launch_args): + with pytest.raises( + TypeError, + match="launch_args argument was not of type dict of str and str or None", + ): + LaunchSettings( + launcher="local", launch_args=launch_args, env_vars={"ENV": "VAR"} + ) + + +def test_type_env_vars(): + env_vars = "invalid" + with pytest.raises( + TypeError, match="env_vars argument was not of type dict of str and str" + ): + LaunchSettings(launcher="local", env_vars=env_vars) diff --git a/tests/temp_tests/test_settings/test_lsfScheduler.py b/tests/temp_tests/test_settings/test_lsfScheduler.py index 5e6b7fd0c4..038e1408e5 100644 --- a/tests/temp_tests/test_settings/test_lsfScheduler.py +++ b/tests/temp_tests/test_settings/test_lsfScheduler.py @@ -75,3 +75,33 @@ def test_create_bsub(): lsfScheduler.batch_args.set_queue("default") args = lsfScheduler.format_batch_args() assert args == ["-core_isolation", "-nnodes", "1", "-W", "10:10", "-q", "default"] + + +def test_batch_arguments_type_set_hostlist(): + bs = BatchSettings(batch_scheduler="lsf", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="host_list argument must be a list of strings"): + bs.batch_args.set_hostlist([25, 37]) + + +def test_batch_arguments_type_set_smts(): + bs = BatchSettings(batch_scheduler="lsf", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="smts argument was not of type int"): + bs.batch_args.set_smts("invalid") + + +def test_batch_arguments_type_set_project(): + bs = BatchSettings(batch_scheduler="lsf", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="project argument was not of type str"): + bs.batch_args.set_project(27) + + +def test_batch_arguments_type_set_tasks(): + bs = BatchSettings(batch_scheduler="lsf", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="tasks argument was not of type int"): + bs.batch_args.set_tasks("invalid") + + +def test_batch_arguments_type_set_walltime(): + bs = BatchSettings(batch_scheduler="lsf", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="walltime argument was not of type str"): + bs.batch_args.set_walltime(27) diff --git a/tests/temp_tests/test_settings/test_pbsScheduler.py b/tests/temp_tests/test_settings/test_pbsScheduler.py index 36fde6776d..718311a322 100644 --- a/tests/temp_tests/test_settings/test_pbsScheduler.py +++ b/tests/temp_tests/test_settings/test_pbsScheduler.py @@ -86,3 +86,21 @@ def test_format_pbs_batch_args(): "-A", "myproject", ] + + +def test_batch_arguments_type_set_hostlist(scheduler): + bs = BatchSettings(batch_scheduler="pbs", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="host_list argument must be a list of strings"): + bs.batch_args.set_hostlist([25, 37]) + + +def test_batch_arguments_type_set_ncpus(): + bs = BatchSettings(batch_scheduler="pbs", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="num_cpus argument was not of type int"): + bs.batch_args.set_ncpus("invalid") + + +def test_batch_arguments_type_set_walltime(): + bs = BatchSettings(batch_scheduler="pbs", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="walltime argument was not of type str"): + bs.batch_args.set_walltime(27) diff --git a/tests/temp_tests/test_settings/test_slurmScheduler.py b/tests/temp_tests/test_settings/test_slurmScheduler.py index 8ab489cc8b..b0f32b7a28 100644 --- a/tests/temp_tests/test_settings/test_slurmScheduler.py +++ b/tests/temp_tests/test_settings/test_slurmScheduler.py @@ -134,3 +134,27 @@ def test_sbatch_manual(): formatted = slurmScheduler.format_batch_args() result = ["--nodes=5", "--account=A3531", "--time=10:00:00"] assert formatted == result + + +def test_batch_arguments_type_set_walltime(): + bs = BatchSettings(batch_scheduler="slurm", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="walltime argument was not of type str"): + bs.batch_args.set_walltime(27) + + +def test_batch_arguments_type_set_cpus_per_task(): + bs = BatchSettings(batch_scheduler="slurm", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="cpus_per_task argument was not of type int"): + bs.batch_args.set_cpus_per_task("invalid") + + +def test_batch_arguments_type_set_partition(): + bs = BatchSettings(batch_scheduler="slurm", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="partition argument was not of type str"): + bs.batch_args.set_partition(27) + + +def test_batch_arguments_type_set_hostlist(scheduler): + bs = BatchSettings(batch_scheduler="slurm", env_vars={"ENV": "VAR"}) + with pytest.raises(TypeError, match="host_list argument must be a list of strings"): + bs.batch_args.set_hostlist([25, 37])