hpc-runner 0.2.2__py3-none-any.whl → 0.3.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.
- hpc_runner/_version.py +2 -2
- hpc_runner/schedulers/local/scheduler.py +70 -41
- hpc_runner/schedulers/local/templates/job.sh.j2 +22 -4
- {hpc_runner-0.2.2.dist-info → hpc_runner-0.3.0.dist-info}/METADATA +1 -1
- {hpc_runner-0.2.2.dist-info → hpc_runner-0.3.0.dist-info}/RECORD +7 -7
- {hpc_runner-0.2.2.dist-info → hpc_runner-0.3.0.dist-info}/WHEEL +0 -0
- {hpc_runner-0.2.2.dist-info → hpc_runner-0.3.0.dist-info}/entry_points.txt +0 -0
hpc_runner/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.3.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -9,6 +9,7 @@ from datetime import datetime
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import TYPE_CHECKING
|
|
11
11
|
|
|
12
|
+
from hpc_runner.core.config import get_config
|
|
12
13
|
from hpc_runner.core.exceptions import AccountingNotAvailable, JobNotFoundError
|
|
13
14
|
from hpc_runner.core.job_info import JobInfo
|
|
14
15
|
from hpc_runner.core.result import ArrayJobResult, JobResult, JobStatus
|
|
@@ -26,6 +27,14 @@ class LocalScheduler(BaseScheduler):
|
|
|
26
27
|
name = "local"
|
|
27
28
|
|
|
28
29
|
_job_counter: int = 0
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
"""Initialize local scheduler with config-driven settings."""
|
|
33
|
+
config = get_config()
|
|
34
|
+
local_config = config.get_scheduler_config("local")
|
|
35
|
+
|
|
36
|
+
self.module_init_script = local_config.get("module_init_script", "")
|
|
37
|
+
|
|
29
38
|
_processes: dict[str, subprocess.Popen] = {} # type: ignore[type-arg]
|
|
30
39
|
_exit_codes: dict[str, int] = {}
|
|
31
40
|
_output_paths: dict[str, dict[str, Path]] = {}
|
|
@@ -37,8 +46,9 @@ class LocalScheduler(BaseScheduler):
|
|
|
37
46
|
LocalScheduler._job_counter += 1
|
|
38
47
|
job_id = f"local_{LocalScheduler._job_counter}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
|
|
39
48
|
|
|
40
|
-
# Set up environment
|
|
49
|
+
# Set up environment
|
|
41
50
|
env = os.environ.copy() if job.inherit_env else {}
|
|
51
|
+
env.update(job.env_vars)
|
|
42
52
|
|
|
43
53
|
# Generate and write script
|
|
44
54
|
script = self.generate_script(job)
|
|
@@ -48,69 +58,87 @@ class LocalScheduler(BaseScheduler):
|
|
|
48
58
|
|
|
49
59
|
workdir = Path(job.workdir) if job.workdir else Path.cwd()
|
|
50
60
|
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
# Check if output should pass through to console (no redirection)
|
|
62
|
+
passthrough = job.stdout is None and job.stderr is None
|
|
63
|
+
|
|
64
|
+
if not passthrough:
|
|
65
|
+
# Determine output paths
|
|
66
|
+
stdout_file = job.stdout or f"{job.name}.{job_id}.out"
|
|
67
|
+
stdout_path = workdir / stdout_file
|
|
68
|
+
if job.merge_output:
|
|
69
|
+
stderr_path = stdout_path # Merge stderr into stdout
|
|
70
|
+
else:
|
|
71
|
+
stderr_file = job.stderr or f"{job.name}.{job_id}.err"
|
|
72
|
+
stderr_path = workdir / stderr_file
|
|
59
73
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
# Store output paths
|
|
75
|
+
LocalScheduler._output_paths[job_id] = {
|
|
76
|
+
"stdout": stdout_path,
|
|
77
|
+
"stderr": stderr_path,
|
|
78
|
+
}
|
|
65
79
|
|
|
66
80
|
if interactive:
|
|
67
81
|
# Blocking execution
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
else:
|
|
78
|
-
with open(stderr_path, "w") as stderr_f:
|
|
82
|
+
if passthrough:
|
|
83
|
+
result = subprocess.run(
|
|
84
|
+
[str(script_path)],
|
|
85
|
+
cwd=workdir,
|
|
86
|
+
env=env,
|
|
87
|
+
)
|
|
88
|
+
else:
|
|
89
|
+
with open(stdout_path, "w") as stdout_f:
|
|
90
|
+
if job.merge_output:
|
|
79
91
|
result = subprocess.run(
|
|
80
92
|
[str(script_path)],
|
|
81
93
|
cwd=workdir,
|
|
82
94
|
env=env,
|
|
83
95
|
stdout=stdout_f,
|
|
84
|
-
stderr=
|
|
96
|
+
stderr=subprocess.STDOUT,
|
|
85
97
|
)
|
|
98
|
+
else:
|
|
99
|
+
with open(stderr_path, "w") as stderr_f:
|
|
100
|
+
result = subprocess.run(
|
|
101
|
+
[str(script_path)],
|
|
102
|
+
cwd=workdir,
|
|
103
|
+
env=env,
|
|
104
|
+
stdout=stdout_f,
|
|
105
|
+
stderr=stderr_f,
|
|
106
|
+
)
|
|
86
107
|
LocalScheduler._exit_codes[job_id] = result.returncode
|
|
87
108
|
script_path.unlink(missing_ok=True)
|
|
88
109
|
else:
|
|
89
110
|
# Background execution
|
|
90
|
-
|
|
91
|
-
if job.merge_output:
|
|
111
|
+
if passthrough:
|
|
92
112
|
proc = subprocess.Popen(
|
|
93
113
|
[str(script_path)],
|
|
94
114
|
cwd=workdir,
|
|
95
115
|
env=env,
|
|
96
|
-
stdout=stdout_f,
|
|
97
|
-
stderr=subprocess.STDOUT,
|
|
98
116
|
)
|
|
99
117
|
else:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
stdout_f = open(stdout_path, "w")
|
|
119
|
+
if job.merge_output:
|
|
120
|
+
proc = subprocess.Popen(
|
|
121
|
+
[str(script_path)],
|
|
122
|
+
cwd=workdir,
|
|
123
|
+
env=env,
|
|
124
|
+
stdout=stdout_f,
|
|
125
|
+
stderr=subprocess.STDOUT,
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
stderr_f = open(stderr_path, "w")
|
|
129
|
+
proc = subprocess.Popen(
|
|
130
|
+
[str(script_path)],
|
|
131
|
+
cwd=workdir,
|
|
132
|
+
env=env,
|
|
133
|
+
stdout=stdout_f,
|
|
134
|
+
stderr=stderr_f,
|
|
135
|
+
)
|
|
136
|
+
proc._stdout_file = stdout_f # type: ignore[attr-defined]
|
|
137
|
+
if not job.merge_output:
|
|
138
|
+
proc._stderr_file = stderr_f # type: ignore[attr-defined]
|
|
108
139
|
LocalScheduler._processes[job_id] = proc
|
|
109
140
|
# Store script path for cleanup
|
|
110
141
|
proc._script_path = script_path # type: ignore[attr-defined]
|
|
111
|
-
proc._stdout_file = stdout_f # type: ignore[attr-defined]
|
|
112
|
-
if not job.merge_output:
|
|
113
|
-
proc._stderr_file = stderr_f # type: ignore[attr-defined]
|
|
114
142
|
|
|
115
143
|
return JobResult(job_id=job_id, scheduler=self, job=job)
|
|
116
144
|
|
|
@@ -137,6 +165,7 @@ class LocalScheduler(BaseScheduler):
|
|
|
137
165
|
def _submit_array_task(self, job: "Job", job_id: str, index: int) -> None:
|
|
138
166
|
"""Submit a single array task."""
|
|
139
167
|
env = os.environ.copy() if job.inherit_env else {}
|
|
168
|
+
env.update(job.env_vars)
|
|
140
169
|
env["HPC_ARRAY_TASK_ID"] = str(index)
|
|
141
170
|
|
|
142
171
|
script = self.generate_script(job)
|
|
@@ -5,20 +5,38 @@
|
|
|
5
5
|
# Exit on error
|
|
6
6
|
set -e
|
|
7
7
|
|
|
8
|
+
# Module system initialization
|
|
9
|
+
{% if scheduler.module_init_script %}
|
|
10
|
+
. {{ scheduler.module_init_script }}
|
|
11
|
+
{% else %}
|
|
12
|
+
if [ -f /etc/profile.d/modules.sh ]; then
|
|
13
|
+
. /etc/profile.d/modules.sh
|
|
14
|
+
elif [ -f /usr/share/Modules/init/bash ]; then
|
|
15
|
+
. /usr/share/Modules/init/bash
|
|
16
|
+
elif [ -f /etc/modules/init/bash ]; then
|
|
17
|
+
. /etc/modules/init/bash
|
|
18
|
+
fi
|
|
19
|
+
{% endif %}
|
|
20
|
+
|
|
8
21
|
{% if job.modules_path %}
|
|
9
|
-
# Additional module paths
|
|
22
|
+
# Additional module paths
|
|
10
23
|
{% for path in job.modules_path %}
|
|
11
|
-
|
|
24
|
+
module use {{ path }}
|
|
12
25
|
{% endfor %}
|
|
13
26
|
{% endif %}
|
|
14
27
|
|
|
15
28
|
{% if job.modules %}
|
|
16
|
-
#
|
|
29
|
+
# Load modules
|
|
17
30
|
{% for mod in job.modules %}
|
|
18
|
-
|
|
31
|
+
module load {{ mod }}
|
|
19
32
|
{% endfor %}
|
|
20
33
|
{% endif %}
|
|
21
34
|
|
|
35
|
+
{% if job.venv %}
|
|
36
|
+
# Activate virtual environment
|
|
37
|
+
source {{ job.venv }}/bin/activate
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
22
40
|
{% if job.env_prepend %}
|
|
23
41
|
# Prepend to environment variables
|
|
24
42
|
{% for key, value in job.env_prepend.items() %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
hpc_runner/__init__.py,sha256=1xnewzCt8FVqseOG5PRmLbiMz0I8V8_TrTyIjW0Q8_A,1414
|
|
2
|
-
hpc_runner/_version.py,sha256=
|
|
2
|
+
hpc_runner/_version.py,sha256=5zTqm8rgXsWYBpB2M3Zw_K1D-aV8wP7NsBLrmMKkrAQ,704
|
|
3
3
|
hpc_runner/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
hpc_runner/cli/__init__.py,sha256=qF_2phBjYZc_rHCyJeZevCvbOCfXQbLCwb-DY5mJNUo,26
|
|
5
5
|
hpc_runner/cli/cancel.py,sha256=8qRkPjlSGs6OGs7-_ilwpUlWpGQe7ch8aB_rEWiiLAI,901
|
|
@@ -23,8 +23,8 @@ hpc_runner/schedulers/__init__.py,sha256=v55_DYgiigiFjXJhI7_XFtvxHoyDFWOntWRB9-H
|
|
|
23
23
|
hpc_runner/schedulers/base.py,sha256=vhugT9lFrSZb8BMDO_x-h4nSF2oLg2nOvd347g3qfUY,6223
|
|
24
24
|
hpc_runner/schedulers/detection.py,sha256=b5_qdyroMQsvIf_DYY_RDoje6ozKLA3RS-fWWNR9qUU,1467
|
|
25
25
|
hpc_runner/schedulers/local/__init__.py,sha256=bM0RT5SBxs7TsGDUeUi--Z_vlVt9dgokJcftX92VE58,147
|
|
26
|
-
hpc_runner/schedulers/local/scheduler.py,sha256=
|
|
27
|
-
hpc_runner/schedulers/local/templates/job.sh.j2,sha256=
|
|
26
|
+
hpc_runner/schedulers/local/scheduler.py,sha256=aNfA9XnF8MGWxjhGturO_mzy9MQLVTt0ZN3NzSexGgs,14440
|
|
27
|
+
hpc_runner/schedulers/local/templates/job.sh.j2,sha256=MwQnjW6p6XNHSJ9EbcC0H3H4USHhZbMel1dmvOJj-2Y,1483
|
|
28
28
|
hpc_runner/schedulers/sge/__init__.py,sha256=aR_jJD-YA0HOYPaBwW_CEwi3PASXY2x9sOfmrj6-cjM,144
|
|
29
29
|
hpc_runner/schedulers/sge/args.py,sha256=LBRj4UUDJ5jR8tEoCVF4ivjEKjqDI6LMvFsFzTgtOwk,6553
|
|
30
30
|
hpc_runner/schedulers/sge/parser.py,sha256=P6bG7II2icqSrnzgxGanPITV12X1zMvWYV04L6RIH2c,8381
|
|
@@ -51,7 +51,7 @@ hpc_runner/tui/styles/monitor.tcss,sha256=-XJ_mF02AlaEuX81N6tkYKhKYDcBKYTDKXejJO
|
|
|
51
51
|
hpc_runner/workflow/__init__.py,sha256=Y5h7wfnlWcav_f2USZaP6r5m7I5KFam8eEJGo4UqJ0w,221
|
|
52
52
|
hpc_runner/workflow/dependency.py,sha256=PjhgCurnlfcKYO_arlUDLCKOpwqq324l09Sj0v-iwOU,639
|
|
53
53
|
hpc_runner/workflow/pipeline.py,sha256=MYV95Kp-5m2YVxYDk_zIYUsyt31ctl7jnVA10F2OJgg,5540
|
|
54
|
-
hpc_runner-0.
|
|
55
|
-
hpc_runner-0.
|
|
56
|
-
hpc_runner-0.
|
|
57
|
-
hpc_runner-0.
|
|
54
|
+
hpc_runner-0.3.0.dist-info/METADATA,sha256=2-0_jdDuVnmszJzaJDpDOBW_Zfuasem_vr4vXvXJS9Q,7157
|
|
55
|
+
hpc_runner-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
56
|
+
hpc_runner-0.3.0.dist-info/entry_points.txt,sha256=_IpvKqwtDP7R-jxj2p4D8ijKAIJp8eG9lmDZkVtrOkc,84
|
|
57
|
+
hpc_runner-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|