resubmit 0.0.4__tar.gz → 0.0.6__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.4/src/resubmit.egg-info → resubmit-0.0.6}/PKG-INFO +1 -1
- {resubmit-0.0.4 → resubmit-0.0.6}/pyproject.toml +1 -1
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit/__bookkeeping.py +1 -27
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit/__submit.py +4 -8
- {resubmit-0.0.4 → resubmit-0.0.6/src/resubmit.egg-info}/PKG-INFO +1 -1
- {resubmit-0.0.4 → resubmit-0.0.6}/tests/test_bookkeeping.py +2 -2
- resubmit-0.0.6/tests/test_resubmit.py +115 -0
- resubmit-0.0.4/tests/test_resubmit.py +0 -117
- {resubmit-0.0.4 → resubmit-0.0.6}/LICENSE +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/README.md +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/setup.cfg +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit/__debug.py +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit/__init__.py +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit.egg-info/SOURCES.txt +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit.egg-info/dependency_links.txt +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit.egg-info/requires.txt +0 -0
- {resubmit-0.0.4 → resubmit-0.0.6}/src/resubmit.egg-info/top_level.txt +0 -0
|
@@ -5,27 +5,6 @@ from itertools import product
|
|
|
5
5
|
import logging
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def _is_regex_spec(val: Any) -> bool:
|
|
9
|
-
"""Return True if val looks like a regex specifier.
|
|
10
|
-
|
|
11
|
-
Accepted forms:
|
|
12
|
-
- compiled `re.Pattern`
|
|
13
|
-
- tuple (`re.Pattern`, exclude: bool)
|
|
14
|
-
- dict with keys `pattern` (re.Pattern) and optional `exclude` (bool)
|
|
15
|
-
- string starting with 're:' (e.g. 're:^foo.*') meaning include matches
|
|
16
|
-
- string starting with '!re:' meaning exclude matches
|
|
17
|
-
"""
|
|
18
|
-
if hasattr(val, "search") and callable(val.search):
|
|
19
|
-
return True
|
|
20
|
-
if isinstance(val, tuple) and len(val) >= 1 and hasattr(val[0], "search"):
|
|
21
|
-
return True
|
|
22
|
-
if isinstance(val, dict) and "pattern" in val:
|
|
23
|
-
return True
|
|
24
|
-
if isinstance(val, str) and (val.startswith("re:") or val.startswith("!re:")):
|
|
25
|
-
return True
|
|
26
|
-
return False
|
|
27
|
-
|
|
28
|
-
|
|
29
8
|
def _normalize_regex_spec(val: Any) -> Tuple[re.Pattern, bool]:
|
|
30
9
|
"""Return (compiled_pattern, exclude_flag) for a given regex spec.
|
|
31
10
|
|
|
@@ -115,11 +94,6 @@ def create_jobs_dataframe(params: Dict[str, Any]) -> pd.DataFrame:
|
|
|
115
94
|
base = k[: -len("_unique")]
|
|
116
95
|
unique_items[base] = v
|
|
117
96
|
continue
|
|
118
|
-
elif callable(v):
|
|
119
|
-
callables[k] = v
|
|
120
|
-
elif _is_regex_spec(v):
|
|
121
|
-
# treat a regex spec provided under the same key as a filter for that column
|
|
122
|
-
regex_specs[k] = v
|
|
123
97
|
else:
|
|
124
98
|
static_items[k] = v
|
|
125
99
|
|
|
@@ -206,7 +180,7 @@ def submit_jobs(
|
|
|
206
180
|
|
|
207
181
|
jobs_df = create_jobs_dataframe(jobs_args)
|
|
208
182
|
records = jobs_df.to_dict(orient="records")
|
|
209
|
-
from .__submit import
|
|
183
|
+
from .__submit import _submit_jobs
|
|
210
184
|
|
|
211
185
|
return _submit_jobs(
|
|
212
186
|
records,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from typing import Any, Callable, Iterable, List, Optional, Dict
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def
|
|
6
|
+
def _submit_jobs(
|
|
7
7
|
jobs_args: Iterable[dict],
|
|
8
8
|
func: Callable[[List[dict]], Any],
|
|
9
9
|
*,
|
|
@@ -15,6 +15,7 @@ def submit_jobs(
|
|
|
15
15
|
block: bool,
|
|
16
16
|
prompt: bool,
|
|
17
17
|
local_run: bool,
|
|
18
|
+
job_name: Optional[str] = "resubmit",
|
|
18
19
|
slurm_additional_parameters: Optional[Dict] = None,
|
|
19
20
|
):
|
|
20
21
|
"""Submit jobs described by `jobs_args` where each entry is a dict of kwargs for `func`.
|
|
@@ -48,18 +49,13 @@ def submit_jobs(
|
|
|
48
49
|
print("submitting jobs")
|
|
49
50
|
executor = submitit.AutoExecutor(folder=folder)
|
|
50
51
|
|
|
51
|
-
# default slurm params (keep cluster-specific options out unless explicitly set)
|
|
52
|
-
if slurm_additional_parameters is None:
|
|
53
|
-
slurm_additional_parameters = {"gpus": num_gpus}
|
|
54
|
-
else:
|
|
55
|
-
slurm_additional_parameters = dict(slurm_additional_parameters)
|
|
56
|
-
slurm_additional_parameters.setdefault("gpus", num_gpus)
|
|
57
|
-
|
|
58
52
|
print("Slurm additional parameters:", slurm_additional_parameters)
|
|
59
53
|
|
|
60
54
|
executor.update_parameters(
|
|
55
|
+
name=job_name,
|
|
61
56
|
timeout_min=timeout_min,
|
|
62
57
|
cpus_per_task=cpus_per_task,
|
|
58
|
+
gpus_per_node=num_gpus,
|
|
63
59
|
mem_gb=mem_gb,
|
|
64
60
|
slurm_additional_parameters=slurm_additional_parameters,
|
|
65
61
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import pandas as pd
|
|
3
|
-
from
|
|
3
|
+
from resubmit.__bookkeeping import create_jobs_dataframe, ensure_unique_combinations
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def test_create_jobs_basic():
|
|
@@ -11,7 +11,7 @@ def test_create_jobs_basic():
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def test_create_jobs_callable():
|
|
14
|
-
params = {"a": [1, 2], "
|
|
14
|
+
params = {"a": [1, 2], "b__callable": lambda df: df["a"] * 10}
|
|
15
15
|
df = create_jobs_dataframe(params)
|
|
16
16
|
assert list(df["b"]) == [10, 20]
|
|
17
17
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from resubmit import maybe_attach_debugger
|
|
3
|
+
from resubmit.__submit import _submit_jobs
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def dummy_func(jobs):
|
|
7
|
+
# return a list of strings to show behavior
|
|
8
|
+
return [f"ok-{j['id']}" for j in jobs]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_submit_local_run():
|
|
12
|
+
jobs = [{"id": 1}, {"id": 2}]
|
|
13
|
+
res = _submit_jobs(
|
|
14
|
+
jobs,
|
|
15
|
+
dummy_func,
|
|
16
|
+
timeout_min=1,
|
|
17
|
+
local_run=True,
|
|
18
|
+
num_gpus=0,
|
|
19
|
+
cpus_per_task=1,
|
|
20
|
+
mem_gb=8,
|
|
21
|
+
folder="dummy/%j",
|
|
22
|
+
block=False,
|
|
23
|
+
prompt=False,
|
|
24
|
+
)
|
|
25
|
+
assert res == ["ok-1", "ok-2"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_maybe_attach_debugger_noop():
|
|
29
|
+
# should not raise when port is None or 0
|
|
30
|
+
maybe_attach_debugger(None)
|
|
31
|
+
maybe_attach_debugger(0)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_slurm_parameters_optional(monkeypatch):
|
|
35
|
+
events = {}
|
|
36
|
+
|
|
37
|
+
class DummyExecutor:
|
|
38
|
+
def __init__(self, folder):
|
|
39
|
+
events["folder"] = folder
|
|
40
|
+
|
|
41
|
+
def update_parameters(self, **kwargs):
|
|
42
|
+
# capture the parameters passed to the executor
|
|
43
|
+
events["update"] = kwargs
|
|
44
|
+
|
|
45
|
+
def map_array(self, func, jobs_list):
|
|
46
|
+
return []
|
|
47
|
+
|
|
48
|
+
class DummyModule:
|
|
49
|
+
AutoExecutor = DummyExecutor
|
|
50
|
+
|
|
51
|
+
import sys
|
|
52
|
+
|
|
53
|
+
monkeypatch.setitem(sys.modules, "submitit", DummyModule)
|
|
54
|
+
|
|
55
|
+
jobs = [{"id": 1}]
|
|
56
|
+
# default: no constraint/reservation keys
|
|
57
|
+
_submit_jobs(
|
|
58
|
+
jobs,
|
|
59
|
+
dummy_func,
|
|
60
|
+
timeout_min=1,
|
|
61
|
+
local_run=False,
|
|
62
|
+
num_gpus=2,
|
|
63
|
+
prompt=False,
|
|
64
|
+
cpus_per_task=4,
|
|
65
|
+
mem_gb=16,
|
|
66
|
+
folder="logs/%j",
|
|
67
|
+
block=False,
|
|
68
|
+
)
|
|
69
|
+
slurm = events["update"]["slurm_additional_parameters"]
|
|
70
|
+
assert slurm["gpus"] == 2
|
|
71
|
+
assert "constraint" not in slurm
|
|
72
|
+
assert "reservation" not in slurm
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_slurm_parameters_settable(monkeypatch):
|
|
76
|
+
events = {}
|
|
77
|
+
|
|
78
|
+
class DummyExecutor:
|
|
79
|
+
def __init__(self, folder):
|
|
80
|
+
events["folder"] = folder
|
|
81
|
+
|
|
82
|
+
def update_parameters(self, **kwargs):
|
|
83
|
+
events["update"] = kwargs
|
|
84
|
+
|
|
85
|
+
def map_array(self, func, jobs_list):
|
|
86
|
+
return []
|
|
87
|
+
|
|
88
|
+
class DummyModule:
|
|
89
|
+
AutoExecutor = DummyExecutor
|
|
90
|
+
|
|
91
|
+
import sys
|
|
92
|
+
|
|
93
|
+
monkeypatch.setitem(sys.modules, "submitit", DummyModule)
|
|
94
|
+
|
|
95
|
+
jobs = [{"id": 1}]
|
|
96
|
+
_submit_jobs(
|
|
97
|
+
jobs,
|
|
98
|
+
dummy_func,
|
|
99
|
+
timeout_min=1,
|
|
100
|
+
local_run=False,
|
|
101
|
+
prompt=False,
|
|
102
|
+
slurm_additional_parameters={
|
|
103
|
+
"constraint": "thin",
|
|
104
|
+
"reservation": "safe",
|
|
105
|
+
},
|
|
106
|
+
cpus_per_task=4,
|
|
107
|
+
mem_gb=16,
|
|
108
|
+
folder="logs/%j",
|
|
109
|
+
block=False,
|
|
110
|
+
num_gpus=1,
|
|
111
|
+
)
|
|
112
|
+
slurm = events["update"]["slurm_additional_parameters"]
|
|
113
|
+
assert slurm["constraint"] == "thin"
|
|
114
|
+
assert slurm["reservation"] == "safe"
|
|
115
|
+
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from resubmit import maybe_attach_debugger
|
|
3
|
-
from resubmit.__submit import submit_jobs
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def dummy_func(jobs):
|
|
7
|
-
# return a list of strings to show behavior
|
|
8
|
-
return [f"ok-{j['id']}" for j in jobs]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def test_submit_local_run():
|
|
12
|
-
jobs = [{"id": 1}, {"id": 2}]
|
|
13
|
-
res = submit_jobs(jobs, dummy_func, timeout_min=1, local_run=True)
|
|
14
|
-
assert res == ["ok-1", "ok-2"]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_maybe_attach_debugger_noop():
|
|
18
|
-
# should not raise when port is None or 0
|
|
19
|
-
maybe_attach_debugger(None)
|
|
20
|
-
maybe_attach_debugger(0)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_slurm_parameters_optional(monkeypatch):
|
|
24
|
-
events = {}
|
|
25
|
-
|
|
26
|
-
class DummyExecutor:
|
|
27
|
-
def __init__(self, folder):
|
|
28
|
-
events['folder'] = folder
|
|
29
|
-
|
|
30
|
-
def update_parameters(self, **kwargs):
|
|
31
|
-
# capture the parameters passed to the executor
|
|
32
|
-
events['update'] = kwargs
|
|
33
|
-
|
|
34
|
-
def map_array(self, func, jobs_list):
|
|
35
|
-
return []
|
|
36
|
-
|
|
37
|
-
class DummyModule:
|
|
38
|
-
AutoExecutor = DummyExecutor
|
|
39
|
-
|
|
40
|
-
import sys
|
|
41
|
-
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
42
|
-
|
|
43
|
-
jobs = [{"id": 1}]
|
|
44
|
-
# default: no constraint/reservation keys
|
|
45
|
-
submit_jobs(jobs, dummy_func, timeout_min=1, local_run=False, num_gpus=2, prompt=False)
|
|
46
|
-
slurm = events['update']['slurm_additional_parameters']
|
|
47
|
-
assert slurm['gpus'] == 2
|
|
48
|
-
assert 'constraint' not in slurm
|
|
49
|
-
assert 'reservation' not in slurm
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def test_slurm_parameters_settable(monkeypatch):
|
|
53
|
-
events = {}
|
|
54
|
-
|
|
55
|
-
class DummyExecutor:
|
|
56
|
-
def __init__(self, folder):
|
|
57
|
-
events['folder'] = folder
|
|
58
|
-
|
|
59
|
-
def update_parameters(self, **kwargs):
|
|
60
|
-
events['update'] = kwargs
|
|
61
|
-
|
|
62
|
-
def map_array(self, func, jobs_list):
|
|
63
|
-
return []
|
|
64
|
-
|
|
65
|
-
class DummyModule:
|
|
66
|
-
AutoExecutor = DummyExecutor
|
|
67
|
-
|
|
68
|
-
import sys
|
|
69
|
-
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
70
|
-
|
|
71
|
-
jobs = [{"id": 1}]
|
|
72
|
-
submit_jobs(
|
|
73
|
-
jobs,
|
|
74
|
-
dummy_func,
|
|
75
|
-
timeout_min=1,
|
|
76
|
-
local_run=False,
|
|
77
|
-
constraint='thin',
|
|
78
|
-
reservation='safe',
|
|
79
|
-
prompt=False,
|
|
80
|
-
)
|
|
81
|
-
slurm = events['update']['slurm_additional_parameters']
|
|
82
|
-
assert slurm['constraint'] == 'thin'
|
|
83
|
-
assert slurm['reservation'] == 'safe'
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def test_slurm_parameters_arg_precedence(monkeypatch):
|
|
87
|
-
events = {}
|
|
88
|
-
|
|
89
|
-
class DummyExecutor:
|
|
90
|
-
def __init__(self, folder):
|
|
91
|
-
events['folder'] = folder
|
|
92
|
-
|
|
93
|
-
def update_parameters(self, **kwargs):
|
|
94
|
-
events['update'] = kwargs
|
|
95
|
-
|
|
96
|
-
def map_array(self, func, jobs_list):
|
|
97
|
-
return []
|
|
98
|
-
|
|
99
|
-
class DummyModule:
|
|
100
|
-
AutoExecutor = DummyExecutor
|
|
101
|
-
|
|
102
|
-
import sys
|
|
103
|
-
monkeypatch.setitem(sys.modules, 'submitit', DummyModule)
|
|
104
|
-
|
|
105
|
-
jobs = [{"id": 1}]
|
|
106
|
-
# slurm_additional_parameters has constraint='foo' but explicit arg should override
|
|
107
|
-
submit_jobs(
|
|
108
|
-
jobs,
|
|
109
|
-
dummy_func,
|
|
110
|
-
timeout_min=1,
|
|
111
|
-
local_run=False,
|
|
112
|
-
slurm_additional_parameters={'constraint': 'foo'},
|
|
113
|
-
constraint='bar',
|
|
114
|
-
prompt=False,
|
|
115
|
-
)
|
|
116
|
-
slurm = events['update']['slurm_additional_parameters']
|
|
117
|
-
assert slurm['constraint'] == 'bar'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|