starbash 0.1.11__py3-none-any.whl → 0.1.15__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.
- repo/__init__.py +1 -1
- repo/manager.py +14 -23
- repo/repo.py +52 -10
- starbash/__init__.py +10 -3
- starbash/aliases.py +49 -4
- starbash/analytics.py +3 -2
- starbash/app.py +287 -565
- starbash/check_version.py +18 -0
- starbash/commands/__init__.py +2 -1
- starbash/commands/info.py +26 -21
- starbash/commands/process.py +76 -24
- starbash/commands/repo.py +25 -68
- starbash/commands/select.py +140 -148
- starbash/commands/user.py +88 -23
- starbash/database.py +41 -27
- starbash/defaults/starbash.toml +1 -0
- starbash/exception.py +21 -0
- starbash/main.py +29 -7
- starbash/paths.py +23 -9
- starbash/processing.py +724 -0
- starbash/recipes/README.md +3 -0
- starbash/recipes/master_bias/starbash.toml +4 -1
- starbash/recipes/master_dark/starbash.toml +0 -1
- starbash/recipes/osc.py +190 -0
- starbash/recipes/osc_dual_duo/starbash.toml +31 -34
- starbash/recipes/osc_simple/starbash.toml +82 -0
- starbash/recipes/osc_single_duo/starbash.toml +51 -32
- starbash/recipes/seestar/starbash.toml +82 -0
- starbash/recipes/starbash.toml +8 -9
- starbash/selection.py +29 -38
- starbash/templates/repo/master.toml +7 -3
- starbash/templates/repo/processed.toml +7 -2
- starbash/templates/userconfig.toml +9 -0
- starbash/toml.py +13 -13
- starbash/tool.py +186 -149
- starbash-0.1.15.dist-info/METADATA +216 -0
- starbash-0.1.15.dist-info/RECORD +45 -0
- starbash/recipes/osc_dual_duo/starbash.py +0 -147
- starbash-0.1.11.dist-info/METADATA +0 -147
- starbash-0.1.11.dist-info/RECORD +0 -40
- {starbash-0.1.11.dist-info → starbash-0.1.15.dist-info}/WHEEL +0 -0
- {starbash-0.1.11.dist-info → starbash-0.1.15.dist-info}/entry_points.txt +0 -0
- {starbash-0.1.11.dist-info → starbash-0.1.15.dist-info}/licenses/LICENSE +0 -0
starbash/commands/select.py
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
"""Selection commands for filtering sessions and targets."""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from typing import Any
|
|
3
|
+
import logging
|
|
5
4
|
from collections import Counter
|
|
6
|
-
import typer
|
|
7
5
|
from pathlib import Path
|
|
8
|
-
from
|
|
6
|
+
from typing import Annotated, Any
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
9
|
from rich.table import Table
|
|
10
|
-
import logging
|
|
11
10
|
|
|
12
11
|
import starbash
|
|
13
|
-
from starbash import to_shortdate
|
|
12
|
+
from starbash import console, to_shortdate
|
|
14
13
|
from starbash.app import Starbash, copy_images_to_dir
|
|
15
|
-
from starbash.database import Database, SessionRow, get_column_name
|
|
16
|
-
from starbash import console
|
|
17
14
|
from starbash.commands import (
|
|
18
|
-
format_duration,
|
|
19
15
|
TABLE_COLUMN_STYLE,
|
|
16
|
+
TABLE_HEADER_STYLE,
|
|
20
17
|
TABLE_VALUE_STYLE,
|
|
18
|
+
format_duration,
|
|
21
19
|
)
|
|
20
|
+
from starbash.database import Database, SessionRow, get_column_name
|
|
22
21
|
|
|
23
22
|
app = typer.Typer()
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
def get_column(sb: Starbash, column_name: str) -> Counter:
|
|
27
|
-
|
|
28
26
|
# Also do a complete unfiltered search so we can compare for the users
|
|
29
|
-
allsessions = sb.db.search_session(
|
|
27
|
+
allsessions = sb.db.search_session([])
|
|
30
28
|
|
|
31
29
|
column_name = get_column_name(column_name)
|
|
32
30
|
allfound = [session[column_name] for session in allsessions if session[column_name]]
|
|
@@ -43,9 +41,7 @@ def complete_date(incomplete: str, column_name: str):
|
|
|
43
41
|
in the returned str->count, just include the date portion (YYYY-MM-DD)."""
|
|
44
42
|
|
|
45
43
|
# 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
|
|
44
|
+
starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
|
|
49
45
|
with Starbash("select.complete.date", stderr_logging=True) as sb:
|
|
50
46
|
c = get_column(sb, column_name)
|
|
51
47
|
|
|
@@ -64,9 +60,7 @@ def complete_date(incomplete: str, column_name: str):
|
|
|
64
60
|
|
|
65
61
|
def complete_column(incomplete: str, column_name: str):
|
|
66
62
|
# 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
|
|
63
|
+
starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
|
|
70
64
|
with Starbash("repo.complete.column", stderr_logging=True) as sb:
|
|
71
65
|
c = get_column(sb, column_name)
|
|
72
66
|
|
|
@@ -81,6 +75,7 @@ def clear():
|
|
|
81
75
|
with Starbash("selection.clear") as sb:
|
|
82
76
|
sb.selection.clear()
|
|
83
77
|
console.print("[green]Selection cleared - now selecting all sessions[/green]")
|
|
78
|
+
do_list_sessions(sb, brief=not starbash.verbose_output)
|
|
84
79
|
|
|
85
80
|
|
|
86
81
|
@app.command()
|
|
@@ -89,9 +84,7 @@ def target(
|
|
|
89
84
|
str,
|
|
90
85
|
typer.Argument(
|
|
91
86
|
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
|
-
),
|
|
87
|
+
autocompletion=lambda incomplete: complete_column(incomplete, Database.OBJECT_KEY),
|
|
95
88
|
),
|
|
96
89
|
],
|
|
97
90
|
):
|
|
@@ -102,6 +95,7 @@ def target(
|
|
|
102
95
|
sb.selection.targets = []
|
|
103
96
|
sb.selection.add_target(target_name)
|
|
104
97
|
console.print(f"[green]Selection limited to target: {target_name}[/green]")
|
|
98
|
+
do_list_sessions(sb, brief=not starbash.verbose_output)
|
|
105
99
|
|
|
106
100
|
|
|
107
101
|
@app.command()
|
|
@@ -110,9 +104,7 @@ def telescope(
|
|
|
110
104
|
str,
|
|
111
105
|
typer.Argument(
|
|
112
106
|
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
|
-
),
|
|
107
|
+
autocompletion=lambda incomplete: complete_column(incomplete, Database.TELESCOP_KEY),
|
|
116
108
|
),
|
|
117
109
|
],
|
|
118
110
|
):
|
|
@@ -122,9 +114,8 @@ def telescope(
|
|
|
122
114
|
# In the future, we could support adding multiple telescopes
|
|
123
115
|
sb.selection.telescopes = []
|
|
124
116
|
sb.selection.add_telescope(telescope_name)
|
|
125
|
-
console.print(
|
|
126
|
-
|
|
127
|
-
)
|
|
117
|
+
console.print(f"[green]Selection limited to telescope: {telescope_name}[/green]")
|
|
118
|
+
do_list_sessions(sb, brief=not starbash.verbose_output)
|
|
128
119
|
|
|
129
120
|
|
|
130
121
|
def complete_name(incomplete: str, names: list[str]):
|
|
@@ -149,18 +140,14 @@ def date(
|
|
|
149
140
|
str,
|
|
150
141
|
typer.Argument(
|
|
151
142
|
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
|
-
),
|
|
143
|
+
autocompletion=lambda incomplete: complete_date(incomplete, Database.START_KEY),
|
|
155
144
|
),
|
|
156
145
|
],
|
|
157
146
|
end_date: Annotated[
|
|
158
147
|
str | None,
|
|
159
148
|
typer.Argument(
|
|
160
149
|
help="End date for 'between' operation (YYYY-MM-DD)",
|
|
161
|
-
autocompletion=lambda incomplete: complete_date(
|
|
162
|
-
incomplete, Database.START_KEY
|
|
163
|
-
),
|
|
150
|
+
autocompletion=lambda incomplete: complete_date(incomplete, Database.START_KEY),
|
|
164
151
|
),
|
|
165
152
|
] = None,
|
|
166
153
|
):
|
|
@@ -176,19 +163,13 @@ def date(
|
|
|
176
163
|
|
|
177
164
|
if operation == "after":
|
|
178
165
|
sb.selection.set_date_range(start=date_value, end=None)
|
|
179
|
-
console.print(
|
|
180
|
-
f"[green]Selection limited to sessions after {date_value}[/green]"
|
|
181
|
-
)
|
|
166
|
+
console.print(f"[green]Selection limited to sessions after {date_value}[/green]")
|
|
182
167
|
elif operation == "before":
|
|
183
168
|
sb.selection.set_date_range(start=None, end=date_value)
|
|
184
|
-
console.print(
|
|
185
|
-
f"[green]Selection limited to sessions before {date_value}[/green]"
|
|
186
|
-
)
|
|
169
|
+
console.print(f"[green]Selection limited to sessions before {date_value}[/green]")
|
|
187
170
|
elif operation == "between":
|
|
188
171
|
if not end_date:
|
|
189
|
-
console.print(
|
|
190
|
-
"[red]Error: 'between' operation requires two dates[/red]"
|
|
191
|
-
)
|
|
172
|
+
console.print("[red]Error: 'between' operation requires two dates[/red]")
|
|
192
173
|
raise typer.Exit(1)
|
|
193
174
|
sb.selection.set_date_range(start=date_value, end=end_date)
|
|
194
175
|
console.print(
|
|
@@ -200,90 +181,91 @@ def date(
|
|
|
200
181
|
)
|
|
201
182
|
raise typer.Exit(1)
|
|
202
183
|
|
|
184
|
+
do_list_sessions(sb, brief=not starbash.verbose_output)
|
|
203
185
|
|
|
204
|
-
@app.command(name="list")
|
|
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
|
-
):
|
|
213
|
-
"""List sessions (filtered based on the current selection)"""
|
|
214
186
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if sessions and isinstance(sessions, list):
|
|
218
|
-
len_all = sb.db.len_table(Database.SESSIONS_TABLE)
|
|
219
|
-
table = Table(title=f"Sessions ({len(sessions)} selected out of {len_all})")
|
|
220
|
-
sb.analytics.set_data("session.num_selected", len(sessions))
|
|
221
|
-
sb.analytics.set_data("session.num_total", len_all)
|
|
222
|
-
|
|
223
|
-
table.add_column("#", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
224
|
-
table.add_column("Date", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
225
|
-
table.add_column("# images", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
226
|
-
table.add_column("Time", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
227
|
-
table.add_column("Type/Filter", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
228
|
-
table.add_column("Telescope", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
229
|
-
table.add_column(
|
|
230
|
-
"About", style=TABLE_COLUMN_STYLE, no_wrap=True
|
|
231
|
-
) # type of frames, filter, target
|
|
232
|
-
|
|
233
|
-
total_images = 0
|
|
234
|
-
total_seconds = 0.0
|
|
235
|
-
filters = set()
|
|
236
|
-
image_types = set()
|
|
237
|
-
telescopes = set()
|
|
238
|
-
|
|
239
|
-
def get_key(k: str, default: Any = "N/A") -> Any:
|
|
240
|
-
"""Convert keynames to SQL legal column names"""
|
|
241
|
-
k = get_column_name(k)
|
|
242
|
-
return sess.get(k, default)
|
|
243
|
-
|
|
244
|
-
for session_index, sess in enumerate(sessions):
|
|
245
|
-
date_iso = get_key(Database.START_KEY)
|
|
246
|
-
date = to_shortdate(date_iso)
|
|
247
|
-
|
|
248
|
-
object = get_key(Database.OBJECT_KEY)
|
|
249
|
-
filter = get_key(Database.FILTER_KEY)
|
|
250
|
-
filters.add(filter)
|
|
251
|
-
image_type = get_key(Database.IMAGETYP_KEY)
|
|
252
|
-
image_types.add(image_type)
|
|
253
|
-
telescope = get_key(Database.TELESCOP_KEY)
|
|
254
|
-
telescopes.add(telescope)
|
|
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
|
-
|
|
263
|
-
# Format total exposure time as integer seconds
|
|
264
|
-
exptime_raw = get_key(Database.EXPTIME_TOTAL_KEY)
|
|
265
|
-
try:
|
|
266
|
-
exptime_float = float(exptime_raw)
|
|
267
|
-
total_seconds += exptime_float
|
|
268
|
-
total_secs = format_duration(int(exptime_float))
|
|
269
|
-
except (ValueError, TypeError):
|
|
270
|
-
total_secs = exptime_raw
|
|
271
|
-
|
|
272
|
-
# Count images
|
|
273
|
-
try:
|
|
274
|
-
num_images = int(get_key(Database.NUM_IMAGES_KEY, 0))
|
|
275
|
-
total_images += num_images
|
|
276
|
-
except (ValueError, TypeError):
|
|
277
|
-
num_images = get_key(Database.NUM_IMAGES_KEY)
|
|
278
|
-
|
|
279
|
-
type_str = image_type
|
|
280
|
-
if image_type.upper() == "LIGHT":
|
|
281
|
-
image_type = filter
|
|
282
|
-
elif image_type.upper() == "FLAT":
|
|
283
|
-
image_type = f"{image_type}/{filter}"
|
|
284
|
-
else: # either bias or dark
|
|
285
|
-
object = "" # Don't show meaningless target
|
|
187
|
+
def do_list_sessions(sb: Starbash, brief: bool = False):
|
|
188
|
+
"""List sessions (filtered based on the current selection)"""
|
|
286
189
|
|
|
190
|
+
sessions = sb.search_session()
|
|
191
|
+
if sessions and isinstance(sessions, list):
|
|
192
|
+
len_all = sb.db.len_table(Database.SESSIONS_TABLE)
|
|
193
|
+
table = Table(
|
|
194
|
+
title=f"Sessions ({len(sessions)} selected out of {len_all})",
|
|
195
|
+
header_style=TABLE_HEADER_STYLE,
|
|
196
|
+
)
|
|
197
|
+
sb.analytics.set_data("session.num_selected", len(sessions))
|
|
198
|
+
sb.analytics.set_data("session.num_total", len_all)
|
|
199
|
+
|
|
200
|
+
table.add_column("#", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
201
|
+
table.add_column("Date", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
202
|
+
table.add_column("# images", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
203
|
+
table.add_column("Time", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
204
|
+
table.add_column("Type/Filter", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
205
|
+
table.add_column("Telescope", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
206
|
+
table.add_column(
|
|
207
|
+
"About", style=TABLE_COLUMN_STYLE, no_wrap=True
|
|
208
|
+
) # type of frames, filter, target
|
|
209
|
+
|
|
210
|
+
total_images = 0
|
|
211
|
+
total_seconds = 0.0
|
|
212
|
+
filters = set()
|
|
213
|
+
image_types = set()
|
|
214
|
+
telescopes = set()
|
|
215
|
+
|
|
216
|
+
def get_key(k: str, default: Any = "N/A") -> Any:
|
|
217
|
+
"""Convert keynames to SQL legal column names"""
|
|
218
|
+
k = get_column_name(k)
|
|
219
|
+
return sess.get(k, default)
|
|
220
|
+
|
|
221
|
+
brief_max_rows = 10
|
|
222
|
+
for session_index, sess in enumerate(sessions):
|
|
223
|
+
date_iso = get_key(Database.START_KEY)
|
|
224
|
+
date = to_shortdate(date_iso)
|
|
225
|
+
|
|
226
|
+
object = get_key(Database.OBJECT_KEY)
|
|
227
|
+
filter = get_key(Database.FILTER_KEY)
|
|
228
|
+
filters.add(filter)
|
|
229
|
+
image_type = get_key(Database.IMAGETYP_KEY)
|
|
230
|
+
image_types.add(image_type)
|
|
231
|
+
telescope = get_key(Database.TELESCOP_KEY)
|
|
232
|
+
telescopes.add(telescope)
|
|
233
|
+
|
|
234
|
+
# Show the non normalized target name
|
|
235
|
+
metadata = sess.get("metadata")
|
|
236
|
+
if metadata:
|
|
237
|
+
long_name = metadata.get("OBJECT")
|
|
238
|
+
if long_name:
|
|
239
|
+
object = long_name
|
|
240
|
+
|
|
241
|
+
# Format total exposure time as integer seconds
|
|
242
|
+
exptime_raw = get_key(Database.EXPTIME_TOTAL_KEY)
|
|
243
|
+
try:
|
|
244
|
+
exptime_float = float(exptime_raw)
|
|
245
|
+
total_seconds += exptime_float
|
|
246
|
+
total_secs = format_duration(int(exptime_float))
|
|
247
|
+
except (ValueError, TypeError):
|
|
248
|
+
total_secs = exptime_raw
|
|
249
|
+
|
|
250
|
+
# Count images
|
|
251
|
+
try:
|
|
252
|
+
num_images = int(get_key(Database.NUM_IMAGES_KEY, 0))
|
|
253
|
+
total_images += num_images
|
|
254
|
+
except (ValueError, TypeError):
|
|
255
|
+
num_images = get_key(Database.NUM_IMAGES_KEY)
|
|
256
|
+
|
|
257
|
+
if image_type.upper() == "LIGHT":
|
|
258
|
+
image_type = filter
|
|
259
|
+
elif image_type.upper() == "FLAT":
|
|
260
|
+
image_type = f"{image_type}/{filter}"
|
|
261
|
+
else: # either bias or dark
|
|
262
|
+
object = "" # Don't show meaningless target
|
|
263
|
+
|
|
264
|
+
if brief and session_index == brief_max_rows:
|
|
265
|
+
table.add_row("...", "...", "...", "...", "...", "...", "...")
|
|
266
|
+
elif brief and session_index > brief_max_rows:
|
|
267
|
+
pass # Show nothing
|
|
268
|
+
else:
|
|
287
269
|
table.add_row(
|
|
288
270
|
str(session_index + 1),
|
|
289
271
|
date,
|
|
@@ -294,27 +276,41 @@ def list_sessions(
|
|
|
294
276
|
object,
|
|
295
277
|
)
|
|
296
278
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
279
|
+
# Add totals row
|
|
280
|
+
if sessions:
|
|
281
|
+
table.add_row(
|
|
282
|
+
"",
|
|
283
|
+
"",
|
|
284
|
+
f"[bold]{total_images}[/bold]",
|
|
285
|
+
f"[bold]{format_duration(int(total_seconds))}[/bold]",
|
|
286
|
+
"",
|
|
287
|
+
"",
|
|
288
|
+
"",
|
|
289
|
+
)
|
|
308
290
|
|
|
309
|
-
|
|
291
|
+
console.print(table)
|
|
310
292
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
293
|
+
# FIXME - move these analytics elsewhere so they can be reused when search_session()
|
|
294
|
+
# is used to generate processing lists.
|
|
295
|
+
sb.analytics.set_data("session.total_images", total_images)
|
|
296
|
+
sb.analytics.set_data("session.total_exposure_seconds", int(total_seconds))
|
|
297
|
+
sb.analytics.set_data("session.telescopes", telescopes)
|
|
298
|
+
sb.analytics.set_data("session.filters", filters)
|
|
299
|
+
sb.analytics.set_data("session.image_types", image_types)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
@app.command(name="list")
|
|
303
|
+
def list_sessions(
|
|
304
|
+
brief: bool = typer.Option(
|
|
305
|
+
False,
|
|
306
|
+
"--brief",
|
|
307
|
+
help="If there are many sessions, show only a few.",
|
|
308
|
+
),
|
|
309
|
+
):
|
|
310
|
+
"""List sessions (filtered based on the current selection)"""
|
|
311
|
+
|
|
312
|
+
with Starbash("selection.list") as sb:
|
|
313
|
+
do_list_sessions(sb, brief=brief)
|
|
318
314
|
|
|
319
315
|
|
|
320
316
|
def selection_by_number(
|
|
@@ -351,9 +347,7 @@ def export(
|
|
|
351
347
|
],
|
|
352
348
|
destdir: Annotated[
|
|
353
349
|
str,
|
|
354
|
-
typer.Argument(
|
|
355
|
-
help="Directory path to export to (if it doesn't exist it will be created)"
|
|
356
|
-
),
|
|
350
|
+
typer.Argument(help="Directory path to export to (if it doesn't exist it will be created)"),
|
|
357
351
|
],
|
|
358
352
|
):
|
|
359
353
|
"""Export the images for the indicated session number.
|
|
@@ -368,9 +362,7 @@ def export(
|
|
|
368
362
|
# Get images for this session
|
|
369
363
|
images = sb.get_session_images(session)
|
|
370
364
|
if not images:
|
|
371
|
-
console.print(
|
|
372
|
-
f"[red]Error: No images found for session {session_num}.[/red]"
|
|
373
|
-
)
|
|
365
|
+
console.print(f"[red]Error: No images found for session {session_num}.[/red]")
|
|
374
366
|
raise typer.Exit(0)
|
|
375
367
|
|
|
376
368
|
# Determine output directory
|
|
@@ -395,7 +387,7 @@ def show_selection(ctx: typer.Context):
|
|
|
395
387
|
if summary["status"] == "all":
|
|
396
388
|
console.print(f"[yellow]{summary['message']}[/yellow]")
|
|
397
389
|
else:
|
|
398
|
-
table = Table(title="Current Selection")
|
|
390
|
+
table = Table(title="Current Selection", header_style=TABLE_HEADER_STYLE)
|
|
399
391
|
table.add_column("Criteria", style=TABLE_COLUMN_STYLE)
|
|
400
392
|
table.add_column("Value", style=TABLE_VALUE_STYLE)
|
|
401
393
|
|
starbash/commands/user.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
from textwrap import dedent
|
|
2
|
+
from typing import Annotated
|
|
3
|
+
|
|
1
4
|
import typer
|
|
2
|
-
from
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
from rich.prompt import Confirm, Prompt
|
|
3
7
|
|
|
4
8
|
from starbash.app import Starbash
|
|
5
|
-
from starbash import
|
|
6
|
-
from rich.panel import Panel
|
|
9
|
+
from starbash.paths import get_user_documents_dir
|
|
7
10
|
|
|
8
11
|
app = typer.Typer()
|
|
9
12
|
|
|
@@ -21,6 +24,8 @@ def analytics(
|
|
|
21
24
|
Enable or disable analytics (crash reports and usage data).
|
|
22
25
|
"""
|
|
23
26
|
with Starbash("analytics.change") as sb:
|
|
27
|
+
from starbash import console
|
|
28
|
+
|
|
24
29
|
sb.analytics.set_data("analytics.enabled", enable)
|
|
25
30
|
sb.user_repo.set("analytics.enabled", enable)
|
|
26
31
|
sb.user_repo.write_config()
|
|
@@ -41,6 +46,8 @@ def name(
|
|
|
41
46
|
Set your name for attribution in generated images.
|
|
42
47
|
"""
|
|
43
48
|
with Starbash("user.name") as sb:
|
|
49
|
+
from starbash import console
|
|
50
|
+
|
|
44
51
|
sb.user_repo.set("user.name", user_name)
|
|
45
52
|
sb.user_repo.write_config()
|
|
46
53
|
console.print(f"User name set to: {user_name}")
|
|
@@ -59,27 +66,46 @@ def email(
|
|
|
59
66
|
Set your email for attribution in generated images.
|
|
60
67
|
"""
|
|
61
68
|
with Starbash("user.email") as sb:
|
|
69
|
+
from starbash import console
|
|
70
|
+
|
|
62
71
|
sb.user_repo.set("user.email", user_email)
|
|
63
72
|
sb.user_repo.write_config()
|
|
64
73
|
console.print(f"User email set to: {user_email}")
|
|
65
74
|
|
|
66
75
|
|
|
67
|
-
def
|
|
68
|
-
console
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
def _ask_masters(sb: Starbash) -> None:
|
|
77
|
+
from starbash import console
|
|
78
|
+
|
|
79
|
+
has_masters = sb.repo_manager.get_repo_by_kind("master") is not None
|
|
80
|
+
if not has_masters:
|
|
81
|
+
want_default_dirs = Confirm.ask(
|
|
82
|
+
dedent("""
|
|
83
|
+
Would you like to create default output directories in your Documents folder
|
|
84
|
+
(recommended - you can change this later with [cyan]'sb repo ...'[/cyan])?
|
|
85
|
+
"""),
|
|
86
|
+
default=True,
|
|
87
|
+
console=console,
|
|
74
88
|
)
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
if want_default_dirs:
|
|
90
|
+
console.print("Creating default repositories...")
|
|
91
|
+
master_path = str(get_user_documents_dir() / "repos" / "master")
|
|
92
|
+
processed_path = str(get_user_documents_dir() / "repos" / "processed")
|
|
93
|
+
sb.add_local_repo(path=master_path, repo_type="master")
|
|
94
|
+
sb.add_local_repo(path=processed_path, repo_type="processed")
|
|
95
|
+
console.print(f"✅ Created master repository at: {master_path}")
|
|
96
|
+
console.print(f"✅ Created processed repository at: {processed_path}")
|
|
97
|
+
console.print()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _ask_user_config(sb: Starbash) -> None:
|
|
101
|
+
from starbash import console
|
|
77
102
|
|
|
78
103
|
# Ask for username
|
|
79
|
-
user_name =
|
|
104
|
+
user_name = Prompt.ask(
|
|
80
105
|
"Enter your name (for attribution in generated images)",
|
|
81
|
-
default="",
|
|
106
|
+
default=sb.user_repo.get("user.name", ""),
|
|
82
107
|
show_default=False,
|
|
108
|
+
console=console,
|
|
83
109
|
)
|
|
84
110
|
sb.analytics.set_data("analytics.use_name", user_name != "")
|
|
85
111
|
if user_name:
|
|
@@ -89,10 +115,11 @@ def do_reinit(sb: Starbash) -> None:
|
|
|
89
115
|
console.print("[dim]Skipped name[/dim]")
|
|
90
116
|
|
|
91
117
|
# Ask for email
|
|
92
|
-
user_email =
|
|
118
|
+
user_email = Prompt.ask(
|
|
93
119
|
"Enter your email address (for attribution in generated images)",
|
|
94
|
-
default="",
|
|
120
|
+
default=sb.user_repo.get("user.email", ""),
|
|
95
121
|
show_default=False,
|
|
122
|
+
console=console,
|
|
96
123
|
)
|
|
97
124
|
sb.analytics.set_data("analytics.use_email", user_email != "")
|
|
98
125
|
if user_email:
|
|
@@ -102,10 +129,11 @@ def do_reinit(sb: Starbash) -> None:
|
|
|
102
129
|
console.print("[dim]Skipped email[/dim]")
|
|
103
130
|
|
|
104
131
|
# Ask about including email in crash reports
|
|
105
|
-
include_in_reports =
|
|
106
|
-
"Would you like to include your email address with crash reports/analytics
|
|
132
|
+
include_in_reports = Confirm.ask(
|
|
133
|
+
"Would you like to include your email address with crash reports/analytics?\n"
|
|
107
134
|
"(This helps us follow up if we need more information about issues.)",
|
|
108
|
-
default=False,
|
|
135
|
+
default=sb.user_repo.get("analytics.include_user", False),
|
|
136
|
+
console=console,
|
|
109
137
|
)
|
|
110
138
|
sb.analytics.set_data("analytics.use_email_report", include_in_reports)
|
|
111
139
|
sb.user_repo.set("analytics.include_user", include_in_reports)
|
|
@@ -118,24 +146,59 @@ def do_reinit(sb: Starbash) -> None:
|
|
|
118
146
|
# Save all changes
|
|
119
147
|
sb.user_repo.write_config()
|
|
120
148
|
|
|
149
|
+
|
|
150
|
+
def do_reinit(sb: Starbash) -> None:
|
|
151
|
+
from starbash import console
|
|
152
|
+
|
|
153
|
+
console.print()
|
|
121
154
|
console.print(
|
|
122
155
|
Panel.fit(
|
|
123
|
-
"[bold
|
|
124
|
-
"
|
|
156
|
+
"[bold cyan]Starbash getting started...[/bold cyan]\n\n"
|
|
157
|
+
"Let's do your first time setup. You can skip any question by pressing Enter.\n"
|
|
158
|
+
"If you need to re-run this setup later, just run: [cyan]'sb user setup'[/cyan]",
|
|
159
|
+
border_style="cyan",
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
console.print()
|
|
163
|
+
console.print()
|
|
164
|
+
_ask_user_config(sb)
|
|
165
|
+
_ask_masters(sb)
|
|
166
|
+
|
|
167
|
+
console.print(
|
|
168
|
+
Panel.fit(
|
|
169
|
+
dedent("""
|
|
170
|
+
[bold green]Basic setup is complete[/bold green]
|
|
171
|
+
You are almost ready to start using Starbash!
|
|
172
|
+
|
|
173
|
+
Recommended next steps (to get your first auto-generated images):
|
|
174
|
+
1. Add your source raw image repositories (starbash will only READ from these):
|
|
175
|
+
[cyan]sb repo add /path/to/your/raw_images[/cyan]
|
|
176
|
+
2. Ask starbash to auto-generate 'master' darks, biases and flats:
|
|
177
|
+
[cyan]sb process masters[/cyan]
|
|
178
|
+
3. Process your images using automated workflows:
|
|
179
|
+
[cyan]sb process auto[/cyan]
|
|
180
|
+
4. (Highly recommended) Tell your shell to auto-complete starbash commands:
|
|
181
|
+
[cyan]sb shell-complete --install-completion[/cyan]
|
|
182
|
+
|
|
183
|
+
This project is currently very 'alpha' but we are eager to have it work for you.
|
|
184
|
+
For full instructions and support [link=https://github.com/geeksville/starbash]visit our github[/link].
|
|
185
|
+
If you find problems or have questions, just open an issue and we'll work with you.
|
|
186
|
+
"""),
|
|
125
187
|
border_style="green",
|
|
188
|
+
title="Almost done!",
|
|
126
189
|
)
|
|
127
190
|
)
|
|
128
191
|
|
|
129
192
|
|
|
130
193
|
@app.command()
|
|
131
|
-
def
|
|
194
|
+
def setup():
|
|
132
195
|
"""
|
|
133
196
|
Configure starbash via a brief guided process.
|
|
134
197
|
|
|
135
198
|
This will ask you for your name, email, and analytics preferences.
|
|
136
199
|
You can skip any question by pressing Enter.
|
|
137
200
|
"""
|
|
138
|
-
with Starbash("user.
|
|
201
|
+
with Starbash("user.setup") as sb:
|
|
139
202
|
do_reinit(sb)
|
|
140
203
|
|
|
141
204
|
|
|
@@ -143,6 +206,8 @@ def reinit():
|
|
|
143
206
|
def main_callback(ctx: typer.Context):
|
|
144
207
|
"""Main callback for the Starbash application."""
|
|
145
208
|
if ctx.invoked_subcommand is None:
|
|
209
|
+
from starbash import console
|
|
210
|
+
|
|
146
211
|
# No command provided, show help
|
|
147
212
|
console.print(ctx.get_help())
|
|
148
213
|
raise typer.Exit()
|