starbash 0.2.5__tar.gz → 0.2.7__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.
Files changed (66) hide show
  1. {starbash-0.2.5 → starbash-0.2.7}/PKG-INFO +2 -4
  2. {starbash-0.2.5 → starbash-0.2.7}/pyproject.toml +21 -17
  3. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/__init__.py +6 -0
  4. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/analytics.py +12 -5
  5. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/app.py +9 -8
  6. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/check_version.py +2 -2
  7. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/info.py +6 -6
  8. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/process.py +6 -6
  9. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/repo.py +10 -9
  10. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/select.py +12 -11
  11. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/user.py +5 -5
  12. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/database.py +2 -1
  13. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/doit.py +64 -19
  14. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/dwarf3.py +8 -8
  15. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/filtering.py +13 -0
  16. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/linux.py +1 -1
  17. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/main.py +1 -1
  18. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/parameters.py +3 -2
  19. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/paths.py +2 -2
  20. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/processed_target.py +7 -5
  21. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/processing.py +35 -5
  22. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/recipes/osc.py +4 -4
  23. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/score.py +8 -8
  24. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/selection.py +2 -1
  25. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/sim_siril/connection.py +3 -2
  26. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/__init__.py +3 -1
  27. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/base.py +206 -51
  28. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/context.py +13 -11
  29. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/graxpert.py +6 -1
  30. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/python.py +14 -8
  31. starbash-0.2.7/src/starbash/tool/rcastro.py +162 -0
  32. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/tool/siril.py +16 -2
  33. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/windows.py +1 -1
  34. starbash-0.2.5/src/repo/__init__.py +0 -8
  35. starbash-0.2.5/src/repo/http_client.py +0 -5
  36. starbash-0.2.5/src/repo/manager.py +0 -146
  37. starbash-0.2.5/src/repo/repo.py +0 -693
  38. {starbash-0.2.5 → starbash-0.2.7}/LICENSE +0 -0
  39. {starbash-0.2.5 → starbash-0.2.7}/README.md +0 -0
  40. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/aliases.py +0 -0
  41. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/commands/__init__.py +0 -0
  42. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/defaults/__init__.py +0 -0
  43. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/defaults/starbash.toml +0 -0
  44. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/doit_types.py +0 -0
  45. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/exception.py +0 -0
  46. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/icon.py +0 -0
  47. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/os.py +0 -0
  48. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/processing_like.py +0 -0
  49. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/recipes/README.md +0 -0
  50. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/recipes/__init__.py +0 -0
  51. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/rich.py +0 -0
  52. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/safety.py +0 -0
  53. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/sim_siril/__init__.py +0 -0
  54. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/sim_siril/enums.py +0 -0
  55. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/sim_siril/utility.py +0 -0
  56. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/stage_utils.py +0 -0
  57. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/stages.py +0 -0
  58. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/__init__.py +0 -0
  59. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/repo/master.toml +0 -0
  60. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/repo/processed.toml +0 -0
  61. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/target/master.toml +0 -0
  62. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/target/processed.toml +0 -0
  63. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/templates/userconfig.toml +0 -0
  64. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/toml.py +0 -0
  65. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/ui/main.py +0 -0
  66. {starbash-0.2.5 → starbash-0.2.7}/src/starbash/url.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: starbash
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: A tool for automating/standardizing/sharing astrophotography workflows.
5
5
  License-File: LICENSE
6
6
  Author: Kevin Hester
@@ -13,16 +13,14 @@ Classifier: Programming Language :: Python :: 3.14
13
13
  Requires-Dist: astropy (>=7.1.1,<8.0.0)
14
14
  Requires-Dist: doit (>=0.36.0,<0.37.0)
15
15
  Requires-Dist: graxpert[cpuonly] (>=3.2.0a2,<4.0.0)
16
- Requires-Dist: multidict (>=6.7.0,<7.0.0)
17
16
  Requires-Dist: numpy (==2.2.6)
