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 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.2.2'
32
- __version_tuple__ = version_tuple = (0, 2, 2)
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 with modules (modules not actually loaded locally)
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
- # Determine output paths
52
- stdout_file = job.stdout or f"{job.name}.{job_id}.out"
53
- stdout_path = workdir / stdout_file
54
- if job.merge_output:
55
- stderr_path = stdout_path # Merge stderr into stdout
56
- else:
57
- stderr_file = job.stderr or f"{job.name}.{job_id}.err"
58
- stderr_path = workdir / stderr_file
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
- # Store output paths
61
- LocalScheduler._output_paths[job_id] = {
62
- "stdout": stdout_path,
63
- "stderr": stderr_path,
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
- with open(stdout_path, "w") as stdout_f:
69
- if job.merge_output:
70
- result = subprocess.run(
71
- [str(script_path)],
72
- cwd=workdir,
73
- env=env,
74
- stdout=stdout_f,
75
- stderr=subprocess.STDOUT,
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=stderr_f,
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
- stdout_f = open(stdout_path, "w")
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
- stderr_f = open(stderr_path, "w")
101
- proc = subprocess.Popen(
102
- [str(script_path)],
103
- cwd=workdir,
104
- env=env,
105
- stdout=stdout_f,
106
- stderr=stderr_f,
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 (simulated for local)
22
+ # Additional module paths
10
23
  {% for path in job.modules_path %}
11
- # module use {{ path }}
24
+ module use {{ path }}
12
25
  {% endfor %}
13
26
  {% endif %}
14
27
 
15
28
  {% if job.modules %}
16
- # Modules (simulated for local - not actually loaded)
29
+ # Load modules
17
30
  {% for mod in job.modules %}
18
- # module load {{ mod }}
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hpc-runner
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Unified HPC job submission across multiple schedulers
5
5
  Project-URL: Homepage, https://github.com/sjalloq/hpc-runner
6
6
  Project-URL: Repository, https://github.com/sjalloq/hpc-runner
@@ -1,5 +1,5 @@
1
1
  hpc_runner/__init__.py,sha256=1xnewzCt8FVqseOG5PRmLbiMz0I8V8_TrTyIjW0Q8_A,1414
2
- hpc_runner/_version.py,sha256=o3ZTescp-19Z9cvBGq9dQnbppljgzdUYUf98Nov0spY,704
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=tTq_5uZEIYCjK3PmPjI_iBAPijwUlTmSaLNoy4_AB5c,13310
27
- hpc_runner/schedulers/local/templates/job.sh.j2,sha256=HDXgj-1hOvSQmR1sBCtES-sqIdqkBDQzql-espxE4g4,1092
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.2.2.dist-info/METADATA,sha256=_ZecSWdP7JpNPJQZKBxZm_NdQ3hN0dSByf1t9eF28mg,7157
55
- hpc_runner-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
56
- hpc_runner-0.2.2.dist-info/entry_points.txt,sha256=_IpvKqwtDP7R-jxj2p4D8ijKAIJp8eG9lmDZkVtrOkc,84
57
- hpc_runner-0.2.2.dist-info/RECORD,,
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,,