hpc-runner 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.
Files changed (56) hide show
  1. hpc_runner/__init__.py +57 -0
  2. hpc_runner/_version.py +34 -0
  3. hpc_runner/cli/__init__.py +1 -0
  4. hpc_runner/cli/cancel.py +38 -0
  5. hpc_runner/cli/config.py +109 -0
  6. hpc_runner/cli/main.py +76 -0
  7. hpc_runner/cli/monitor.py +30 -0
  8. hpc_runner/cli/run.py +292 -0
  9. hpc_runner/cli/status.py +66 -0
  10. hpc_runner/core/__init__.py +31 -0
  11. hpc_runner/core/config.py +177 -0
  12. hpc_runner/core/descriptors.py +110 -0
  13. hpc_runner/core/exceptions.py +38 -0
  14. hpc_runner/core/job.py +328 -0
  15. hpc_runner/core/job_array.py +58 -0
  16. hpc_runner/core/job_info.py +104 -0
  17. hpc_runner/core/resources.py +49 -0
  18. hpc_runner/core/result.py +161 -0
  19. hpc_runner/core/types.py +13 -0
  20. hpc_runner/py.typed +0 -0
  21. hpc_runner/schedulers/__init__.py +60 -0
  22. hpc_runner/schedulers/base.py +194 -0
  23. hpc_runner/schedulers/detection.py +52 -0
  24. hpc_runner/schedulers/local/__init__.py +5 -0
  25. hpc_runner/schedulers/local/scheduler.py +354 -0
  26. hpc_runner/schedulers/local/templates/job.sh.j2 +28 -0
  27. hpc_runner/schedulers/sge/__init__.py +5 -0
  28. hpc_runner/schedulers/sge/args.py +232 -0
  29. hpc_runner/schedulers/sge/parser.py +287 -0
  30. hpc_runner/schedulers/sge/scheduler.py +881 -0
  31. hpc_runner/schedulers/sge/templates/batch.sh.j2 +82 -0
  32. hpc_runner/schedulers/sge/templates/interactive.sh.j2 +78 -0
  33. hpc_runner/templates/__init__.py +5 -0
  34. hpc_runner/templates/engine.py +55 -0
  35. hpc_runner/tui/__init__.py +5 -0
  36. hpc_runner/tui/app.py +436 -0
  37. hpc_runner/tui/components/__init__.py +17 -0
  38. hpc_runner/tui/components/detail_panel.py +187 -0
  39. hpc_runner/tui/components/filter_bar.py +174 -0
  40. hpc_runner/tui/components/filter_popup.py +345 -0
  41. hpc_runner/tui/components/job_table.py +260 -0
  42. hpc_runner/tui/providers/__init__.py +5 -0
  43. hpc_runner/tui/providers/jobs.py +197 -0
  44. hpc_runner/tui/screens/__init__.py +7 -0
  45. hpc_runner/tui/screens/confirm.py +67 -0
  46. hpc_runner/tui/screens/job_details.py +210 -0
  47. hpc_runner/tui/screens/log_viewer.py +170 -0
  48. hpc_runner/tui/snapshot.py +153 -0
  49. hpc_runner/tui/styles/monitor.tcss +567 -0
  50. hpc_runner/workflow/__init__.py +6 -0
  51. hpc_runner/workflow/dependency.py +20 -0
  52. hpc_runner/workflow/pipeline.py +180 -0
  53. hpc_runner-0.2.0.dist-info/METADATA +285 -0
  54. hpc_runner-0.2.0.dist-info/RECORD +56 -0
  55. hpc_runner-0.2.0.dist-info/WHEEL +4 -0
  56. hpc_runner-0.2.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,180 @@