18
17
  Requires-Dist: platformdirs (>=4.5.0,<5.0.0)
19
18
  Requires-Dist: pyqt6 (>=6.10.1,<7.0.0)
20
- Requires-Dist: requests-cache (>=1.2.1,<2.0.0)
21
19
  Requires-Dist: restrictedpython (>=8.1,<9.0)
22
20
  Requires-Dist: rich (>=14.2.0,<15.0.0)
23
21
  Requires-Dist: sentry-sdk (>=2.42.1,<3.0.0)
24
22
  Requires-Dist: textual (>=6.8.0,<7.0.0)
25
- Requires-Dist: tomlkit (>=0.13.3,<0.14.0)
23
+ Requires-Dist: toml-repo (>=0.1.6,<0.2.0)
26
24
  Requires-Dist: typer (>=0.20.0,<0.21.0)
27
25
  Requires-Dist: update-checker (>=0.18.0,<0.19.0)
28
26
  Project-URL: Documentation, https://github.com/geeksville/starbash/blob/main/README.md
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "starbash"
3
- version = "0.2.5"
3
+ version = "0.2.7"
4
4
  description = "A tool for automating/standardizing/sharing astrophotography workflows."
5
5
  authors = ["Kevin Hester <kevinh@geeksville.com>"]
6
6
  readme = "README.md"
@@ -9,13 +9,13 @@ repository = "https://github.com/geeksville/starbash"
9
9
  documentation = "https://github.com/geeksville/starbash/blob/main/README.md" # FIXME provide something better
10
10
  packages = [
11
11
  { include = "starbash", from = "src" },
12
- { include = "repo", from = "src" },
13
12
  ]
14
13
 
15
14
  [tool.poetry.dependencies]
16
15
  python = ">=3.12,<3.15" # RestrictedPython doesn't yet work on 3.15
17
- tomlkit = ">=0.13.3,<0.14.0"
18
- multidict = ">=6.7.0,<7.0.0"
16
+
17
+ # Note: to use toml-repo from the local submodule rather than pypi use:
18
+ # toml-repo = {path = "toml-repo", develop = true}
19
19
  rich = ">=14.2.0,<15.0.0"
20
20
  restrictedpython = ">=8.1,<9.0"
21
21
  astropy = ">=7.1.1,<8.0.0"
@@ -23,7 +23,6 @@ platformdirs = ">=4.5.0,<5.0.0"
23
23
  typer = "^0.20.0"
24
24
  sentry-sdk = "^2.42.1"
25
25
  update-checker = "^0.18.0"
26
- requests-cache = "^1.2.1"
27
26
  doit = "^0.36.0"
28
27
  textual = "^6.8.0"
29
28
 
@@ -35,9 +34,10 @@ graxpert = {version = "^3.2.0a2", extras = ["cpuonly"]}
35
34
  # experimenting with siril-scripts/processing/VeraLux_HyperMetric_Stretch.py
36
35
  numpy = "2.2.6"
37
36
  pyqt6 = "^6.10.1"
37
+ toml-repo = "^0.1.6"
38
38
 
39
39
  [tool.poetry.group.dev.dependencies]
40
- pytest = ">=8.4.2,<9.0.0"
40
+ pytest = ">=8.4.2,<10.0.0"
41
41
  pytest-cov = "^6.0.0"
42
42
  pytest-xdist = "^3.8.0"
43
43
  pre-commit = "^4.3.0"
