cmd-queue 0.1.19__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
Potentially problematic release.
This version of cmd-queue might be problematic. Click here for more details.
- cmd_queue/__init__.py +1 -1
- cmd_queue/__main__.pyi +3 -0
- cmd_queue/airflow_queue.pyi +84 -0
- cmd_queue/base_queue.py +5 -0
- cmd_queue/base_queue.pyi +86 -0
- cmd_queue/cli_boilerplate.pyi +32 -0
- cmd_queue/main.py +4 -1
- cmd_queue/main.pyi +66 -0
- cmd_queue/monitor_app.pyi +41 -0
- cmd_queue/py.typed +0 -0
- cmd_queue/serial_queue.pyi +124 -0
- cmd_queue/slurm_queue.py +37 -8
- cmd_queue/slurm_queue.pyi +97 -0
- cmd_queue/tmux_queue.py +20 -0
- cmd_queue/tmux_queue.pyi +93 -0
- cmd_queue/util/richer.pyi +14 -0
- cmd_queue/util/texter.pyi +14 -0
- cmd_queue/util/textual_extensions.pyi +62 -0
- cmd_queue/util/util_algo.pyi +7 -0
- cmd_queue/util/util_network_text.pyi +89 -0
- cmd_queue/util/util_networkx.pyi +7 -0
- cmd_queue/util/util_tags.pyi +8 -0
- cmd_queue/util/util_tmux.pyi +13 -0
- cmd_queue/util/util_yaml.pyi +43 -0
- {cmd_queue-0.1.19.dist-info → cmd_queue-0.2.0.dist-info}/METADATA +247 -183
- cmd_queue-0.2.0.dist-info/RECORD +45 -0
- {cmd_queue-0.1.19.dist-info → cmd_queue-0.2.0.dist-info}/WHEEL +1 -1
- {cmd_queue-0.1.19.dist-info → cmd_queue-0.2.0.dist-info}/entry_points.txt +0 -1
- cmd_queue-0.1.19.dist-info/RECORD +0 -26
- {cmd_queue-0.1.19.dist-info → cmd_queue-0.2.0.dist-info}/LICENSE +0 -0
- {cmd_queue-0.1.19.dist-info → cmd_queue-0.2.0.dist-info}/top_level.txt +0 -0
cmd_queue/__init__.py
CHANGED
cmd_queue/__main__.pyi
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from cmd_queue import base_queue
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AirflowJob(base_queue.Job):
|
|
6
|
+
unused_kwargs: Incomplete
|
|
7
|
+
command: Incomplete
|
|
8
|
+
name: Incomplete
|
|
9
|
+
output_fpath: Incomplete
|
|
10
|
+
depends: Incomplete
|
|
11
|
+
cpus: Incomplete
|
|
12
|
+
gpus: Incomplete
|
|
13
|
+
mem: Incomplete
|
|
14
|
+
begin: Incomplete
|
|
15
|
+
shell: Incomplete
|
|
16
|
+
|
|
17
|
+
def __init__(self,
|
|
18
|
+
command,
|
|
19
|
+
name: Incomplete | None = ...,
|
|
20
|
+
output_fpath: Incomplete | None = ...,
|
|
21
|
+
depends: Incomplete | None = ...,
|
|
22
|
+
partition: Incomplete | None = ...,
|
|
23
|
+
cpus: Incomplete | None = ...,
|
|
24
|
+
gpus: Incomplete | None = ...,
|
|
25
|
+
mem: Incomplete | None = ...,
|
|
26
|
+
begin: Incomplete | None = ...,
|
|
27
|
+
shell: Incomplete | None = ...,
|
|
28
|
+
**kwargs) -> None:
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
def __nice__(self):
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
def finalize_text(self):
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AirflowQueue(base_queue.Queue):
|
|
39
|
+
jobs: Incomplete
|
|
40
|
+
name: Incomplete
|
|
41
|
+
unused_kwargs: Incomplete
|
|
42
|
+
queue_id: Incomplete
|
|
43
|
+
dpath: Incomplete
|
|
44
|
+
log_dpath: Incomplete
|
|
45
|
+
fpath: Incomplete
|
|
46
|
+
shell: Incomplete
|
|
47
|
+
header_commands: Incomplete
|
|
48
|
+
all_depends: Incomplete
|
|
49
|
+
|
|
50
|
+
def __init__(self,
|
|
51
|
+
name: Incomplete | None = ...,
|
|
52
|
+
shell: Incomplete | None = ...,
|
|
53
|
+
**kwargs) -> None:
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def is_available(cls):
|
|
58
|
+
...
|
|
59
|
+
|
|
60
|
+
def run(self, block: bool = ..., system: bool = ...) -> None:
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def finalize_text(self):
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
def submit(self, command, **kwargs):
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
def print_commands(self,
|
|
70
|
+
with_status: bool = ...,
|
|
71
|
+
with_gaurds: bool = ...,
|
|
72
|
+
with_locks: int = ...,
|
|
73
|
+
exclude_tags: Incomplete | None = ...,
|
|
74
|
+
style: str = ...,
|
|
75
|
+
with_rich: Incomplete | None = ...,
|
|
76
|
+
colors: int = ...,
|
|
77
|
+
**kwargs) -> None:
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
rprint = print_commands
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def demo() -> None:
|
|
84
|
+
...
|
cmd_queue/base_queue.py
CHANGED
|
@@ -135,6 +135,11 @@ class Queue(ub.NiceRepr):
|
|
|
135
135
|
name = kwargs.get('name', None)
|
|
136
136
|
if name is None:
|
|
137
137
|
name = kwargs['name'] = self.name + '-job-{}'.format(self.num_real_jobs)
|
|
138
|
+
|
|
139
|
+
# TODO: make sure name is path safe.
|
|
140
|
+
if ':' in name:
|
|
141
|
+
raise ValueError('Name must be path-safe')
|
|
142
|
+
|
|
138
143
|
if self.all_depends:
|
|
139
144
|
depends = kwargs.get('depends', None)
|
|
140
145
|
if depends is None:
|
cmd_queue/base_queue.pyi
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
import ubelt as ub
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DuplicateJobError(KeyError):
|
|
7
|
+
...
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class UnknownBackendError(KeyError):
|
|
11
|
+
...
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Job(ub.NiceRepr):
|
|
15
|
+
name: Incomplete
|
|
16
|
+
command: Incomplete
|
|
17
|
+
depends: Incomplete
|
|
18
|
+
kwargs: Incomplete
|
|
19
|
+
|
|
20
|
+
def __init__(self,
|
|
21
|
+
command: Incomplete | None = ...,
|
|
22
|
+
name: Incomplete | None = ...,
|
|
23
|
+
depends: Incomplete | None = ...,
|
|
24
|
+
**kwargs) -> None:
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
def __nice__(self):
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Queue(ub.NiceRepr):
|
|
32
|
+
num_real_jobs: int
|
|
33
|
+
all_depends: Incomplete
|
|
34
|
+
named_jobs: Incomplete
|
|
35
|
+
|
|
36
|
+
def __init__(self) -> None:
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
def change_backend(self, backend, **kwargs):
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def __len__(self):
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
def sync(self) -> Queue:
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
def write(self):
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
def submit(self, command, **kwargs):
|
|
52
|
+
...
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def available_backends(cls):
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def create(cls, backend: str = ..., **kwargs):
|
|
60
|
+
...
|
|
61
|
+
|
|
62
|
+
def write_network_text(self,
|
|
63
|
+
reduced: bool = ...,
|
|
64
|
+
rich: str = ...,
|
|
65
|
+
vertical_chains: bool = ...) -> None:
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
def print_commands(self,
|
|
69
|
+
with_status: bool = False,
|
|
70
|
+
with_gaurds: bool = False,
|
|
71
|
+
with_locks: bool | int = 1,
|
|
72
|
+
exclude_tags: List[str] | None = None,
|
|
73
|
+
style: str = 'colors',
|
|
74
|
+
**kwargs) -> None:
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
def rprint(self, **kwargs) -> None:
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
def print_graph(self,
|
|
81
|
+
reduced: bool = True,
|
|
82
|
+
vertical_chains: bool = ...) -> None:
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
def monitor(self) -> None:
|
|
86
|
+
...
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
import scriptconfig as scfg
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
|
|
5
|
+
import cmd_queue
|
|
6
|
+
|
|
7
|
+
__docstubs__: str
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CMDQueueConfig(scfg.DataConfig):
|
|
11
|
+
run: Incomplete
|
|
12
|
+
backend: Incomplete
|
|
13
|
+
queue_name: Incomplete
|
|
14
|
+
print_commands: Incomplete
|
|
15
|
+
print_queue: Incomplete
|
|
16
|
+
with_textual: Incomplete
|
|
17
|
+
other_session_handler: Incomplete
|
|
18
|
+
virtualenv_cmd: Incomplete
|
|
19
|
+
tmux_workers: Incomplete
|
|
20
|
+
slurm_options: Incomplete
|
|
21
|
+
|
|
22
|
+
def __post_init__(self) -> None:
|
|
23
|
+
...
|
|
24
|
+
|
|
25
|
+
def create_queue(config, **kwargs) -> cmd_queue.Queue:
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
def run_queue(config,
|
|
29
|
+
queue: cmd_queue.Queue,
|
|
30
|
+
print_kwargs: None | Dict = None,
|
|
31
|
+
**kwargs) -> None:
|
|
32
|
+
...
|
cmd_queue/main.py
CHANGED
|
@@ -94,12 +94,15 @@ class CommonShowRun(CommonConfig):
|
|
|
94
94
|
|
|
95
95
|
backend = scfg.Value('tmux', help='the execution backend to use', choices=['tmux', 'slurm', 'serial', 'airflow'])
|
|
96
96
|
|
|
97
|
+
gpus = scfg.Value(None, help='a comma separated list of the gpu numbers to spread across. tmux backend only.')
|
|
98
|
+
|
|
97
99
|
def _build_queue(config):
|
|
98
100
|
import cmd_queue
|
|
99
101
|
import json
|
|
100
102
|
queue = cmd_queue.Queue.create(size=max(1, config['workers']),
|
|
101
103
|
backend=config['backend'],
|
|
102
|
-
name=config['qname']
|
|
104
|
+
name=config['qname'],
|
|
105
|
+
gpus=config['gpus'])
|
|
103
106
|
# Run a new CLI queue
|
|
104
107
|
data = json.loads(config.cli_queue_fpath.read_text())
|
|
105
108
|
print('data = {}'.format(ub.urepr(data, nl=1)))
|
cmd_queue/main.pyi
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import scriptconfig as scfg
|
|
2
|
+
from _typeshed import Incomplete
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CommonConfig(scfg.DataConfig):
|
|
6
|
+
qname: Incomplete
|
|
7
|
+
dpath: Incomplete
|
|
8
|
+
|
|
9
|
+
def __post_init__(config) -> None:
|
|
10
|
+
...
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def main(cls, cmdline: int = ..., **kwargs) -> None:
|
|
14
|
+
...
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CommonShowRun(CommonConfig):
|
|
18
|
+
workers: Incomplete
|
|
19
|
+
backend: Incomplete
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CmdQueueCLI(scfg.ModalCLI):
|
|
23
|
+
|
|
24
|
+
class cleanup(CommonConfig):
|
|
25
|
+
yes: Incomplete
|
|
26
|
+
__command__: str
|
|
27
|
+
|
|
28
|
+
def run(config) -> None:
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
class run(CommonShowRun):
|
|
32
|
+
__command__: str
|
|
33
|
+
|
|
34
|
+
def run(config) -> None:
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
class show(CommonShowRun):
|
|
38
|
+
__command__: str
|
|
39
|
+
|
|
40
|
+
def run(config) -> None:
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
class submit(CommonConfig):
|
|
44
|
+
jobname: Incomplete
|
|
45
|
+
depends: Incomplete
|
|
46
|
+
command: Incomplete
|
|
47
|
+
__command__: str
|
|
48
|
+
|
|
49
|
+
def run(config) -> None:
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
class new(CommonConfig):
|
|
53
|
+
__command__: str
|
|
54
|
+
header: Incomplete
|
|
55
|
+
|
|
56
|
+
def run(config) -> None:
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
class list(CommonConfig):
|
|
60
|
+
__command__: str
|
|
61
|
+
|
|
62
|
+
def run(config) -> None:
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
main: Incomplete
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from cmd_queue.util.textual_extensions import InstanceRunnableApp
|
|
3
|
+
from textual.widget import Widget
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class JobTable(Widget):
|
|
7
|
+
table_fn: Incomplete
|
|
8
|
+
|
|
9
|
+
def __init__(self, table_fn: Incomplete | None = ..., **kwargs) -> None:
|
|
10
|
+
...
|
|
11
|
+
|
|
12
|
+
def on_mount(self) -> None:
|
|
13
|
+
...
|
|
14
|
+
|
|
15
|
+
def render(self):
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CmdQueueMonitorApp(InstanceRunnableApp):
|
|
20
|
+
job_table: Incomplete
|
|
21
|
+
kill_fn: Incomplete
|
|
22
|
+
graceful_exit: bool
|
|
23
|
+
|
|
24
|
+
def __init__(self,
|
|
25
|
+
table_fn,
|
|
26
|
+
kill_fn: Incomplete | None = ...,
|
|
27
|
+
**kwargs) -> None:
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def demo(CmdQueueMonitorApp):
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
async def on_load(self, event) -> None:
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
async def action_quit(self) -> None:
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
async def on_mount(self, event) -> None:
|
|
41
|
+
...
|
cmd_queue/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
from os import PathLike
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from cmd_queue import base_queue
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def indent(text: str, prefix: str = ' '):
|
|
8
|
+
...
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BashJob(base_queue.Job):
|
|
12
|
+
name: str
|
|
13
|
+
pathid: str
|
|
14
|
+
command: str
|
|
15
|
+
depends: List[BashJob] | None
|
|
16
|
+
bookkeeper: bool
|
|
17
|
+
info_dpath: PathLike | None
|
|
18
|
+
log: bool
|
|
19
|
+
tags: List[str] | str | None
|
|
20
|
+
allow_indent: bool
|
|
21
|
+
kwargs: Incomplete
|
|
22
|
+
pass_fpath: Incomplete
|
|
23
|
+
fail_fpath: Incomplete
|
|
24
|
+
stat_fpath: Incomplete
|
|
25
|
+
log_fpath: Incomplete
|
|
26
|
+
|
|
27
|
+
def __init__(self,
|
|
28
|
+
command,
|
|
29
|
+
name: Incomplete | None = ...,
|
|
30
|
+
depends: Incomplete | None = ...,
|
|
31
|
+
gpus: Incomplete | None = ...,
|
|
32
|
+
cpus: Incomplete | None = ...,
|
|
33
|
+
mem: Incomplete | None = ...,
|
|
34
|
+
bookkeeper: int = ...,
|
|
35
|
+
info_dpath: Incomplete | None = ...,
|
|
36
|
+
log: bool = ...,
|
|
37
|
+
tags: Incomplete | None = ...,
|
|
38
|
+
allow_indent: bool = ...,
|
|
39
|
+
**kwargs) -> None:
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def finalize_text(self,
|
|
43
|
+
with_status: bool = ...,
|
|
44
|
+
with_gaurds: bool = ...,
|
|
45
|
+
conditionals: Incomplete | None = ...,
|
|
46
|
+
**kwargs):
|
|
47
|
+
...
|
|
48
|
+
|
|
49
|
+
def print_commands(self,
|
|
50
|
+
with_status: bool = False,
|
|
51
|
+
with_gaurds: bool = False,
|
|
52
|
+
with_rich: Incomplete | None = ...,
|
|
53
|
+
style: str = 'colors',
|
|
54
|
+
**kwargs) -> None:
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SerialQueue(base_queue.Queue):
|
|
59
|
+
name: Incomplete
|
|
60
|
+
rootid: Incomplete
|
|
61
|
+
dpath: Incomplete
|
|
62
|
+
unused_kwargs: Incomplete
|
|
63
|
+
fpath: Incomplete
|
|
64
|
+
state_fpath: Incomplete
|
|
65
|
+
environ: Incomplete
|
|
66
|
+
header: str
|
|
67
|
+
header_commands: Incomplete
|
|
68
|
+
jobs: Incomplete
|
|
69
|
+
cwd: Incomplete
|
|
70
|
+
job_info_dpath: Incomplete
|
|
71
|
+
|
|
72
|
+
def __init__(self,
|
|
73
|
+
name: str = ...,
|
|
74
|
+
dpath: Incomplete | None = ...,
|
|
75
|
+
rootid: Incomplete | None = ...,
|
|
76
|
+
environ: Incomplete | None = ...,
|
|
77
|
+
cwd: Incomplete | None = ...,
|
|
78
|
+
**kwargs) -> None:
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def pathid(self):
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
def __nice__(self):
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def is_available(cls):
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
def order_jobs(self) -> None:
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
def finalize_text(self,
|
|
96
|
+
with_status: bool = ...,
|
|
97
|
+
with_gaurds: bool = ...,
|
|
98
|
+
with_locks: bool = ...,
|
|
99
|
+
exclude_tags: Incomplete | None = ...):
|
|
100
|
+
...
|
|
101
|
+
|
|
102
|
+
def add_header_command(self, command) -> None:
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
def print_commands(self, *args, **kwargs):
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
rprint = print_commands
|
|
109
|
+
|
|
110
|
+
def run(self,
|
|
111
|
+
block: bool = ...,
|
|
112
|
+
system: bool = ...,
|
|
113
|
+
shell: int = ...,
|
|
114
|
+
capture: bool = ...,
|
|
115
|
+
mode: str = ...,
|
|
116
|
+
verbose: int = ...,
|
|
117
|
+
**kw) -> None:
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def job_details(self) -> None:
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
def read_state(self):
|
|
124
|
+
...
|
cmd_queue/slurm_queue.py
CHANGED
|
@@ -41,23 +41,51 @@ from cmd_queue import base_queue # NOQA
|
|
|
41
41
|
from cmd_queue.util import util_tags
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
try:
|
|
45
|
+
from functools import cache # Python 3.9+ only
|
|
46
|
+
except ImportError:
|
|
47
|
+
from ubelt import memoize as cache
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@cache
|
|
51
|
+
def _unit_registery():
|
|
52
|
+
import sys
|
|
53
|
+
if sys.version_info[0:2] == (3, 9):
|
|
54
|
+
# backwards compatability support for numpy 2.0 and pint on cp39
|
|
55
|
+
try:
|
|
56
|
+
import numpy as np
|
|
57
|
+
except ImportError:
|
|
58
|
+
...
|
|
59
|
+
else:
|
|
60
|
+
if not np.__version__.startswith('1.'):
|
|
61
|
+
np.cumproduct = np.cumprod
|
|
62
|
+
import pint
|
|
63
|
+
reg = pint.UnitRegistry()
|
|
64
|
+
return reg
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _coerce_mem_megabytes(mem):
|
|
45
68
|
"""
|
|
69
|
+
Transform input into an integer representing amount of megabytes.
|
|
70
|
+
|
|
46
71
|
Args:
|
|
47
72
|
mem (int | str): integer number of megabytes or a parseable string
|
|
48
73
|
|
|
74
|
+
Returns:
|
|
75
|
+
int: number of megabytes
|
|
76
|
+
|
|
49
77
|
Example:
|
|
78
|
+
>>> # xdoctest: +REQUIRES(module:pint)
|
|
50
79
|
>>> from cmd_queue.slurm_queue import * # NOQA
|
|
51
|
-
>>> print(
|
|
52
|
-
>>> print(
|
|
53
|
-
>>> print(
|
|
54
|
-
>>> print(
|
|
80
|
+
>>> print(_coerce_mem_megabytes(30602))
|
|
81
|
+
>>> print(_coerce_mem_megabytes('4GB'))
|
|
82
|
+
>>> print(_coerce_mem_megabytes('32GB'))
|
|
83
|
+
>>> print(_coerce_mem_megabytes('300000000 bytes'))
|
|
55
84
|
"""
|
|
56
85
|
if isinstance(mem, int):
|
|
57
86
|
assert mem > 0
|
|
58
87
|
elif isinstance(mem, str):
|
|
59
|
-
|
|
60
|
-
reg = pint.UnitRegistry()
|
|
88
|
+
reg = _unit_registery()
|
|
61
89
|
mem = reg.parse_expression(mem)
|
|
62
90
|
mem = int(mem.to('megabytes').m)
|
|
63
91
|
else:
|
|
@@ -190,6 +218,7 @@ class SlurmJob(base_queue.Job):
|
|
|
190
218
|
Represents a slurm job that hasn't been submitted yet
|
|
191
219
|
|
|
192
220
|
Example:
|
|
221
|
+
>>> # xdoctest: +REQUIRES(module:pint)
|
|
193
222
|
>>> from cmd_queue.slurm_queue import * # NOQA
|
|
194
223
|
>>> self = SlurmJob('python -c print("hello world")', 'hi', cpus=5, gpus=1, mem='10GB')
|
|
195
224
|
>>> command = self._build_sbatch_args()
|
|
@@ -245,7 +274,7 @@ class SlurmJob(base_queue.Job):
|
|
|
245
274
|
if self.cpus:
|
|
246
275
|
sbatch_args.append(f'--cpus-per-task={self.cpus}')
|
|
247
276
|
if self.mem:
|
|
248
|
-
mem =
|
|
277
|
+
mem = _coerce_mem_megabytes(self.mem)
|
|
249
278
|
sbatch_args.append(f'--mem={mem}')
|
|
250
279
|
if self.gpus and 'gres' not in self._sbatch_kvargs:
|
|
251
280
|
ub.schedule_deprecation(
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from cmd_queue import base_queue
|
|
3
|
+
|
|
4
|
+
__dev__: str
|
|
5
|
+
SLURM_SBATCH_KVARGS: Incomplete
|
|
6
|
+
SLURM_SBATCH_FLAGS: Incomplete
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SlurmJob(base_queue.Job):
|
|
10
|
+
unused_kwargs: Incomplete
|
|
11
|
+
command: Incomplete
|
|
12
|
+
name: Incomplete
|
|
13
|
+
output_fpath: Incomplete
|
|
14
|
+
depends: Incomplete
|
|
15
|
+
cpus: Incomplete
|
|
16
|
+
gpus: Incomplete
|
|
17
|
+
mem: Incomplete
|
|
18
|
+
begin: Incomplete
|
|
19
|
+
shell: Incomplete
|
|
20
|
+
tags: Incomplete
|
|
21
|
+
jobid: Incomplete
|
|
22
|
+
|
|
23
|
+
def __init__(self,
|
|
24
|
+
command,
|
|
25
|
+
name: Incomplete | None = ...,
|
|
26
|
+
output_fpath: Incomplete | None = ...,
|
|
27
|
+
depends: Incomplete | None = ...,
|
|
28
|
+
cpus: Incomplete | None = ...,
|
|
29
|
+
gpus: Incomplete | None = ...,
|
|
30
|
+
mem: Incomplete | None = ...,
|
|
31
|
+
begin: Incomplete | None = ...,
|
|
32
|
+
shell: Incomplete | None = ...,
|
|
33
|
+
tags: Incomplete | None = ...,
|
|
34
|
+
**kwargs) -> None:
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
def __nice__(self):
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SlurmQueue(base_queue.Queue):
|
|
42
|
+
jobs: Incomplete
|
|
43
|
+
unused_kwargs: Incomplete
|
|
44
|
+
queue_id: Incomplete
|
|
45
|
+
dpath: Incomplete
|
|
46
|
+
log_dpath: Incomplete
|
|
47
|
+
fpath: Incomplete
|
|
48
|
+
shell: Incomplete
|
|
49
|
+
header_commands: Incomplete
|
|
50
|
+
all_depends: Incomplete
|
|
51
|
+
|
|
52
|
+
def __init__(self,
|
|
53
|
+
name: Incomplete | None = ...,
|
|
54
|
+
shell: Incomplete | None = ...,
|
|
55
|
+
**kwargs) -> None:
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def __nice__(self):
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def is_available(cls):
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
def submit(self, command, **kwargs):
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
def add_header_command(self, command) -> None:
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
def order_jobs(self):
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
jobname_to_varname: Incomplete
|
|
75
|
+
|
|
76
|
+
def finalize_text(self, exclude_tags: Incomplete | None = ..., **kwargs):
|
|
77
|
+
...
|
|
78
|
+
|
|
79
|
+
def run(self, block: bool = ..., system: bool = ..., **kw):
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
def monitor(self, refresh_rate: float = ...):
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
def kill(self) -> None:
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
def read_state(self):
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
def print_commands(self, *args, **kwargs):
|
|
92
|
+
...
|
|
93
|
+
|
|
94
|
+
rprint = print_commands
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
SLURM_NOTES: str
|
cmd_queue/tmux_queue.py
CHANGED
|
@@ -1055,4 +1055,24 @@ if 0:
|
|
|
1055
1055
|
tmux kill-session -t my_session_id
|
|
1056
1056
|
|
|
1057
1057
|
tmux new-session -d -s my_session_id -e "MYVAR1" -- "bash"
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
#### to start a tmux session with 4 panes
|
|
1062
|
+
tmux new-session -d -s my_session_id1 "bash"
|
|
1063
|
+
tmux send -t my_session_id1 "tmux split-window -h -t 0" Enter
|
|
1064
|
+
tmux send -t my_session_id1 "tmux split-window -v -t 0" Enter
|
|
1065
|
+
tmux send -t my_session_id1 "tmux split-window -v -t 2" Enter
|
|
1066
|
+
|
|
1067
|
+
# Now send a command to each pane
|
|
1068
|
+
tmux send -t my_session_id1 "tmux select-pane -t 0" Enter
|
|
1069
|
+
tmux send -t my_session_id1 "echo pane0" Enter
|
|
1070
|
+
tmux send -t my_session_id1 "tmux select-pane -t 1" Enter
|
|
1071
|
+
tmux send -t my_session_id1 "echo pane1" Enter
|
|
1072
|
+
tmux send -t my_session_id1 "tmux select-pane -t 2" Enter
|
|
1073
|
+
tmux send -t my_session_id1 "echo pane2" Enter
|
|
1074
|
+
tmux send -t my_session_id1 "tmux select-pane -t 3" Enter
|
|
1075
|
+
tmux send -t my_session_id1 "echo pane3" Enter
|
|
1076
|
+
|
|
1077
|
+
|
|
1058
1078
|
"""
|