snowglobe-cli 0.2.2__tar.gz → 0.2.3__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.2 → snowglobe_cli-0.2.3}/PKG-INFO +1 -1
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/pyproject.toml +1 -1
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/cost.py +19 -15
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/PKG-INFO +1 -1
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/LICENSE +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/README.md +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/setup.cfg +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/__main__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/access.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/app.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/context.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/cost.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/debug.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/diff.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/optimizer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/prompts.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/report.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/shell.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/shell_completer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/access.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/query_history.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/query_profile.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/config/loader.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/access_service.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/cost_service.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/optimizer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/query_service.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/report_service.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/risk_service.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/explainer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/resolver.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/ai/cortex_optimizer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/optimizer/query_optimizer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/role_graph.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/user_graph.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/access.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/access_path.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/object_ref.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/object_type.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/optimizer.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/privilege.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/query.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/output/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/output/cli.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/queries/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/queries/query_history.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/snowflake/connection.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/state/db.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/state/state.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/templates/report.md.j2 +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tests/access_tests.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/__main__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/app.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/access.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/home.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/refresh.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/reports.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/risk.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/tune.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/styles.tcss +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/__init__.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/access_paths.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/cache_badge.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/header.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/nav.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/SOURCES.txt +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/dependency_links.txt +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/entry_points.txt +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/requires.txt +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/top_level.txt +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_access.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_optimizer_engine.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_output.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_query_validation.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_state_db.py +0 -0
- {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_tui_tune.py +0 -0
|
@@ -50,6 +50,7 @@ class CostScreen(Vertical):
|
|
|
50
50
|
_drill_day_service_type: str | None = None
|
|
51
51
|
_drill_day_resource: str | None = None
|
|
52
52
|
_drill_day_user: str | None = None
|
|
53
|
+
_drill_day_resource_kind: str = "other" # "warehouse" | "ai" | "other"
|
|
53
54
|
# Becomes True after the user explicitly picks a view, so Select.Changed
|
|
54
55
|
# events fired during the initial mount don't auto-trigger a Snowflake fetch.
|
|
55
56
|
_user_initiated: bool = False
|
|
@@ -150,12 +151,7 @@ class CostScreen(Vertical):
|
|
|
150
151
|
self._drill_day_service_type = key
|
|
151
152
|
self._fetch_day_resource_drill(self._drill_day, key)
|
|
152
153
|
elif self._current_view == "drill_day_resource":
|
|
153
|
-
|
|
154
|
-
can_drill = (
|
|
155
|
-
upper == _WAREHOUSE_SERVICE_TYPE
|
|
156
|
-
or any(kw in upper for kw in _AI_SERVICE_KEYWORDS)
|
|
157
|
-
)
|
|
158
|
-
if can_drill:
|
|
154
|
+
if self._drill_day_resource_kind in ("warehouse", "ai"):
|
|
159
155
|
self._fetch_day_resource_users(
|
|
160
156
|
self._drill_day, self._drill_day_service_type, key
|
|
161
157
|
)
|
|
@@ -164,7 +160,7 @@ class CostScreen(Vertical):
|
|
|
164
160
|
"No user-level detail available for this resource type.", timeout=3
|
|
165
161
|
)
|
|
166
162
|
elif self._current_view == "drill_day_resource_users":
|
|
167
|
-
if
|
|
163
|
+
if self._drill_day_resource_kind == "warehouse":
|
|
168
164
|
self._fetch_day_user_queries(self._drill_day, self._drill_day_resource, key)
|
|
169
165
|
else:
|
|
170
166
|
self.app.notify("No query detail available for AI services.", timeout=3)
|
|
@@ -673,11 +669,20 @@ class CostScreen(Vertical):
|
|
|
673
669
|
self.app.call_from_thread(self._fetch_failed, e)
|
|
674
670
|
return
|
|
675
671
|
self.app.call_from_thread(
|
|
676
|
-
self._render_day_resource_drill, df, date, service_type, label, found, note
|
|
672
|
+
self._render_day_resource_drill, df, date, service_type, label, found, note, is_ai
|
|
677
673
|
)
|
|
678
674
|
|
|
679
675
|
def _render_day_resource_drill(self, df: pd.DataFrame, date: str, service_type: str,
|
|
680
|
-
label: str, found: bool, note: str | None
|
|
676
|
+
label: str, found: bool, note: str | None,
|
|
677
|
+
is_ai: bool = False) -> None:
|
|
678
|
+
# Store kind so navigation decisions don't depend on the SERVICE_TYPE string.
|
|
679
|
+
if is_ai:
|
|
680
|
+
self._drill_day_resource_kind = "ai"
|
|
681
|
+
elif label == "Warehouse":
|
|
682
|
+
self._drill_day_resource_kind = "warehouse"
|
|
683
|
+
else:
|
|
684
|
+
self._drill_day_resource_kind = "other"
|
|
685
|
+
|
|
681
686
|
self._reset_table()
|
|
682
687
|
table = self.query_one(DataTable)
|
|
683
688
|
note_suffix = f" · ⚠ {note}" if note else ""
|
|
@@ -706,12 +711,11 @@ class CostScreen(Vertical):
|
|
|
706
711
|
cells.append(str(int(row.get("REQUEST_COUNT", 0))))
|
|
707
712
|
cells += [f"{pct:.1f}%", _bar(credits / max_c)]
|
|
708
713
|
table.add_row(*cells, key=str(row["RESOURCE_NAME"]))
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
714
|
+
user_hint = (
|
|
715
|
+
" · click to see users"
|
|
716
|
+
if self._drill_day_resource_kind in ("warehouse", "ai")
|
|
717
|
+
else ""
|
|
713
718
|
)
|
|
714
|
-
user_hint = " · click to see users" if can_drill_users else ""
|
|
715
719
|
self._set_status(
|
|
716
720
|
f"{service_type} — {date} · {total:,.4f} credits{note_suffix}{user_hint} · Esc to return"
|
|
717
721
|
)
|
|
@@ -764,7 +768,7 @@ class CostScreen(Vertical):
|
|
|
764
768
|
)
|
|
765
769
|
query_hint = (
|
|
766
770
|
" · click user to see top queries"
|
|
767
|
-
if
|
|
771
|
+
if self._drill_day_resource_kind == "warehouse"
|
|
768
772
|
else ""
|
|
769
773
|
)
|
|
770
774
|
self._set_status(
|
|
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
|
|
File without changes
|
|
File without changes
|