@@ -117,19 +117,22 @@ exclude = [
117
117
  [tool.ruff.lint]
118
118
  # Enable these rule sets
119
119
  select = [
120
- "E", # pycodestyle errors
121
- "F", # pyflakes
122
- "I", # isort (import sorting)
123
- "W", # pycodestyle warnings
124
- "UP", # pyupgrade
125
- "B", # flake8-bugbear
120
+ "E", # pycodestyle errors
121
+ "F", # pyflakes
122
+ "I", # isort (import sorting)
123
+ "W", # pycodestyle warnings
124
+ "UP", # pyupgrade
125
+ "B", # flake8-bugbear
126
+ "ANN", # flake8-annotations (type annotation enforcement)
126
127
  ]
127
128
 
128
129
  # Ignore specific rules that are too noisy for this codebase
129
130
  ignore = [
130
- "E501", # Line too long (handled by formatter)
131
- "B904", # Within an `except` clause, raise exceptions with `raise ... from err`
132
- "B006", # Do not use mutable data structures for argument defaults
131
+ "E501", # Line too long (handled by formatter)
132
+ "B904", # Within an `except` clause, raise exceptions with `raise ... from err`
133
+ "B006", # Do not use mutable data structures for argument defaults
134
+ "ANN401", # Dynamically typed expressions (Any) are sometimes necessary
135
+ "ANN204", # Missing return type for __init__ / __new__ / __post_init__
133
136
  ]
134
137
 
135
138
  [tool.ruff.lint.per-file-ignores]
@@ -142,14 +145,15 @@ ignore = [
142
145
  "F401", # Imported but unused
143
146
  "F841", # Local variable assigned but never used
144
147
  "PLC0415", # Import should be at top of file
148
+ "ANN", # Type annotations not required in tests
145
149
  ]
146
150
 
147
151
  [tool.basedpyright]
148
152
  # Enable import validation to catch runtime import errors at analysis time
149
153
  include = ["src"]
150
154
  exclude = ["**/__pycache__", ".venv", "build", "dist"]
151
- extraPaths = ["GraXpert"] # Include local GraXpert package for type checking
152
- typeCheckingMode = "basic" # Catches import errors without being overly strict
155
+ extraPaths = ["GraXpert", "toml-repo"] # Include local sources for type checking
156
+ typeCheckingMode = "standard" # Standard type checking: catches type errors, missing annotations, etc.
153
157
  reportMissingImports = true
154
158
  reportImportCycles = true
155
159
  reportUndefinedVariable = true
@@ -5,6 +5,12 @@ from typing import Any
5
5
 
6
6
  from rich.console import Console
7
7
 
8
+ # Configure toml_repo for starbash's conventions before any repo operations
9
+ from toml_repo import set_config_suffix, set_pkg_resource_root
10
+
11
+ set_config_suffix("starbash.toml")
12
+ set_pkg_resource_root("starbash")
13
+
8
14
  # Common type aliases for clarity
9
15
  type StageDict = dict[str, Any] # a processing stage definition from our toml
10
16
  type InputDef = dict[Any, Any] # an input definition within a stage
@@ -1,6 +1,8 @@
1
1
  import logging
2
2
  import os
3
3
  import platform
4
+ import types
5
+ from typing import Any
4
6
 
5
7
  from sentry_sdk.integrations.excepthook import ExcepthookIntegration
6
8
 
@@ -121,17 +123,22 @@ def analytics_exception(exc: BaseException) -> bool:
121
123
  class NopAnalytics:
122
124
  """Used when users have disabled analytics/crash reporting."""
123
125
 
124
- def __enter__(self):
126
+ def __enter__(self) -> "NopAnalytics":
125
127
  return self
126
128
 
127
- def __exit__(self, exc_type, exc_value, traceback):
129
+ def __exit__(
130
+ self,
131
+ exc_type: type[BaseException] | None,
132
+ exc_value: BaseException | None,
133
+ traceback: types.TracebackType | None,
134
+ ) -> bool:
128
135
  return False
129
136
 
130
- def set_data(self, key, value):
137
+ def set_data(self, key: str, value: Any) -> None:
131
138
  pass
132
139
 
133
140
 
134
- def analytics_start_span(**kwargs):
141
+ def analytics_start_span(**kwargs: Any) -> Any:
135
142
  """Start an analytics/tracing span if analytics is enabled, otherwise return a no-op context manager."""
136
143
  if analytics_allowed:
137
144
  import sentry_sdk
@@ -141,7 +148,7 @@ def analytics_start_span(**kwargs):
141
148
  return NopAnalytics()
142
149
 
143
150
 
144
- def analytics_start_transaction(**kwargs):
151
+ def analytics_start_transaction(**kwargs: Any) -> Any:
145
152
  """Start an analytics/tracing transaction if analytics is enabled, otherwise return a no-op context manager."""
146
153
  if analytics_allowed:
147
154
  import sentry_sdk
@@ -1,6 +1,7 @@
1
1
  import faulthandler
2
2
  import logging
3
3
  import sys
4
+ import types
4
5
  from importlib.metadata import version
5
6
  from pathlib import Path
6
7
  from sqlite3 import OperationalError
@@ -12,9 +13,9 @@ import typer
12
13
  from astropy.io import fits
13
14
  from rich.logging import RichHandler
14
15
  from rich.progress import track
16
+ from toml_repo import Repo, RepoManager, get_config_suffix
15
17
 
16
18
  import starbash
17
- from repo import Repo, RepoManager, repo_suffix
18
19
  from starbash.aliases import (
19
20
  Aliases,
20
21
  get_aliases,
@@ -52,7 +53,7 @@ critical_keys = [Database.DATE_OBS_KEY, Database.IMAGETYP_KEY]
52
53
  force_local_recipes = False # Set to True to always use local recipes for testing
53
54
 
54
55
 
55
- def setup_logging(console: rich.console.Console):
56
+ def setup_logging(console: rich.console.Console) -> None:
56
57
  """
57
58
  Configures basic logging.
58
59
  """
@@ -297,7 +298,7 @@ class Starbash:
297
298
  def __enter__(self) -> "Starbash":
298
299
  return self
299
300
 
300
- def __exit__(self, exc_type, exc, tb) -> bool:
301
+ def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> bool:
301
302
  from starbash import _is_test_env
302
303
  from starbash.exception import UserHandledError
303
304
 
@@ -379,7 +380,7 @@ class Starbash:
379
380
  p = Path(path)
380
381
  console = starbash.console
381
382
 
382
- repo_toml = p / repo_suffix # the starbash.toml file at the root of the repo
383
+ repo_toml = p / get_config_suffix() # the starbash.toml file at the root of the repo
383
384
  if repo_toml.exists():
384
385
  logging.debug("Using existing repository config file: %s", repo_toml)
385
386
  else:
@@ -387,7 +388,7 @@ class Starbash:
387
388
  console.print(f"Creating {repo_type} repository: {p}")
388
389
  toml_from_template(
389
390
  f"repo/{repo_type}",
390
- p / repo_suffix,
391
+ p / get_config_suffix(),
391
392
  overrides={
392
393
  "REPO_TYPE": repo_type,
393
394
  "REPO_PATH": str(p),
@@ -758,7 +759,7 @@ class Starbash:
758
759
  # (otherwise invariants will get messed up)
759
760
  self._add_session(headers)
760
761
 
761
- def reindex_repo(self, repo: Repo, subdir: str | None = None):
762
+ def reindex_repo(self, repo: Repo, subdir: str | None = None) -> None:
762
763
  """Reindex all repositories managed by the RepoManager."""
763
764
 
764
765
  # make sure this new repo is listed in the repos table
@@ -790,9 +791,9 @@ class Starbash:
790
791
  else:
791
792
  self.add_image_and_session(repo, f, force=starbash.force_regen)
792
793
  except OSError as e:
793
- logging.error(f'Skipping file due to "{f}": {e}')
794
+ logging.error(f'Skipping "{f}" due to: [red]{e}[/red]')
794
795
 
795
- def reindex_repos(self):
796
+ def reindex_repos(self) -> None:
796
797
  """Reindex all repositories managed by the RepoManager."""
797
798
  logging.debug("Reindexing all repositories...")
798
799
 
@@ -11,7 +11,7 @@ __all__ = [
11
11
  _is_connected: bool | None = None
12
12
 
13
13
 
14
- def is_connected(host="8.8.8.8", port=53, timeout=3) -> bool:
14
+ def is_connected(host: str = "8.8.8.8", port: int = 53, timeout: int = 3) -> bool:
15
15
  """
16
16
  Host: 1.1.1.1 (Cloudflare DNS) or 8.8.8.8 (Google DNS) (it is important to not use domain names)
17
17
  Port: 53/tcp
@@ -37,7 +37,7 @@ def is_connected(host="8.8.8.8", port=53, timeout=3) -> bool:
37
37
  socket.setdefaulttimeout(old_timeout)
38
38
 
39
39
 
40
- def check_version():
40
+ def check_version() -> None:
41
41
  """Check if a newer version of starbash is available on PyPI."""
42
42
  try:
43
43
  if is_connected():
@@ -62,21 +62,21 @@ def dump_column(sb: Starbash, human_name: str, column_name: str) -> None:
62
62
 
63
63
 
64
64
  @app.command()
65
- def target():
65
+ def target() -> None:
66
66
  """List targets (filtered based on the current selection)."""
67
67
  with Starbash("info.target") as sb:
68
68
  dump_column(sb, "Target", Database.OBJECT_KEY)
69
69
 
70
70
 
71
71
  @app.command()
72
- def telescope():
72
+ def telescope() -> None:
73
73
  """List telescopes/instruments (filtered based on the current selection)."""
74
74
  with Starbash("info.telescope") as sb:
75
75
  dump_column(sb, "Telescope", Database.TELESCOP_KEY)
76
76
 
77
77
 
78
78
  @app.command()
79
- def filter():
79
+ def filter() -> None:
80
80
  """List all filters (filtered based on the current selection)."""
81
81
  with Starbash("info.filter") as sb:
82
82
  dump_column(sb, "Filter", Database.FILTER_KEY)
@@ -93,7 +93,7 @@ def master(
93
93
  str | None,
94
94
  kind_arg,
95
95
  ] = None,
96
- ):
96
+ ) -> None:
97
97
  """List all precalculated master images (darks, biases, flats)."""
98
98
  with Starbash("info.master") as sb:
99
99
  from starbash import console
@@ -146,13 +146,13 @@ def masters(
146
146
  str | None,
147
147
  kind_arg,
148
148
  ] = None,
149
- ):
149
+ ) -> None:
150
150
  """Alias for 'info master' command."""
151
151
  master(kind)
152
152
 
153
153
 
154
154
  @app.callback(invoke_without_command=True)
155
- def main_callback(ctx: typer.Context):
155
+ def main_callback(ctx: typer.Context) -> None:
156
156
  """Show user preferences location and other app info.
157
157
 
158
158
  This is the default command when no subcommand is specified.
@@ -39,7 +39,7 @@ def siril(
39
39
  help="Automatically launch Siril GUI after generating directory tree",
40
40
  ),
41
41
  ] = False,
42
- ):
42
+ ) -> None:
43
43
  """Generate Siril directory tree and optionally run Siril GUI.
44
44
 
45
45
  Creates a properly structured directory tree for Siril processing with
@@ -64,7 +64,7 @@ def siril(
64
64
 
65
65
  # Get images for this session
66
66
 
67
- def session_to_dir(src_session: SessionRow, subdir_name: str):
67
+ def session_to_dir(src_session: SessionRow, subdir_name: str) -> None:
68
68
  """Copy the images from the specified session to the subdir"""
69
69
  img_dir = output_dir / subdir_name
70
70
  img_dir.mkdir(parents=True, exist_ok=True)
@@ -196,7 +196,7 @@ def auto(
196
196
  help="Don't automatically generated master frames",
197
197
  ),
198
198
  ] = False,
199
- ):
199
+ ) -> None:
200
200
  """Automatic processing with sensible defaults.
201
201
 
202
202
  If session number is specified, processes only that session.
@@ -254,7 +254,7 @@ def auto(
254
254
  )
255
255
  def doit(
256
256
  ctx: typer.Context,
257
- ):
257
+ ) -> None:
258
258
  """(private) for developer debugging of the underlying 'doit' dependency system.
259
259
 
260
260
  You probably don't need to use this - unless you are a starbash developer.
@@ -268,7 +268,7 @@ def doit(
268
268
 
269
269
 
270
270
  @app.command()
271
- def masters():
271
+ def masters() -> None:
272
272
  """Generate master flats, darks, and biases from selected raw frames.
273
273
 
274
274
  Analyzes the current selection to find all available calibration frames
@@ -289,7 +289,7 @@ def masters():
289
289
 
290
290
 
291
291
  @app.callback(invoke_without_command=True)
292
- def main_callback(ctx: typer.Context):
292
+ def main_callback(ctx: typer.Context) -> None:
293
293
  """Process images using automated workflows.
294
294
 
295
295
  These commands handle calibration, registration, stacking, and
@@ -1,11 +1,12 @@
1
1
  import logging
2
+ from collections.abc import Generator
2
3
  from textwrap import dedent
3
4
  from typing import Annotated
4
5
 
5
6
  import typer
7
+ from toml_repo import Repo
6
8
 
7
9
  import starbash
8
- from repo import Repo
9
10
  from starbash import console
10
11
  from starbash.app import Starbash
11
12
  from starbash.paths import get_user_documents_dir
@@ -13,7 +14,7 @@ from starbash.paths import get_user_documents_dir
13
14
  app = typer.Typer(invoke_without_command=True)
14
15
 
15
16
 
16
- def repo_enumeration(sb: Starbash):
17
+ def repo_enumeration(sb: Starbash) -> dict[int, Repo]:
17
18
  """return a dict of int (1 based) to Repo instances"""
18
19
  verbose = False # assume not verbose for enum picking
19
20
  repos = sb.repo_manager.repos if verbose else sb.repo_manager.regular_repos
@@ -21,7 +22,7 @@ def repo_enumeration(sb: Starbash):
21
22
  return {i + 1: repo for i, repo in enumerate(repos)}
22
23
 
23
24
 
24
- def complete_repo_by_num(incomplete: str):
25
+ def complete_repo_by_num(incomplete: str) -> Generator[tuple[str, str], None, None]:
25
26
  # We need to use stderr_logging to prevent confusing the bash completion parser
26
27
  starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
27
28
  with Starbash("repo.complete.num", stderr_logging=True) as sb:
@@ -30,7 +31,7 @@ def complete_repo_by_num(incomplete: str):
30
31
  yield (str(num), repo.url)
31
32
 
32
33
 
33
- def complete_repo_by_url(incomplete: str):
34
+ def complete_repo_by_url(incomplete: str) -> Generator[tuple[str, str], None, None]:
34
35
  # We need to use stderr_logging to prevent confusing the bash completion parser
35
36
  starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
36
37
  with Starbash("repo.complete.url", stderr_logging=True) as sb:
@@ -42,7 +43,7 @@ def complete_repo_by_url(incomplete: str):
42
43
 
43
44
 
44
45
  @app.command()
45
- def list():
46
+ def list() -> None:
46
47
  """
47
48
  lists all repositories.
48
49
  """
@@ -64,7 +65,7 @@ def list():
64
65
  @app.callback()
65
66
  def main(
66
67
  ctx: typer.Context,
67
- ):
68
+ ) -> None:
68
69
  """
69
70
  Manage repositories.
70
71
 
@@ -88,7 +89,7 @@ def add(
88
89
  "--processed",
89
90
  help="Mark this new repository for processed output files.",
90
91
  ),
91
- ):
92
+ ) -> None:
92
93
  """
93
94
  Add a repository. path is either a local path or a remote URL.
94
95
  """
