starbash 0.1.8__py3-none-any.whl → 0.1.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

starbash/toml.py ADDED
@@ -0,0 +1,29 @@
1
+ import tomlkit
2
+ from tomlkit.toml_file import TOMLFile
3
+ from pathlib import Path
4
+ from importlib import resources
5
+ from typing import Any
6
+
7
+ from starbash import url
8
+
9
+ def toml_from_template(template_name: str, dest_path: Path, overrides: dict[str, Any] = {}) -> tomlkit.TOMLDocument:
10
+ """Load a TOML document from a template file.
11
+ expand {vars} in the template using the `overrides` dictionary.
12
+ """
13
+
14
+ tomlstr = (
15
+ resources.files("starbash")
16
+ .joinpath(f"templates/{template_name}.toml")
17
+ .read_text()
18
+ )
19
+
20
+ # add default vars always available
21
+ vars = {
22
+ "PROJECT_URL": url.project
23
+ }
24
+ vars.update(overrides)
25
+ tomlstr = tomlstr.format(**vars)
26
+
27
+ toml = tomlkit.parse(tomlstr)
28
+ TOMLFile(dest_path).write(toml)
29
+ return toml
starbash/tool.py CHANGED
@@ -3,6 +3,7 @@ import shutil
3
3
  import textwrap
4
4
  import tempfile
5
5
  import subprocess
6
+ import select
6
7
  import re
7
8
 
8
9
  import logging
@@ -44,13 +45,68 @@ def expand_context(s: str, context: dict) -> str:
44
45
 
45
46
  # throw an error if any remaining unexpanded variables remain unexpanded
46
47
  unexpanded_vars = re.findall(r"\{([^{}]+)\}", expanded)
48
+
49
+ # Remove duplicates
50
+ unexpanded_vars = list(dict.fromkeys(unexpanded_vars))
47
51
  if unexpanded_vars:
48
52
  raise KeyError("Missing context variable(s): " + ", ".join(unexpanded_vars))
49
53
 
50
54
  return expanded
51
55
 
52
56
 
53
- def make_safe_globals(context: dict = {}) -> dict:
57
+ def expand_context_unsafe(s: str, context: dict) -> str:
58
+ """Expand a string with Python expressions in curly braces using RestrictedPython.
59
+
60
+ Context variables are directly available in expressions without a prefix.
61
+
62
+ Supports expressions like:
63
+ - "foo {1 + 2}" -> "foo 3"
64
+ - "bar {name}" -> "bar <value of context['name']>"
65
+ - "path {instrument}/{date}/file.fits" -> "path MyScope/2025-01-01/file.fits"
66
+ - "sum {x + y}" -> "sum <value of context['x'] + context['y']>"
67
+
68
+ Args:
69
+ s: String with Python expressions in curly braces
70
+ context: Dictionary of variables available directly in expressions
71
+
72
+ Returns:
73
+ String with all expressions evaluated and substituted
74
+
75
+ Raises:
76
+ ValueError: If any expression cannot be evaluated (syntax errors, missing variables, etc.)
77
+
78
+ Note: Uses RestrictedPython for safety, but still has security implications.
79
+ This is a more powerful but less safe alternative to expand_context().
80
+ """
81
+ # Find all expressions in curly braces
82
+ pattern = r"\{([^{}]+)\}"
83
+
84
+ def eval_expression(match):
85
+ """Evaluate a single expression and return its string representation."""
86
+ expr = match.group(1).strip()
87
+
88
+ try:
89
+ # Compile the expression with RestrictedPython
90
+ byte_code = RestrictedPython.compile_restricted(
91
+ expr, filename="<template expression>", mode="eval"
92
+ )
93
+
94
+ # Evaluate with safe globals and the context
95
+ result = eval(byte_code, make_safe_globals(context), None)
96
+ return str(result)
97
+
98
+ except Exception as e:
99
+ raise ValueError(f"Failed to evaluate expression '{expr}'") from e
100
+
101
+ # Replace all expressions
102
+ expanded = re.sub(pattern, eval_expression, s)
103
+
104
+ logger.debug(f"Unsafe expanded '{s}' into '{expanded}'")
105
+
106
+ return expanded
107
+
108
+
109
+ def make_safe_globals(extra_globals: dict = {}) -> dict:
54
110
  """Generate a set of RestrictedPython globals for AstoGlue exec/eval usage"""
