dayhoff-tools 1.3.4__py3-none-any.whl → 1.3.6__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.
@@ -130,17 +130,29 @@ def parse_launch_time(launch_time_str: str) -> datetime:
130
130
  formats = [
131
131
  "%Y-%m-%dT%H:%M:%S.%fZ",
132
132
  "%Y-%m-%dT%H:%M:%SZ",
133
+ "%Y-%m-%dT%H:%M:%S%z", # ISO format with timezone
134
+ "%Y-%m-%dT%H:%M:%S+00:00", # Explicit UTC offset
133
135
  "%Y-%m-%d %H:%M:%S",
134
136
  ]
137
+
138
+ # First try parsing with fromisoformat for better timezone handling
139
+ try:
140
+ # Handle the ISO format properly
141
+ return datetime.fromisoformat(launch_time_str.replace('Z', '+00:00'))
142
+ except (ValueError, AttributeError):
143
+ pass
144
+
145
+ # Fallback to manual format parsing
135
146
  for fmt in formats:
136
147
  try:
137
148
  parsed = datetime.strptime(launch_time_str, fmt)
138
- # If the format includes 'Z', it's UTC
139
- if fmt.endswith('Z'):
149
+ # If no timezone info, assume UTC
150
+ if parsed.tzinfo is None:
140
151
  parsed = parsed.replace(tzinfo=timezone.utc)
141
152
  return parsed
142
153
  except ValueError:
143
154
  continue
155
+
144
156
  # Fallback: assume it's recent
145
157
  return datetime.now(timezone.utc)
146
158
 