1
+ """Pipeline API for job workflows with dependencies."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ from hpc_runner.core.job import Job
9
+ from hpc_runner.workflow.dependency import DependencyType
10
+
11
+ if TYPE_CHECKING:
12
+ from hpc_runner.core.result import JobResult
13
+ from hpc_runner.schedulers.base import BaseScheduler
14
+
15
+
16
+ @dataclass
17
+ class PipelineJob:
18
+ """A job within a pipeline."""
19
+
20
+ job: Job
21
+ name: str
22
+ depends_on: list[PipelineJob] = field(default_factory=list)
23
+ result: JobResult | None = None
24
+
25
+
26
+ class Pipeline:
27
+ """Workflow pipeline with job dependencies.
28
+
29
+ Example:
30
+ with Pipeline("build-test") as p:
31
+ build = p.add("make build", name="build", cpu=4)
32
+ test = p.add("make test", name="test", depends_on=["build"])
33
+ package = p.add("make package", name="package", depends_on=["test"])
34
+
35
+ results = p.submit()
36
+ p.wait()
37
+ """
38
+
39
+ def __init__(self, name: str = "pipeline") -> None:
40
+ self.name = name
41
+ self.jobs: list[PipelineJob] = []
42
+ self._name_map: dict[str, PipelineJob] = {}
43
+ self._submitted = False
44
+
45
+ def add(
46
+ self,
47
+ command: str,
48
+ name: str | None = None,
49
+ depends_on: list[str | PipelineJob] | None = None,
50
+ **job_kwargs: Any,
51
+ ) -> PipelineJob:
52
+ """Add a job to the pipeline.
53
+
54
+ Args:
55
+ command: Command to execute
56
+ name: Job name (auto-generated if None)
57
+ depends_on: List of job names or PipelineJob objects
58
+ **job_kwargs: Additional Job parameters
59
+ """
60
+ if name is None:
61
+ name = f"step_{len(self.jobs) + 1}"
62
+
63
+ if name in self._name_map:
64
+ raise ValueError(f"Job name '{name}' already exists in pipeline")
65
+
66
+ job = Job(command=command, name=f"{self.name}_{name}", **job_kwargs)
67
+
68
+ dependencies: list[PipelineJob] = []
69
+ if depends_on:
70
+ for dep in depends_on:
71
+ if isinstance(dep, str):
72
+ if dep not in self._name_map:
73
+ raise ValueError(f"Unknown dependency: {dep}")
74
+ dependencies.append(self._name_map[dep])
75
+ else:
76
+ dependencies.append(dep)
77
+
78
+ pipeline_job = PipelineJob(job=job, name=name, depends_on=dependencies)
79
+ self.jobs.append(pipeline_job)
80
+ self._name_map[name] = pipeline_job
81
+
82
+ return pipeline_job
83
+
84
+ def submit(
85
+ self,
86
+ scheduler: BaseScheduler | None = None,
87
+ dependency_type: DependencyType = DependencyType.AFTEROK,
88
+ ) -> dict[str, JobResult]:
89
+ """Submit all jobs respecting dependencies.
90
+
91
+ Args:
92
+ scheduler: Scheduler to use (auto-detect if None)
93
+ dependency_type: Type of dependency to use
94
+
95
+ Returns:
96
+ Dict mapping job names to results
97
+ """
98
+ from hpc_runner.schedulers import get_scheduler
99
+
100
+ if self._submitted:
101
+ raise RuntimeError("Pipeline has already been submitted")
102
+
103
+ if scheduler is None:
104
+ scheduler = get_scheduler()
105
+
106
+ results: dict[str, JobResult] = {}
107
+
108
+ for pjob in self._topological_sort():
109
+ # Set up dependencies
110
+ if pjob.depends_on:
111
+ dep_results = [results[d.name] for d in pjob.depends_on]
112
+ pjob.job.dependencies = dep_results
113
+ pjob.job.dependency_type = str(dependency_type)
114
+
115
+ # Submit
116
+ result = scheduler.submit(pjob.job)
117
+ pjob.result = result
118
+ results[pjob.name] = result
119
+
120
+ self._submitted = True
121
+ return results
122
+
123
+ def _topological_sort(self) -> list[PipelineJob]:
124
+ """Sort jobs by dependency order (Kahn's algorithm)."""
125
+ # Build in-degree map
126
+ in_degree: dict[str, int] = {pj.name: 0 for pj in self.jobs}
127
+ for pj in self.jobs:
128
+ for dep in pj.depends_on:
129
+ in_degree[pj.name] += 1
130
+
131
+ # Find all jobs with no dependencies
132
+ queue = [pj for pj in self.jobs if in_degree[pj.name] == 0]
133
+ result: list[PipelineJob] = []
134
+
135
+ while queue:
136
+ pj = queue.pop(0)
137
+ result.append(pj)
138
+
139
+ # Reduce in-degree for dependent jobs
140
+ for other_pj in self.jobs:
141
+ if pj in other_pj.depends_on:
142
+ in_degree[other_pj.name] -= 1
143
+ if in_degree[other_pj.name] == 0:
144
+ queue.append(other_pj)
145
+
146
+ if len(result) != len(self.jobs):
147
+ raise ValueError("Circular dependency detected in pipeline")
148
+
149
+ return result
150
+
151
+ def wait(self, poll_interval: float = 5.0) -> dict[str, JobResult]:
152
+ """Wait for all jobs to complete.
153
+
154
+ Returns:
155
+ Dict mapping job names to results
156
+ """
157
+ if not self._submitted:
158
+ raise RuntimeError("Pipeline has not been submitted")
159
+
160
+ for pjob in self.jobs:
161
+ if pjob.result:
162
+ pjob.result.wait(poll_interval=poll_interval)
163
+
164
+ return {pj.name: pj.result for pj in self.jobs if pj.result}
165
+
166
+ def get_job(self, name: str) -> PipelineJob | None:
167
+ """Get a job by name."""
168
+ return self._name_map.get(name)
169
+
170
+ def __enter__(self) -> Pipeline:
171
+ return self
172
+
173
+ def __exit__(self, *args: Any) -> None:
174
+ pass
175
+
176
+ def __len__(self) -> int:
177
+ return len(self.jobs)
178
+
179
+ def __iter__(self):
180
+ return iter(self.jobs)
@@ -0,0 +1,285 @@
1
+ Metadata-Version: 2.4
2
+ Name: hpc-runner
3
+ Version: 0.2.0
4
+ Summary: Unified HPC job submission across multiple schedulers
5
+ Project-URL: Homepage, https://github.com/sjalloq/hpc-runner
6
+ Project-URL: Repository, https://github.com/sjalloq/hpc-runner
7
+ Author: Shareef Jalloq
8
+ License-Expression: MIT
9
+ Keywords: cluster,hpc,job-submission,pbs,sge,slurm
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: System :: Clustering
21
+ Classifier: Topic :: System :: Distributed Computing
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: jinja2>=3.0
24
+ Requires-Dist: rich-click>=1.7
25
+ Requires-Dist: textual>=6.11
26
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
27
+ Provides-Extra: all
28
+ Requires-Dist: build; extra == 'all'
29
+ Requires-Dist: hatch-vcs; extra == 'all'
30
+ Requires-Dist: mypy; extra == 'all'
31
+ Requires-Dist: pytest-cov; extra == 'all'
32
+ Requires-Dist: pytest>=7.0; extra == 'all'
33
+ Requires-Dist: ruff; extra == 'all'
34
+ Requires-Dist: twine; extra == 'all'
35
+ Provides-Extra: dev
36
+ Requires-Dist: build; extra == 'dev'
37
+ Requires-Dist: hatch-vcs; extra == 'dev'
38
+ Requires-Dist: mypy; extra == 'dev'
39
+ Requires-Dist: pytest-cov; extra == 'dev'
40
+ Requires-Dist: pytest>=7.0; extra == 'dev'
41
+ Requires-Dist: ruff; extra == 'dev'
42
+ Requires-Dist: twine; extra == 'dev'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # hpc-runner
46
+
47
+ **Unified HPC job submission across multiple schedulers**
48
+
49
+ Write your jobs once, run them on any cluster - SGE, Slurm, PBS, or locally for testing.
50
+
51
+ ## Features
52
+
53
+ - **Unified CLI** - Same commands work across SGE, Slurm, PBS
54
+ - **Python API** - Programmatic job submission with dependencies and pipelines
55
+ - **Auto-detection** - Automatically finds your cluster's scheduler
56
+ - **Interactive TUI** - Monitor jobs with a terminal dashboard
57
+ - **Job Dependencies** - Chain jobs with afterok, afterany, afternotok
58
+ - **Array Jobs** - Batch processing with throttling support
59
+ - **Virtual Environment Handling** - Automatic venv activation on compute nodes
60
+ - **Module Integration** - Load environment modules in job scripts
61
+ - **Dry-run Mode** - Preview generated scripts before submission
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install hpc-runner
67
+ ```
68
+
69
+ Or with uv:
70
+
71
+ ```bash
72
+ uv pip install hpc-runner
73
+ ```
74
+
75
+ ## Quick Start
76
+
77
+ ### CLI
78
+
79
+ ```bash
80
+ # Basic job submission
81
+ hpc run python train.py
82
+
83
+ # With resources
84
+ hpc run --cpu 4 --mem 16G --time 4:00:00 "python train.py"
85
+
86
+ # GPU job
87
+ hpc run --queue gpu --cpu 4 --mem 32G "python train.py --epochs 100"
88
+
89
+ # Preview without submitting
90
+ hpc run --dry-run --cpu 8 "make -j8"
91
+
92
+ # Interactive session
93
+ hpc run --interactive bash
94
+
95
+ # Array job
96
+ hpc run --array 1-100 "python process.py --task-id \$SGE_TASK_ID"
97
+
98
+ # Wait for completion
99
+ hpc run --wait python long_job.py
100
+ ```
101
+
102
+ ### Python API
103
+
104
+ ```python
105
+ from hpc_runner import Job
106
+
107
+ # Create and submit a job
108
+ job = Job(
109
+ command="python train.py",
110
+ cpu=4,
111
+ mem="16G",
112
+ time="4:00:00",
113
+ queue="gpu",
114
+ )
115
+ result = job.submit()
116
+
117
+ # Wait for completion
118
+ status = result.wait()
119
+ print(f"Exit code: {result.returncode}")
120
+
121
+ # Read output
122
+ print(result.read_stdout())
123
+ ```
124
+
125
+ ### Job Dependencies
126
+
127
+ ```python
128
+ from hpc_runner import Job
129
+
130
+ # First job
131
+ preprocess = Job(command="python preprocess.py", cpu=8, mem="32G")
132
+ result1 = preprocess.submit()
133
+
134
+ # Second job runs after first succeeds
135
+ train = Job(command="python train.py", cpu=4, mem="48G", queue="gpu")
136
+ train.after(result1, type="afterok")
137
+ result2 = train.submit()
138
+ ```
139
+
140
+ ### Pipelines
141
+
142
+ ```python
143
+ from hpc_runner import Pipeline
144
+
145
+ with Pipeline("ml_workflow") as p:
146
+ p.add("python preprocess.py", name="preprocess", cpu=8)
147
+ p.add("python train.py", name="train", depends_on=["preprocess"], queue="gpu")
148
+ p.add("python evaluate.py", name="evaluate", depends_on=["train"])
149
+
150
+ results = p.submit()
151
+ p.wait()
152
+ ```
153
+
154
+ ## Scheduler Support
155
+
156
+ | Scheduler | Status | Notes |
157
+ |-----------|--------|-------|
158
+ | SGE | Fully implemented | qsub, qstat, qdel, qrsh |
159
+ | Local | Fully implemented | Run as subprocess (for testing) |
160
+ | Slurm | Planned | sbatch, squeue, scancel |
161
+ | PBS | Planned | qsub, qstat, qdel |
162
+
163
+ ### Auto-detection Priority
164
+
165
+ 1. `HPC_SCHEDULER` environment variable
166
+ 2. SGE (`SGE_ROOT` or `qstat` available)
167
+ 3. Slurm (`sbatch` available)
168
+ 4. PBS (`qsub` with PBS)
169
+ 5. Local fallback
170
+
171
+ ## Configuration
172
+
173
+ hpc-runner uses TOML configuration files. Location priority:
174
+
175
+ 1. `--config /path/to/config.toml`
176
+ 2. `./hpc-tools.toml`
177
+ 3. `./pyproject.toml` under `[tool.hpc-tools]`
178
+ 4. Git repository root `hpc-tools.toml`
179
+ 5. `~/.config/hpc-tools/config.toml`
180
+ 6. Package defaults
181
+
182
+ ### Example Configuration
183
+
184
+ ```toml
185
+ [defaults]
186
+ cpu = 1
187
+ mem = "4G"
188
+ time = "1:00:00"
189
+ inherit_env = true
190
+
191
+ [schedulers.sge]
192
+ parallel_environment = "smp"
193
+ memory_resource = "mem_free"
194
+ purge_modules = true
195
+
196
+ [types.gpu]
197
+ queue = "gpu"
198
+ resources = [{name = "gpu", value = 1}]
199
+
200
+ [types.interactive]
201
+ queue = "interactive"
202
+ time = "8:00:00"
203
+ ```
204
+
205
+ Use named job types:
206
+
207
+ ```bash
208
+ hpc run --job-type gpu "python train.py"
209
+ ```
210
+
211
+ ## TUI Monitor
212
+
213
+ Launch the interactive job monitor:
214
+
215
+ ```bash
216
+ hpc monitor
217
+ ```
218
+
219
+ Key bindings:
220
+ - `q` - Quit
221
+ - `r` - Refresh
222
+ - `u` - Toggle user filter (my jobs / all)
223
+ - `/` - Search
224
+ - `Enter` - View job details
225
+ - `Tab` - Switch tabs
226
+
227
+ ## CLI Reference
228
+
229
+ ```
230
+ hpc run [OPTIONS] COMMAND
231
+
232
+ Options:
233
+ --job-name TEXT Job name
234
+ --cpu INTEGER Number of CPUs
235
+ --mem TEXT Memory (e.g., 16G, 4096M)
236
+ --time TEXT Time limit (e.g., 4:00:00)
237
+ --queue TEXT Queue/partition name
238
+ --directory PATH Working directory
239
+ --module TEXT Module to load (repeatable)
240
+ --array TEXT Array spec (e.g., 1-100, 1-100%5)
241
+ --depend TEXT Job dependencies
242
+ --inherit-env Inherit environment (default: true)
243
+ --no-inherit-env Don't inherit environment
244
+ --interactive Run interactively (qrsh/srun)
245
+ --local Run locally (no scheduler)
246
+ --dry-run Show script without submitting
247
+ --wait Wait for completion
248
+ --keep-script Keep job script for debugging
249
+ -h, --help Show help
250
+
251
+ Other commands:
252
+ hpc status [JOB_ID] Check job status
253
+ hpc cancel JOB_ID Cancel a job
254
+ hpc monitor Interactive TUI
255
+ hpc config show Show active configuration
256
+ ```
257
+
258
+ ## Development
259
+
260
+ ```bash
261
+ # Setup environment
262
+ source sourceme
263
+ source sourceme --clean # Clean rebuild
264
+
265
+ # Run tests
266
+ pytest
267
+ pytest -v
268
+ pytest -k "test_job"
269
+
270
+ # Type checking
271
+ mypy src/hpc_runner
272
+
273
+ # Linting
274
+ ruff check src/hpc_runner
275
+ ruff format src/hpc_runner
276
+ ```
277
+
278
+ ## Documentation
279
+
280
+ - [Programmatic API Reference](docs/programmatic_api.md)
281
+ - [TUI Styling Guide](docs/TEXTUAL_STYLING_COOKBOOK.md)
282
+
283
+ ## License
284
+
285
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,56 @@
1
+ hpc_runner/__init__.py,sha256=1xnewzCt8FVqseOG5PRmLbiMz0I8V8_TrTyIjW0Q8_A,1414
2
+ hpc_runner/_version.py,sha256=Dg8AmJomLVpjKL6prJylOONZAPRtB86LOce7dorQS_A,704
3
+ hpc_runner/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ hpc_runner/cli/__init__.py,sha256=SkyeG7kzxbBGgO9fU96VvHjMjLaSdGI3KFVcqeUAYtg,25
5
+ hpc_runner/cli/cancel.py,sha256=8qRkPjlSGs6OGs7-_ilwpUlWpGQe7ch8aB_rEWiiLAI,901
6
+ hpc_runner/cli/config.py,sha256=dxNNOyuUyzuk9UUUaELp5WkhHrkZnXGi7zQkJdUl4YA,2920
7
+ hpc_runner/cli/main.py,sha256=Did1C3P0Cz7VjuR_a4a0dgHD9u_an_kxaBLNcMWYHR4,2061
8
+ hpc_runner/cli/monitor.py,sha256=aqr39IqwEUz_eczDLMw1dyfs_Gz6mtqKM2eMHI80f4g,698
9
+ hpc_runner/cli/run.py,sha256=fGK0gwIiQdUl0i2aC5FnwSs9MmuKF6ZZFgg7pn2NitU,9646
10
+ hpc_runner/cli/status.py,sha256=LMKvfIiR2U-r8kZOLw1L1-Xfli0mCtX-sSqI6_gy0i0,1957
11
+ hpc_runner/core/__init__.py,sha256=C6R3f_AWv5KOfZ3p2iJiht2B2r1LC62atHWntz51o9c,643
12
+ hpc_runner/core/config.py,sha256=UTbJnIveShGAS_YtS_tRT8H-_Jzq1qGidg3qSQZL6_Q,5184
13
+ hpc_runner/core/descriptors.py,sha256=xaoK3-YbVUcBdeumaY4JZ9noq-d5fqglIwZQqsWvYzU,3307
14
+ hpc_runner/core/exceptions.py,sha256=Z5JIzbpznCCx-wT4uZtHtwxstKZGIAxMubCJV64QzOc,889
15
+ hpc_runner/core/job.py,sha256=N_7HpDzxJipbJU0nVHOoYuaVAGjEXfMzgxJ9ve54mok,11052
16
+ hpc_runner/core/job_array.py,sha256=7VHoZHRzN5JvzWZ_e5pAMeTrNB7-OZw06A8548oK8_c,1595
17
+ hpc_runner/core/job_info.py,sha256=QE4iHH3uqYp4KdvZmBtfFUUaZfmPLkrF6LtlK4RuSJM,2858
18
+ hpc_runner/core/resources.py,sha256=ng1biVsXgGy6AWG50I50aC4LWB1pd60qFLpj5FjIpQc,1275
19
+ hpc_runner/core/result.py,sha256=UGw6ZRmdGI4oVD5ENzrSK72Igx7QNo-OJX9hLVyldp8,4914
20
+ hpc_runner/core/types.py,sha256=a6Yq7vhcpBwgA_hGZwGXiZgCy8wG87FIXBT3LN5qHw8,251
21
+ hpc_runner/schedulers/__init__.py,sha256=v55_DYgiigiFjXJhI7_XFtvxHoyDFWOntWRB9-HWMrM,1623
22
+ hpc_runner/schedulers/base.py,sha256=vhugT9lFrSZb8BMDO_x-h4nSF2oLg2nOvd347g3qfUY,6223
23
+ hpc_runner/schedulers/detection.py,sha256=b5_qdyroMQsvIf_DYY_RDoje6ozKLA3RS-fWWNR9qUU,1467
24
+ hpc_runner/schedulers/local/__init__.py,sha256=bM0RT5SBxs7TsGDUeUi--Z_vlVt9dgokJcftX92VE58,147
25
+ hpc_runner/schedulers/local/scheduler.py,sha256=tTq_5uZEIYCjK3PmPjI_iBAPijwUlTmSaLNoy4_AB5c,13310
26
+ hpc_runner/schedulers/local/templates/job.sh.j2,sha256=pv_R20o5G3LU-DIEIC7gpt7fYIZJmzkrIQEwmVkUWUI,522
27
+ hpc_runner/schedulers/sge/__init__.py,sha256=aR_jJD-YA0HOYPaBwW_CEwi3PASXY2x9sOfmrj6-cjM,144
28
+ hpc_runner/schedulers/sge/args.py,sha256=LBRj4UUDJ5jR8tEoCVF4ivjEKjqDI6LMvFsFzTgtOwk,6553
29
+ hpc_runner/schedulers/sge/parser.py,sha256=P6bG7II2icqSrnzgxGanPITV12X1zMvWYV04L6RIH2c,8381
30
+ hpc_runner/schedulers/sge/scheduler.py,sha256=-vz58MQzaJD97TqE4KfrnR3drLhQgHy8bpjpNwpHt2s,31998
31
+ hpc_runner/schedulers/sge/templates/batch.sh.j2,sha256=au-Hr7o55J1SutLLlpcTBJhRvQYHM4d9bSHk95u3nv4,1696
32
+ hpc_runner/schedulers/sge/templates/interactive.sh.j2,sha256=CY_hcmWoK8EuBNHmP7_lrfMf_i5BjZn8YY9Fi4ousZI,1622
33
+ hpc_runner/templates/__init__.py,sha256=kiaaYBS4QXfGie83SS0rfmZtlbyRUkGkR_yw04oExNQ,137
34
+ hpc_runner/templates/engine.py,sha256=XDW9C51rz9O2rcB3mpjVHQ0qkeG4386gXa8fwaDYsxs,1393
35
+ hpc_runner/tui/__init__.py,sha256=xuet6Iz1ZL6Ys5h95DMcuiapZNo8QA-sFU3R0NflbgE,136
36
+ hpc_runner/tui/app.py,sha256=rsiA2ViNGkfo6pWf2lvVRM3LVM1MunLB8CcNMLHRzso,16466
37
+ hpc_runner/tui/snapshot.py,sha256=sAcxdGaKsFXQMByPip-o1YwFaU-MLf_jGwDlZvEYTxY,5194
38
+ hpc_runner/tui/components/__init__.py,sha256=cS1VT2uhaWDq18-FvT9Hje_Uev7pI8WGFgWVNERfJMQ,303
39
+ hpc_runner/tui/components/detail_panel.py,sha256=3sRxO8J6ceBUctKm-LSF_aujIa63TEdWZJt2v08ae28,6983
40
+ hpc_runner/tui/components/filter_bar.py,sha256=v3YqUnieTzipJCaUHsVIcXc1VwTM3TorYBW-H6Ai5vo,4965
41
+ hpc_runner/tui/components/filter_popup.py,sha256=_car5ic8SS32183XWvbvVX8q1paNoX2Un-Ohy3z2vwo,10428
42
+ hpc_runner/tui/components/job_table.py,sha256=3gqYey0L9i2WInKl7Hknh31_E_PEPSKdFvVwSsG7uuY,9444
43
+ hpc_runner/tui/providers/__init__.py,sha256=iLzT7HR2ETSf6MxDw64yVn99kiHqzEDOHqNU7XLAEME,100
44
+ hpc_runner/tui/providers/jobs.py,sha256=YjhufHvBJu6QICIZLs5FhFBAcQMEyEhw-heSzYxYwvo,6340
45
+ hpc_runner/tui/screens/__init__.py,sha256=EoyZZGr_fruzDuDXtsKXyY5QhHbEFVbm820eiRtciBc,221
46
+ hpc_runner/tui/screens/confirm.py,sha256=ZBjrqcIk6f_5KGLzsSCfewZdyERnR0x2W2A34KYlkbI,2101
47
+ hpc_runner/tui/screens/job_details.py,sha256=B7KiZunhfM7QW3xVvmEBQnOB5CQfxYpH9Td0JC6M29A,7488
48
+ hpc_runner/tui/screens/log_viewer.py,sha256=II6B2Vj4KY-nx1wWWq_5K2gsmi6dSyQm-suaEzauEcM,5888
49
+ hpc_runner/tui/styles/monitor.tcss,sha256=-XJ_mF02AlaEuX81N6tkYKhKYDcBKYTDKXejJO5efkI,11349
50
+ hpc_runner/workflow/__init__.py,sha256=Y5h7wfnlWcav_f2USZaP6r5m7I5KFam8eEJGo4UqJ0w,221
51
+ hpc_runner/workflow/dependency.py,sha256=PjhgCurnlfcKYO_arlUDLCKOpwqq324l09Sj0v-iwOU,639
52
+ hpc_runner/workflow/pipeline.py,sha256=MYV95Kp-5m2YVxYDk_zIYUsyt31ctl7jnVA10F2OJgg,5540
53
+ hpc_runner-0.2.0.dist-info/METADATA,sha256=5wCFmYvXMhg6Y2RQS66K3cUvjML64lRsulpgyRf_5O8,7015
54
+ hpc_runner-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
55
+ hpc_runner-0.2.0.dist-info/entry_points.txt,sha256=Ou3LsalLkY9mNOrUwyCDN8Q4PekM1K5h52hAU6fADk8,48
56
+ hpc_runner-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ hpc = hpc_runner.cli.main:cli