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.
Files changed (83) hide show
  1. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/PKG-INFO +1 -1
  2. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/pyproject.toml +1 -1
  3. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/cost.py +19 -15
  4. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/PKG-INFO +1 -1
  5. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/LICENSE +0 -0
  6. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/README.md +0 -0
  7. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/setup.cfg +0 -0
  8. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/__init__.py +0 -0
  9. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/__main__.py +0 -0
  10. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/__init__.py +0 -0
  11. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/access.py +0 -0
  12. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/app.py +0 -0
  13. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/context.py +0 -0
  14. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/cost.py +0 -0
  15. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/debug.py +0 -0
  16. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/diff.py +0 -0
  17. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/optimizer.py +0 -0
  18. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/prompts.py +0 -0
  19. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/report.py +0 -0
  20. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/shell.py +0 -0
  21. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/cli/shell_completer.py +0 -0
  22. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/access.py +0 -0
  23. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/query_history.py +0 -0
  24. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/collectors/query_profile.py +0 -0
  25. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/config/loader.py +0 -0
  26. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/access_service.py +0 -0
  27. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/cost_service.py +0 -0
  28. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/optimizer.py +0 -0
  29. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/query_service.py +0 -0
  30. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/report_service.py +0 -0
  31. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/core/risk_service.py +0 -0
  32. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/__init__.py +0 -0
  33. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/explainer.py +0 -0
  34. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/access/resolver.py +0 -0
  35. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/ai/cortex_optimizer.py +0 -0
  36. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/engines/optimizer/query_optimizer.py +0 -0
  37. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/__init__.py +0 -0
  38. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/role_graph.py +0 -0
  39. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/graphs/user_graph.py +0 -0
  40. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/__init__.py +0 -0
  41. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/access.py +0 -0
  42. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/access_path.py +0 -0
  43. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/object_ref.py +0 -0
  44. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/object_type.py +0 -0
  45. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/optimizer.py +0 -0
  46. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/privilege.py +0 -0
  47. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/models/query.py +0 -0
  48. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/output/__init__.py +0 -0
  49. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/output/cli.py +0 -0
  50. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/queries/__init__.py +0 -0
  51. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/queries/query_history.py +0 -0
  52. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/snowflake/connection.py +0 -0
  53. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/state/db.py +0 -0
  54. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/state/state.py +0 -0
  55. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/templates/report.md.j2 +0 -0
  56. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tests/access_tests.py +0 -0
  57. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/__init__.py +0 -0
  58. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/__main__.py +0 -0
  59. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/app.py +0 -0
  60. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/__init__.py +0 -0
  61. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/access.py +0 -0
  62. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/home.py +0 -0
  63. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/refresh.py +0 -0
  64. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/reports.py +0 -0
  65. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/risk.py +0 -0
  66. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/screens/tune.py +0 -0
  67. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/styles.tcss +0 -0
  68. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/__init__.py +0 -0
  69. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/access_paths.py +0 -0
  70. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/cache_badge.py +0 -0
  71. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/header.py +0 -0
  72. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe/tui/widgets/nav.py +0 -0
  73. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/SOURCES.txt +0 -0
  74. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/dependency_links.txt +0 -0
  75. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/entry_points.txt +0 -0
  76. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/requires.txt +0 -0
  77. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/snowglobe_cli.egg-info/top_level.txt +0 -0
  78. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_access.py +0 -0
  79. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_optimizer_engine.py +0 -0
  80. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_output.py +0 -0
  81. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_query_validation.py +0 -0
  82. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_state_db.py +0 -0
  83. {snowglobe_cli-0.2.2 → snowglobe_cli-0.2.3}/tests/test_tui_tune.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snowglobe-cli
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Explainable cost and access visibility for Snowflake
5
5
  Author-email: Jaryd Thornton <jaryd90@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "snowglobe-cli"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Explainable cost and access visibility for Snowflake"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12.3"
@@ -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
- upper = (self._drill_day_service_type or "").upper()
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 (self._drill_day_service_type or "").upper() == _WAREHOUSE_SERVICE_TYPE:
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) -> 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
- upper = service_type.upper()
710
- can_drill_users = (
711
- upper == _WAREHOUSE_SERVICE_TYPE
712
- or any(kw in upper for kw in _AI_SERVICE_KEYWORDS)
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 (self._drill_day_service_type or "").upper() == _WAREHOUSE_SERVICE_TYPE
771
+ if self._drill_day_resource_kind == "warehouse"
768
772
  else ""
769
773
  )
770
774
  self._set_status(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snowglobe-cli
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Explainable cost and access visibility for Snowflake
5
5
  Author-email: Jaryd Thornton <jaryd90@gmail.com>
6
6
  License-Expression: Apache-2.0
File without changes
File without changes
File without changes