@@ -326,11 +338,10 @@ def launch_engine(
326
338
  @engine_app.command("list")
327
339
  def list_engines(
328
340
  user: Optional[str] = typer.Option(None, "--user", "-u", help="Filter by user"),
329
- all_users: bool = typer.Option(False, "--all", "-a", help="Show all users' engines"),
330
341
  running_only: bool = typer.Option(False, "--running", help="Show only running engines"),
331
342
  stopped_only: bool = typer.Option(False, "--stopped", help="Show only stopped engines"),
332
343
  ):
333
- """List all engines."""
344
+ """List engines (shows all engines by default)."""
334
345
  current_user = check_aws_sso()
335
346
 
336
347
  params = {}
@@ -606,14 +617,18 @@ def ssh_engine(
606
617
  @engine_app.command("config-ssh")
607
618
  def config_ssh(
608
619
  clean: bool = typer.Option(False, "--clean", help="Remove all managed entries"),
620
+ all_engines: bool = typer.Option(False, "--all", "-a", help="Include all engines from all users"),
609
621
  ):
610
- """Update SSH config with all available engines."""
622
+ """Update SSH config with available engines."""
611
623
  username = check_aws_sso()
612
624
 
613
625
  if clean:
614
626
  console.print("Removing all managed SSH entries...")
615
627
  else:
616
- console.print("Updating SSH config with all running engines...")
628
+ if all_engines:
629
+ console.print("Updating SSH config with all running engines...")
630
+ else:
631
+ console.print(f"Updating SSH config with running engines for [cyan]{username}[/cyan] and [cyan]shared[/cyan]...")
617
632
 
618
633
  # Get all engines
619
634
  response = make_api_request("GET", "/engines")
@@ -623,6 +638,14 @@ def config_ssh(
623
638
 
624
639
  engines = response.json().get("engines", [])
625
640
  running_engines = [e for e in engines if e["state"].lower() == "running"]
641
+
642
+ # Filter engines based on options
643
+ if not all_engines:
644
+ # Show only current user's engines and shared engines
645
+ running_engines = [
646
+ e for e in running_engines
647
+ if e["user"] == username or e["user"] == "shared"
648
+ ]
626
649
 
627
650
  # Read existing config
628
651
  config_path = Path.home() / ".ssh" / "config"
@@ -673,7 +696,8 @@ def config_ssh(
673
696
  f"[green]✓ Updated SSH config with {len(running_engines)} engines[/green]"
674
697
  )
675
698
  for engine in running_engines:
676
- console.print(f"{engine['name']} {engine['instance_id']}")
699
+ user_display = f"[dim]({engine['user']})[/dim]" if engine['user'] != username else ""
700
+ console.print(f" • {engine['name']} → {engine['instance_id']} {user_display}")
677
701
 
678
702
 
679
703
  @engine_app.command("keep-awake")
@@ -1008,7 +1032,7 @@ def studio_status():
1008
1032
  # Format status with colors
1009
1033
  status = studio['status']
1010
1034
  if status == "in-use":
1011
- status_display = "[magenta]attached[/magenta]"
1035
+ status_display = "[bright_blue]attached[/bright_blue]"
1012
1036
  elif status in ["attaching", "detaching"]:
1013
1037
  status_display = f"[yellow]{status}[/yellow]"
1014
1038
  else:
@@ -1246,7 +1270,7 @@ def list_studios(
1246
1270
  for studio in studios:
1247
1271
  # Change status display
1248
1272
  if studio["status"] == "in-use":
1249
- status_display = "[magenta]attached[/magenta]"
1273
+ status_display = "[bright_blue]attached[/bright_blue]"
1250
1274
  elif studio["status"] in ["attaching", "detaching"]:
1251
1275
  status_display = "[yellow]" + studio["status"] + "[/yellow]"
1252
1276
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dayhoff-tools
3
- Version: 1.3.4
3
+ Version: 1.3.6
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
@@ -3,7 +3,7 @@ dayhoff_tools/chemistry/standardizer.py,sha256=uMn7VwHnx02nc404eO6fRuS4rsl4dvSPf
3
3
  dayhoff_tools/chemistry/utils.py,sha256=jt-7JgF-GeeVC421acX-bobKbLU_X94KNOW24p_P-_M,2257
4
4
  dayhoff_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  dayhoff_tools/cli/cloud_commands.py,sha256=33qcWLmq-FwEXMdL3F0OHm-5Stlh2r65CldyEZgQ1no,40904
6
- dayhoff_tools/cli/engine_commands.py,sha256=w0wzs4aQUdzeyAyhHH9lHxpJEG8acrbguQ4Rd0u5bA4,48179
6
+ dayhoff_tools/cli/engine_commands.py,sha256=iKyfpjDlOUpZjgjXAnEmLLkdFXFGQHPgnbblbaY1rzM,49206
7
7
  dayhoff_tools/cli/main.py,sha256=rgeEHD9lJ8SBCR34BTLb7gVInHUUdmEBNXAJnq5yEU4,4795
8
8
  dayhoff_tools/cli/swarm_commands.py,sha256=5EyKj8yietvT5lfoz8Zx0iQvVaNgc3SJX1z2zQR6o6M,5614
9
9
  dayhoff_tools/cli/utility_commands.py,sha256=qs8vH9TBFHsOPC3X8cU3qZigM3dDn-2Ytq4o_F2WubU,27874
@@ -27,7 +27,7 @@ dayhoff_tools/intake/uniprot.py,sha256=BZYJQF63OtPcBBnQ7_P9gulxzJtqyorgyuDiPeOJq
27
27
  dayhoff_tools/logs.py,sha256=DKdeP0k0kliRcilwvX0mUB2eipO5BdWUeHwh-VnsICs,838
28
28
  dayhoff_tools/sqlite.py,sha256=jV55ikF8VpTfeQqqlHSbY8OgfyfHj8zgHNpZjBLos_E,18672
29
29
  dayhoff_tools/warehouse.py,sha256=8YbnQ--usrEgDQGfvpV4MrMji55A0rq2hZaOgFGh6ag,15896
30
- dayhoff_tools-1.3.4.dist-info/METADATA,sha256=YZw82MtQpm4aWNzOfEl62Iov6ZRXtw6LfZ43eI9psKE,2842
31
- dayhoff_tools-1.3.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
32
- dayhoff_tools-1.3.4.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
33
- dayhoff_tools-1.3.4.dist-info/RECORD,,
30
+ dayhoff_tools-1.3.6.dist-info/METADATA,sha256=uZRVYjvuh-1cjuDxrOBMEsZPzfxydAiYIWL3IAhsYaA,2842
31
+ dayhoff_tools-1.3.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
32
+ dayhoff_tools-1.3.6.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
33
+ dayhoff_tools-1.3.6.dist-info/RECORD,,