starbash 0.1.8__py3-none-any.whl → 0.1.10__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.

Potentially problematic release.


This version of starbash might be problematic. Click here for more details.

@@ -2,18 +2,20 @@
2
2
 
3
3
  import os
4
4
  from typing import Any
5
+ from collections import Counter
5
6
  import typer
6
7
  from pathlib import Path
7
8
  from typing_extensions import Annotated
8
- from datetime import datetime
9
9
  from rich.table import Table
10
+ import logging
10
11
 
12
+ import starbash
13
+ from starbash import to_shortdate
11
14
  from starbash.app import Starbash, copy_images_to_dir
12
- from starbash.database import Database, get_column_name
15
+ from starbash.database import Database, SessionRow, get_column_name
13
16
  from starbash import console
14
17
  from starbash.commands import (
15
18
  format_duration,
16
- to_shortdate,
17
19
  TABLE_COLUMN_STYLE,
18
20
  TABLE_VALUE_STYLE,
19
21
  )
@@ -21,6 +23,58 @@ from starbash.commands import (
21
23
  app = typer.Typer()
22
24
 
23
25
 
26
+ def get_column(sb: Starbash, column_name: str) -> Counter:
27
+
28
+ # Also do a complete unfiltered search so we can compare for the users
29
+ allsessions = sb.db.search_session(("", []))
30
+
31
+ column_name = get_column_name(column_name)
32
+ allfound = [session[column_name] for session in allsessions if session[column_name]]
33
+
34
+ # Count occurrences of each telescope
35
+ all_counts = Counter(allfound)
36
+
37
+ return all_counts
38
+
39
+
40
+ def complete_date(incomplete: str, column_name: str):
41
+ """calls get_column() and assumes the returned str->count object has iso datetime strings as the keys
42
+ it merges the counts for all dates that are on the same local timezone day.
43
+ in the returned str->count, just include the date portion (YYYY-MM-DD)."""
44
+
45
+ # We need to use stderr_logging to prevent confusing the bash completion parser
46
+ starbash.log_filter_level = (
47
+ logging.ERROR
48
+ ) # avoid showing output while doing completion
49
+ with Starbash("select.complete.date", stderr_logging=True) as sb:
50
+ c = get_column(sb, column_name)
51
+
52
+ # Merge counts by date (YYYY-MM-DD) in local timezone
53
+ date_counts = Counter()
54
+ for datetime_str, count in c.items():
55
+ # Extract just the date portion (YYYY-MM-DD) from local datetime
56
+ date_only = to_shortdate(datetime_str)
57
+ date_counts[date_only] += count
58
+
59
+ # Yield completions matching the incomplete input
60
+ for date, count in sorted(date_counts.items(), reverse=True):
61
+ if date.startswith(incomplete):
62
+ yield (date, f"{count} sessions")
63
+
64
+
65
+ def complete_column(incomplete: str, column_name: str):
66
+ # We need to use stderr_logging to prevent confusing the bash completion parser
67
+ starbash.log_filter_level = (
68
+ logging.ERROR
69
+ ) # avoid showing output while doing completion
70
+ with Starbash("repo.complete.column", stderr_logging=True) as sb:
71
+ c = get_column(sb, column_name)
72
+
73
+ for item, count in c.items():
74
+ if item.lower().startswith(incomplete.lower()):
75
+ yield (item, f"{count} sessions")
76
+
77
+
24
78
  @app.command(name="any")
25
79
  def clear():
26
80
  """Remove any filters on sessions, etc... (select everything)."""
@@ -34,7 +88,10 @@ def target(
34
88
  target_name: Annotated[
35
89
  str,
36
90
  typer.Argument(
37
- help="Target name to add to the selection (e.g., 'M31', 'NGC 7000')"
91
+ help="Target name to add to the selection (e.g., 'M31', 'NGC 7000')",
92
+ autocompletion=lambda incomplete: complete_column(
93
+ incomplete, Database.OBJECT_KEY
94
+ ),
38
95
  ),
39
96
  ],
40
97
  ):
@@ -52,7 +109,10 @@ def telescope(
52
109
  telescope_name: Annotated[
53
110
  str,
54
111
  typer.Argument(
55
- help="Telescope name to add to the selection (e.g., 'Vespera', 'EdgeHD 8')"
112
+ help="Telescope name to add to the selection (e.g., 'Vespera', 'EdgeHD 8')",
113
+ autocompletion=lambda incomplete: complete_column(
114
+ incomplete, Database.TELESCOP_KEY
115
+ ),
56
116
  ),
57
117
  ],
58
118
  ):
@@ -67,21 +127,41 @@ def telescope(
67
127
  )
68
128
 
69
129
 
130
+ def complete_name(incomplete: str, names: list[str]):
131
+ """Return typer style autocompletion from a list of string constants."""
132
+ for name in names:
133
+ if name.startswith(incomplete):
134
+ yield name
135
+
136
+
70
137
  @app.command()
71
138
  def date(
72
139
  operation: Annotated[
73
140
  str,
74
- typer.Argument(help="Date operation: 'after', 'before', or 'between'"),
141
+ typer.Argument(
142
+ help="Date operation: 'after', 'before', or 'between'",
143
+ autocompletion=lambda incomplete: complete_name(
144
+ incomplete, ["after", "before", "between"]
145
+ ),
146
+ ),
75
147
  ],
76
148
  date_value: Annotated[
77
149
  str,
78
150
  typer.Argument(
79
- help="Date in ISO format (YYYY-MM-DD) or two dates separated by space for 'between'"
151
+ help="Date in ISO format (YYYY-MM-DD) or two dates separated by space for 'between'",
152
+ autocompletion=lambda incomplete: complete_date(
153
+ incomplete, Database.START_KEY
154
+ ),
80
155
  ),
81
156
  ],
82
157
  end_date: Annotated[
83
158
  str | None,
84
- typer.Argument(help="End date for 'between' operation (YYYY-MM-DD)"),
159
+ typer.Argument(
160
+ help="End date for 'between' operation (YYYY-MM-DD)",
161
+ autocompletion=lambda incomplete: complete_date(
162
+ incomplete, Database.START_KEY
163
+ ),
164
+ ),
85
165
  ] = None,
86
166
  ):
87
167
  """Limit to sessions in the specified date range.
@@ -122,7 +202,14 @@ def date(
122
202
 
123
203
 
124
204
  @app.command(name="list")
125
- def list_sessions():
205
+ def list_sessions(
206
+ verbose: bool = typer.Option(
207
+ False,
208
+ "--verbose",
209
+ "-v",
210
+ help="Show all sessions (normally Dark/Bias/Flat are hidden)",
211
+ )
212
+ ):
126
213
  """List sessions (filtered based on the current selection)"""
127
214
 
128
215
  with Starbash("selection.list") as sb:
@@ -166,6 +253,13 @@ def list_sessions():
166
253
  telescope = get_key(Database.TELESCOP_KEY)
167
254
  telescopes.add(telescope)
168
255
 
256
+ # Show the non normalized target name
257
+ metadata = sess.get("metadata")
258
+ if metadata:
259
+ long_name = metadata.get("OBJECT")
260
+ if long_name:
261
+ object = long_name
262
+
169
263
  # Format total exposure time as integer seconds
170
264
  exptime_raw = get_key(Database.EXPTIME_TOTAL_KEY)
171
265
  try:
@@ -223,6 +317,32 @@ def list_sessions():
223
317
  sb.analytics.set_data("session.image_types", image_types)
224
318
 
225
319
 
320
+ def selection_by_number(
321
+ sb: Starbash,
322
+ session_num: int,
323
+ ) -> SessionRow:
324
+ """Get the session corresponding to the given session number in the current selection."""
325
+ # Get the filtered sessions
326
+ sessions = sb.search_session()
327
+
328
+ if not sessions or not isinstance(sessions, list):
329
+ console.print("[red]No sessions found. Check your selection criteria.[/red]")
330
+ raise typer.Exit(1)
331
+
332
+ # Validate session number
333
+ if session_num < 1 or session_num > len(sessions):
334
+ console.print(
335
+ f"[red]Error: Session number {session_num} is out of range. "
336
+ f"Valid range is 1-{len(sessions)}.[/red]"
337
+ )
338
+ console.print("[yellow]Use 'select list' to see available sessions.[/yellow]")
339
+ raise typer.Exit(1)
340
+
341
+ # Get the selected session (convert from 1-based to 0-based index)
342
+ session = sessions[session_num - 1]
343
+ return session
344
+
345
+
226
346
  @app.command()
227
347
  def export(
228
348
  session_num: Annotated[
@@ -242,36 +362,16 @@ def export(
242
362
  The session number corresponds to the '#' column in 'select list' output.
243
363
  """
244
364
  with Starbash("selection.export") as sb:
245
- # Get the filtered sessions
246
- sessions = sb.search_session()
247
-
248
- if not sessions or not isinstance(sessions, list):
249
- console.print(
250
- "[red]No sessions found. Check your selection criteria.[/red]"
251
- )
252
- raise typer.Exit(1)
253
-
254
- # Validate session number
255
- if session_num < 1 or session_num > len(sessions):
256
- console.print(
257
- f"[red]Error: Session number {session_num} is out of range. "
258
- f"Valid range is 1-{len(sessions)}.[/red]"
259
- )
260
- console.print(
261
- "[yellow]Use 'select list' to see available sessions.[/yellow]"
262
- )
263
- raise typer.Exit(1)
264
-
265
365
  # Get the selected session (convert from 1-based to 0-based index)
266
- session = sessions[session_num - 1]
366
+ session = selection_by_number(sb, session_num)
267
367
 
268
- # Get the session's database row ID
269
- session_id = session.get("id")
270
- if session_id is None:
368
+ # Get images for this session
369
+ images = sb.get_session_images(session)
370
+ if not images:
271
371
  console.print(
272
- f"[red]Error: Could not find session ID for session {session_num}.[/red]"
372
+ f"[red]Error: No images found for session {session_num}.[/red]"
273
373
  )
274
- raise typer.Exit(1)
374
+ raise typer.Exit(0)
275
375
 
276
376
  # Determine output directory
277
377
  output_dir = Path(destdir)
@@ -279,15 +379,6 @@ def export(
279
379
  # Create output directory if it doesn't exist
280
380
  output_dir.mkdir(parents=True, exist_ok=True)
281
381
 
282
- # Get images for this session
283
- images = sb.get_session_images(session_id)
284
-
285
- if not images:
286
- console.print(
287
- f"[yellow]Warning: No images found for session {session_num}.[/yellow]"
288
- )
289
- raise typer.Exit(0)
290
-
291
382
  copy_images_to_dir(images, output_dir)
292
383
 
293
384