dayhoff-tools 1.3.27__tar.gz → 1.3.29__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 (32) hide show
  1. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/PKG-INFO +1 -1
  2. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/engine_commands.py +57 -4
  3. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/pyproject.toml +1 -1
  4. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/README.md +0 -0
  5. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/__init__.py +0 -0
  6. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/chemistry/standardizer.py +0 -0
  7. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/chemistry/utils.py +0 -0
  8. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/__init__.py +0 -0
  9. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/cloud_commands.py +0 -0
  10. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/main.py +0 -0
  11. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/swarm_commands.py +0 -0
  12. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/cli/utility_commands.py +0 -0
  13. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/base.py +0 -0
  14. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/deploy_aws.py +0 -0
  15. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/deploy_gcp.py +0 -0
  16. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/deploy_utils.py +0 -0
  17. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/job_runner.py +0 -0
  18. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/processors.py +0 -0
  19. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/deployment/swarm.py +0 -0
  20. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/embedders.py +0 -0
  21. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/fasta.py +0 -0
  22. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/file_ops.py +0 -0
  23. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/h5.py +0 -0
  24. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/gcp.py +0 -0
  25. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/gtdb.py +0 -0
  26. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/kegg.py +0 -0
  27. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/mmseqs.py +0 -0
  28. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/structure.py +0 -0
  29. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/intake/uniprot.py +0 -0
  30. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/logs.py +0 -0
  31. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/sqlite.py +0 -0
  32. {dayhoff_tools-1.3.27 → dayhoff_tools-1.3.29}/dayhoff_tools/warehouse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dayhoff-tools
3
- Version: 1.3.27
3
+ Version: 1.3.29
4
4
  Summary: Common tools for all the repos at Dayhoff Labs
5
5
  Author: Daniel Martin-Alarcon
6
6
  Author-email: dma@dayhofflabs.com
@@ -15,7 +15,7 @@ from botocore.exceptions import ClientError, NoCredentialsError
15
15
  from rich import box
16
16
  from rich.console import Console
17
17
  from rich.panel import Panel
18
- from rich.progress import Progress, SpinnerColumn, TextColumn
18
+ from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
19
19
  from rich.prompt import Confirm, IntPrompt, Prompt
20
20
  from rich.table import Table
21
21
  import re
@@ -1314,6 +1314,40 @@ def create_ami(
1314
1314
  )
1315
1315
  console.print(f" Excluding volume at {device_name}")
1316
1316
 
1317
+ # --- Check & detach attached studios --------------------------------------------------
1318
+ # If any user studios are still attached we must detach them before the instance reboots
1319
+ # for snapshot consistency; otherwise Studio-Manager metadata becomes stale.
1320
+
1321
+ attached_resp = make_api_request("GET", f"/engines/{engine['instance_id']}/studios")
1322
+ attached_studios = attached_resp.json().get("studios", []) if attached_resp.status_code == 200 else []
1323
+
1324
+ if attached_studios:
1325
+ console.print(f"[yellow]⚠ {len(attached_studios)} studio(s) attached to this engine.[/yellow]")
1326
+ for s in attached_studios:
1327
+ console.print(f" • {s['user']} ({s['studio_id']})")
1328
+
1329
+ if not Confirm.ask("Detach all studios before AMI creation?"):
1330
+ console.print("AMI creation cancelled.")
1331
+ return
1332
+
1333
+ console.print("Detaching studios…")
1334
+ for s in attached_studios:
1335
+ resp = make_api_request("POST", f"/studios/{s['studio_id']}/detach")
1336
+ if resp.status_code != 200:
1337
+ console.print(f"[red]❌ Failed to detach {s['studio_id']} – aborting.[/red]")
1338
+ return
1339
+
1340
+ # Wait briefly for volumes to become available (max 2 min)
1341
+ import time, boto3
1342
+ ec2_wait = boto3.client("ec2", region_name="us-east-1")
1343
+ vol_ids = [s['studio_id'] for s in attached_studios]
1344
+ console.print("Waiting for volumes to detach…")
1345
+ waiter = ec2_wait.get_waiter("volume_available")
1346
+ try:
1347
+ waiter.wait(VolumeIds=vol_ids, WaiterConfig={"Delay": 5, "MaxAttempts": 24})
1348
+ except Exception:
1349
+ console.print("[yellow]Proceeding even though some volumes may still be detaching.[/yellow]")
1350
+
1317
1351
  # Create the AMI
1318
1352
  with Progress(
1319
1353
  SpinnerColumn(),
@@ -1594,9 +1628,28 @@ def attach_studio(
1594
1628
  raise typer.Exit(1)
1595
1629
  console.print("[green]✓ Engine started[/green]")
1596
1630
  console.print("Waiting for engine to be ready...")
1597
- import time
1598
-
1599
- time.sleep(10)
1631
+ # Wait until the engine is fully running & marked ready (max 5 min)
1632
+ console.print("Waiting for engine to be ready (this can take a couple of minutes)…")
1633
+ # Progress classes already imported at module level – do not re-import to avoid UnboundLocalError
1634
+
1635
+ with Progress(SpinnerColumn(), TimeElapsedColumn(), TextColumn("[progress.description]{task.description}"), transient=True) as prog:
1636
+ prog.add_task("Awaiting engine readiness…", total=None)
1637
+ max_attempts = 30 # 30 × 10 s ≈ 5 min
1638
+ for _ in range(max_attempts):
1639
+ time.sleep(10)
1640
+
1641
+ status_resp = make_api_request("GET", f"/engines/{engine['instance_id']}")
1642
+ if status_resp.status_code != 200:
1643
+ continue
1644
+
1645
+ detailed = status_resp.json().get("engine", {})
1646
+ state_ok = detailed.get("state", "").lower() == "running"
1647
+ ready_ok = detailed.get("ready") is True
1648
+
1649
+ if state_ok and ready_ok:
1650
+ break
1651
+ else:
1652
+ console.print("[yellow]Engine is still starting up. If attachment fails, wait a little longer and retry.[/yellow]")
1600
1653
  else:
1601
1654
  raise typer.Exit(1)
1602
1655
 
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
5
5
 
6
6
  [project]
7
7
  name = "dayhoff-tools"
8
- version = "1.3.27"
8
+ version = "1.3.29"
9
9
  description = "Common tools for all the repos at Dayhoff Labs"
10
10
  authors = [
11
11
  {name = "Daniel Martin-Alarcon", email = "dma@dayhofflabs.com"}
File without changes