55
111
  # Define the global and local namespaces for the restricted execution.
56
112
  # FIXME - this is still unsafe, policies need to be added to limit import/getattr etc...
@@ -88,9 +144,9 @@ def make_safe_globals(context: dict = {}) -> dict:
88
144
  "__name__": "__starbash_script__",
89
145
  "__metaclass__": type,
90
146
  # Extra globals auto imported into the scripts context
91
- "context": context,
92
147
  "logger": logging.getLogger("script"), # Allow logging within the script
93
148
  }
149
+ execution_globals.update(extra_globals)
94
150
  return execution_globals
95
151
 
96
152
 
@@ -106,67 +162,95 @@ def strip_comments(text: str) -> str:
106
162
  return "\n".join(lines)
107
163
 
108
164
 
109
- def tool_run(cmd: str, cwd: str, commands: str | None = None) -> None:
110
- """Executes an external tool with an optional script of commands in a given working directory."""
111
-
112
- logger.debug(f"Running {cmd} in {cwd}: stdin={commands}")
113
- result = subprocess.run(
114
- cmd, input=commands, shell=True, capture_output=True, text=True, cwd=cwd
115
- )
116
-
117
- if result.stderr:
118
- logger.warning(f"Tool error message:\n{result.stderr.strip()}")
119
-
120
- if result.returncode != 0:
121
- # If we got an error, print the entire tool stdout as a warning
122
- logger.warning(f"Tool output:\n{result.stdout.strip()}")
123
- raise RuntimeError(f"Tool failed with exit code {result.returncode}")
124
- else:
125
- logger.debug("Tool command successful.")
165
+ def tool_run(
166
+ cmd: str, cwd: str, commands: str | None = None, timeout: float | None = None
167
+ ) -> None:
168
+ """Executes an external tool with an optional script of commands in a given working directory.
126
169
 
127
- if result.stdout:
128
- logger.debug(f"Tool output:\n{result.stdout.strip()}")
129
-
130
-
131
- # siril_path = "/home/kevinh/packages/Siril-1.4.0~beta3-x86_64.AppImage"
132
- siril_path = "org.siril.Siril" # flatpak
133
-
134
-
135
- def siril_run(temp_dir: str, commands: str, input_files: list[str] = []) -> None:
136
- """Executes Siril with a script of commands in a given working directory."""
137
-
138
- # Create symbolic links for all input files in the temp directory
139
- for f in input_files:
140
- os.symlink(
141
- os.path.abspath(str(f)), os.path.join(temp_dir, os.path.basename(str(f)))
142
- )
170
+ Streams stdout and stderr in real-time to the logger, allowing you to see subprocess output
171
+ as it happens rather than waiting for completion.
172
+ """
143
173
 
144
- # We dedent here because the commands are often indented multiline strings
145
- script_content = textwrap.dedent(
146
- f"""
147
- requires 1.4.0-beta3
148
- {textwrap.dedent(strip_comments(commands))}
149
- """
150
- )
174
+ logger.debug(f"Running {cmd} in {cwd}: stdin={commands}")
151
175
 
152
- logger.info(
153
- f"Running Siril in {temp_dir}, ({len(input_files)} input files) cmds:\n{script_content}"
176
+ # Start the process with pipes for streaming
177
+ process = subprocess.Popen(
178
+ cmd,
179
+ stdin=subprocess.PIPE if commands else None,
180
+ stdout=subprocess.PIPE,
181
+ stderr=subprocess.PIPE,
182
+ shell=True,
183
+ text=True,
184
+ cwd=cwd,
154
185
  )
155
186
 
156
- # The `-s -` arguments tell Siril to run in script mode and read commands from stdin.
157
- # It seems like the -d command may also be required when siril is in a flatpak
158
- cmd = f"{siril_path} -d {temp_dir} -s -"
159
-
160
- tool_run(cmd, temp_dir, script_content)
161
-
162
-
163
- def graxpert_run(cwd: str, arguments: str) -> None:
164
- """Executes Graxpert with the specified command line arguments"""
165
-
166
- # Arguments look similar to: graxpert -cmd background-extraction -output /tmp/testout tests/test_images/real_crummy.fits
167
- cmd = f"graxpert {arguments}"
168
-
169
- tool_run(cmd, cwd)
187
+ # Send commands to stdin if provided
188
+ if commands and process.stdin:
189
+ try:
190
+ process.stdin.write(commands)
191
+ process.stdin.close()
192
+ except BrokenPipeError:
193
+ # Process may have terminated early
194
+ pass
195
+
196
+ # Stream output line by line in real-time
197
+ assert process.stdout
198
+ assert process.stderr
199
+
200
+ try:
201
+ streams = {
202
+ process.stdout.fileno(): (process.stdout, logger.debug, "tool-stdout"),
203
+ process.stderr.fileno(): (process.stderr, logger.warning, "tool-stderr"),
204
+ }
205
+
206
+ while streams:
207
+ # Wait for data on any stream (with timeout for periodic checking)
208
+ ready, _, _ = select.select(list(streams.keys()), [], [], 0.1)
209
+
210
+ for fd in ready:
211
+ stream, log_func, stream_name = streams[fd]
212
+ line = stream.readline()
213
+
214
+ if line:
215
+ # Strip trailing newline and log immediately
216
+ line = line.rstrip("\n")
217
+ log_func(f"[{stream_name}] {line}")
218
+ else:
219
+ # EOF reached on this stream
220
+ del streams[fd]
221
+
222
+ # Check if process has terminated
223
+ if process.poll() is not None and not streams:
224
+ break
225
+
226
+ # Wait for process to complete with timeout
227
+ try:
228
+ process.wait(timeout=timeout)
229
+ except subprocess.TimeoutExpired:
230
+ process.kill()
231
+ process.wait()
232
+ raise RuntimeError(f"Tool timed out after {timeout} seconds")
233
+
234
+ returncode = process.returncode
235
+
236
+ if returncode != 0:
237
+ raise RuntimeError(f"Tool failed with exit code {returncode}")
238
+ else:
239
+ logger.debug("Tool command successful.")
240
+ finally:
241
+ # Ensure streams are properly closed
242
+ if process.stdout:
243
+ process.stdout.close()
244
+ if process.stderr:
245
+ process.stderr.close()
246
+
247
+
248
+ def executable_path(commands: list[str], name: str) -> str:
249
+ """Find the correct executable path to run for the given tool"""
250
+ for cmd in commands:
251
+ if shutil.which(cmd):
252
+ return cmd
253
+ raise FileNotFoundError(f"{name} not found, you probably need to install it.")
170
254
 
171
255
 
172
256
  class Tool:
@@ -177,6 +261,12 @@ class Tool:
177
261
 
178
262
  # default script file name
179
263
  self.default_script_file = None
264
+ self.set_defaults()
265
+
266
+ def set_defaults(self):
267
+ # default timeout in seconds, if you need to run a tool longer than this, you should change
268
+ # it before calling run()
269
+ self.timeout = 10.0
180
270
 
181
271
  def run_in_temp_dir(self, commands: str, context: dict = {}) -> None:
182
272
  """Run commands inside this tool (with cwd pointing to a temp directory)"""
@@ -204,14 +294,50 @@ class SirilTool(Tool):
204
294
  super().__init__("siril")
205
295
 
206
296
  def run(self, cwd: str, commands: str, context: dict = {}) -> None:
297
+ """Executes Siril with a script of commands in a given working directory."""
207
298
 
208
299
  # Iteratively expand the command string to handle nested placeholders.
209
300
  # The loop continues until the string no longer changes.
210
- expanded = expand_context(commands, context)
301
+ expanded = expand_context_unsafe(commands, context)
211
302
 
212
303
  input_files = context.get("input_files", [])
213
304
 
214
- siril_run(cwd, expanded, input_files)
305
+ temp_dir = cwd
306
+
307
+ # siril_path = "/home/kevinh/packages/Siril-1.4.0~beta3-x86_64.AppImage"
308
+ # Possible siril commands, with preferred option first
309
+ siril_commands = ["org.siril.Siril", "siril-cli", "siril"]
310
+ siril_path = executable_path(siril_commands, "Siril")
311
+ if siril_path == "org.siril.Siril":
312
+ # The executable is inside a flatpak, so run the lighter/faster/no-gui required exe
313
+ # from inside the flatpak
314
+ siril_path = "flatpak run --command=siril-cli org.siril.Siril"
315
+
316
+ # Create symbolic links for all input files in the temp directory
317
+ for f in input_files:
318
+ os.symlink(
319
+ os.path.abspath(str(f)),
320
+ os.path.join(temp_dir, os.path.basename(str(f))),
321
+ )
322
+
323
+ # We dedent here because the commands are often indented multiline strings
324
+ script_content = textwrap.dedent(
325
+ f"""
326
+ requires 1.4.0-beta3
327
+ {textwrap.dedent(strip_comments(expanded))}
328
+ """
329
+ )
330
+
331
+ logger.debug(
332
+ f"Running Siril in {temp_dir}, ({len(input_files)} input files) cmds:\n{script_content}"
333
+ )
334
+ logger.info(f"Running Siril ({len(input_files)} input files)")
335
+
336
+ # The `-s -` arguments tell Siril to run in script mode and read commands from stdin.
337
+ # It seems like the -d command may also be required when siril is in a flatpak
338
+ cmd = f"{siril_path} -d {temp_dir} -s -"
339
+
340
+ tool_run(cmd, temp_dir, script_content, timeout=self.timeout)
215
341
 
216
342
 
217
343
  class GraxpertTool(Tool):
@@ -221,7 +347,12 @@ class GraxpertTool(Tool):
221
347
  super().__init__("graxpert")
222
348
 
223
349
  def run(self, cwd: str, commands: str, context: dict = {}) -> None:
224
- graxpert_run(cwd, commands)
350
+ """Executes Graxpert with the specified command line arguments"""
351
+
352
+ # Arguments look similar to: graxpert -cmd background-extraction -output /tmp/testout tests/test_images/real_crummy.fits
353
+ cmd = f"graxpert {commands}"
354
+
355
+ tool_run(cmd, cwd, timeout=self.timeout)
225
356
 
226
357
 
227
358
  class PythonTool(Tool):
@@ -245,16 +376,17 @@ class PythonTool(Tool):
245
376
  )
