dh-cli 0.4.4__tar.gz → 0.4.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.
Files changed (51) hide show
  1. {dh_cli-0.4.4 → dh_cli-0.4.5}/PKG-INFO +1 -1
  2. {dh_cli-0.4.4 → dh_cli-0.4.5}/pyproject.toml +1 -1
  3. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/test.py +73 -0
  4. {dh_cli-0.4.4 → dh_cli-0.4.5}/.gitignore +0 -0
  5. {dh_cli-0.4.4 → dh_cli-0.4.5}/LICENSE +0 -0
  6. {dh_cli-0.4.4 → dh_cli-0.4.5}/README.md +0 -0
  7. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/__init__.py +0 -0
  8. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/__init__.py +0 -0
  9. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/aws_batch.py +0 -0
  10. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/__init__.py +0 -0
  11. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/boltz.py +0 -0
  12. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/cancel.py +0 -0
  13. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/clean.py +0 -0
  14. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/embed_t5.py +0 -0
  15. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/finalize.py +0 -0
  16. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/list_jobs.py +0 -0
  17. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/local.py +0 -0
  18. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/logs.py +0 -0
  19. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/protmpnn.py +0 -0
  20. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/protmpnn_to_boltz.py +0 -0
  21. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/retry.py +0 -0
  22. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/status.py +0 -0
  23. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/submit.py +0 -0
  24. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/train.py +0 -0
  25. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/commands/wait_for.py +0 -0
  26. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/fasta_utils.py +0 -0
  27. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/h5_utils.py +0 -0
  28. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/job_id.py +0 -0
  29. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/manifest.py +0 -0
  30. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/batch/s3_transport.py +0 -0
  31. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/cloud_commands.py +0 -0
  32. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/codeartifact.py +0 -0
  33. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/__init__.py +0 -0
  34. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/api_client.py +0 -0
  35. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/auth.py +0 -0
  36. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/engine_commands.py +0 -0
  37. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/progress.py +0 -0
  38. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/ssh_config.py +0 -0
  39. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/engines_studios/studio_commands.py +0 -0
  40. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/github_commands.py +0 -0
  41. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/__init__.py +0 -0
  42. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/deploy.py +0 -0
  43. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/local.py +0 -0
  44. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/tf.py +0 -0
  45. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/hz/users.py +0 -0
  46. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/main.py +0 -0
  47. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/utility_commands.py +0 -0
  48. {dh_cli-0.4.4 → dh_cli-0.4.5}/src/dh_cli/warehouse.py +0 -0
  49. {dh_cli-0.4.4 → dh_cli-0.4.5}/tests/hz/test_init.py +0 -0
  50. {dh_cli-0.4.4 → dh_cli-0.4.5}/tests/hz/test_suites.py +0 -0
  51. {dh_cli-0.4.4 → dh_cli-0.4.5}/tests/hz/test_users.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dh-cli
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: Dayhoff Labs developer CLI
5
5
  Author-email: Dayhoff Labs <dev@dayhofflabs.com>
6
6
  License: # PolyForm Noncommercial License 1.0.0
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dh-cli"
7
- version = "0.4.4"
7
+ version = "0.4.5"
8
8
  description = "Dayhoff Labs developer CLI"
9
9
  requires-python = ">=3.11"
10
10
  readme = "README.md"
@@ -1,5 +1,6 @@
1
1
  """Run integration test suites."""
2
2
 
3
+ import os
3
4
  import re
4
5
  from pathlib import Path
5
6
  from typing import Optional
@@ -48,6 +49,75 @@ def _resolve_suites(
48
49
  return matched
49
50
 
50
51
 
52
+ def _ensure_jwt_token(env: str, test_dir: Path) -> None:
53
+ """Ensure HORIZYN_TOKEN is set, prompting interactively if needed.
54
+
55
+ Checks (in order): env var with expiry validation, cached token file,
56
+ then falls back to interactive Cognito passwordless auth.
57
+ Sets os.environ["HORIZYN_TOKEN"] so child processes inherit it.
58
+ """
59
+ import json
60
+ import subprocess
61
+ import time
62
+
63
+ token_script = test_dir / "get_jwt_token.py"
64
+ cache_dir = Path.home() / ".horizyn"
65
+ cache_file = cache_dir / f"token_{env}"
66
+
67
+ def _token_valid(token: str) -> bool:
68
+ """Check JWT expiry without verification (5-minute buffer)."""
69
+ import base64
70
+
71
+ try:
72
+ payload = token.split(".")[1]
73
+ padding = 4 - len(payload) % 4
74
+ if padding != 4:
75
+ payload += "=" * padding
76
+ decoded = json.loads(base64.urlsafe_b64decode(payload))
77
+ return time.time() < (decoded.get("exp", 0) - 300)
78
+ except Exception:
79
+ return False
80
+
81
+ # 1. Check existing env var
82
+ existing = os.environ.get("HORIZYN_TOKEN", "")
83
+ if existing and _token_valid(existing):
84
+ typer.secho(" Using existing HORIZYN_TOKEN", fg=typer.colors.GREEN)
85
+ return
86
+
87
+ # 2. Check cached token file
88
+ if cache_file.exists():
89
+ cached = cache_file.read_text().strip()
90
+ if cached and _token_valid(cached):
91
+ os.environ["HORIZYN_TOKEN"] = cached
92
+ typer.secho(f" Using cached token from {cache_file}", fg=typer.colors.GREEN)
93
+ return
94
+ cache_file.unlink(missing_ok=True)
95
+
96
+ # 3. Interactive: run get_jwt_token.py (prompts go to stderr, token to stdout)
97
+ typer.echo()
98
+ typer.secho(" No valid token found — starting authentication.", fg=typer.colors.YELLOW)
99
+ typer.echo()
100
+
101
+ result = subprocess.run(
102
+ ["python3", str(token_script), "--env", env],
103
+ capture_output=False,
104
+ stdout=subprocess.PIPE,
105
+ text=True,
106
+ )
107
+
108
+ if result.returncode != 0 or not result.stdout.strip():
109
+ typer.secho(" Authentication failed.", fg=typer.colors.RED, err=True)
110
+ raise typer.Exit(1)
111
+
112
+ token = result.stdout.strip()
113
+ os.environ["HORIZYN_TOKEN"] = token
114
+
115
+ # Cache for future runs
116
+ cache_dir.mkdir(mode=0o700, exist_ok=True)
117
+ cache_file.write_text(token)
118
+ cache_file.chmod(0o600)
119
+
120
+
51
121
  @test_app.command("list")
52
122
  def list_tests(
53
123
  target: str = typer.Option("local", "--target", "-t", help="local or deployed."),
@@ -98,9 +168,12 @@ def test_deployed(
98
168
  test_dir = repo / "test/server/deployed"
99
169
 
100
170
  if not suites:
171
+ # run_all_tests.sh handles its own token flow
101
172
  run_script(test_dir / "run_all_tests.sh", args=[env], cwd=test_dir)
102
173
  return
103
174
 
175
+ _ensure_jwt_token(env, test_dir)
176
+
104
177
  available = _discover_suites(test_dir)
105
178
  selected = _resolve_suites(available, suites)
106
179
 
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