starbash 0.1.9__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 +145 -0
- starbash/analytics.py +3 -2
- starbash/app.py +512 -473
- starbash/check_version.py +18 -0
- starbash/commands/__init__.py +2 -1
- starbash/commands/info.py +88 -14
- starbash/commands/process.py +76 -24
- starbash/commands/repo.py +41 -68
- starbash/commands/select.py +141 -142
- starbash/commands/user.py +88 -23
- starbash/database.py +219 -112
- starbash/defaults/starbash.toml +24 -3
- starbash/exception.py +21 -0
- starbash/main.py +29 -7
- starbash/paths.py +35 -5
- starbash/processing.py +724 -0
- starbash/recipes/README.md +3 -0
- starbash/recipes/master_bias/starbash.toml +16 -19
- starbash/recipes/master_dark/starbash.toml +33 -0
- starbash/recipes/master_flat/starbash.toml +26 -18
- starbash/recipes/osc.py +190 -0
- starbash/recipes/osc_dual_duo/starbash.toml +54 -44
- 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 +30 -9
- starbash/selection.py +32 -36
- starbash/templates/repo/master.toml +7 -3
- starbash/templates/repo/processed.toml +15 -0
- starbash/templates/userconfig.toml +9 -0
- starbash/toml.py +13 -13
- starbash/tool.py +230 -96
- 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 -151
- starbash-0.1.9.dist-info/METADATA +0 -145
- starbash-0.1.9.dist-info/RECORD +0 -37
- {starbash-0.1.9.dist-info → starbash-0.1.15.dist-info}/WHEEL +0 -0
- {starbash-0.1.9.dist-info → starbash-0.1.15.dist-info}/entry_points.txt +0 -0
- {starbash-0.1.9.dist-info → starbash-0.1.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
3
|
+
|
|
4
|
+
from update_checker import UpdateChecker
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_version():
|
|
8
|
+
"""Check if a newer version of starbash is available on PyPI."""
|
|
9
|
+
try:
|
|
10
|
+
checker = UpdateChecker()
|
|
11
|
+
current_version = version("starbash")
|
|
12
|
+
result = checker.check("starbash", current_version)
|
|
13
|
+
if result:
|
|
14
|
+
logging.warning(result)
|
|
15
|
+
|
|
16
|
+
except PackageNotFoundError:
|
|
17
|
+
# Package not installed (e.g., running from source during development)
|
|
18
|
+
pass
|
starbash/commands/__init__.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"""Shared utilities for starbash commands."""
|
|
2
2
|
|
|
3
|
-
from datetime import datetime
|
|
4
3
|
from rich.style import Style
|
|
5
4
|
|
|
6
5
|
# Define reusable table styles
|
|
7
6
|
TABLE_COLUMN_STYLE = Style(color="cyan")
|
|
8
7
|
TABLE_VALUE_STYLE = Style(color="green")
|
|
8
|
+
TABLE_HEADER_STYLE = Style(color="magenta", bold=True)
|
|
9
|
+
SPINNER_STYLE = Style(color="magenta", bold=True)
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def format_duration(seconds: int | float) -> str:
|
starbash/commands/info.py
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
"""Info commands for displaying system and data information."""
|
|
2
2
|
|
|
3
|
+
from collections import Counter
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
3
6
|
import typer
|
|
4
|
-
from typing_extensions import Annotated
|
|
5
7
|
from rich.table import Table
|
|
6
|
-
from collections import Counter
|
|
7
8
|
|
|
8
9
|
from starbash.app import Starbash
|
|
9
|
-
from starbash import
|
|
10
|
+
from starbash.commands import (
|
|
11
|
+
TABLE_COLUMN_STYLE,
|
|
12
|
+
TABLE_HEADER_STYLE,
|
|
13
|
+
TABLE_VALUE_STYLE,
|
|
14
|
+
format_duration,
|
|
15
|
+
)
|
|
10
16
|
from starbash.database import Database, get_column_name
|
|
11
|
-
from starbash.paths import get_user_config_dir, get_user_data_dir
|
|
12
|
-
from starbash.commands import format_duration, TABLE_COLUMN_STYLE, TABLE_VALUE_STYLE
|
|
13
17
|
|
|
14
18
|
app = typer.Typer()
|
|
15
19
|
|
|
@@ -27,7 +31,7 @@ def dump_column(sb: Starbash, human_name: str, column_name: str) -> None:
|
|
|
27
31
|
sessions = sb.search_session()
|
|
28
32
|
|
|
29
33
|
# Also do a complete unfiltered search so we can compare for the users
|
|
30
|
-
allsessions = sb.db.search_session(
|
|
34
|
+
allsessions = sb.db.search_session([])
|
|
31
35
|
|
|
32
36
|
column_name = get_column_name(column_name)
|
|
33
37
|
found = [session[column_name] for session in sessions if session[column_name]]
|
|
@@ -42,16 +46,17 @@ def dump_column(sb: Starbash, human_name: str, column_name: str) -> None:
|
|
|
42
46
|
|
|
43
47
|
# Create and display table
|
|
44
48
|
table = Table(
|
|
45
|
-
|
|
49
|
+
header_style=TABLE_HEADER_STYLE,
|
|
50
|
+
title=f"{plural(human_name)} ({len(found_counts)} / {len(all_counts)} selected)",
|
|
46
51
|
)
|
|
47
52
|
table.add_column(human_name, style=TABLE_COLUMN_STYLE, no_wrap=False)
|
|
48
|
-
table.add_column(
|
|
49
|
-
"# of sessions", style=TABLE_COLUMN_STYLE, no_wrap=True, justify="right"
|
|
50
|
-
)
|
|
53
|
+
table.add_column("# of sessions", style=TABLE_COLUMN_STYLE, no_wrap=True, justify="right")
|
|
51
54
|
|
|
52
55
|
for i, count in sorted_list:
|
|
53
56
|
table.add_row(i, str(count))
|
|
54
57
|
|
|
58
|
+
from starbash import console
|
|
59
|
+
|
|
55
60
|
console.print(table)
|
|
56
61
|
|
|
57
62
|
|
|
@@ -76,15 +81,86 @@ def filter():
|
|
|
76
81
|
dump_column(sb, "Filter", Database.FILTER_KEY)
|
|
77
82
|
|
|
78
83
|
|
|
84
|
+
kind_arg = typer.Argument(
|
|
85
|
+
help="Optional image type to filter by (e.g., BIAS, DARK, FLAT, LIGHT)",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@app.command()
|
|
90
|
+
def master(
|
|
91
|
+
kind: Annotated[
|
|
92
|
+
str | None,
|
|
93
|
+
kind_arg,
|
|
94
|
+
] = None,
|
|
95
|
+
):
|
|
96
|
+
"""List all precalculated master images (darks, biases, flats)."""
|
|
97
|
+
with Starbash("info.master") as sb:
|
|
98
|
+
from starbash import console
|
|
99
|
+
|
|
100
|
+
# Get the master repo
|
|
101
|
+
images = sb.get_master_images(kind)
|
|
102
|
+
|
|
103
|
+
if not images:
|
|
104
|
+
kind_msg = f" of type '{kind}'" if kind else ""
|
|
105
|
+
console.print(f"[yellow]No master images{kind_msg} found.[/yellow]")
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# Create table to display results
|
|
109
|
+
title = f"Master Images ({len(images)} total)"
|
|
110
|
+
if kind:
|
|
111
|
+
title = f"Master {kind} Images ({len(images)} total)"
|
|
112
|
+
table = Table(title=title, header_style=TABLE_HEADER_STYLE)
|
|
113
|
+
table.add_column("Date", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
114
|
+
table.add_column("Type", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
115
|
+
table.add_column("Filename", style=TABLE_VALUE_STYLE, no_wrap=False)
|
|
116
|
+
|
|
117
|
+
# Sort by date, then by type
|
|
118
|
+
sorted_images = sorted(
|
|
119
|
+
images,
|
|
120
|
+
key=lambda img: (
|
|
121
|
+
img.get(Database.DATE_OBS_KEY) or img.get(Database.DATE_KEY) or "",
|
|
122
|
+
img.get(Database.IMAGETYP_KEY) or "",
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
for image in sorted_images:
|
|
127
|
+
date = image.get(Database.DATE_OBS_KEY) or image.get(Database.DATE_KEY) or "Unknown"
|
|
128
|
+
# Extract just the date part (YYYY-MM-DD) if it's a full ISO timestamp
|
|
129
|
+
if "T" in date:
|
|
130
|
+
date = date.split("T")[0]
|
|
131
|
+
|
|
132
|
+
kind = image.get(Database.IMAGETYP_KEY)
|
|
133
|
+
if kind:
|
|
134
|
+
kind = sb.aliases.normalize(kind)
|
|
135
|
+
filename = image.get("path") or "Unknown"
|
|
136
|
+
|
|
137
|
+
table.add_row(date, kind, filename)
|
|
138
|
+
|
|
139
|
+
console.print(table)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@app.command(hidden=True)
|
|
143
|
+
def masters(
|
|
144
|
+
kind: Annotated[
|
|
145
|
+
str | None,
|
|
146
|
+
kind_arg,
|
|
147
|
+
] = None,
|
|
148
|
+
):
|
|
149
|
+
"""Alias for 'info master' command."""
|
|
150
|
+
master(kind)
|
|
151
|
+
|
|
152
|
+
|
|
79
153
|
@app.callback(invoke_without_command=True)
|
|
80
154
|
def main_callback(ctx: typer.Context):
|
|
81
155
|
"""Show user preferences location and other app info.
|
|
82
156
|
|
|
83
157
|
This is the default command when no subcommand is specified.
|
|
84
158
|
"""
|
|
159
|
+
from starbash import console
|
|
160
|
+
|
|
85
161
|
if ctx.invoked_subcommand is None:
|
|
86
162
|
with Starbash("info") as sb:
|
|
87
|
-
table = Table(title="Starbash Information")
|
|
163
|
+
table = Table(title="Starbash Information", header_style=TABLE_HEADER_STYLE)
|
|
88
164
|
table.add_column("Setting", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
89
165
|
table.add_column("Value", style=TABLE_VALUE_STYLE)
|
|
90
166
|
|
|
@@ -106,9 +182,7 @@ def main_callback(ctx: typer.Context):
|
|
|
106
182
|
table.add_row("User Repositories", str(len(sb.repo_manager.regular_repos)))
|
|
107
183
|
|
|
108
184
|
# Show database stats
|
|
109
|
-
table.add_row(
|
|
110
|
-
"Sessions Indexed", str(sb.db.len_table(Database.SESSIONS_TABLE))
|
|
111
|
-
)
|
|
185
|
+
table.add_row("Sessions Indexed", str(sb.db.len_table(Database.SESSIONS_TABLE)))
|
|
112
186
|
|
|
113
187
|
table.add_row("Images Indexed", str(sb.db.len_table(Database.IMAGES_TABLE)))
|
|
114
188
|
|
starbash/commands/process.py
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
"""Processing commands for automated image processing workflows."""
|
|
2
2
|
|
|
3
|
-
import typer
|
|
4
3
|
from pathlib import Path
|
|
5
|
-
from
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import rich
|
|
7
|
+
import typer
|
|
6
8
|
|
|
7
9
|
from starbash.app import Starbash, copy_images_to_dir
|
|
8
|
-
from starbash import
|
|
10
|
+
from starbash.commands.__init__ import (
|
|
11
|
+
TABLE_COLUMN_STYLE,
|
|
12
|
+
TABLE_HEADER_STYLE,
|
|
13
|
+
)
|
|
9
14
|
from starbash.commands.select import selection_by_number
|
|
10
15
|
from starbash.database import SessionRow
|
|
16
|
+
from starbash.processing import Processing, ProcessingResult
|
|
11
17
|
|
|
12
18
|
app = typer.Typer()
|
|
13
19
|
|
|
@@ -20,9 +26,7 @@ def siril(
|
|
|
20
26
|
],
|
|
21
27
|
destdir: Annotated[
|
|
22
28
|
str,
|
|
23
|
-
typer.Argument(
|
|
24
|
-
help="Destination directory for Siril directory tree and processing"
|
|
25
|
-
),
|
|
29
|
+
typer.Argument(help="Destination directory for Siril directory tree and processing"),
|
|
26
30
|
],
|
|
27
31
|
run: Annotated[
|
|
28
32
|
bool,
|
|
@@ -42,6 +46,8 @@ def siril(
|
|
|
42
46
|
structure loaded and ready for processing.
|
|
43
47
|
"""
|
|
44
48
|
with Starbash("process.siril") as sb:
|
|
49
|
+
from starbash import console
|
|
50
|
+
|
|
45
51
|
console.print(
|
|
46
52
|
f"[yellow]Processing session {session_num} for Siril in {destdir}...[/yellow]"
|
|
47
53
|
)
|
|
@@ -67,9 +73,9 @@ def siril(
|
|
|
67
73
|
|
|
68
74
|
extras = [
|
|
69
75
|
# FIXME search for BIAS/DARK/FLAT etc... using multiple canonical names
|
|
70
|
-
("
|
|
71
|
-
("
|
|
72
|
-
("
|
|
76
|
+
("bias", "biases"),
|
|
77
|
+
("dark", "darks"),
|
|
78
|
+
("flat", "flats"),
|
|
73
79
|
]
|
|
74
80
|
for typ, subdir in extras:
|
|
75
81
|
candidates = sb.guess_sessions(session, typ)
|
|
@@ -85,6 +91,48 @@ def siril(
|
|
|
85
91
|
# Also FIXME, check for the existence of such a file
|
|
86
92
|
|
|
87
93
|
|
|
94
|
+
def print_results(
|
|
95
|
+
title: str, results: list[ProcessingResult], console: rich.console.Console
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Print processing results in a formatted table.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
title: Title to display above the table
|
|
101
|
+
results: List of ProcessingResult objects to display
|
|
102
|
+
console: Rich console instance for output
|
|
103
|
+
"""
|
|
104
|
+
from rich.table import Table
|
|
105
|
+
|
|
106
|
+
if not results:
|
|
107
|
+
console.print(f"[yellow]{title}: No results to display[/yellow]")
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
table = Table(title=title, show_header=True, header_style=TABLE_HEADER_STYLE)
|
|
111
|
+
table.add_column("Target", style=TABLE_COLUMN_STYLE, no_wrap=True)
|
|
112
|
+
table.add_column("Sessions", justify="right", style=TABLE_COLUMN_STYLE)
|
|
113
|
+
table.add_column("Status", justify="center", style=TABLE_COLUMN_STYLE)
|
|
114
|
+
table.add_column("Notes", style=TABLE_COLUMN_STYLE)
|
|
115
|
+
|
|
116
|
+
for result in results:
|
|
117
|
+
# Format status with color
|
|
118
|
+
if result.success is True:
|
|
119
|
+
status = "[green]✓ Success[/green]"
|
|
120
|
+
elif result.success is False:
|
|
121
|
+
status = "[red]✗ Failed[/red]"
|
|
122
|
+
else:
|
|
123
|
+
status = "[yellow]⊘ Skipped[/yellow]"
|
|
124
|
+
|
|
125
|
+
# Format session count
|
|
126
|
+
session_count = str(len(result.sessions))
|
|
127
|
+
|
|
128
|
+
# Format notes (truncate if too long)
|
|
129
|
+
notes = result.notes or ""
|
|
130
|
+
|
|
131
|
+
table.add_row(result.target, session_count, status, notes)
|
|
132
|
+
|
|
133
|
+
console.print(table)
|
|
134
|
+
|
|
135
|
+
|
|
88
136
|
@app.command()
|
|
89
137
|
def auto(
|
|
90
138
|
session_num: Annotated[
|
|
@@ -109,15 +157,17 @@ def auto(
|
|
|
109
157
|
The output will be saved according to the configured recipes.
|
|
110
158
|
"""
|
|
111
159
|
with Starbash("process.auto") as sb:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
else:
|
|
115
|
-
console.print("[yellow]Auto-processing all selected sessions...[/yellow]")
|
|
160
|
+
with Processing(sb) as proc:
|
|
161
|
+
from starbash import console
|
|
116
162
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
163
|
+
if session_num is not None:
|
|
164
|
+
console.print(f"[yellow]Auto-processing session {session_num}...[/yellow]")
|
|
165
|
+
else:
|
|
166
|
+
console.print("[yellow]Auto-processing all selected sessions...[/yellow]")
|
|
167
|
+
|
|
168
|
+
results = proc.run_all_stages()
|
|
169
|
+
|
|
170
|
+
print_results("Autoprocessed", results, console)
|
|
121
171
|
|
|
122
172
|
|
|
123
173
|
@app.command()
|
|
@@ -132,13 +182,13 @@ def masters():
|
|
|
132
182
|
and will be automatically used for future processing operations.
|
|
133
183
|
"""
|
|
134
184
|
with Starbash("process.masters") as sb:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
185
|
+
with Processing(sb) as proc:
|
|
186
|
+
from starbash import console
|
|
187
|
+
|
|
188
|
+
console.print("[yellow]Generating master frames from current selection...[/yellow]")
|
|
189
|
+
results = proc.run_master_stages()
|
|
190
|
+
|
|
191
|
+
print_results("Generated masters", results, console)
|
|
142
192
|
|
|
143
193
|
|
|
144
194
|
@app.callback(invoke_without_command=True)
|
|
@@ -149,6 +199,8 @@ def main_callback(ctx: typer.Context):
|
|
|
149
199
|
post-processing of astrophotography sessions.
|
|
150
200
|
"""
|
|
151
201
|
if ctx.invoked_subcommand is None:
|
|
202
|
+
from starbash import console
|
|
203
|
+
|
|
152
204
|
# No command provided, show help
|
|
153
205
|
console.print(ctx.get_help())
|
|
154
206
|
raise typer.Exit()
|
starbash/commands/repo.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import typer
|
|
2
|
-
from typing_extensions import Annotated
|
|
3
|
-
from pathlib import Path
|
|
4
1
|
import logging
|
|
2
|
+
from textwrap import dedent
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import typer
|
|
5
6
|
|
|
6
7
|
import starbash
|
|
7
|
-
from repo import
|
|
8
|
+
from repo import Repo
|
|
9
|
+
from starbash import console
|
|
8
10
|
from starbash.app import Starbash
|
|
9
|
-
from starbash import
|
|
10
|
-
from starbash.toml import toml_from_template
|
|
11
|
+
from starbash.paths import get_user_documents_dir
|
|
11
12
|
|
|
12
13
|
app = typer.Typer(invoke_without_command=True)
|
|
13
14
|
|
|
@@ -22,9 +23,7 @@ def repo_enumeration(sb: Starbash):
|
|
|
22
23
|
|
|
23
24
|
def complete_repo_by_num(incomplete: str):
|
|
24
25
|
# We need to use stderr_logging to prevent confusing the bash completion parser
|
|
25
|
-
starbash.log_filter_level =
|
|
26
|
-
logging.ERROR
|
|
27
|
-
) # avoid showing output while doing completion
|
|
26
|
+
starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
|
|
28
27
|
with Starbash("repo.complete.num", stderr_logging=True) as sb:
|
|
29
28
|
for num, repo in repo_enumeration(sb).items():
|
|
30
29
|
if str(num).startswith(incomplete):
|
|
@@ -33,9 +32,7 @@ def complete_repo_by_num(incomplete: str):
|
|
|
33
32
|
|
|
34
33
|
def complete_repo_by_url(incomplete: str):
|
|
35
34
|
# We need to use stderr_logging to prevent confusing the bash completion parser
|
|
36
|
-
starbash.log_filter_level =
|
|
37
|
-
logging.ERROR
|
|
38
|
-
) # avoid showing output while doing completion
|
|
35
|
+
starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
|
|
39
36
|
with Starbash("repo.complete.url", stderr_logging=True) as sb:
|
|
40
37
|
repos = sb.repo_manager.regular_repos
|
|
41
38
|
|
|
@@ -45,28 +42,23 @@ def complete_repo_by_url(incomplete: str):
|
|
|
45
42
|
|
|
46
43
|
|
|
47
44
|
@app.command()
|
|
48
|
-
def list(
|
|
49
|
-
verbose: bool = typer.Option(
|
|
50
|
-
False, "--verbose", "-v", help="Show all repos including system repos"
|
|
51
|
-
),
|
|
52
|
-
):
|
|
45
|
+
def list():
|
|
53
46
|
"""
|
|
54
47
|
lists all repositories.
|
|
55
|
-
Use --verbose to show all repos including system/recipe repos.
|
|
56
48
|
"""
|
|
57
49
|
with Starbash("repo.list") as sb:
|
|
58
|
-
repos = sb.repo_manager.repos if
|
|
50
|
+
repos = sb.repo_manager.repos if starbash.verbose_output else sb.repo_manager.regular_repos
|
|
59
51
|
for i, repo in enumerate(repos):
|
|
60
52
|
kind = repo.kind("input")
|
|
61
53
|
# for unknown repos (probably because we haven't written a starbash.toml file to the root yet),
|
|
62
54
|
# we call them "input" because users will be less confused by that
|
|
63
55
|
|
|
64
|
-
if
|
|
56
|
+
if starbash.verbose_output:
|
|
65
57
|
# No numbers for verbose mode (system repos can't be removed)
|
|
66
|
-
console.print(f"{
|
|
58
|
+
console.print(f"{repo.url} (kind={kind})")
|
|
67
59
|
else:
|
|
68
60
|
# Show numbers for user repos (can be removed later)
|
|
69
|
-
console.print(f"{
|
|
61
|
+
console.print(f"{i + 1:2}: {repo.url} (kind={kind})")
|
|
70
62
|
|
|
71
63
|
|
|
72
64
|
@app.callback()
|
|
@@ -87,10 +79,15 @@ def main(
|
|
|
87
79
|
|
|
88
80
|
@app.command()
|
|
89
81
|
def add(
|
|
90
|
-
path: str,
|
|
82
|
+
path: Annotated[str | None, typer.Argument(help="Path to the respository")] = None,
|
|
91
83
|
master: bool = typer.Option(
|
|
92
84
|
False, "--master", help="Mark this new repository for master files."
|
|
93
85
|
),
|
|
86
|
+
processed: bool = typer.Option(
|
|
87
|
+
False,
|
|
88
|
+
"--processed",
|
|
89
|
+
help="Mark this new repository for processed output files.",
|
|
90
|
+
),
|
|
94
91
|
):
|
|
95
92
|
"""
|
|
96
93
|
Add a repository. path is either a local path or a remote URL.
|
|
@@ -98,43 +95,26 @@ def add(
|
|
|
98
95
|
repo_type = None
|
|
99
96
|
if master:
|
|
100
97
|
repo_type = "master"
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
elif processed:
|
|
99
|
+
repo_type = "processed"
|
|
103
100
|
|
|
104
|
-
|
|
105
|
-
if
|
|
106
|
-
|
|
101
|
+
if path is None:
|
|
102
|
+
if repo_type is not None:
|
|
103
|
+
# if we know the repo type we can auto create a default path
|
|
104
|
+
path = str(get_user_documents_dir() / "repos" / repo_type)
|
|
107
105
|
else:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
p.mkdir(parents=True, exist_ok=True)
|
|
111
|
-
|
|
112
|
-
toml_from_template(
|
|
113
|
-
f"repo/{repo_type}",
|
|
114
|
-
p / repo_suffix,
|
|
115
|
-
overrides={
|
|
116
|
-
"REPO_TYPE": repo_type,
|
|
117
|
-
"REPO_PATH": str(p),
|
|
118
|
-
"DEFAULT_RELATIVE": "{instrument}/{date}/{imagetyp}/master_{imagetyp}.fits",
|
|
119
|
-
},
|
|
120
|
-
)
|
|
121
|
-
else:
|
|
122
|
-
# No type specified, therefore (for now) assume we are just using this as an input
|
|
123
|
-
# repo (and it must exist)
|
|
124
|
-
if not p.exists():
|
|
125
|
-
console.print(f"[red]Error: Repo path does not exist: {p}[/red]")
|
|
126
|
-
raise typer.Exit(code=1)
|
|
127
|
-
|
|
128
|
-
console.print(f"Adding repository: {p}")
|
|
106
|
+
console.print("[red]Error: path is required for input repositories[/red]")
|
|
107
|
+
raise typer.Exit(1)
|
|
129
108
|
|
|
130
|
-
|
|
131
|
-
if
|
|
132
|
-
|
|
109
|
+
with Starbash("repo.add") as sb:
|
|
110
|
+
if repo_type and sb.repo_manager.get_repo_by_kind(repo_type):
|
|
111
|
+
console.print(
|
|
112
|
+
dedent(f"""
|
|
113
|
+
[red]Error[/red]: A repository for '{repo_type}' files already exists. If you'd like to replace it, use 'sb repo remove <url|number>' first.""")
|
|
114
|
+
)
|
|
115
|
+
raise typer.Exit(1)
|
|
133
116
|
|
|
134
|
-
|
|
135
|
-
# r.write_config()
|
|
136
|
-
sb.user_repo.write_config()
|
|
137
|
-
# FIXME, we also need to index the newly added repo!!!
|
|
117
|
+
sb.add_local_repo(path, repo_type=repo_type)
|
|
138
118
|
|
|
139
119
|
|
|
140
120
|
def repo_url_to_repo(sb: Starbash, repo_url: str | None) -> Repo | None:
|
|
@@ -173,9 +153,7 @@ def repo_url_to_repo(sb: Starbash, repo_url: str | None) -> Repo | None:
|
|
|
173
153
|
def remove(
|
|
174
154
|
reponum: Annotated[
|
|
175
155
|
str,
|
|
176
|
-
typer.Argument(
|
|
177
|
-
help="Repository number or URL", autocompletion=complete_repo_by_url
|
|
178
|
-
),
|
|
156
|
+
typer.Argument(help="Repository number or URL", autocompletion=complete_repo_by_url),
|
|
179
157
|
],
|
|
180
158
|
):
|
|
181
159
|
"""
|
|
@@ -186,7 +164,7 @@ def remove(
|
|
|
186
164
|
# Get the repo to remove
|
|
187
165
|
repo_to_remove = repo_url_to_repo(sb, reponum)
|
|
188
166
|
if repo_to_remove is None:
|
|
189
|
-
console.print(
|
|
167
|
+
console.print("[red]Error: You must specify a repository[/red]")
|
|
190
168
|
raise typer.Exit(code=1)
|
|
191
169
|
repo_url = repo_to_remove.url
|
|
192
170
|
|
|
@@ -204,9 +182,6 @@ def reindex(
|
|
|
204
182
|
autocompletion=complete_repo_by_url,
|
|
205
183
|
),
|
|
206
184
|
] = None,
|
|
207
|
-
force: bool = typer.Option(
|
|
208
|
-
default=False, help="Reread FITS headers, even if they are already indexed."
|
|
209
|
-
),
|
|
210
185
|
):
|
|
211
186
|
"""
|
|
212
187
|
Reindex a repository by number.
|
|
@@ -217,14 +192,12 @@ def reindex(
|
|
|
217
192
|
repo_to_reindex = repo_url_to_repo(sb, repo_url)
|
|
218
193
|
|
|
219
194
|
if repo_to_reindex is None:
|
|
220
|
-
sb.reindex_repos(
|
|
195
|
+
sb.reindex_repos()
|
|
221
196
|
else:
|
|
222
197
|
# Get the repo to reindex
|
|
223
198
|
console.print(f"Reindexing repository: {repo_to_reindex.url}")
|
|
224
|
-
sb.reindex_repo(repo_to_reindex
|
|
225
|
-
console.print(
|
|
226
|
-
f"[green]Successfully reindexed repository {repo_to_reindex}[/green]"
|
|
227
|
-
)
|
|
199
|
+
sb.reindex_repo(repo_to_reindex)
|
|
200
|
+
console.print(f"[green]Successfully reindexed repository {repo_to_reindex}[/green]")
|
|
228
201
|
|
|
229
202
|
|
|
230
203
|
if __name__ == "__main__":
|