@@ -155,7 +156,7 @@ def remove(
155
156
  str,
156
157
  typer.Argument(help="Repository number or URL", autocompletion=complete_repo_by_url),
157
158
  ],
158
- ):
159
+ ) -> None:
159
160
  """
160
161
  Remove a repository by number (from list).
161
162
  Use 'starbash repo' to see the repository numbers.
@@ -182,7 +183,7 @@ def reindex(
182
183
  autocompletion=complete_repo_by_url,
183
184
  ),
184
185
  ] = None,
185
- ):
186
+ ) -> None:
186
187
  """
187
188
  Reindex a repository by number.
188
189
  If no number is given, reindex all repositories.
@@ -2,6 +2,7 @@
2
2
 
3
3
  import logging
4
4
  from collections import Counter
5
+ from collections.abc import Generator
5
6
  from pathlib import Path
6
7
  from typing import Annotated, Any
7
8
 
@@ -35,7 +36,7 @@ def get_column(sb: Starbash, column_name: str) -> Counter:
35
36
  return all_counts
36
37
 
37
38
 
38
- def complete_date(incomplete: str, column_name: str):
39
+ def complete_date(incomplete: str, column_name: str) -> Generator[tuple[str, str], None, None]:
39
40
  """calls get_column() and assumes the returned str->count object has iso datetime strings as the keys
40
41
  it merges the counts for all dates that are on the same local timezone day.
41
42
  in the returned str->count, just include the date portion (YYYY-MM-DD)."""