246
377
  # No locals yet
247
378
  execution_locals = None
248
- exec(byte_code, make_safe_globals(context), execution_locals)
379
+ globals = {"context": context}
380
+ exec(byte_code, make_safe_globals(globals), execution_locals)
249
381
  except SyntaxError as e:
250
- logger.error(f"Syntax error in python script: {e}")
251
- raise
382
+ raise # Just rethrow - no need to rewrap
252
383
  except Exception as e:
253
- logger.error(f"Error during python script execution: {e}")
254
- raise
384
+ raise ValueError(f"Error during python script execution") from e
255
385
  finally:
256
386
  os.chdir(original_cwd)
257
387
 
258
388
 
259
389
  # A dictionary mapping tool names to their respective tool instances.
260
- tools = {tool.name: tool for tool in [SirilTool(), GraxpertTool(), PythonTool()]}
390
+ tools: dict[str, Tool] = {
391
+ tool.name: tool for tool in [SirilTool(), GraxpertTool(), PythonTool()]
392
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: starbash
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: A tool for automating/standardizing/sharing astrophotography workflows.
5
5
  License-File: LICENSE
6
6
  Author: Kevin Hester
@@ -20,7 +20,7 @@ Requires-Dist: tomlkit (>=0.13.3,<0.14.0)
20
20
  Requires-Dist: typer (>=0.20.0,<0.21.0)
21
21
  Description-Content-Type: text/markdown
22
22
 
23
- # Starbash
23
+ # [Starbash](https://github.com/geeksville/starbash)
24
24
 
25
25
  <img src="https://raw.githubusercontent.com/geeksville/starbash/refs/heads/main/img/icon.png" alt="Starbash: Astrophotography workflows simplified" width="30%" align="right" style="margin-bottom: 20px;">
26
26
 
@@ -33,6 +33,7 @@ A tool for automating/standardizing/sharing astrophotography workflows.
33
33
  * Automatic - with sensible defaults, that you can change as needed.
34
34
  * Easy - provides a 'seestar like' starting-point for autoprocessing all your sessions (by default).
35
35
  * Fast - even with large image repositories. Automatic master bias and flat generation and reasonable defaults
36
+ * Multi-session - by default. So your workflows can stack from multiple nights (and still use the correct flats etc...)
36
37
  * Sharable - you can share/use recipes for image preprocessing flows.
37
38
 
38
39
  (This project is currently 'alpha' and missing recipes for some workflows, but adding new recipes is easy and we're happy to help. Please file a github issue if your images are not auto-processed and we'll work out a fix.)
@@ -67,7 +68,7 @@ See the current [TODO](TODO.md) file for work items. I'll be looking for pre-al
67
68
 
68
69
  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.
69
70
 
70
- Once pipx is installed just run the following **two** commands (the sb --install-completion will make TAB auto-complete automatically complete sb options (for most platforms)):
71
+ Once pipx is installed just run the following **two** commands (the sb --install-completion will make TAB auto-complete automatically complete sb options (for most platforms)). Installing auto-complete is **highly** recommended because it makes entering starbash commands fast - by pressing the TAB key:
71
72
 
72
73
  ```
73
74
  ➜ pipx install starbash
@@ -88,10 +89,10 @@ FIXME - add getting started instructions (possibly with a screenshare video)
88
89
  ## Supported commands
89
90
 
90
91
  ### Repository Management
91
- - `sb repo [--verbose]` - List installed repos (use `-v` for details)
92
- - `sb repo add <filepath|URL>` - Add a repository
93
- - `sb repo remove <REPONUM>` - Remove the indicated repo from the repo list
94
- - `sb repo reindex [--force] [REPONUM]` - Reindex the specified repo (or all repos if none specified)
92
+ - `sb repo list [--verbose]` - List installed repos (use `-v` for details)
93
+ - `sb repo add [--master] [filepath|URL]` - Add a repository, optionally specifying the type
94
+ - `sb repo remove <REPOURL>` - Remove the indicated repo from the repo list
95
+ - `sb repo reindex [--force] <REPOURL>` - Reindex the specified repo (or all repos if none specified)
95
96
 
96
97
  ### User Preferences
97
98
  - `sb user name "Your Name"` - Set name for attribution in generated images
@@ -108,18 +109,19 @@ FIXME - add getting started instructions (possibly with a screenshare video)
108
109
  - `sb select date <after|before|between> <DATE> [DATE]` - Limit to sessions in the specified date range
109
110
  - `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.
110
111
 
111
- ## Not yet supported commands
112
-
113
- ### Setup & Configuration
112
+ ### Selection information
114
113
  - `sb info` - Show user preferences location and other app info
115
114
  - `sb info target` - List targets (filtered based on the current selection)
116
115
  - `sb info telescope` - List instruments (filtered based on the current selection)
117
116
  - `sb info filter` - List all filters found in current selection
117
+ - `sb info master [KIND]` - List all precalculated master images (darks, biases, flats). Optional KIND argument to filter by image type (e.g., BIAS, DARK, FLAT)
118
+
119
+ ## Not yet supported commands
118
120
 
119
121
  ### Export & Processing
120
- - `sb process siril` - Generate Siril directory tree and run Siril GUI
121
- - `sb process auto` - Automatic processing
122
- - `sb process masters` - Generate master flats, darks, and biases from available raw frames
122
+ - `sb process siril [--run] SESSIONNUM DESTDIR` - Generate Siril directory tree and optionally run Siril GUI
123
+ - `sb process auto [SESSIONNUM]` - Automatic processing. If session # is specified process only that session, otherwise all selected sessions will be processed
124
+ - `sb process masters` - Generate master flats, darks, and biases from available raw frames in the current selection
123
125
 
124
126
  ## Supported tools (now)
125
127
 
@@ -138,3 +140,8 @@ We try to make this project useful and friendly. If you find problems please fi
138
140
  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.
139
141
 
140
142
  Project members can access crash reports [here](https://geeksville.sentry.io/insights/projects/starbash/?project=4510264204132352).
143
+
144
+ ## License
145
+
146
+ Copyright 2025 Kevin Hester, kevinh@geeksville.com.
147
+ Licensed under the [GPL v3](LICENSE)
@@ -0,0 +1,40 @@
1
+ repo/__init__.py,sha256=St2udJPFek-KwjagkH23h8kBYJHyIXrXjQJpL2Vjz_s,229
2
+ repo/manager.py,sha256=4QEt4oRzlTcf75Q7gALBFhtZS_JXOJF6apnSYozRC5c,4812
3
+ repo/repo.py,sha256=7EgzEDzTDuluGFbGHLz_-tracze4jPuzerXJpjUaDKU,10680
4
+ starbash/__init__.py,sha256=0kEchneSvvuKV334VwULs3UZSIJ9Edsfvawuq39LJmo,1146
5
+ starbash/aliases.py,sha256=x2be5VsHmSgwT5WCR_jMjPhnVLhd4Mu1Gw4RctzgOqI,3779
6
+ starbash/analytics.py,sha256=XYe7PN-pymXmmv8x1C2mUV_wecTnY9gHjczUv3fjSo8,4346
7
+ starbash/app.py,sha256=UObVH6dBlWiCboCgRc1uY-2hhGV7tdlHUfIySc3wXg8,43227
8
+ starbash/commands/__init__.py,sha256=sapJ5w5PFGUfmXtUA1bGIFTr0_gf91Gw6rgCcmzmjUw,706
9
+ starbash/commands/info.py,sha256=hE3c7_OlCKir5dYM73p9dFsyfhlN1MuC0j0-BFSQlSs,6162
10
+ starbash/commands/process.py,sha256=c5fsLX0sZRzC_8baT2aZYOpqN57jttL5YEvSJH_U3LU,5236
11
+ starbash/commands/repo.py,sha256=ZIIwpTtvpIiekK2FgrTMU9kNl-df4YH7oBSxOIlP-Ek,8220
12
+ starbash/commands/select.py,sha256=OvViVLpu3jKTgaBGKNuHxXx2QZfUVDdFqYLDoMay5E8,14773
13
+ starbash/commands/user.py,sha256=MIJFhhWokoaBiZ6rKqQaSVxSvO_glwG5dTGhaZy-6PA,4249
14
+ starbash/database.py,sha256=oHE1n4Jf7U2dfd9ONk-iQct_KPx2S11cSj_t7ZylCIg,26843
15
+ starbash/defaults/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ starbash/defaults/starbash.toml,sha256=drG42Q-mOy88d6F31BSbAiN_FTkiGrZSv2wz114MlpM,3112
17
+ starbash/main.py,sha256=DdeV_w4P__q0sTcGjGUm5hBqIDurq8DUKoDQQaawsfA,1600
18
+ starbash/paths.py,sha256=Xr4ZE4yWA_3zu23n8TLXa-wfLRWpQtvjTte0KTMG798,1896
19
+ starbash/recipes/README.md,sha256=OC0CUAL7xhxujOtEg97vrdNLZmGPLusBeOnwTo5rKN8,317
20
+ starbash/recipes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ starbash/recipes/master_bias/starbash.toml,sha256=GAnpwEK9AV0G5agP50nUoJVW30OMDcRTkyMkW2b3sHY,2791
22
+ starbash/recipes/master_dark/starbash.toml,sha256=wynSMp3fQtTY6KtZZM5FGokFxLW2XtKwWNUZOSCqDhs,827
23
+ starbash/recipes/master_flat/starbash.toml,sha256=8Nd8jSSwGbNLPSZn37zIzNFRsmBR-VSDYQuwCOM3qD4,1775
24
+ starbash/recipes/osc_dual_duo/starbash.py,sha256=CkDhm-6sE4ZC44Rvlp6hO3dmBYEA0kfVHVNkJOni7JQ,5666
25
+ starbash/recipes/osc_dual_duo/starbash.toml,sha256=_BkkSn-iYFYIdJANbDKKMz0xAcVSGEU9kZaKsc5r0xI,3241
26
+ starbash/recipes/osc_single_duo/starbash.toml,sha256=Q0JRsv3SVBWie8LeK0xfY03c2dcN5JNLjjPJQKygUDk,2127
27
+ starbash/recipes/starbash.toml,sha256=CDTjGGSaUFpQ7rtLpG_T6xyToBLYsOiIEkRKBeRxitQ,1546
28
+ starbash/selection.py,sha256=404XPXA5nFtlyrFf4uikeJ5VNPShT_h5PBkQbx11IEQ,10964
29
+ starbash/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ starbash/templates/repo/master.toml,sha256=c53CXMdIPlw9E50LRabgHfyn2qOS0dhz7nmXBx0ETQA,392
31
+ starbash/templates/repo/processed.toml,sha256=jVsFjCkTGmIV5RfQ2yOIotLJRqXnPhYdxpQytuSJoKg,321
32
+ starbash/templates/userconfig.toml,sha256=4bpUQ5WlA2Ebbl6c5QxmS2-SXV4IxmN3-H9IghepQEQ,1459
33
+ starbash/toml.py,sha256=aNuCqsQ33HYDpWgr_9vpDpd80h2vOU2-kBQmkUqri7c,783
34
+ starbash/tool.py,sha256=uNWG3P8D77NQxdEdPEhy5pFfBf6-Kk1t6HTyZnRWCeo,13560
35
+ starbash/url.py,sha256=lorxQJ27jSfzsKCb0QvpcvLiPZG55Dkd_c1JPFbni4I,402
36
+ starbash-0.1.10.dist-info/METADATA,sha256=nqI8jba7u59wnkwlChR40t8ngeGmniL4UxED2K01dl8,7999
37
+ starbash-0.1.10.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
38
+ starbash-0.1.10.dist-info/entry_points.txt,sha256=REQyWs8e5TJsNK7JVVWowKVoytMmKlUwuFHLTmSX4hc,67
39
+ starbash-0.1.10.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
40
+ starbash-0.1.10.dist-info/RECORD,,
@@ -1,33 +0,0 @@
1
- repo/__init__.py,sha256=TqspuLjPSNnO38tvCGa0fJvvasgecHl6fE7m0-Lj8ho,148
2
- repo/manager.py,sha256=Fc_akPK7D8sw3961DM5BCQ7O27tnEdAutg8TSNiopgI,13903
3
- starbash/__init__.py,sha256=JNkBTu--Wf10eSHDwcpMS2hOp1VeTHmOGAcKPSlLbyo,618
4
- starbash/analytics.py,sha256=J1J8oXGZkdovXNkqOYGv12vl3p5EZEXHSXpcMrnUwzE,4122
5
- starbash/app.py,sha256=-dx92jUc7_jOJEsncubiRy5SUqMy10343MlRcm1zd9k,17921
6
- starbash/commands/__init__.py,sha256=J7XuX7EMXZg2EBJLvXmm8jAfyhY7Yt9bTvoDaptp0YU,1231
7
- starbash/commands/info.py,sha256=ebYQsieYzkuemCmiSIOwi7EzKJZd7W5oCdprgu3l3Tk,4135
8
- starbash/commands/repo.py,sha256=nPtt7vtkq0lMwkrL8qgsptV26MEathbPp3X2fVBn_ug,4950
9
- starbash/commands/select.py,sha256=mjehAiIPg_v7IZ_IAgNTXxpHjYIcAlV9oGPCLiYHbT4,11371
10
- starbash/commands/user.py,sha256=MIJFhhWokoaBiZ6rKqQaSVxSvO_glwG5dTGhaZy-6PA,4249
11
- starbash/database.py,sha256=w7QzgtupzfGsKoSoBsHCHhukNr2RQnAO323LCWas5dI,17539
12
- starbash/defaults/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- starbash/defaults/starbash.toml,sha256=gciQjE2Q5QgS1aUph9Y4icI0xpYeDOALkzpAjZiabIk,1737
14
- starbash/main.py,sha256=BFmR-jP6RsXh9q6Gl3_3_F_4mMkYwEBhmox6fpz0Cyo,1492
15
- starbash/paths.py,sha256=BKKnSXt3tOh16o7ljDcQLtWKIiepEmud9JFtzRwDHtg,1317
16
- starbash/recipes/README.md,sha256=OC0CUAL7xhxujOtEg97vrdNLZmGPLusBeOnwTo5rKN8,317
17
- starbash/recipes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- starbash/recipes/master_bias/starbash.toml,sha256=KX2hFDVnLaBBULYnNnlSqXkflW4wP_04MnSaREk2IgI,2122
19
- starbash/recipes/master_flat/starbash.toml,sha256=HWZXjXbTiExsC6o5QNr1-5x37PBRo7XNwBEto8Ea-LE,1430
20
- starbash/recipes/osc_dual_duo/starbash.py,sha256=2cI4L6-d50-mL4hY0Oe6ad1v7g18D7ud0Hn0AlHZDOk,5788
21
- starbash/recipes/osc_dual_duo/starbash.toml,sha256=xh3zEqdotRZr7eUcqel-xnQcWH8z-PUFRuWQfLp3F_E,3195
22
- starbash/recipes/osc_single_duo/starbash.toml,sha256=kB-FMek0Z-8vieUfxKqmZMFNnZsSKdufSkLSgH03CkY,2117
23
- starbash/recipes/starbash.toml,sha256=iZs0nLGY1kox0wa5ZzX9t2xTffy4Jbu_Q221Egnsml8,1019
24
- starbash/selection.py,sha256=DPzUlls3n-sBqkwTUns2ZNaPi61PGnh7Z_ZQOC1jXYc,8347
25
- starbash/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- starbash/templates/userconfig.toml,sha256=LCV69jAxLrIPXrkt6U-gU4KLKeb9MHCD1ownqG211Ns,1442
27
- starbash/tool.py,sha256=S1kOTbeHTrA0meqwftgL0SA4VhJdZWWx2h1Wtwu1Izg,8749
28
- starbash/url.py,sha256=lorxQJ27jSfzsKCb0QvpcvLiPZG55Dkd_c1JPFbni4I,402
29
- starbash-0.1.8.dist-info/METADATA,sha256=mEG49YmhE8HSzhWni1dfS8JOzJ2rDYIB_vKI3nmFAUA,7215
30
- starbash-0.1.8.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
31
- starbash-0.1.8.dist-info/entry_points.txt,sha256=REQyWs8e5TJsNK7JVVWowKVoytMmKlUwuFHLTmSX4hc,67
32
- starbash-0.1.8.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
33
- starbash-0.1.8.dist-info/RECORD,,