dh-cli 0.16.0__tar.gz → 0.17.0__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 (137) hide show
  1. {dh_cli-0.16.0 → dh_cli-0.17.0}/PKG-INFO +1 -1
  2. {dh_cli-0.16.0 → dh_cli-0.17.0}/pyproject.toml +1 -1
  3. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/embed_esmc.py +9 -1
  4. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/protmpnn_to_boltz.py +2 -1
  5. dh_cli-0.17.0/tests/batch/test_import_without_pandas.py +16 -0
  6. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_embed_esmc_cli.py +21 -3
  7. {dh_cli-0.16.0 → dh_cli-0.17.0}/.gitignore +0 -0
  8. {dh_cli-0.16.0 → dh_cli-0.17.0}/LICENSE +0 -0
  9. {dh_cli-0.16.0 → dh_cli-0.17.0}/README.md +0 -0
  10. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/__init__.py +0 -0
  11. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/_identity.py +0 -0
  12. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/__init__.py +0 -0
  13. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/aws_batch.py +0 -0
  14. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/__init__.py +0 -0
  15. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/boltz.py +0 -0
  16. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/cancel.py +0 -0
  17. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/clean.py +0 -0
  18. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/cost.py +0 -0
  19. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/disco.py +0 -0
  20. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/embed_t5.py +0 -0
  21. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/equilibrator.py +0 -0
  22. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/esmfold2.py +0 -0
  23. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/finalize.py +0 -0
  24. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/list_jobs.py +0 -0
  25. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/local.py +0 -0
  26. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/logs.py +0 -0
  27. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/orca.py +0 -0
  28. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/protmpnn.py +0 -0
  29. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/retry.py +0 -0
  30. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/rfd3.py +0 -0
  31. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/status.py +0 -0
  32. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/submit.py +0 -0
  33. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/commands/wait_for.py +0 -0
  34. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/cost_report.py +0 -0
  35. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/fasta_utils.py +0 -0
  36. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/h5_utils.py +0 -0
  37. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/job_id.py +0 -0
  38. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/manifest.py +0 -0
  39. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/batch/s3_transport.py +0 -0
  40. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/bedrock/__init__.py +0 -0
  41. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/bedrock/commands.py +0 -0
  42. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/bedrock/cost_report.py +0 -0
  43. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/bedrock/pricing.yaml +0 -0
  44. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/cloud_commands.py +0 -0
  45. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/codeartifact.py +0 -0
  46. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/__init__.py +0 -0
  47. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/api_client.py +0 -0
  48. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/auth.py +0 -0
  49. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/engine_commands.py +0 -0
  50. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/progress.py +0 -0
  51. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/retry.py +0 -0
  52. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/ssh_config.py +0 -0
  53. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/studio_commands.py +0 -0
  54. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/engines_studios/studio_resolve.py +0 -0
  55. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/github_commands.py +0 -0
  56. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/__init__.py +0 -0
  57. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/auth.py +0 -0
  58. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/deploy.py +0 -0
  59. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/local.py +0 -0
  60. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/mcp_server.py +0 -0
  61. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/test.py +0 -0
  62. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/tf.py +0 -0
  63. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/hz/users.py +0 -0
  64. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/main.py +0 -0
  65. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/sweep.py +0 -0
  66. {dh_cli-0.16.0 → dh_cli-0.17.0}/src/dh_cli/warehouse.py +0 -0
  67. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/__init__.py +0 -0
  68. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/cur_fixtures.py +0 -0
  69. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_aws_batch_resources.py +0 -0
  70. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_batch_cost_command.py +0 -0
  71. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_batch_cost_filters.py +0 -0
  72. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_batch_cost_reader.py +0 -0
  73. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_batch_cost_reconcile.py +0 -0
  74. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_batch_cost_report.py +0 -0
  75. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_image_override.py +0 -0
  76. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_no_train_command.py +0 -0
  77. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_submit_cpu_only.py +0 -0
  78. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_submit_image_validation.py +0 -0
  79. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_submit_job_tags.py +0 -0
  80. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_submit_merge.py +0 -0
  81. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/batch/test_submit_mlflow_env.py +0 -0
  82. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/conftest.py +0 -0
  83. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/A_cache_write.json +0 -0
  84. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/B_cache_read.json +0 -0
  85. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/C_plain.json +0 -0
  86. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/D_cursor_user.json +0 -0
  87. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/E_service_role.json +0 -0
  88. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/F_legacy_shared.json +0 -0
  89. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/fixtures/G_unknown_model.json +0 -0
  90. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_build_report.py +0 -0
  91. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_classify_arn.py +0 -0
  92. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_cli_exit_codes.py +0 -0
  93. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_cost_calc.py +0 -0
  94. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_cost_command.py +0 -0
  95. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_cur_reconciliation.py +0 -0
  96. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_key_command.py +0 -0
  97. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_render_formats.py +0 -0
  98. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_resolve_base_model.py +0 -0
  99. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_rotate.py +0 -0
  100. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/bedrock/test_s3_walker.py +0 -0
  101. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/__init__.py +0 -0
  102. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/test_engine_retry_commands.py +0 -0
  103. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/test_retry.py +0 -0
  104. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/test_ssh_config.py +0 -0
  105. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/test_studio_resolution_commands.py +0 -0
  106. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/engines_studios/test_studio_resolve.py +0 -0
  107. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/__init__.py +0 -0
  108. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/conftest.py +0 -0
  109. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_engine_role_cannot_read_github_pat.py +0 -0
  110. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_identity.py +0 -0
  111. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_login.py +0 -0
  112. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_login_error_paths.py +0 -0
  113. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_login_security.py +0 -0
  114. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_logout.py +0 -0
  115. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_rotate.py +0 -0
  116. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/github/test_status.py +0 -0
  117. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/live_smoke.py +0 -0
  118. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/test_auth.py +0 -0
  119. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/test_init.py +0 -0
  120. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/test_mcp_server.py +0 -0
  121. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/test_suites.py +0 -0
  122. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/hz/test_users.py +0 -0
  123. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_aws_status.py +0 -0
  124. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_cloud_gcp.py +0 -0
  125. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_disco_command.py +0 -0
  126. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_disco_jobdef.py +0 -0
  127. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_equilibrator_command.py +0 -0
  128. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_esmfold2_cli.py +0 -0
  129. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_boltz_tar.py +0 -0
  130. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_disco.py +0 -0
  131. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_disco_dispatch.py +0 -0
  132. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_equilibrator.py +0 -0
  133. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_esmfold2.py +0 -0
  134. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_protmpnn.py +0 -0
  135. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_finalize_rfd3.py +0 -0
  136. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_rfd3_command.py +0 -0
  137. {dh_cli-0.16.0 → dh_cli-0.17.0}/tests/test_sweep.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dh-cli