@@ -58,7 +59,7 @@ def complete_date(incomplete: str, column_name: str):
58
59
  yield (date, f"{count} sessions")
59
60
 
60
61
 
61
- def complete_column(incomplete: str, column_name: str):
62
+ def complete_column(incomplete: str, column_name: str) -> Generator[tuple[str, str], None, None]:
62
63
  # We need to use stderr_logging to prevent confusing the bash completion parser
63
64
  starbash.log_filter_level = logging.ERROR # avoid showing output while doing completion
64
65
  with Starbash("repo.complete.column", stderr_logging=True) as sb:
@@ -70,7 +71,7 @@ def complete_column(incomplete: str, column_name: str):
70
71
 
71
72
 
72
73
  @app.command(name="any")
73
- def clear():
74
+ def clear() -> None:
74
75
  """Remove any filters on sessions, etc... (select everything)."""
75
76
  with Starbash("selection.clear") as sb:
76
77
  sb.selection.clear()
@@ -87,7 +88,7 @@ def target(
87
88
  autocompletion=lambda incomplete: complete_column(incomplete, Database.OBJECT_KEY),
88
89
  ),
89
90
  ],
90
- ):
91
+ ) -> None:
91
92
  """Limit the current selection to only the named target."""
92
93
  with Starbash("selection.target") as sb:
93
94
  # For now, replace existing targets with this one
@@ -107,7 +108,7 @@ def telescope(
107
108
  autocompletion=lambda incomplete: complete_column(incomplete, Database.TELESCOP_KEY),
108
109
  ),
109
110
  ],
110
- ):
111
+ ) -> None:
111
112
  """Limit the current selection to only the named telescope."""
112
113
  with Starbash("selection.telescope") as sb:
113
114
  # For now, replace existing telescopes with this one
@@ -118,7 +119,7 @@ def telescope(
118
119
  do_list_sessions(sb, brief=not starbash.verbose_output)
119
120
 
120
121
 
121
- def complete_name(incomplete: str, names: list[str]):
122
+ def complete_name(incomplete: str, names: list[str]) -> Generator[str, None, None]:
122
123
  """Return typer style autocompletion from a list of string constants."""
123
124
  for name in names:
124
125
  if name.startswith(incomplete):
@@ -150,7 +151,7 @@ def date(
150
151
  autocompletion=lambda incomplete: complete_date(incomplete, Database.START_KEY),
151
152
  ),
152
153
  ] = None,
153
- ):
154
+ ) -> None:
154
155
  """Limit to sessions in the specified date range.
155
156
 
156
157
  Examples:
@@ -184,7 +185,7 @@ def date(
184
185
  do_list_sessions(sb, brief=not starbash.verbose_output)
185
186
 
186
187
 
187
- def do_list_sessions(sb: Starbash, brief: bool = False):
188
+ def do_list_sessions(sb: Starbash, brief: bool = False) -> None:
188
189
  """List sessions (filtered based on the current selection)"""
189
190
 
190
191
  sessions = sb.search_session()
@@ -308,7 +309,7 @@ def list_sessions(
308
309
  "--brief",
309
310
  help="If there are many sessions, show only a few.",
310
311
  ),
311
- ):
312
+ ) -> None:
312
313
  """List sessions (filtered based on the current selection)"""
313
314
 
314
315
  with Starbash("selection.list") as sb:
@@ -351,7 +352,7 @@ def export(
351
352
  str,
352
353
  typer.Argument(help="Directory path to export to (if it doesn't exist it will be created)"),
353
354
  ],
354
- ):
355
+ ) -> None:
355
356
  """Export the images for the indicated session number.
356
357
 
357
358
  Uses symbolic links when possible, otherwise copies files.
@@ -377,7 +378,7 @@ def export(
377
378
 
378
379
 
379
380
  @app.callback(invoke_without_command=True)
380
- def show_selection(ctx: typer.Context):
381
+ def show_selection(ctx: typer.Context) -> None:
381
382
  """List information about the current selection.
382
383
 
383
384
  This is the default command when no subcommand is specified.
@@ -19,7 +19,7 @@ def analytics(
19
19
  help="Enable or disable analytics (crash reports and usage data).",
20
20
  ),
21
21
  ],
22
- ):
22
+ ) -> None:
23
23
  """
24
24
  Enable or disable analytics (crash reports and usage data).
25
25
  """
@@ -41,7 +41,7 @@ def name(
41
41
  help="Your name for attribution in generated images.",
42
42
  ),
43
43
  ],
44
- ):
44
+ ) -> None:
45
45
  """
46
46
  Set your name for attribution in generated images.
47
47
  """
@@ -61,7 +61,7 @@ def email(
61
61
  help="Your email for attribution in generated images.",
62
62
  ),
63
63
  ],
64
- ):
64
+ ) -> None:
65
65
  """
66
66
  Set your email for attribution in generated images.
67
67
  """
@@ -194,7 +194,7 @@ def do_reinit(sb: Starbash) -> None:
194
194
 
195
195
 
196
196
  @app.command()
197
- def setup():
197
+ def setup() -> None:
198
198
  """
199
199
  Configure starbash via a brief guided process.
200
200
 
@@ -206,7 +206,7 @@ def setup():
206
206
 
207
207
 
208
208
  @app.callback(invoke_without_command=True)
209
- def main_callback(ctx: typer.Context):
209
+ def main_callback(ctx: typer.Context) -> None:
210
210
  """Main callback for the Starbash application."""
211
211
  if ctx.invoked_subcommand is None:
212
212
  from starbash import console
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import sqlite3
5
+ import types
5
6
  from dataclasses import dataclass
6
7
  from datetime import datetime, timedelta
7
8
  from pathlib import Path
@@ -801,5 +802,5 @@ class Database:
801
802
  def __enter__(self) -> Database:
802
803
  return self
803
804
 
804
- def __exit__(self, exc_type, exc, tb) -> None:
805
+ def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: types.TracebackType | None) -> None:
805
806
  self.close()