starbash 0.1.1__tar.gz → 0.1.4__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.

Potentially problematic release.


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

Files changed (37) hide show
  1. starbash-0.1.4/PKG-INFO +124 -0
  2. starbash-0.1.4/README.md +102 -0
  3. {starbash-0.1.1 → starbash-0.1.4}/pyproject.toml +21 -2
  4. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/__init__.py +5 -0
  5. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/analytics.py +21 -6
  6. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/app.py +145 -17
  7. starbash-0.1.4/src/starbash/commands/repo.py +140 -0
  8. starbash-0.1.4/src/starbash/commands/select.py +326 -0
  9. starbash-0.1.4/src/starbash/commands/user.py +148 -0
  10. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/database.py +152 -20
  11. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/defaults/starbash.toml +2 -34
  12. starbash-0.1.4/src/starbash/main.py +48 -0
  13. starbash-0.1.4/src/starbash/recipes/README.md +3 -0
  14. starbash-0.1.4/src/starbash/recipes/master_bias/starbash.toml +55 -0
  15. starbash-0.1.4/src/starbash/recipes/master_flat/starbash.toml +46 -0
  16. starbash-0.1.4/src/starbash/recipes/osc_dual_duo/starbash.py +151 -0
  17. starbash-0.1.4/src/starbash/recipes/osc_dual_duo/starbash.toml +88 -0
  18. starbash-0.1.4/src/starbash/recipes/osc_single_duo/starbash.toml +67 -0
  19. starbash-0.1.4/src/starbash/recipes/starbash.toml +34 -0
  20. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/repo/manager.py +82 -21
  21. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/selection.py +36 -0
  22. starbash-0.1.4/src/starbash/templates/__init__.py +0 -0
  23. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/templates/userconfig.toml +33 -1
  24. starbash-0.1.1/PKG-INFO +0 -96
  25. starbash-0.1.1/README.md +0 -73
  26. starbash-0.1.1/src/starbash/commands/repo.py +0 -68
  27. starbash-0.1.1/src/starbash/commands/selection.py +0 -117
  28. starbash-0.1.1/src/starbash/commands/user.py +0 -63
  29. starbash-0.1.1/src/starbash/main.py +0 -150
  30. {starbash-0.1.1 → starbash-0.1.4}/LICENSE +0 -0
  31. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/commands/__init__.py +0 -0
  32. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/defaults/__init__.py +0 -0
  33. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/paths.py +0 -0
  34. {starbash-0.1.1/src/starbash/templates → starbash-0.1.4/src/starbash/recipes}/__init__.py +0 -0
  35. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/repo/__init__.py +0 -0
  36. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/tool.py +0 -0
  37. {starbash-0.1.1 → starbash-0.1.4}/src/starbash/url.py +0 -0
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: starbash
3
+ Version: 0.1.4
4
+ Summary: A tool for automating/standardizing/sharing astrophotography workflows.
5
+ License-File: LICENSE
6
+ Author: Kevin Hester
7
+ Author-email: kevinh@geeksville.com
8
+ Requires-Python: >=3.12,<3.15
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: astropy (>=7.1.1,<8.0.0)
14
+ Requires-Dist: multidict (>=6.7.0,<7.0.0)
15
+ Requires-Dist: platformdirs (>=4.5.0,<5.0.0)
16
+ Requires-Dist: restrictedpython (>=8.1,<9.0)
17
+ Requires-Dist: rich (>=14.2.0,<15.0.0)
18
+ Requires-Dist: sentry-sdk (>=2.42.1,<3.0.0)
19
+ Requires-Dist: tomlkit (>=0.13.3,<0.14.0)
20
+ Requires-Dist: typer (>=0.20.0,<0.21.0)
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Starbash
24
+
25
+ [![PyPI - Version](https://img.shields.io/pypi/v/starbash)](https://pypi.org/project/starbash/)
26
+ [![GitHub branch check runs](https://img.shields.io/github/check-runs/geeksville/starbash/main)](https://github.com/geeksville/starbash/actions)
27
+ [![codecov](https://codecov.io/github/geeksville/starbash/graph/badge.svg?token=47RE10I7O1)](https://codecov.io/github/geeksville/starbash)
28
+
29
+ ![app icon](https://raw.githubusercontent.com/geeksville/starbash/refs/heads/main/img/icon.png "Starbash: Astrophotography workflows simplified")
30
+
31
+ A tool for automating/standardizing/sharing astrophotography workflows.
32
+
33
+ # Current status
34
+
35
+ Not quite ready 😊. But making good progress.
36
+
37
+ See the current [TODO](TODO.md) file for work items. I'll be looking for pre-alpha testers/feedback soon.
38
+
39
+ ## Current features
40
+
41
+ * Automatically recognizes and auto-parses the default NINA, Asiair and Seestar raw file repos (adding support for other layouts is easy)
42
+ * Multisession support by default (including automatic selection of correct flats, biases and dark frames)
43
+ * 'Repos' can contain raw files, generated masters, preprocessed files, or recipes.
44
+
45
+ ## Features coming soon
46
+
47
+ * Automatically performs **complete** preprocessing on OSC (broadband, narrowband or dual Duo filter), Mono (LRGB, SHO) data. i.e. give you 'seestar level' auto-preprocessing, so you only need to do the (optional) custom post-processing.
48
+ * Generates a per target report/config file which can be customized if the detected defaults or preprocessing are not what you want
49
+ * 'Recipes' provide repeatable/human-readable/sharable descriptions of all processing steps
50
+ * Repos can be on the local disk or shared via HTTPS/github/etc. This is particularly useful for recipe repos
51
+ * Uses Siril and Graxpert for its pre-processing operations (support for Pixinsight based recipes will probably be coming at some point...)
52
+ * The target report can be used to auto generate a human friendly 'postable/sharable' report about that image
53
+ * Target reports are sharable so that you can request comments by others and others can rerender with different settings
54
+
55
+ ## Installing
56
+
57
+ Currently the easiest way to install this command-line based tool is to install is via [pipx](https://pipx.pypa.io/stable/). If you don't already have pipx and you have python installed, you can auto install it by running "pip install --user pipx." If you don't have python installed see the pipx link for pipx installers for any OS.
58
+
59
+ Once pipx is installed just run:
60
+
61
+ ```
62
+ pipx install starbash
63
+ installed package starbash 0.1.3, installed using Python 3.12.3
64
+ These apps are now globally available
65
+ - sb
66
+ - starbash
67
+ done! ✨ 🌟 ✨
68
+ ```
69
+
70
+ FIXME - add getting started instructions (possibly with a screenshare video)
71
+
72
+ ## Supported commands
73
+
74
+ ### Repository Management
75
+ - `sb repo [--verbose]` - List installed repos (use `-v` for details)
76
+ - `sb repo add <filepath|URL>` - Add a repository
77
+ - `sb repo remove <REPONUM>` - Remove the indicated repo from the repo list
78
+ - `sb repo reindex [--force] [REPONUM]` - Reindex the specified repo (or all repos if none specified)
79
+
80
+ ### User Preferences
81
+ - `sb user name "Your Name"` - Set name for attribution in generated images
82
+ - `sb user email "foo@example.com"` - Set email for attribution in generated images
83
+ - `sb user analytics <on|off>` - Turn analytics collection on/off
84
+ - `sb user reinit` - Configure starbash via a brief guided process
85
+
86
+ ### Selection & Filtering
87
+ - `sb select` - Show information about the current selection
88
+ - `sb select list` - List sessions (filtered based on the current selection)
89
+ - `sb select any` - Remove all filters (select everything)
90
+ - `sb select target <TARGETNAME>` - Limit selection to the named target
91
+ - `sb select telescope <TELESCOPENAME>` - Limit selection to the named telescope
92
+ - `sb select date <after|before|between> <DATE> [DATE]` - Limit to sessions in the specified date range
93
+ - `sb select export SESSIONNUM DESTDIR` - Export the images for indicated session number into the specified directory (or current directory if not specified). If possible symbolic links are used, if not the files are copied.
94
+
95
+ ## Not yet supported commands
96
+
97
+ ### Setup & Configuration
98
+ - `sb info` - Show user preferences location and other app info
99
+ - `sb info target` - List targets (filtered based on the current selection)
100
+ - `sb info telescope` - List instruments (filtered based on the current selection)
101
+ - `sb info filter` - List all filters found in current selection
102
+
103
+ ### Export & Processing
104
+ - `sb process siril` - Generate Siril directory tree and run Siril GUI
105
+ - `sb process auto` - Automatic processing
106
+ - `sb process masters` - Generate master flats, darks, and biases from available raw frames
107
+
108
+ ## Supported tools (now)
109
+
110
+ * Siril
111
+ * Graxpert
112
+ * Python (you can add python code to recipes if necessary)
113
+
114
+ ## Supported tools (future?)
115
+
116
+ * Pixinsight?
117
+ * Autostakkert?
118
+
119
+ ## Developing
120
+
121
+ We try to make this project useful and friendly. If you find problems please file a github issue.
122
+ We accept pull-requests and enjoy discussing possible new development directions via github issues. If you might want to work on this, just describe what your interests are and we can talk about how to get it merged.
123
+
124
+ Project members can access crash reports [here](https://geeksville.sentry.io/insights/projects/starbash/?project=4510264204132352).
@@ -0,0 +1,102 @@
1
+ # Starbash
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/starbash)](https://pypi.org/project/starbash/)
4
+ [![GitHub branch check runs](https://img.shields.io/github/check-runs/geeksville/starbash/main)](https://github.com/geeksville/starbash/actions)
5
+ [![codecov](https://codecov.io/github/geeksville/starbash/graph/badge.svg?token=47RE10I7O1)](https://codecov.io/github/geeksville/starbash)
6
+
7
+ ![app icon](https://raw.githubusercontent.com/geeksville/starbash/refs/heads/main/img/icon.png "Starbash: Astrophotography workflows simplified")
8
+
9
+ A tool for automating/standardizing/sharing astrophotography workflows.
10
+
11
+ # Current status
12
+
13
+ Not quite ready 😊. But making good progress.
14
+
15
+ See the current [TODO](TODO.md) file for work items. I'll be looking for pre-alpha testers/feedback soon.
16
+
17
+ ## Current features
18
+
19
+ * Automatically recognizes and auto-parses the default NINA, Asiair and Seestar raw file repos (adding support for other layouts is easy)
20
+ * Multisession support by default (including automatic selection of correct flats, biases and dark frames)
21
+ * 'Repos' can contain raw files, generated masters, preprocessed files, or recipes.
22
+
23
+ ## Features coming soon
24
+
25
+ * Automatically performs **complete** preprocessing on OSC (broadband, narrowband or dual Duo filter), Mono (LRGB, SHO) data. i.e. give you 'seestar level' auto-preprocessing, so you only need to do the (optional) custom post-processing.
26
+ * Generates a per target report/config file which can be customized if the detected defaults or preprocessing are not what you want
27
+ * 'Recipes' provide repeatable/human-readable/sharable descriptions of all processing steps
28
+ * Repos can be on the local disk or shared via HTTPS/github/etc. This is particularly useful for recipe repos
29
+ * Uses Siril and Graxpert for its pre-processing operations (support for Pixinsight based recipes will probably be coming at some point...)
30
+ * The target report can be used to auto generate a human friendly 'postable/sharable' report about that image
31
+ * Target reports are sharable so that you can request comments by others and others can rerender with different settings
32
+
33
+ ## Installing
34
+
35
+ Currently the easiest way to install this command-line based tool is to install is via [pipx](https://pipx.pypa.io/stable/). If you don't already have pipx and you have python installed, you can auto install it by running "pip install --user pipx." If you don't have python installed see the pipx link for pipx installers for any OS.
36
+
37
+ Once pipx is installed just run:
38
+
39
+ ```
40
+ pipx install starbash
41
+ installed package starbash 0.1.3, installed using Python 3.12.3
42
+ These apps are now globally available
43
+ - sb
44
+ - starbash
45
+ done! ✨ 🌟 ✨
46
+ ```
47
+
48
+ FIXME - add getting started instructions (possibly with a screenshare video)
49
+
50
+ ## Supported commands
51
+
52
+ ### Repository Management
53
+ - `sb repo [--verbose]` - List installed repos (use `-v` for details)
54
+ - `sb repo add <filepath|URL>` - Add a repository
55
+ - `sb repo remove <REPONUM>` - Remove the indicated repo from the repo list
56
+ - `sb repo reindex [--force] [REPONUM]` - Reindex the specified repo (or all repos if none specified)
57
+
58
+ ### User Preferences
59
+ - `sb user name "Your Name"` - Set name for attribution in generated images
60
+ - `sb user email "foo@example.com"` - Set email for attribution in generated images
61
+ - `sb user analytics <on|off>` - Turn analytics collection on/off
62
+ - `sb user reinit` - Configure starbash via a brief guided process
63
+
64
+ ### Selection & Filtering
65
+ - `sb select` - Show information about the current selection
66
+ - `sb select list` - List sessions (filtered based on the current selection)
67
+ - `sb select any` - Remove all filters (select everything)
68
+ - `sb select target <TARGETNAME>` - Limit selection to the named target
69
+ - `sb select telescope <TELESCOPENAME>` - Limit selection to the named telescope
70
+ - `sb select date <after|before|between> <DATE> [DATE]` - Limit to sessions in the specified date range
71
+ - `sb select export SESSIONNUM DESTDIR` - Export the images for indicated session number into the specified directory (or current directory if not specified). If possible symbolic links are used, if not the files are copied.
72
+
73
+ ## Not yet supported commands
74
+
75
+ ### Setup & Configuration
76
+ - `sb info` - Show user preferences location and other app info
77
+ - `sb info target` - List targets (filtered based on the current selection)
78
+ - `sb info telescope` - List instruments (filtered based on the current selection)
79
+ - `sb info filter` - List all filters found in current selection
80
+
81
+ ### Export & Processing
82
+ - `sb process siril` - Generate Siril directory tree and run Siril GUI
83
+ - `sb process auto` - Automatic processing
84
+ - `sb process masters` - Generate master flats, darks, and biases from available raw frames
85
+
86
+ ## Supported tools (now)
87
+
88
+ * Siril
89
+ * Graxpert
90
+ * Python (you can add python code to recipes if necessary)
91
+
92
+ ## Supported tools (future?)
93
+
94
+ * Pixinsight?
95
+ * Autostakkert?
96
+
97
+ ## Developing
98
+
99
+ We try to make this project useful and friendly. If you find problems please file a github issue.
100
+ We accept pull-requests and enjoy discussing possible new development directions via github issues. If you might want to work on this, just describe what your interests are and we can talk about how to get it merged.
101
+
102
+ Project members can access crash reports [here](https://geeksville.sentry.io/insights/projects/starbash/?project=4510264204132352).
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "starbash"
3
- version = "0.1.1"
4
- description = ""
3
+ version = "0.1.4"
4
+ description = "A tool for automating/standardizing/sharing astrophotography workflows."
5
5
  authors = ["Kevin Hester <kevinh@geeksville.com>"]
6
6
  readme = "README.md"
7
7
  packages = [{ include = "starbash", from = "src" }]
@@ -19,6 +19,7 @@ sentry-sdk = "^2.42.1"
19
19
 
20
20
  [tool.poetry.group.dev.dependencies]
21
21
  pytest = ">=8.4.2,<9.0.0"
22
+ pytest-cov = "^6.0.0"
22
23
 
23
24
  [tool.poetry.scripts]
24
25
  starbash = "starbash.main:app"
@@ -28,6 +29,24 @@ sb = "starbash.main:app" # std alias for convenience
28
29
  markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"]
29
30
  addopts = "-m 'not slow'"
30
31
 
32
+ [tool.coverage.run]
33
+ source = ["src"]
34
+ omit = ["*/tests/*", "*/__pycache__/*"]
35
+
36
+ [tool.coverage.report]
37
+ exclude_lines = [
38
+ "pragma: no cover",
39
+ "def __repr__",
40
+ "raise AssertionError",
41
+ "raise NotImplementedError",
42
+ "if __name__ == .__main__.:",
43
+ "if TYPE_CHECKING:",
44
+ "class .*\\bProtocol\\):",
45
+ "@(abc\\.)?abstractmethod",
46
+ ]
47
+ show_missing = true
48
+ precision = 2
49
+
31
50
  [build-system]
32
51
  requires = ["poetry-core>=2.0.0,<3.0.0"]
33
52
  build-backend = "poetry.core.masonry.api"
@@ -1,6 +1,11 @@
1
+ import logging
2
+
1
3
  from .database import Database # re-export for convenience
2
4
  from rich.console import Console
3
5
 
4
6
  console = Console()
5
7
 
8
+ # Global variable for log filter level (can be changed via --debug flag)
9
+ log_filter_level = logging.INFO
10
+
6
11
  __all__ = ["Database"]
@@ -1,5 +1,7 @@
1
1
  import logging
2
+ import os
2
3
 
4
+ import starbash
3
5
  from starbash import console
4
6
  import starbash.url as url
5
7
 
@@ -8,11 +10,12 @@ analytics_allowed = False
8
10
 
9
11
 
10
12
  def analytics_setup(allowed: bool = False, user_email: str | None = None) -> None:
11
- import sentry_sdk
12
-
13
13
  global analytics_allowed
14
14
  analytics_allowed = allowed
15
15
  if analytics_allowed:
16
+ import sentry_sdk
17
+ from sentry_sdk.integrations.logging import LoggingIntegration
18
+
16
19
  logging.info(
17
20
  f"Analytics/crash-reports enabled. To change [link={url.analytics_docs}]click here[/link]",
18
21
  extra={"markup": True},
@@ -22,6 +25,13 @@ def analytics_setup(allowed: bool = False, user_email: str | None = None) -> Non
22
25
  send_default_pii=True,
23
26
  enable_logs=True,
24
27
  traces_sample_rate=1.0,
28
+ integrations=[
29
+ LoggingIntegration(
30
+ level=starbash.log_filter_level, # Capture INFO and above as breadcrumbs
31
+ event_level=None, # Don't automatically convert error messages to sentry events
32
+ sentry_logs_level=starbash.log_filter_level, # Capture INFO and above as logs
33
+ ),
34
+ ],
25
35
  )
26
36
 
27
37
  if user_email:
@@ -41,11 +51,13 @@ def analytics_shutdown() -> None:
41
51
  sentry_sdk.flush()
42
52
 
43
53
 
54
+ def is_running_in_pytest() -> bool:
55
+ """Detect if code is being run inside pytest."""
56
+ return "PYTEST_CURRENT_TEST" in os.environ
57
+
58
+
44
59
  def is_development_environment() -> bool:
45
60
  """Detect if running in a development environment."""
46
- import os
47
- import sys
48
- from pathlib import Path
49
61
 
50
62
  # Check for explicit environment variable
51
63
  if os.getenv("STARBASH_ENV") == "development":
@@ -68,7 +80,10 @@ def analytics_exception(exc: Exception) -> bool:
68
80
  if analytics_allowed:
69
81
  import sentry_sdk
70
82
 
71
- report_id = sentry_sdk.capture_exception(exc)
83
+ if is_running_in_pytest():
84
+ report_id = "TESTING-ENVIRONMENT"
85
+ else:
86
+ report_id = sentry_sdk.capture_exception(exc)
72
87
 
73
88
  logging.info(
74
89
  f"""An unexpected error has occurred and been reported. Thank you for your help.
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  from importlib import resources
3
3
  from pathlib import Path
4
-
4
+ import typer
5
5
  import tomlkit
6
6
  from tomlkit.toml_file import TOMLFile
7
7
  import glob
@@ -10,6 +10,10 @@ from astropy.io import fits
10
10
  import itertools
11
11
  from rich.progress import track
12
12
  from rich.logging import RichHandler
13
+ import shutil
14
+
15
+ import starbash
16
+ from starbash import console
13
17
  from starbash.database import Database
14
18
  from starbash.repo.manager import Repo
15
19
  from starbash.tool import Tool
@@ -31,30 +35,81 @@ def setup_logging():
31
35
  Configures basic logging.
32
36
  """
33
37
  logging.basicConfig(
34
- level="INFO", # don't print messages of lower priority than this
38
+ level=starbash.log_filter_level, # use the global log filter level
35
39
  format="%(message)s",
36
40
  datefmt="[%X]",
37
41
  handlers=[RichHandler(rich_tracebacks=True)],
38
42
  )
39
43
 
40
44
 
41
- setup_logging()
45
+ def get_user_config_path() -> Path:
46
+ """Returns the path to the user config file."""
47
+ config_dir = get_user_config_dir()
48
+ return config_dir / "starbash.toml"
42
49
 
43
50
 
44
51
  def create_user() -> Path:
45
52
  """Create user directories if they don't exist yet."""
46
- config_dir = get_user_config_dir()
47
- userconfig_path = config_dir / "starbash.toml"
48
- if not (userconfig_path).exists():
53
+ path = get_user_config_path()
54
+ if not path.exists():
49
55
  tomlstr = (
50
56
  resources.files("starbash")
51
57
  .joinpath("templates/userconfig.toml")
52
58
  .read_text()
53
59
  )
54
60
  toml = tomlkit.parse(tomlstr)
55
- TOMLFile(userconfig_path).write(toml)
56
- logging.info(f"Created user config file: {userconfig_path}")
57
- return config_dir
61
+ TOMLFile(path).write(toml)
62
+ logging.info(f"Created user config file: {path}")
63
+ return get_user_config_dir()
64
+
65
+
66
+ def copy_images_to_dir(images: list[dict[str, Any]], output_dir: Path) -> None:
67
+ """Copy images to the specified output directory (using symbolic links if possible)."""
68
+
69
+ # Export images
70
+ console.print(f"[cyan]Exporting {len(images)} images to {output_dir}...[/cyan]")
71
+
72
+ linked_count = 0
73
+ copied_count = 0
74
+ error_count = 0
75
+
76
+ for image in images:
77
+ # Get the source path from the image metadata
78
+ source_path = Path(image.get("path", ""))
79
+
80
+ if not source_path.exists():
81
+ console.print(f"[red]Warning: Source file not found: {source_path}[/red]")
82
+ error_count += 1
83
+ continue
84
+
85
+ # Determine destination filename
86
+ dest_path = output_dir / source_path.name
87
+ if dest_path.exists():
88
+ console.print(f"[yellow]Skipping existing file: {dest_path}[/yellow]")
89
+ error_count += 1
90
+ continue
91
+
92
+ # Try to create a symbolic link first
93
+ try:
94
+ dest_path.symlink_to(source_path.resolve())
95
+ linked_count += 1
96
+ except (OSError, NotImplementedError):
97
+ # If symlink fails, try to copy
98
+ try:
99
+ shutil.copy2(source_path, dest_path)
100
+ copied_count += 1
101
+ except Exception as e:
102
+ console.print(f"[red]Error copying {source_path.name}: {e}[/red]")
103
+ error_count += 1
104
+
105
+ # Print summary
106
+ console.print(f"[green]Export complete![/green]")
107
+ if linked_count > 0:
108
+ console.print(f" Linked: {linked_count} files")
109
+ if copied_count > 0:
110
+ console.print(f" Copied: {copied_count} files")
111
+ if error_count > 0:
112
+ console.print(f" [red]Errors: {error_count} files[/red]")
58
113
 
59
114
 
60
115
  class Starbash:
@@ -89,7 +144,7 @@ class Starbash:
89
144
  self.analytics.__enter__()
90
145
 
91
146
  logging.info(
92
- f"Repo manager initialized with {len(self.repo_manager.repos)} default repo references."
147
+ f"Repo manager initialized with {len(self.repo_manager.repos)} repos."
93
148
  )
94
149
  # self.repo_manager.dump()
95
150
 
@@ -117,7 +172,8 @@ class Starbash:
117
172
 
118
173
  def __exit__(self, exc_type, exc, tb) -> bool:
119
174
  handled = False
120
- if exc:
175
+ # Don't suppress typer.Exit - it's used for controlled exit codes
176
+ if exc and not isinstance(exc, typer.Exit):
121
177
  handled = analytics_exception(exc)
122
178
  self.close()
123
179
  return handled
@@ -128,11 +184,12 @@ class Starbash:
128
184
  date = header.get(Database.DATE_OBS_KEY)
129
185
  if not date or not image_type:
130
186
  logging.warning(
131
- "Image %s missing critical FITS header, please submit image at https://github.com/geeksville/starbash/issues/new",
187
+ "Image %s missing either DATE-OBS or IMAGETYP FITS header, skipping...",
132
188
  f,
133
189
  )
134
190
  else:
135
191
  exptime = header.get(Database.EXPTIME_KEY, 0)
192
+ telescop = header.get(Database.TELESCOP_KEY, "unspecified")
136
193
  new = {
137
194
  Database.FILTER_KEY: filter,
138
195
  Database.START_KEY: date,
@@ -142,6 +199,7 @@ class Starbash:
142
199
  Database.NUM_IMAGES_KEY: 1,
143
200
  Database.EXPTIME_TOTAL_KEY: exptime,
144
201
  Database.OBJECT_KEY: header.get(Database.OBJECT_KEY, "unspecified"),
202
+ Database.TELESCOP_KEY: telescop,
145
203
  }
146
204
  session = self.db.get_session(new)
147
205
  self.db.upsert_session(new, existing=session)
@@ -156,16 +214,86 @@ class Starbash:
156
214
  conditions = self.selection.get_query_conditions()
157
215
  return self.db.search_session(conditions)
158
216
 
217
+ def get_session_images(self, session_id: int) -> list[dict[str, Any]]:
218
+ """
219
+ Get all images belonging to a specific session.
220
+
221
+ Sessions are defined by a unique combination of filter, imagetyp (image type),
222
+ object (target name), telescope, and date range. This method queries the images
223
+ table for all images matching the session's criteria in a single database query.
224
+
225
+ Args:
226
+ session_id: The database ID of the session
227
+
228
+ Returns:
229
+ List of image records (dictionaries with path, metadata, etc.)
230
+ Returns empty list if session not found or has no images.
231
+
232
+ Raises:
233
+ ValueError: If session_id is not found in the database
234
+ """
235
+ # First get the session details
236
+ session = self.db.get_session_by_id(session_id)
237
+ if session is None:
238
+ raise ValueError(f"Session with id {session_id} not found")
239
+
240
+ # Query images that match ALL session criteria including date range
241
+ conditions = {
242
+ Database.FILTER_KEY: session[Database.FILTER_KEY],
243
+ Database.IMAGETYP_KEY: session[Database.IMAGETYP_KEY],
244
+ Database.OBJECT_KEY: session[Database.OBJECT_KEY],
245
+ Database.TELESCOP_KEY: session[Database.TELESCOP_KEY],
246
+ "date_start": session[Database.START_KEY],
247
+ "date_end": session[Database.END_KEY],
248
+ }
249
+
250
+ # Single query with all conditions
251
+ images = self.db.search_image(conditions)
252
+ return images if images else []
253
+
254
+ def remove_repo_ref(self, url: str) -> None:
255
+ """
256
+ Remove a repository reference from the user configuration.
257
+
258
+ Args:
259
+ url: The repository URL to remove (e.g., 'file:///path/to/repo')
260
+
261
+ Raises:
262
+ ValueError: If the repository URL is not found in user configuration
263
+ """
264
+ # Get the repo-ref list from user config
265
+ repo_refs = self.user_repo.config.get("repo-ref")
266
+
267
+ if not repo_refs:
268
+ raise ValueError(f"No repository references found in user configuration.")
269
+
270
+ # Find and remove the matching repo-ref
271
+ found = False
272
+ refs_copy = [r for r in repo_refs] # Make a copy to iterate
273
+ for ref in refs_copy:
274
+ ref_dir = ref.get("dir", "")
275
+ # Match by converting to file:// URL format if needed
276
+ if ref_dir == url or f"file://{ref_dir}" == url:
277
+ repo_refs.remove(ref)
278
+ found = True
279
+ break
280
+
281
+ if not found:
282
+ raise ValueError(f"Repository '{url}' not found in user configuration.")
283
+
284
+ # Write the updated config
285
+ self.user_repo.write_config()
286
+
159
287
  def reindex_repo(self, repo: Repo, force: bool = False):
160
288
  """Reindex all repositories managed by the RepoManager."""
161
289
  # FIXME, add a method to get just the repos that contain images
162
290
  if repo.is_scheme("file") and repo.kind != "recipe":
163
291
  logging.debug("Reindexing %s...", repo.url)
164
292
 
293
+ whitelist = None
165
294
  config = self.repo_manager.merged.get("config")
166
- if not config:
167
- raise ValueError(f"App config not found.")
168
- whitelist = config["fits-whitelist"]
295
+ if config:
296
+ whitelist = config.get("fits-whitelist", None)
169
297
 
170
298
  path = repo.get_path()
171
299
  if not path:
@@ -191,7 +319,7 @@ class Starbash:
191
319
  items = header.items()
192
320
  headers = {}
193
321
  for key, value in items:
194
- if key in whitelist:
322
+ if (not whitelist) or (key in whitelist):
195
323
  headers[key] = value
196
324
  logging.debug("Headers for %s: %s", f, headers)
197
325
  headers["path"] = str(f)
@@ -207,7 +335,7 @@ class Starbash:
207
335
 
208
336
  def reindex_repos(self, force: bool = False):
209
337
  """Reindex all repositories managed by the RepoManager."""
210
- logging.info("Reindexing all repositories...")
338
+ logging.debug("Reindexing all repositories...")
211
339
 
212
340
  for repo in track(self.repo_manager.repos, description="Reindexing repos..."):
213
341
  self.reindex_repo(repo, force=force)