3
- Version: 0.16.0
3
+ Version: 0.17.0
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.16.0"
7
+ version = "0.17.0"
8
8
  description = "Dayhoff Labs developer CLI"
9
9
  requires-python = ">=3.11"
10
10
  readme = "README.md"
@@ -27,13 +27,16 @@ DEFAULT_WORKERS = 50
27
27
  DEFAULT_SEQS_PER_CHUNK = 5000
28
28
  DEFAULT_JOB_DEFINITION = "dayhoff-embed-esmc"
29
29
  DEFAULT_IMAGE_URI = "074735440724.dkr.ecr.us-east-1.amazonaws.com/dayhoff:esmc-latest"
30
+ # (vCPUs, MiB) overriding the job def (4 vCPU / 15000 MiB), which 300m/600m use as-is.
31
+ # 6B's loader holds the whole fp32 checkpoint in host RAM: measured peak RSS 34.3 GiB (slice 5), +15%.
32
+ MODEL_RESOURCES = {"6b": (8, 40960)}
30
33
 
31
34
 
32
35
  @click.command()
33
36
  @click.argument("input_fasta", type=click.Path(exists=True))
34
37
  @click.option(
35
38
  "--model",
36
- type=click.Choice(["300m", "600m"]),
39
+ type=click.Choice(["300m", "600m", "6b"]),
37
40
  default="600m",
38
41
  show_default=True,
39
42
  help="ESMC model size",
@@ -114,6 +117,7 @@ def embed_esmc(
114
117
  actual_seqs_per_chunk = (num_sequences + num_chunks - 1) // num_chunks
115
118
 
116
119
  job_id = generate_job_id("esmc")
120
+ vcpus, memory_mb = MODEL_RESOURCES.get(model, (None, None))
117
121
 
118
122
  click.echo()
119
123
  click.echo(f"Job ID: {job_id}")
@@ -126,6 +130,8 @@ def embed_esmc(
126
130
  click.echo(f"Seqs per chunk: ~{actual_seqs_per_chunk:,}")
127
131
  click.echo(f"Queue: {queue}")
128
132
  click.echo(f"Job definition: {DEFAULT_JOB_DEFINITION}")
133
+ if vcpus is not None:
134
+ click.echo(f"Resources: {vcpus} vCPU / {memory_mb} MiB (override)")
129
135
  click.echo(f"Storage: {'S3 (remote)' if use_s3 else 'Primordial'}")
130
136
 
131
137
  if dry_run:
@@ -217,6 +223,8 @@ def embed_esmc(
217
223
  retry_attempts=3,
218
224
  depends_on=depends_on,
219
225
  share_identifier=get_aws_username(),
226
+ vcpus=vcpus,
227
+ memory_mb=memory_mb,
220
228
  )
221
229
  except BatchError as e:
222
230
  manifest.status = JobStatus.FAILED
@@ -4,7 +4,6 @@ import shutil
4
4
  from pathlib import Path
5
5
 
6
6
  import click
7
- import pandas as pd
8
7
  import yaml
9
8
 
10
9
 
@@ -44,6 +43,8 @@ def protmpnn_to_boltz(results_dir, top, output, config_dir):
44
43
  dh batch boltz boltz_in/
45
44
  dh batch boltz --local boltz_in/
46
45
  """
46
+ import pandas as pd
47
+
47
48
  results_path = Path(results_dir).resolve()
48
49
  csv_path = results_path / "results.csv"
49
50
 
@@ -0,0 +1,16 @@
1
+ """`dh batch` must load without pandas, which is not a dh-cli dependency."""
2
+
3
+ import subprocess
4
+ import sys
5
+
6
+
7
+ def test_batch_cli_help_without_pandas():
8
+ code = (
9
+ "import sys; sys.modules['pandas'] = None\n"
10
+ "from click.testing import CliRunner\n"
11
+ "from dh_cli.batch import batch_cli\n"
12
+ "r = CliRunner().invoke(batch_cli, ['--help'])\n"
13
+ "assert r.exit_code == 0, r.output\n"
14
+ )
15
+ result = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True)
16
+ assert result.returncode == 0, result.stderr
@@ -77,10 +77,28 @@ def test_dry_run_prints_plan_no_submit(runner, fasta):
77
77
  assert "Dry run" in out
78
78
 
79
79
 
80
- def test_model_6b_rejected(runner, fasta):
80
+ def test_model_6b_accepted(runner, fasta):
81
81
  result = runner.invoke(esmc_cmd.embed_esmc, [str(fasta), "--dry-run", "--model", "6b"])
82
- assert result.exit_code != 0
83
- assert "Invalid value" in result.output
82
+ assert result.exit_code == 0, result.output
83
+ assert "ESMC-6b" in result.output
84
+
85
+
86
+ def test_6b_submit_overrides_resources(runner, fasta):
87
+ result, client, _, _ = _invoke_submit(runner, fasta, ["--model", "6b"])
88
+ assert result.exit_code == 0, result.output
89
+ kwargs = client.submit_job.call_args.kwargs
90
+ vcpus, memory_mb = esmc_cmd.MODEL_RESOURCES["6b"]
91
+ assert (kwargs["vcpus"], kwargs["memory_mb"]) == (vcpus, memory_mb)
92
+ # The loader holds the whole fp32 checkpoint (~25.4 GB) in host RAM.
93
+ assert memory_mb > 25.4e9 / 2**20
94
+
95
+
96
+ def test_600m_submit_uses_job_definition_resources(runner, fasta):
97
+ result, client, _, _ = _invoke_submit(runner, fasta)
98
+ assert result.exit_code == 0, result.output
99
+ kwargs = client.submit_job.call_args.kwargs
100
+ assert kwargs.get("vcpus") is None
101
+ assert kwargs.get("memory_mb") is None
84
102
 
85
103
 
86
104
  def test_submit_default_env_s3_mode(runner, fasta):
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes