hyperun 0.2.4__tar.gz → 0.2.5__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.
- {hyperun-0.2.4 → hyperun-0.2.5}/PKG-INFO +1 -1
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun/cli.py +19 -8
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/PKG-INFO +1 -1
- {hyperun-0.2.4 → hyperun-0.2.5}/pyproject.toml +1 -1
- {hyperun-0.2.4 → hyperun-0.2.5}/tests/test_cli.py +20 -1
- {hyperun-0.2.4 → hyperun-0.2.5}/LICENSE +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/README.md +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun/__init__.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun/browser_login.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun/client.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun/config.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/SOURCES.txt +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/dependency_links.txt +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/entry_points.txt +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/requires.txt +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/hyperun.egg-info/top_level.txt +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/setup.cfg +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/tests/test_browser_login.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/tests/test_client.py +0 -0
- {hyperun-0.2.4 → hyperun-0.2.5}/tests/test_config.py +0 -0
|
@@ -114,12 +114,13 @@ def job_arguments() -> argparse.ArgumentParser:
|
|
|
114
114
|
# first time a vendor is added.
|
|
115
115
|
shared.add_argument(
|
|
116
116
|
"--vendor", action="append", metavar="NAME",
|
|
117
|
-
help="who the machine may be bought from
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
117
|
+
help="who the machine may be bought from, in the order they are asked. "
|
|
118
|
+
"Repeat it to allow several. Omit it, and --region, and the job is sent "
|
|
119
|
+
"with shadeform, runpod and aws in that order (a spot job goes to aws "
|
|
120
|
+
"alone); add --placement-mode cheapest to buy the cheapest of them "
|
|
121
|
+
"instead of the first that answers. aws, runpod and shadeform can "
|
|
122
|
+
"actually run a job; gcp, azure, lambda and nebius can only be PRICED, "
|
|
123
|
+
"so name one of those only with --placement-mode compare.",
|
|
123
124
|
)
|
|
124
125
|
# DDPSRUN-REGIONS. Missing until 2026-09-08, so every job this CLI submitted
|
|
125
126
|
# ran in the operator's one default region and there was no way to say
|
|
@@ -1055,9 +1056,19 @@ def cmd_status(args: argparse.Namespace) -> int:
|
|
|
1055
1056
|
if view.get("gpu"):
|
|
1056
1057
|
vendor = f" ({view['vendor']})" if view.get("vendor") else ""
|
|
1057
1058
|
print(f" running on {view['gpu']}{vendor}")
|
|
1059
|
+
# HYPERUN-PLACEMENT-NOTE. Where the job was asked to go, next to where it went,
|
|
1060
|
+
# so a person -- or an agent relaying to one -- sees a vendor that differs from
|
|
1061
|
+
# the one they chose. An older server sends no note, and nothing is printed.
|
|
1062
|
+
if view.get("placement_note"):
|
|
1063
|
+
print(f" placement {view['placement_note']}")
|
|
1058
1064
|
if view.get("recovery_count"):
|
|
1059
|
-
# Not a failure
|
|
1060
|
-
|
|
1065
|
+
# Not a failure: the job was restarted. It used to say "the machine was
|
|
1066
|
+
# reclaimed" every time, which was wrong for job-a9ea30b8ba7a -- its three
|
|
1067
|
+
# restarts were offerings that failed to START, not machines taken back.
|
|
1068
|
+
failed = view.get("failed_offerings") or 0
|
|
1069
|
+
why = (f"{failed} offering(s) failed to start or were lost, and were skipped"
|
|
1070
|
+
if failed else "the machine was lost and the job was restarted")
|
|
1071
|
+
print(f" restarts {view['recovery_count']} ({why})")
|
|
1061
1072
|
if view.get("message"):
|
|
1062
1073
|
print(f" message {view['message']}")
|
|
1063
1074
|
if view.get("result_path"):
|
|
@@ -34,7 +34,7 @@ build-backend = "setuptools.build_meta"
|
|
|
34
34
|
|
|
35
35
|
[project]
|
|
36
36
|
name = "hyperun"
|
|
37
|
-
version = "0.2.
|
|
37
|
+
version = "0.2.5"
|
|
38
38
|
description = "Submit a GPU job and get results back. No kubectl, no cloud account."
|
|
39
39
|
requires-python = ">=3.9"
|
|
40
40
|
dependencies = ["requests>=2.31", "PyYAML>=6.0"]
|
|
@@ -268,7 +268,26 @@ def test_status_calls_a_restart_what_it_is(fake, capsys):
|
|
|
268
268
|
run(["status", "job-a8acdef80a07"])
|
|
269
269
|
printed = capsys.readouterr().out
|
|
270
270
|
assert "L40S (runpod)" in printed
|
|
271
|
-
|
|
271
|
+
# With no failed offerings the restarts were machines lost mid-run.
|
|
272
|
+
assert "the machine was lost and the job was restarted" in printed
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def test_status_says_offerings_failed_and_where_the_job_was_asked_to_go(fake, capsys):
|
|
276
|
+
# job-a9ea30b8ba7a: three g6.xlarge zones failed to START, and the CLI called
|
|
277
|
+
# it "the machine was reclaimed". The server's note is printed as it is, so the
|
|
278
|
+
# person sees the job asked AWS alone while they had chosen "any vendor".
|
|
279
|
+
fake.status_result = {
|
|
280
|
+
"job_id": "job-a9ea30b8ba7a", "name": "x", "phase": "Running",
|
|
281
|
+
"recovery_count": 3, "failed_offerings": 3, "gpu": "g6.xlarge", "vendor": "aws",
|
|
282
|
+
"placement_note": "The job named no vendor and no region, so the operator's one "
|
|
283
|
+
"default region (AWS) was the only candidate; it runs on aws "
|
|
284
|
+
"g6.xlarge.",
|
|
285
|
+
}
|
|
286
|
+
run(["status", "job-a9ea30b8ba7a"])
|
|
287
|
+
printed = capsys.readouterr().out
|
|
288
|
+
assert "3 offering(s) failed to start or were lost" in printed
|
|
289
|
+
assert "reclaimed" not in printed
|
|
290
|
+
assert "placement The job named no vendor" in printed
|
|
272
291
|
|
|
273
292
|
|
|
274
293
|
def test_logs_prints_every_line_without_its_timestamp(fake, capsys):
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|