From 068fdf565003ecad97e61998168c93d9626fbff2 Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 19:53:55 +0200 Subject: [PATCH 1/6] Add SlurmConfig.from_cluster() classmethod for autodiscovery --- mdfactory/analysis/submit.py | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/mdfactory/analysis/submit.py b/mdfactory/analysis/submit.py index b14caf9..d5b5aab 100644 --- a/mdfactory/analysis/submit.py +++ b/mdfactory/analysis/submit.py @@ -30,6 +30,97 @@ class SlurmConfig: constraint: str | None = None job_name_prefix: str = "mdfactory-analysis" + @classmethod + def from_cluster( + cls, + *, + needs_gpu: bool = False, + time: str = "2h", + cpus_per_task: int = 4, + mem_gb: int = 8, + qos: str | None = None, + constraint: str | None = None, + job_name_prefix: str = "mdfactory-analysis", + ) -> "SlurmConfig": + """Create SlurmConfig from autodiscovered cluster info. + + Uses lazy import of ``mdfactory.performance.cluster`` to avoid + hard dependency on SLURM commands at import time. + + Parameters + ---------- + needs_gpu : bool + If True, select a GPU-enabled partition. + time : str + Job time limit (default: "2h"). + cpus_per_task : int + CPUs per task (default: 4). + mem_gb : int + Memory per task in GB (default: 8). + qos : str or None + Quality of service. If None, uses first available from cluster. + constraint : str or None + SLURM constraint string. + job_name_prefix : str + Prefix for SLURM job names. + + Returns + ------- + SlurmConfig + Configured instance with autodiscovered account and partition. + + Raises + ------ + RuntimeError + If SLURM is not available or no suitable partition found. + """ + from mdfactory.performance.cluster import discover_cluster, select_partition + + cluster = discover_cluster() + if cluster is None: + raise RuntimeError( + "SLURM autodiscovery failed: not running on a SLURM cluster " + "or SLURM commands (sinfo) are not available." + ) + + # Select appropriate partition + partition = select_partition( + cluster, + needs_gpu=needs_gpu, + min_cpus=cpus_per_task, + min_mem_gb=mem_gb, + ) + if partition is None: + raise RuntimeError( + f"No suitable partition found for requirements: " + f"needs_gpu={needs_gpu}, min_cpus={cpus_per_task}, min_mem_gb={mem_gb}" + ) + + # Get account (required) + account = cluster.default_account + if account is None: + raise RuntimeError( + "SLURM autodiscovery failed: no default account found. " + "Please specify --account explicitly." + ) + + # Use first QOS if available and not explicitly set + resolved_qos = qos + if resolved_qos is None and cluster.qos_policies: + # Don't auto-select QOS; let SLURM use partition default + pass + + return cls( + account=account, + partition=partition.name, + time=time, + cpus_per_task=cpus_per_task, + mem_gb=mem_gb, + qos=resolved_qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + def normalize_slurm_time(value: str) -> str: """Normalize SLURM time strings to accepted formats.""" From 6c2ec2e9f3217fe3902ef4c47545ad25d31adb86 Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 19:54:18 +0200 Subject: [PATCH 2/6] Use autodiscovery fallback when --account not provided in SLURM commands --- mdfactory/cli.py | 214 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 190 insertions(+), 24 deletions(-) diff --git a/mdfactory/cli.py b/mdfactory/cli.py index 478015e..a817231 100644 --- a/mdfactory/cli.py +++ b/mdfactory/cli.py @@ -1187,8 +1187,6 @@ def analysis_run( if source is None: raise ValueError("Provide SOURCE as a simulation directory or build summary YAML.") - if slurm and account is None: - raise ValueError("--account is required when using --slurm.") if analysis_workers is not None and analysis_workers < 1: raise ValueError("--analysis-workers must be >= 1.") @@ -1233,16 +1231,50 @@ def analysis_run( print(result_df) return - slurm_cfg = SlurmConfig( - account=account or "", - partition=partition, - time=time, - cpus_per_task=cpus, - mem_gb=mem_gb, - qos=qos, - constraint=constraint, - job_name_prefix=job_name_prefix, - ) + # Use autodiscovery if account not provided + if account is None: + try: + slurm_cfg = SlurmConfig.from_cluster( + needs_gpu=False, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + # Override partition if user specified one explicitly + if partition != "cpu": # user changed from default + slurm_cfg = SlurmConfig( + account=slurm_cfg.account, + partition=partition, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + logger.info( + f"Using autodiscovered SLURM config: account={slurm_cfg.account}, " + f"partition={slurm_cfg.partition}" + ) + except RuntimeError as e: + raise ValueError( + f"SLURM autodiscovery failed: {e}\n" + "Please specify --account explicitly." + ) from e + else: + slurm_cfg = SlurmConfig( + account=account, + partition=partition, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) if log_dir is None: log_dir = determine_log_dir(sim_paths) result_df = submit_analyses_slurm( @@ -1520,19 +1552,51 @@ def analysis_artifacts_run( print(summary) return + # Use autodiscovery if account not provided if account is None: - raise ValueError("--account is required when using --slurm.") - - slurm_cfg = SlurmConfig( - account=account, - partition=partition, - time=time, - cpus_per_task=cpus, - mem_gb=mem_gb, - qos=qos, - constraint=constraint, - job_name_prefix=job_name_prefix, - ) + try: + slurm_cfg = SlurmConfig.from_cluster( + needs_gpu=False, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + # Override partition if user specified one explicitly + if partition != "cpu": # user changed from default + slurm_cfg = SlurmConfig( + account=slurm_cfg.account, + partition=partition, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + logger.info( + f"Using autodiscovered SLURM config: account={slurm_cfg.account}, " + f"partition={slurm_cfg.partition}" + ) + except RuntimeError as e: + raise ValueError( + f"SLURM autodiscovery failed: {e}\n" + "Please specify --account explicitly." + ) from e + else: + slurm_cfg = SlurmConfig( + account=account, + partition=partition, + time=time, + cpus_per_task=cpus, + mem_gb=mem_gb, + qos=qos, + constraint=constraint, + job_name_prefix=job_name_prefix, + ) + if log_dir is None: log_dir = determine_log_dir(sim_paths) result_df = submit_artifacts_slurm( @@ -1750,6 +1814,108 @@ def config_edit(): subprocess.run([editor, str(config_path)], check=False) +@config_app.command(name="cluster") +def config_cluster( + json_output: Annotated[bool, Parameter("--json", help="Output in JSON format.")] = False, +): + """Show discovered SLURM cluster information. + + Queries the local SLURM scheduler and displays available partitions, + accounts, and QOS policies. Useful for verifying autodiscovery works + and understanding cluster resources before submitting jobs. + + On non-SLURM machines, prints a helpful message instead of failing. + """ + import json as json_module + + from mdfactory.performance.cluster import discover_cluster + + cluster = discover_cluster() + + if cluster is None: + if json_output: + print(json_module.dumps({"error": "SLURM not available", "cluster": None})) + else: + print("SLURM cluster not detected.") + print() + print("This machine does not appear to be a SLURM cluster node,") + print("or SLURM commands (sinfo, sacctmgr) are not in PATH.") + print() + print("To use SLURM submission, run this command on a cluster login node.") + return + + if json_output: + # Build JSON-serializable structure + data = { + "default_account": cluster.default_account, + "accounts": cluster.accounts, + "qos_policies": cluster.qos_policies, + "partitions": [ + { + "name": p.name, + "state": p.state, + "is_default": p.is_default, + "max_time": p.max_time, + "default_time": p.default_time, + "total_nodes": p.total_nodes, + "node_types": [ + { + "cpus": nt.cpus, + "memory_mb": nt.memory_mb, + "gpus": nt.gpus, + "gpu_type": nt.gpu_type, + "features": list(nt.features), + } + for nt in p.node_types + ], + } + for p in cluster.partitions + ], + } + print(json_module.dumps(data, indent=2)) + return + + # Human-readable output + print("SLURM Cluster Information") + print("=" * 50) + print() + + # Account info + print(f"Default Account: {cluster.default_account or '(none)'}") + if cluster.accounts: + print(f"Available Accounts: {', '.join(cluster.accounts)}") + print() + + # QOS info + if cluster.qos_policies: + print(f"QOS Policies: {', '.join(cluster.qos_policies)}") + print() + + # Partition info + print("Partitions:") + print("-" * 50) + for partition in cluster.partitions: + default_marker = " (default)" if partition.is_default else "" + state_marker = f" [{partition.state}]" if partition.state != "up" else "" + print(f"\n {partition.name}{default_marker}{state_marker}") + print(f" Nodes: {partition.total_nodes}") + print(f" Max Time: {partition.max_time}") + if partition.default_time != partition.max_time: + print(f" Default Time: {partition.default_time}") + + # Summarize node types + for nt in partition.node_types: + gpu_info = "" + if nt.gpus > 0: + gpu_type_str = nt.gpu_type or "GPU" + gpu_info = f", {nt.gpus}x {gpu_type_str}" + mem_gb = nt.memory_mb // 1024 + features_str = "" + if nt.features: + features_str = f" [{', '.join(nt.features)}]" + print(f" - {nt.cpus} CPUs, {mem_gb} GB{gpu_info}{features_str}") + + def main(): app() From 6c820737f8d8dbe786a4187d87cc4b91ce46946a Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 19:54:56 +0200 Subject: [PATCH 3/6] Add tests for SlurmConfig.from_cluster() autodiscovery --- mdfactory/tests/test_submit.py | 150 +++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/mdfactory/tests/test_submit.py b/mdfactory/tests/test_submit.py index 3d6524a..3078361 100644 --- a/mdfactory/tests/test_submit.py +++ b/mdfactory/tests/test_submit.py @@ -385,3 +385,153 @@ def submit(self, func, sim_path, analysis_names, **kwargs): assert len(submitted_kwargs) == 1 assert submitted_kwargs[0]["analysis_kwargs"] == {"start_ns": 50.0, "stride": 2} + + +# --- SlurmConfig.from_cluster tests --- + + +class TestSlurmConfigFromCluster: + """Tests for SlurmConfig.from_cluster() autodiscovery method.""" + + def test_from_cluster_success(self, monkeypatch): + """Test successful autodiscovery creates correct config.""" + from mdfactory.performance import cluster as cluster_mod + + # Create mock cluster info + mock_partition = cluster_mod.Partition( + name="compute", + state="up", + max_time="3-00:00:00", + default_time="1:00:00", + node_types=[ + cluster_mod.NodeType(cpus=32, memory_mb=128 * 1024, gpus=0), + ], + total_nodes=10, + is_default=True, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition], + accounts=["myaccount", "otheraccount"], + qos_policies=["normal", "high"], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + config = submit_mod.SlurmConfig.from_cluster( + time="4h", + cpus_per_task=8, + mem_gb=16, + ) + + assert config.account == "myaccount" + assert config.partition == "compute" + assert config.time == "4h" + assert config.cpus_per_task == 8 + assert config.mem_gb == 16 + + def test_from_cluster_no_slurm_raises(self, monkeypatch): + """Test that missing SLURM raises RuntimeError.""" + from mdfactory.performance import cluster as cluster_mod + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: None) + + import pytest + + with pytest.raises(RuntimeError, match="not running on a SLURM cluster"): + submit_mod.SlurmConfig.from_cluster() + + def test_from_cluster_no_account_raises(self, monkeypatch): + """Test that missing default account raises RuntimeError.""" + from mdfactory.performance import cluster as cluster_mod + + mock_partition = cluster_mod.Partition( + name="compute", + state="up", + max_time="1-00:00:00", + default_time="1:00:00", + node_types=[cluster_mod.NodeType(cpus=16, memory_mb=64 * 1024)], + total_nodes=5, + is_default=True, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition], + accounts=[], + qos_policies=[], + default_account=None, + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + import pytest + + with pytest.raises(RuntimeError, match="no default account found"): + submit_mod.SlurmConfig.from_cluster() + + def test_from_cluster_no_suitable_partition_raises(self, monkeypatch): + """Test that no matching partition raises RuntimeError.""" + from mdfactory.performance import cluster as cluster_mod + + # Partition with only 4 CPUs - won't match request for 32 CPUs + mock_partition = cluster_mod.Partition( + name="tiny", + state="up", + max_time="1:00:00", + default_time="0:30:00", + node_types=[cluster_mod.NodeType(cpus=4, memory_mb=8 * 1024)], + total_nodes=2, + is_default=True, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition], + accounts=["myaccount"], + qos_policies=[], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + import pytest + + with pytest.raises(RuntimeError, match="No suitable partition found"): + submit_mod.SlurmConfig.from_cluster(min_cpus=32) + + def test_from_cluster_selects_gpu_partition(self, monkeypatch): + """Test that needs_gpu=True selects GPU partition.""" + from mdfactory.performance import cluster as cluster_mod + + cpu_partition = cluster_mod.Partition( + name="cpu", + state="up", + max_time="7-00:00:00", + default_time="1:00:00", + node_types=[cluster_mod.NodeType(cpus=64, memory_mb=256 * 1024, gpus=0)], + total_nodes=100, + is_default=True, + ) + gpu_partition = cluster_mod.Partition( + name="gpu", + state="up", + max_time="2-00:00:00", + default_time="1:00:00", + node_types=[ + cluster_mod.NodeType( + cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100" + ) + ], + total_nodes=20, + is_default=False, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[cpu_partition, gpu_partition], + accounts=["myaccount"], + qos_policies=[], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + config = submit_mod.SlurmConfig.from_cluster(needs_gpu=True) + + assert config.partition == "gpu" + assert config.account == "myaccount" From dcf71978784a7f3a49de6140ef593421581d48b5 Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 19:55:25 +0200 Subject: [PATCH 4/6] Add tests for mdfactory config cluster CLI command --- mdfactory/tests/test_cli_cluster.py | 155 ++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 mdfactory/tests/test_cli_cluster.py diff --git a/mdfactory/tests/test_cli_cluster.py b/mdfactory/tests/test_cli_cluster.py new file mode 100644 index 0000000..f0d8ad3 --- /dev/null +++ b/mdfactory/tests/test_cli_cluster.py @@ -0,0 +1,155 @@ +# ABOUTME: Tests for the `mdfactory config cluster` CLI command, verifying +# ABOUTME: SLURM autodiscovery output in human-readable and JSON formats. +"""Tests for mdfactory config cluster CLI command.""" + +import json + +from mdfactory import cli +from mdfactory.performance import cluster as cluster_mod + + +class TestConfigClusterCommand: + """Tests for the config cluster CLI command.""" + + def test_config_cluster_no_slurm(self, monkeypatch, capsys): + """Test graceful message when SLURM is not available.""" + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: None) + + cli.config_cluster(json_output=False) + + captured = capsys.readouterr() + assert "SLURM cluster not detected" in captured.out + assert "login node" in captured.out + + def test_config_cluster_no_slurm_json(self, monkeypatch, capsys): + """Test JSON output when SLURM is not available.""" + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: None) + + cli.config_cluster(json_output=True) + + captured = capsys.readouterr() + data = json.loads(captured.out) + assert data["cluster"] is None + assert "error" in data + + def test_config_cluster_with_slurm(self, monkeypatch, capsys): + """Test human-readable output with SLURM cluster.""" + mock_partition = cluster_mod.Partition( + name="compute", + state="up", + max_time="7-00:00:00", + default_time="1:00:00", + node_types=[ + cluster_mod.NodeType(cpus=64, memory_mb=256 * 1024, gpus=0), + ], + total_nodes=100, + is_default=True, + ) + gpu_partition = cluster_mod.Partition( + name="gpu", + state="up", + max_time="2-00:00:00", + default_time="1:00:00", + node_types=[ + cluster_mod.NodeType( + cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100" + ), + ], + total_nodes=20, + is_default=False, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition, gpu_partition], + accounts=["myaccount", "shared"], + qos_policies=["normal", "high"], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + cli.config_cluster(json_output=False) + + captured = capsys.readouterr() + assert "SLURM Cluster Information" in captured.out + assert "Default Account: myaccount" in captured.out + assert "compute" in captured.out + assert "(default)" in captured.out + assert "gpu" in captured.out + assert "a100" in captured.out + assert "64 CPUs" in captured.out + assert "4x a100" in captured.out + + def test_config_cluster_with_slurm_json(self, monkeypatch, capsys): + """Test JSON output with SLURM cluster.""" + mock_partition = cluster_mod.Partition( + name="compute", + state="up", + max_time="7-00:00:00", + default_time="1:00:00", + node_types=[ + cluster_mod.NodeType( + cpus=64, + memory_mb=256 * 1024, + gpus=0, + features=("avx512", "intel"), + ), + ], + total_nodes=100, + is_default=True, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition], + accounts=["myaccount"], + qos_policies=["normal"], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + cli.config_cluster(json_output=True) + + captured = capsys.readouterr() + data = json.loads(captured.out) + + assert data["default_account"] == "myaccount" + assert data["accounts"] == ["myaccount"] + assert data["qos_policies"] == ["normal"] + assert len(data["partitions"]) == 1 + + part = data["partitions"][0] + assert part["name"] == "compute" + assert part["is_default"] is True + assert part["total_nodes"] == 100 + assert len(part["node_types"]) == 1 + + nt = part["node_types"][0] + assert nt["cpus"] == 64 + assert nt["memory_mb"] == 256 * 1024 + assert nt["gpus"] == 0 + assert nt["features"] == ["avx512", "intel"] + + def test_config_cluster_down_partition(self, monkeypatch, capsys): + """Test display of partition with down state.""" + mock_partition = cluster_mod.Partition( + name="maintenance", + state="drained", + max_time="1:00:00", + default_time="0:30:00", + node_types=[cluster_mod.NodeType(cpus=16, memory_mb=32 * 1024)], + total_nodes=5, + is_default=False, + ) + mock_cluster = cluster_mod.ClusterInfo( + partitions=[mock_partition], + accounts=["myaccount"], + qos_policies=[], + default_account="myaccount", + ) + + monkeypatch.setattr(cluster_mod, "discover_cluster", lambda: mock_cluster) + + cli.config_cluster(json_output=False) + + captured = capsys.readouterr() + assert "maintenance" in captured.out + assert "[drained]" in captured.out From c6000ad2b979ff1d6226fb150b1573160db172f6 Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 20:14:22 +0200 Subject: [PATCH 5/6] Fix test parameter name: min_cpus -> cpus_per_task --- mdfactory/tests/test_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdfactory/tests/test_submit.py b/mdfactory/tests/test_submit.py index 3078361..fe8a2fa 100644 --- a/mdfactory/tests/test_submit.py +++ b/mdfactory/tests/test_submit.py @@ -494,7 +494,7 @@ def test_from_cluster_no_suitable_partition_raises(self, monkeypatch): import pytest with pytest.raises(RuntimeError, match="No suitable partition found"): - submit_mod.SlurmConfig.from_cluster(min_cpus=32) + submit_mod.SlurmConfig.from_cluster(cpus_per_task=32) def test_from_cluster_selects_gpu_partition(self, monkeypatch): """Test that needs_gpu=True selects GPU partition.""" From e585c73c8383586796166c84d1828fc8c263427d Mon Sep 17 00:00:00 2001 From: Gregor Weiss <52161555+gregorweiss@users.noreply.github.com> Date: Wed, 20 May 2026 21:13:51 +0200 Subject: [PATCH 6/6] Apply ruff formatting fixes --- mdfactory/cli.py | 6 ++---- mdfactory/tests/test_cli_cluster.py | 4 +--- mdfactory/tests/test_submit.py | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/mdfactory/cli.py b/mdfactory/cli.py index a817231..8964b1b 100644 --- a/mdfactory/cli.py +++ b/mdfactory/cli.py @@ -1261,8 +1261,7 @@ def analysis_run( ) except RuntimeError as e: raise ValueError( - f"SLURM autodiscovery failed: {e}\n" - "Please specify --account explicitly." + f"SLURM autodiscovery failed: {e}\nPlease specify --account explicitly." ) from e else: slurm_cfg = SlurmConfig( @@ -1582,8 +1581,7 @@ def analysis_artifacts_run( ) except RuntimeError as e: raise ValueError( - f"SLURM autodiscovery failed: {e}\n" - "Please specify --account explicitly." + f"SLURM autodiscovery failed: {e}\nPlease specify --account explicitly." ) from e else: slurm_cfg = SlurmConfig( diff --git a/mdfactory/tests/test_cli_cluster.py b/mdfactory/tests/test_cli_cluster.py index f0d8ad3..c663379 100644 --- a/mdfactory/tests/test_cli_cluster.py +++ b/mdfactory/tests/test_cli_cluster.py @@ -51,9 +51,7 @@ def test_config_cluster_with_slurm(self, monkeypatch, capsys): max_time="2-00:00:00", default_time="1:00:00", node_types=[ - cluster_mod.NodeType( - cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100" - ), + cluster_mod.NodeType(cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100"), ], total_nodes=20, is_default=False, diff --git a/mdfactory/tests/test_submit.py b/mdfactory/tests/test_submit.py index fe8a2fa..d542c70 100644 --- a/mdfactory/tests/test_submit.py +++ b/mdfactory/tests/test_submit.py @@ -515,9 +515,7 @@ def test_from_cluster_selects_gpu_partition(self, monkeypatch): max_time="2-00:00:00", default_time="1:00:00", node_types=[ - cluster_mod.NodeType( - cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100" - ) + cluster_mod.NodeType(cpus=32, memory_mb=128 * 1024, gpus=4, gpu_type="a100") ], total_nodes=20, is_default=False,