snowglobe-cli 0.2.0__tar.gz → 0.2.1__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.
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/PKG-INFO +1 -1
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/pyproject.toml +1 -1
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/cost.py +2 -1
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/home.py +23 -12
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/styles.tcss +16 -4
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/PKG-INFO +1 -1
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/LICENSE +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/README.md +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/setup.cfg +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/__main__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/access.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/app.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/context.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/cost.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/debug.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/diff.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/optimizer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/prompts.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/report.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/shell.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/cli/shell_completer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/collectors/access.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/collectors/query_history.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/collectors/query_profile.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/config/loader.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/access_service.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/cost_service.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/optimizer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/query_service.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/report_service.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/core/risk_service.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/engines/access/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/engines/access/explainer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/engines/access/resolver.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/engines/ai/cortex_optimizer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/engines/optimizer/query_optimizer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/graphs/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/graphs/role_graph.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/graphs/user_graph.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/access.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/access_path.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/object_ref.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/object_type.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/optimizer.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/privilege.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/models/query.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/output/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/output/cli.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/queries/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/queries/query_history.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/snowflake/connection.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/state/db.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/state/state.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/templates/report.md.j2 +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tests/access_tests.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/__main__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/app.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/access.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/refresh.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/reports.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/risk.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/screens/tune.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/widgets/__init__.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/widgets/access_paths.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/widgets/cache_badge.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/widgets/header.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe/tui/widgets/nav.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/SOURCES.txt +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/dependency_links.txt +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/entry_points.txt +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/requires.txt +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/snowglobe_cli.egg-info/top_level.txt +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_access.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_optimizer_engine.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_output.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_query_validation.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_state_db.py +0 -0
- {snowglobe_cli-0.2.0 → snowglobe_cli-0.2.1}/tests/test_tui_tune.py +0 -0
|
@@ -562,7 +562,8 @@ class CostScreen(Vertical):
|
|
|
562
562
|
self.app.call_from_thread(self._render_day_drill, df, date)
|
|
563
563
|
|
|
564
564
|
def _render_day_drill(self, df: pd.DataFrame, date: str) -> None:
|
|
565
|
-
|
|
565
|
+
self._reset_table()
|
|
566
|
+
table = self.query_one(DataTable)
|
|
566
567
|
if df is None or df.empty:
|
|
567
568
|
table.add_columns("(no warehouse activity on this date)")
|
|
568
569
|
self._set_status(f"{date} · no data · Esc to return")
|
|
@@ -46,7 +46,7 @@ class HomeScreen(Vertical):
|
|
|
46
46
|
with Vertical(id="home-trend", classes="panel"):
|
|
47
47
|
yield Static("30d spend trend", classes="panel-title")
|
|
48
48
|
yield DataTable(id="home-trend-table",
|
|
49
|
-
cursor_type="
|
|
49
|
+
cursor_type="row", zebra_stripes=True)
|
|
50
50
|
with Vertical(id="home-queries", classes="panel"):
|
|
51
51
|
yield Static("Recent expensive queries (7d)", classes="panel-title")
|
|
52
52
|
yield DataTable(id="home-queries-table",
|
|
@@ -193,6 +193,7 @@ class HomeScreen(Vertical):
|
|
|
193
193
|
str(row["DATE"]),
|
|
194
194
|
f"{credits:,.2f}",
|
|
195
195
|
"█" * bar_width,
|
|
196
|
+
key=str(row["DATE"]),
|
|
196
197
|
)
|
|
197
198
|
|
|
198
199
|
# --- Recent expensive queries (one Snowflake call on mount) -----
|
|
@@ -229,17 +230,27 @@ class HomeScreen(Vertical):
|
|
|
229
230
|
)
|
|
230
231
|
|
|
231
232
|
def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
|
|
232
|
-
# Drill: open the query in the Tune screen.
|
|
233
233
|
key = event.row_key.value if event.row_key else None
|
|
234
234
|
if not key:
|
|
235
235
|
return
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
|
|
237
|
+
if event.data_table.id == "home-trend-table":
|
|
238
|
+
# Drill into that day on the Cost screen.
|
|
239
|
+
try:
|
|
240
|
+
from textual.widgets import ContentSwitcher
|
|
241
|
+
from snowglobe.tui.screens.cost import CostScreen
|
|
242
|
+
self.app.query_one(ContentSwitcher).current = "cost"
|
|
243
|
+
self.app.query_one(CostScreen)._fetch_day_drill(key)
|
|
244
|
+
except Exception as e:
|
|
245
|
+
self.app.notify(f"Could not open day detail: {e}", severity="warning", timeout=4)
|
|
246
|
+
else:
|
|
247
|
+
# Queries table — open in Tune.
|
|
248
|
+
try:
|
|
249
|
+
from textual.widgets import ContentSwitcher, Input
|
|
250
|
+
from snowglobe.tui.screens.tune import TuneScreen
|
|
251
|
+
self.app.query_one(ContentSwitcher).current = "tune"
|
|
252
|
+
tune = self.app.query_one(TuneScreen)
|
|
253
|
+
tune.query_one("#tu-query-id", Input).value = key
|
|
254
|
+
self.app.notify(f"Loaded {key[:24]}… into Tune. Press Analyse.", timeout=4)
|
|
255
|
+
except Exception:
|
|
256
|
+
self.app.notify(f"Query: {key[:24]}…", timeout=4)
|
|
@@ -365,16 +365,22 @@ Tree > .tree--label-highlighted {
|
|
|
365
365
|
margin-right: 1;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
#tu-sql {
|
|
368
|
+
#tu-sql-scroll {
|
|
369
369
|
height: 1fr;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
#tu-sql {
|
|
370
373
|
background: $background;
|
|
371
374
|
padding: 1;
|
|
372
375
|
}
|
|
373
376
|
|
|
377
|
+
#tu-heuristics-scroll {
|
|
378
|
+
height: 1fr;
|
|
379
|
+
}
|
|
380
|
+
|
|
374
381
|
#tu-heuristics {
|
|
375
382
|
padding: 1;
|
|
376
383
|
color: $foreground;
|
|
377
|
-
height: 1fr;
|
|
378
384
|
}
|
|
379
385
|
|
|
380
386
|
#tu-insights-table,
|
|
@@ -388,11 +394,14 @@ Tree > .tree--label-highlighted {
|
|
|
388
394
|
height: 1fr;
|
|
389
395
|
}
|
|
390
396
|
|
|
397
|
+
#tu-ai-scroll {
|
|
398
|
+
height: 1fr;
|
|
399
|
+
}
|
|
400
|
+
|
|
391
401
|
#tu-ai {
|
|
392
402
|
background: $background;
|
|
393
403
|
color: $foreground;
|
|
394
404
|
padding: 1;
|
|
395
|
-
height: 1fr;
|
|
396
405
|
}
|
|
397
406
|
|
|
398
407
|
/* --- Reports screen --- */
|
|
@@ -402,8 +411,11 @@ Tree > .tree--label-highlighted {
|
|
|
402
411
|
margin-bottom: 1;
|
|
403
412
|
}
|
|
404
413
|
|
|
405
|
-
#rp-preview {
|
|
414
|
+
#rp-preview-scroll {
|
|
406
415
|
height: 1fr;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
#rp-preview {
|
|
407
419
|
background: $background;
|
|
408
420
|
border: round $primary;
|
|
409
421
|
padding: 1;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|