Skip to content

Commit 631e45b

Browse files
committed
Refactored ArraySpec
1 parent ce6db63 commit 631e45b

15 files changed

Lines changed: 459 additions & 509 deletions

File tree

src/qq_lib/batch/interface/interface.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from typing import TYPE_CHECKING, Any, cast
1313

1414
from qq_lib.batch.interface._arfe import _AtomicRemoteFileEditor
15-
from qq_lib.batch.interface.array_spec import ArraySpec
1615
from qq_lib.core.common import convert_absolute_to_relative
1716
from qq_lib.core.config import CFG
1817
from qq_lib.core.error import QQError
@@ -27,6 +26,7 @@
2726
if TYPE_CHECKING:
2827
from collections.abc import Callable
2928

29+
from qq_lib.core.array_spec import ArraySpec
3030
from qq_lib.properties.depend import Depend
3131
from qq_lib.properties.resources import Resources
3232

@@ -35,7 +35,7 @@
3535
"""
3636
Type alias for a batch system class.
3737
"""
38-
type AnyBatchClass = type[BatchInterface[Any, Any, Any, Any]]
38+
type AnyBatchClass = type[BatchInterface[Any, Any, Any]]
3939

4040

4141
class _BatchMeta(ABCMeta):
@@ -137,7 +137,6 @@ class BatchInterface[
137137
TBatchJob: BatchJobInterface = BatchJobInterface,
138138
TBatchQueue: BatchQueueInterface = BatchQueueInterface,
139139
TBatchNode: BatchNodeInterface = BatchNodeInterface,
140-
TArraySpec: ArraySpec = ArraySpec,
141140
](ABC, metaclass=_BatchMeta):
142141
"""
143142
Abstract base class for batch system integrations.
@@ -222,7 +221,7 @@ def job_submit(
222221
depend: list[Depend],
223222
env_vars: dict[str, str],
224223
account: str | None = None,
225-
array: TArraySpec | None = None,
224+
array: ArraySpec | None = None,
226225
server: str | None = None,
227226
remote_host: str | None = None,
228227
) -> str:
@@ -239,7 +238,7 @@ def job_submit(
239238
depend (list[Depend]): List of job dependencies.
240239
env_vars (dict[str, str]): Dictionary of environment variables to propagate to the job.
241240
account (str | None): Optional account name to use for the job.
242-
array (TArraySpec | None): Optional array job specification.
241+
array (ArraySpec | None): Optional array job specification.
243242
server (str | None): Optional name of the server to submit the job to.
244243
remote_host (str | None): Optional name of the machine to submit the job from.
245244

src/qq_lib/batch/pbs/array_spec.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/qq_lib/batch/pbs/pbs.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from pathlib import Path
1313

1414
from qq_lib.batch.interface import BatchInterface
15-
from qq_lib.batch.pbs.array_spec import PBSArraySpec
1615
from qq_lib.batch.pbs.common import parse_multi_pbs_dump_to_dictionaries
1716
from qq_lib.batch.pbs.node import PBSNode
1817
from qq_lib.batch.pbs.queue import PBSQueue
18+
from qq_lib.core.array_spec import ArraySpec
1919
from qq_lib.core.common import equals_normalized
2020
from qq_lib.core.config import CFG
2121
from qq_lib.core.error import QQError
@@ -29,7 +29,7 @@
2929
logger = get_logger(__name__)
3030

3131

32-
class PBS(BatchInterface[PBSJob, PBSQueue, PBSNode, PBSArraySpec]):
32+
class PBS(BatchInterface[PBSJob, PBSQueue, PBSNode]):
3333
"""
3434
Implementation of BatchInterface for PBS Pro batch system.
3535
"""
@@ -76,7 +76,7 @@ def job_submit(
7676
depend: list[Depend],
7777
env_vars: dict[str, str],
7878
account: str | None = None,
79-
array: PBSArraySpec | None = None,
79+
array: ArraySpec | None = None,
8080
server: str | None = None,
8181
remote_host: str | None = None,
8282
) -> str:
@@ -589,7 +589,7 @@ def _translate_submit(
589589
job_name: str,
590590
depend: list[Depend],
591591
env_vars: dict[str, str],
592-
array: PBSArraySpec | None,
592+
array: ArraySpec | None,
593593
) -> str:
594594
"""
595595
Generate the PBS submission command for a job.
@@ -603,7 +603,7 @@ def _translate_submit(
603603
job_name (str): Name of the job.
604604
depend (list[Depend]): List of dependencies of the job.
605605
env_vars (dict[str, str]): Dictionary of environment variables to set.
606-
array (PBSArraySpec | None): Optional array job specification.
606+
array (ArraySpec | None): Optional array job specification.
607607
608608
Returns:
609609
str: The fully constructed qsub command string.
@@ -612,7 +612,7 @@ def _translate_submit(
612612

613613
# translate array specification
614614
if array:
615-
command += f"-J {array.translate()} "
615+
command += f"-J {cls._translate_array(array)} "
616616

617617
# translate environment variables
618618
if env_vars:
@@ -865,6 +865,28 @@ def _translate_dependencies(cls, depend: list[Depend]) -> str | None:
865865

866866
return ",".join(Depend.to_str(x).replace("=", ":") for x in depend)
867867

868+
@classmethod
869+
def _translate_array(cls, array: ArraySpec) -> str:
870+
"""
871+
Translate an `ArraySpec` object into a PBS-compatible array job specification string.
872+
873+
Args:
874+
array (ArraySpec): The array job specification to translate.
875+
876+
Returns:
877+
str: The translated PBS array job specification string.
878+
"""
879+
parts: list[str] = []
880+
for elem in array.elements:
881+
match elem:
882+
case int(index):
883+
parts.append(str(index))
884+
case (int(start), int(stop)):
885+
parts.append(f"{start}-{stop}")
886+
case (int(start), int(stop), int(step)):
887+
parts.append(f"{start}-{stop}:{step}")
888+
return ",".join(parts)
889+
868890
@classmethod
869891
def _collect_ams_env_vars(cls) -> dict[str, str]:
870892
"""

src/qq_lib/batch/slurm/array_spec.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/qq_lib/batch/slurm/slurm.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from qq_lib.batch.interface import BatchInterface
1111
from qq_lib.batch.pbs.pbs import PBS
12-
from qq_lib.batch.slurm.array_spec import SlurmArraySpec
12+
from qq_lib.core.array_spec import ArraySpec
1313
from qq_lib.core.config import CFG
1414
from qq_lib.core.error import QQError
1515
from qq_lib.core.logger import get_logger
@@ -28,7 +28,7 @@
2828
logger = get_logger(__name__)
2929

3030

31-
class Slurm(BatchInterface[SlurmJob, SlurmQueue, SlurmNode, SlurmArraySpec]):
31+
class Slurm(BatchInterface[SlurmJob, SlurmQueue, SlurmNode]):
3232
"""
3333
Implementation of BatchInterface for Slurm batch system.
3434
"""
@@ -59,7 +59,7 @@ def job_submit(
5959
depend: list[Depend],
6060
env_vars: dict[str, str],
6161
account: str | None = None,
62-
array: SlurmArraySpec | None = None,
62+
array: ArraySpec | None = None,
6363
server: str | None = None,
6464
remote_host: str | None = None,
6565
) -> str:
@@ -411,7 +411,7 @@ def _translate_submit(
411411
depend: list[Depend],
412412
env_vars: dict[str, str],
413413
account: str | None,
414-
array: SlurmArraySpec | None,
414+
array: ArraySpec | None,
415415
) -> str:
416416
"""
417417
Generate the Slurm submission command for a job.
@@ -425,7 +425,7 @@ def _translate_submit(
425425
depend (list[Depend]): List of dependencies of the job.
426426
env_vars (dict[str, str]): Dictionary of environment variables and their values to propagate to the job's environment.
427427
account (str | None): Optional name of the account to use for the job.
428-
array (SlurmArraySpec | None): Optional array job specification.
428+
array (ArraySpec | None): Optional array job specification.
429429
430430
Returns:
431431
str: The fully constructed sbatch command string.
@@ -434,7 +434,7 @@ def _translate_submit(
434434
command = f"sbatch -J {job_name} -p {queue} -e {qq_output} -o {qq_output} "
435435

436436
if array:
437-
command += f"--array={array.translate()} "
437+
command += f"--array={cls._translate_array(array)} "
438438

439439
if account:
440440
command += f"--account {account} "
@@ -582,6 +582,20 @@ def _translate_dependencies(cls, depend: list[Depend]) -> str | None:
582582

583583
return ",".join(Depend.to_str(x).replace("=", ":") for x in depend)
584584

585+
@classmethod
586+
def _translate_array(cls, array: ArraySpec) -> str:
587+
"""
588+
Translate an `ArraySpec` object into a Slurm-compatible array job specification string.
589+
590+
Args:
591+
array (ArraySpec): The array job specification to translate.
592+
593+
Returns:
594+
str: The translated Slurm array job specification string.
595+
"""
596+
# Slurm array syntax is the same as PBS syntax
597+
return PBS._translate_array(array)
598+
585599
@classmethod
586600
def _get_default_server_resources(cls) -> Resources:
587601
"""

src/qq_lib/batch/slurmlumi/slurm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
from typing import cast
99

1010
from qq_lib.batch.slurm import Slurm
11-
from qq_lib.batch.slurm.array_spec import SlurmArraySpec
1211
from qq_lib.batch.slurmit4i import SlurmIT4I
1312
from qq_lib.batch.slurmlumi.node import SlurmLumiNode
13+
from qq_lib.core.array_spec import ArraySpec
1414
from qq_lib.core.config import CFG
1515
from qq_lib.core.error import QQError
1616
from qq_lib.core.logger import get_logger
@@ -46,7 +46,7 @@ def job_submit(
4646
depend: list[Depend],
4747
env_vars: dict[str, str],
4848
account: str | None = None,
49-
array: SlurmArraySpec | None = None,
49+
array: ArraySpec | None = None,
5050
server: str | None = None,
5151
remote_host: str | None = None,
5252
) -> str:
Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
# Released under MIT License.
22
# Copyright (c) 2025-2026 Ladislav Bartos and Robert Vacha Lab
33

4-
from abc import ABC, abstractmethod
5-
64
from qq_lib.core.error import QQError
75

86
type ArrayElement = int | tuple[int, int] | tuple[int, int, int]
97

108

11-
class ArraySpec(ABC):
9+
class ArraySpec:
1210
"""
13-
Abstract specification for job-array task indices.
14-
15-
Each scheduler backend provides a concrete subclass that knows how
16-
to translate index specifications into the syntax that particular scheduler expects.
11+
Specification for job-array task indices.
1712
1813
Args:
1914
elements (list[ArrayElement]): Non-empty list of indices and ranges.
@@ -24,17 +19,7 @@ class ArraySpec(ABC):
2419

2520
def __init__(self, elements: list[ArrayElement]):
2621
_validate_elements(elements)
27-
self._elements = _merge_elements(elements)
28-
29-
@abstractmethod
30-
def translate(self) -> str:
31-
"""
32-
Translate this specification into the scheduler's native syntax.
33-
34-
Returns:
35-
str: A string suitable for passing to the scheduler's array flag
36-
(e.g. `--array=` for Slurm, `-J` for PBS).
37-
"""
22+
self.elements = _merge_elements(elements)
3823

3924

4025
def _validate_elements(elements: list[ArrayElement]) -> None:

src/qq_lib/submit/submitter.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,15 @@ def submit(self, remote: str | None = None) -> str:
149149
QQError: If job submission fails.
150150
"""
151151
job_id = self._batch_system.job_submit(
152-
self._resources,
153-
self._queue,
154-
self._script,
155-
self._job_name,
156-
self._depend,
157-
self._create_env_vars_dict(),
158-
self._account,
159-
self._server,
152+
res=self._resources,
153+
queue=self._queue,
154+
script=self._script,
155+
job_name=self._job_name,
156+
depend=self._depend,
157+
env_vars=self._create_env_vars_dict(),
158+
account=self._account,
159+
array=None,
160+
server=self._server,
160161
remote_host=remote,
161162
)
162163

0 commit comments

Comments
 (0)