resubmit 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- resubmit-0.0.3/LICENSE +21 -0
- resubmit-0.0.3/PKG-INFO +89 -0
- resubmit-0.0.3/README.md +76 -0
- resubmit-0.0.3/pyproject.toml +22 -0
- resubmit-0.0.3/setup.cfg +4 -0
- resubmit-0.0.3/src/resubmit/__init__.py +6 -0
- resubmit-0.0.3/src/resubmit/debug.py +26 -0
- resubmit-0.0.3/src/resubmit/submit.py +85 -0
- resubmit-0.0.3/src/resubmit.egg-info/PKG-INFO +89 -0
- resubmit-0.0.3/src/resubmit.egg-info/SOURCES.txt +12 -0
- resubmit-0.0.3/src/resubmit.egg-info/dependency_links.txt +1 -0
- resubmit-0.0.3/src/resubmit.egg-info/requires.txt +4 -0
- resubmit-0.0.3/src/resubmit.egg-info/top_level.txt +1 -0
- resubmit-0.0.3/tests/test_resubmit.py +116 -0
resubmit-0.0.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
resubmit-0.0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: resubmit
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: Small wrapper around submitit to simplify cluster submissions
|
|
5
|
+
Author: Amir Mehrpanah
|
|
6
|
+
License: MIT
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: submitit>=0.8
|
|
10
|
+
Provides-Extra: debug
|
|
11
|
+
Requires-Dist: debugpy; extra == "debug"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# resubmit
|
|
15
|
+
|
|
16
|
+
Small utility library to simplify job submission with Submitit on SLURM clusters.
|
|
17
|
+
|
|
18
|
+
Quick usage:
|
|
19
|
+
|
|
20
|
+
- Install locally for development:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install -e .[debug]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- Use in your project:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from resubmit import submit_jobs, maybe_attach_debugger
|
|
30
|
+
|
|
31
|
+
# attach remote debugger if requested
|
|
32
|
+
maybe_attach_debugger(args.get("port", None))
|
|
33
|
+
|
|
34
|
+
# submit jobs (list of dicts)
|
|
35
|
+
submit_jobs(jobs_list, my_entrypoint, timeout_min=60, block=True)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
### submit_jobs(...) 🔧
|
|
41
|
+
|
|
42
|
+
Submit multiple jobs to a Slurm cluster using Submitit.
|
|
43
|
+
|
|
44
|
+
Signature (short):
|
|
45
|
+
|
|
46
|
+
`submit_jobs(jobs_args: Iterable[dict], func: Callable[[List[dict]], Any], *, timeout_min: int, cpus_per_task: int = 16, mem_gb: int = 64, num_gpus: int = 1, account: Optional[str] = None, folder: str = "logs/%j", block: bool = False, prompt: bool = True, local_run: bool = False, slurm_additional_parameters: Optional[Dict] = None, constraint: Optional[str] = None, reservation: Optional[str] = None)`
|
|
47
|
+
|
|
48
|
+
- `jobs_args`: iterable of per-job kwargs (each item is passed to `func`).
|
|
49
|
+
- `func`: entrypoint called for each job (should accept a list or single job dict depending on your usage).
|
|
50
|
+
- `timeout_min`, `cpus_per_task`, `mem_gb`, `num_gpus`: common Slurm resources.
|
|
51
|
+
- `account`: optional Slurm account name.
|
|
52
|
+
- `folder`: logs folder for Submitit files (supports `%j` for job id).
|
|
53
|
+
- `block`: if True, waits for all jobs and returns results.
|
|
54
|
+
- `prompt`: if True, asks for confirmation interactively; set to `False` for CI or tests.
|
|
55
|
+
- `local_run`: run the jobs locally without Submitit (useful for debugging).
|
|
56
|
+
- `slurm_additional_parameters`: pass any extra Slurm key/value pairs to Submitit.
|
|
57
|
+
- `constraint` / `reservation`: cluster-specific options kept out of defaults — provide them explicitly if you need them (they take precedence over values in `slurm_additional_parameters`).
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
submit_jobs(
|
|
63
|
+
jobs_list,
|
|
64
|
+
my_entrypoint,
|
|
65
|
+
timeout_min=60,
|
|
66
|
+
num_gpus=2,
|
|
67
|
+
prompt=False,
|
|
68
|
+
constraint="gpu",
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### maybe_attach_debugger(port: Optional[int]) 🐞
|
|
73
|
+
|
|
74
|
+
Attach `debugpy` to the job when `port` is provided (> 0). Safe no-op if `port` is `None` or `<= 0`.
|
|
75
|
+
|
|
76
|
+
- If `debugpy` (and `submitit`) are not available on the node, a `RuntimeError` is raised with an explanatory message.
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# attach remote debugger only when a port is provided (e.g., from CLI args)
|
|
82
|
+
maybe_attach_debugger(args.get("port"))
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
Tips:
|
|
88
|
+
- Use `prompt=False` when calling `submit_jobs` from scripts or CI to avoid interactive prompts.
|
|
89
|
+
- Tests demonstrate non-interactive behavior (`prompt=False`) and optional `constraint`/`reservation` handling.
|
resubmit-0.0.3/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# resubmit
|
|
2
|
+
|
|
3
|
+
Small utility library to simplify job submission with Submitit on SLURM clusters.
|
|
4
|
+
|
|
5
|
+
Quick usage:
|
|
6
|
+
|
|
7
|
+
- Install locally for development:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install -e .[debug]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- Use in your project:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from resubmit import submit_jobs, maybe_attach_debugger
|
|
17
|
+
|
|
18
|
+
# attach remote debugger if requested
|
|
19
|
+
maybe_attach_debugger(args.get("port", None))
|
|
20
|
+
|
|
21
|
+
# submit jobs (list of dicts)
|
|
22
|
+
submit_jobs(jobs_list, my_entrypoint, timeout_min=60, block=True)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
### submit_jobs(...) 🔧
|
|
28
|
+
|
|
29
|
+
Submit multiple jobs to a Slurm cluster using Submitit.
|
|
30
|
+
|
|
31
|
+
Signature (short):
|
|
32
|
+
|
|
33
|
+
`submit_jobs(jobs_args: Iterable[dict], func: Callable[[List[dict]], Any], *, timeout_min: int, cpus_per_task: int = 16, mem_gb: int = 64, num_gpus: int = 1, account: Optional[str] = None, folder: str = "logs/%j", block: bool = False, prompt: bool = True, local_run: bool = False, slurm_additional_parameters: Optional[Dict] = None, constraint: Optional[str] = None, reservation: Optional[str] = None)`
|
|
34
|
+
|
|
35
|
+
- `jobs_args`: iterable of per-job kwargs (each item is passed to `func`).
|
|
36
|
+
- `func`: entrypoint called for each job (should accept a list or single job dict depending on your usage).
|
|
37
|
+
- `timeout_min`, `cpus_per_task`, `mem_gb`, `num_gpus`: common Slurm resources.
|
|
38
|
+
- `account`: optional Slurm account name.
|
|
39
|
+
- `folder`: logs folder for Submitit files (supports `%j` for job id).
|
|
40
|
+
- `block`: if True, waits for all jobs and returns results.
|
|
41
|
+
- `prompt`: if True, asks for confirmation interactively; set to `False` for CI or tests.
|
|
42
|
+
- `local_run`: run the jobs locally without Submitit (useful for debugging).
|
|
43
|
+
- `slurm_additional_parameters`: pass any extra Slurm key/value pairs to Submitit.
|
|
44
|
+
- `constraint` / `reservation`: cluster-specific options kept out of defaults — provide them explicitly if you need them (they take precedence over values in `slurm_additional_parameters`).
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
submit_jobs(
|
|
50
|
+
jobs_list,
|
|
51
|
+
my_entrypoint,
|
|
52
|
+
timeout_min=60,
|
|
53
|
+
num_gpus=2,
|
|
54
|
+
prompt=False,
|
|
55
|
+
constraint="gpu",
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### maybe_attach_debugger(port: Optional[int]) 🐞
|
|
60
|
+
|
|
61
|
+
Attach `debugpy` to the job when `port` is provided (> 0). Safe no-op if `port` is `None` or `<= 0`.
|
|
62
|
+
|
|
63
|
+
- If `debugpy` (and `submitit`) are not available on the node, a `RuntimeError` is raised with an explanatory message.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# attach remote debugger only when a port is provided (e.g., from CLI args)
|
|
69
|
+
maybe_attach_debugger(args.get("port"))
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
Tips:
|
|
75
|
+
- Use `prompt=False` when calling `submit_jobs` from scripts or CI to avoid interactive prompts.
|
|
76
|
+
- Tests demonstrate non-interactive behavior (`prompt=False`) and optional `constraint`/`reservation` handling.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel", "build"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "resubmit"
|
|
7
|
+
version = "0.0.3"
|
|
8
|
+
description = "Small wrapper around submitit to simplify cluster submissions"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [ { name = "Amir Mehrpanah" } ]
|
|
12
|
+
dependencies = ["submitit>=0.8"]
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
debug = ["debugpy"]
|
|
16
|
+
|
|
17
|
+
[tool.setuptools.packages.find]
|
|
18
|
+
where = ["src"]
|
|
19
|
+
include = ["resubmit*"]
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
package-dir = { "" = "src" }
|
resubmit-0.0.3/setup.cfg
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Debug helpers (attach remote debugger when running via Submitit)."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
def maybe_attach_debugger(port: Optional[int]) -> None:
|
|
7
|
+
"""Attach debugpy to the current job when `port` is provided (> 0).
|
|
8
|
+
|
|
9
|
+
Safe no-op if `port` is None or <= 0. Raises informative errors if debugpy is missing.
|
|
10
|
+
"""
|
|
11
|
+
if port is None or port <= 0:
|
|
12
|
+
return
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
import submitit
|
|
16
|
+
import debugpy
|
|
17
|
+
except Exception as exc: # pragma: no cover - environmental dependency
|
|
18
|
+
raise RuntimeError(
|
|
19
|
+
"debugging requires 'submitit' and 'debugpy' packages installed on the compute node"
|
|
20
|
+
) from exc
|
|
21
|
+
|
|
22
|
+
job_env = submitit.JobEnvironment()
|
|
23
|
+
print(f"Debugger is running on node {job_env.hostname} port {port}")
|
|
24
|
+
debugpy.listen((job_env.hostname, port))
|
|
25
|
+
print("Waiting for debugger attach")
|
|
26
|
+
debugpy.wait_for_client()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Core submission utilities wrapping submitit."""
|
|
2
|
+
from typing import Any, Callable, Iterable, List, Optional, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def submit_jobs(
|
|
6
|
+
jobs_args: Iterable[dict],
|
|
7
|
+
func: Callable[[List[dict]], Any],
|
|
8
|
+
*,
|
|
9
|
+
timeout_min: int,
|
|
10
|
+
cpus_per_task: int = 16,
|
|
11
|
+
mem_gb: int = 64,
|
|
12
|
+
num_gpus: int = 1,
|
|
13
|
+
account: Optional[str] = None,
|
|
14
|
+
folder: str = "logs/%j",
|
|
15
|
+
block: bool = False,
|
|
16
|
+
prompt: bool = True,
|
|
17
|
+
local_run: bool = False,
|
|
18
|
+
slurm_additional_parameters: Optional[Dict] = None,
|
|
19
|
+
constraint: Optional[str] = None,
|
|
20
|
+
reservation: Optional[str] = None,
|
|
21
|
+
):
|
|
22
|
+
"""Submit jobs described by `jobs_args` where each entry is a dict of kwargs for `func`.
|
|
23
|
+
|
|
24
|
+
- If `local_run` is True, the function is called directly: `func(jobs_args)`.
|
|
25
|
+
- Otherwise, submits via submitit.AutoExecutor and returns job objects or, if `block` is True, waits and returns results.
|
|
26
|
+
|
|
27
|
+
Optional Slurm settings `constraint` and `reservation` can be provided via explicit
|
|
28
|
+
parameters (they take precedence) or by passing `slurm_additional_parameters`.
|
|
29
|
+
If not provided, they are omitted so the code is not tied to cluster-specific
|
|
30
|
+
defaults.
|
|
31
|
+
"""
|
|
32
|
+
jobs_list = list(jobs_args) if not isinstance(jobs_args, list) else jobs_args
|
|
33
|
+
|
|
34
|
+
if len(jobs_list) == 0:
|
|
35
|
+
print("No jobs to run exiting")
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
if local_run:
|
|
39
|
+
print("Running locally (local_run=True)")
|
|
40
|
+
return func(jobs_list)
|
|
41
|
+
|
|
42
|
+
if prompt:
|
|
43
|
+
print("Do you want to continue? [y/n]", flush=True)
|
|
44
|
+
if input() != "y":
|
|
45
|
+
print("Aborted")
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
import submitit
|
|
49
|
+
print("submitting jobs")
|
|
50
|
+
executor = submitit.AutoExecutor(folder=folder)
|
|
51
|
+
|
|
52
|
+
# default slurm params (keep cluster-specific options out unless explicitly set)
|
|
53
|
+
if slurm_additional_parameters is None:
|
|
54
|
+
slurm_additional_parameters = {"gpus": num_gpus}
|
|
55
|
+
else:
|
|
56
|
+
slurm_additional_parameters = dict(slurm_additional_parameters)
|
|
57
|
+
slurm_additional_parameters.setdefault("gpus", num_gpus)
|
|
58
|
+
|
|
59
|
+
# Allow explicit overrides similar to `account`.
|
|
60
|
+
if account is not None:
|
|
61
|
+
slurm_additional_parameters["account"] = account
|
|
62
|
+
if reservation is not None:
|
|
63
|
+
slurm_additional_parameters["reservation"] = reservation
|
|
64
|
+
if constraint is not None:
|
|
65
|
+
slurm_additional_parameters["constraint"] = constraint
|
|
66
|
+
|
|
67
|
+
print("Slurm additional parameters:", slurm_additional_parameters)
|
|
68
|
+
|
|
69
|
+
executor.update_parameters(
|
|
70
|
+
timeout_min=timeout_min,
|
|
71
|
+
cpus_per_task=cpus_per_task,
|
|
72
|
+
mem_gb=mem_gb,
|
|
73
|
+
slurm_additional_parameters=slurm_additional_parameters,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
jobs = executor.map_array(func, jobs_list)
|
|
77
|
+
print("Job submitted")
|
|
78
|
+
|
|
79
|
+
if block:
|
|
80
|
+
print("Waiting for job to finish")
|
|
81
|
+
results = [job.result() for job in jobs]
|
|
82
|
+
print("All jobs finished")
|
|
83
|
+
return results
|
|
84
|
+
|
|
85
|
+
return jobs
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: resubmit
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: Small wrapper around submitit to simplify cluster submissions
|
|
5
|
+
Author: Amir Mehrpanah
|
|
6
|
+
License: MIT
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: submitit>=0.8
|
|
10
|
+
Provides-Extra: debug
|
|
11
|
+
Requires-Dist: debugpy; extra == "debug"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# resubmit
|
|
15
|
+
|
|
16
|
+
Small utility library to simplify job submission with Submitit on SLURM clusters.
|
|
17
|
+
|
|
18
|
+
Quick usage:
|
|
19
|
+
|
|
20
|
+
- Install locally for development:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install -e .[debug]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- Use in your project:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from resubmit import submit_jobs, maybe_attach_debugger
|
|
30
|
+
|
|
31
|
+
# attach remote debugger if requested
|
|
32
|
+
maybe_attach_debugger(args.get("port", None))
|
|
33
|
+
|
|
34
|
+
# submit jobs (list of dicts)
|
|
35
|
+
submit_jobs(jobs_list, my_entrypoint, timeout_min=60, block=True)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
### submit_jobs(...) 🔧
|
|
41
|
+
|
|
42
|
+
Submit multiple jobs to a Slurm cluster using Submitit.
|
|
43
|
+
|
|
44
|
+
Signature (short):
|
|
45
|
+
|
|
46
|
+
`submit_jobs(jobs_args: Iterable[dict], func: Callable[[List[dict]], Any], *, timeout_min: int, cpus_per_task: int = 16, mem_gb: int = 64, num_gpus: int = 1, account: Optional[str] = None, folder: str = "logs/%j", block: bool = False, prompt: bool = True, local_run: bool = False, slurm_additional_parameters: Optional[Dict] = None, constraint: Optional[str] = None, reservation: Optional[str] = None)`
|
|
47
|
+
|
|
48
|
+
- `jobs_args`: iterable of per-job kwargs (each item is passed to `func`).
|
|
49
|
+
- `func`: entrypoint called for each job (should accept a list or single job dict depending on your usage).
|
|
50
|
+
- `timeout_min`, `cpus_per_task`, `mem_gb`, `num_gpus`: common Slurm resources.
|
|
51
|
+
- `account`: optional Slurm account name.
|
|
52
|
+
- `folder`: logs folder for Submitit files (supports `%j` for job id).
|
|
53
|
+
- `block`: if True, waits for all jobs and returns results.
|
|
54
|
+
- `prompt`: if True, asks for confirmation interactively; set to `False` for CI or tests.
|
|
55
|
+
- `local_run`: run the jobs locally without Submitit (useful for debugging).
|
|
56
|
+
- `slurm_additional_parameters`: pass any extra Slurm key/value pairs to Submitit.
|
|
57
|
+
- `constraint` / `reservation`: cluster-specific options kept out of defaults — provide them explicitly if you need them (they take precedence over values in `slurm_additional_parameters`).
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
submit_jobs(
|
|
63
|
+
jobs_list,
|
|
64
|
+
my_entrypoint,
|
|
65
|
+
timeout_min=60,
|
|
66
|
+
num_gpus=2,
|
|
67
|
+
prompt=False,
|
|
68
|
+
constraint="gpu",
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### maybe_attach_debugger(port: Optional[int]) 🐞
|
|
73
|
+
|
|
74
|
+
Attach `debugpy` to the job when `port` is provided (> 0). Safe no-op if `port` is `None` or `<= 0`.
|
|
75
|
+
|
|
76
|
+
- If `debugpy` (and `submitit`) are not available on the node, a `RuntimeError` is raised with an explanatory message.
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
# attach remote debugger only when a port is provided (e.g., from CLI args)
|
|
82
|
+
maybe_attach_debugger(args.get("port"))
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
Tips:
|
|
88
|
+
- Use `prompt=False` when calling `submit_jobs` from scripts or CI to avoid interactive prompts.
|
|
89
|
+
- Tests demonstrate non-interactive behavior (`prompt=False`) and optional `constraint`/`reservation` handling.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/resubmit/__init__.py
|
|
5
|
+
src/resubmit/debug.py
|
|
6
|
+
src/resubmit/submit.py
|
|
7
|
+
src/resubmit.egg-info/PKG-INFO
|
|
8
|
+
src/resubmit.egg-info/SOURCES.txt
|
|
9
|
+
src/resubmit.egg-info/dependency_links.txt
|
|
10
|
+
src/resubmit.egg-info/requires.txt
|
|
11
|
+
src/resubmit.egg-info/top_level.txt
|
|
12
|
+
tests/test_resubmit.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
resubmit
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from resubmit import submit_jobs, maybe_attach_debugger
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def dummy_func(jobs):
|
|
6
|
+
# return a list of strings to show behavior
|
|
7
|
+
return [f"ok-{j['id']}" for j in jobs]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_submit_local_run():
|
|
11
|
+
jobs = [{"id": 1}, {"id": 2}]
|
|
12
|
+
res = submit_jobs(jobs, dummy_func, timeout_min=1, local_run=True)
|
|
13
|
+
assert res == ["ok-1", "ok-2"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_maybe_attach_debugger_noop():
|
|
17
|
+
# should not raise when port is None or 0
|
|
18
|
+
maybe_attach_debugger(None)
|
|
19
|
+
maybe_attach_debugger(0)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_slurm_parameters_optional(monkeypatch):
|
|
23
|
+
events = {}
|
|
24
|
+
|
|
25
|
+
class DummyExecutor:
|
|
26
|
+
def __init__(self, folder):
|
|
27
|
+
events['folder'] = folder
|
|
28
|
+
|
|
29
|
+
def update_parameters(self, **kwargs):
|
|
30
|
+
# capture the parameters passed to the executor
|
|
31
|
+
events['update'] = kwargs
|
|
32
|
+
|
|
33
|
+
def map_array(self, func, jobs_list):
|
|
34
|
+
return []
|
|
35
|
+
|
|
36
|
+
class DummyModule:
|
|
37
|
+
AutoExecutor = DummyExecutor
|
|
38
|
+
|
|
39
|
+
import sys
|
|
40
|
+
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
41
|
+
|
|
42
|
+
jobs = [{"id": 1}]
|
|
43
|
+
# default: no constraint/reservation keys
|
|
44
|
+
submit_jobs(jobs, dummy_func, timeout_min=1, local_run=False, num_gpus=2, prompt=False)
|
|
45
|
+
slurm = events['update']['slurm_additional_parameters']
|
|
46
|
+
assert slurm['gpus'] == 2
|
|
47
|
+
assert 'constraint' not in slurm
|
|
48
|
+
assert 'reservation' not in slurm
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_slurm_parameters_settable(monkeypatch):
|
|
52
|
+
events = {}
|
|
53
|
+
|
|
54
|
+
class DummyExecutor:
|
|
55
|
+
def __init__(self, folder):
|
|
56
|
+
events['folder'] = folder
|
|
57
|
+
|
|
58
|
+
def update_parameters(self, **kwargs):
|
|
59
|
+
events['update'] = kwargs
|
|
60
|
+
|
|
61
|
+
def map_array(self, func, jobs_list):
|
|
62
|
+
return []
|
|
63
|
+
|
|
64
|
+
class DummyModule:
|
|
65
|
+
AutoExecutor = DummyExecutor
|
|
66
|
+
|
|
67
|
+
import sys
|
|
68
|
+
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
69
|
+
|
|
70
|
+
jobs = [{"id": 1}]
|
|
71
|
+
submit_jobs(
|
|
72
|
+
jobs,
|
|
73
|
+
dummy_func,
|
|
74
|
+
timeout_min=1,
|
|
75
|
+
local_run=False,
|
|
76
|
+
constraint='thin',
|
|
77
|
+
reservation='safe',
|
|
78
|
+
prompt=False,
|
|
79
|
+
)
|
|
80
|
+
slurm = events['update']['slurm_additional_parameters']
|
|
81
|
+
assert slurm['constraint'] == 'thin'
|
|
82
|
+
assert slurm['reservation'] == 'safe'
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_slurm_parameters_arg_precedence(monkeypatch):
|
|
86
|
+
events = {}
|
|
87
|
+
|
|
88
|
+
class DummyExecutor:
|
|
89
|
+
def __init__(self, folder):
|
|
90
|
+
events['folder'] = folder
|
|
91
|
+
|
|
92
|
+
def update_parameters(self, **kwargs):
|
|
93
|
+
events['update'] = kwargs
|
|
94
|
+
|
|
95
|
+
def map_array(self, func, jobs_list):
|
|
96
|
+
return []
|
|
97
|
+
|
|
98
|
+
class DummyModule:
|
|
99
|
+
AutoExecutor = DummyExecutor
|
|
100
|
+
|
|
101
|
+
import sys
|
|
102
|
+
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
103
|
+
|
|
104
|
+
jobs = [{"id": 1}]
|
|
105
|
+
# slurm_additional_parameters has constraint='foo' but explicit arg should override
|
|
106
|
+
submit_jobs(
|
|
107
|
+
jobs,
|
|
108
|
+
dummy_func,
|
|
109
|
+
timeout_min=1,
|
|
110
|
+
local_run=False,
|
|
111
|
+
slurm_additional_parameters={'constraint': 'foo'},
|
|
112
|
+
constraint='bar',
|
|
113
|
+
prompt=False,
|
|
114
|
+
)
|
|
115
|
+
slurm = events['update']['slurm_additional_parameters']
|
|
116
|
+
assert slurm['constraint'] == 'bar'
|