pretensor 0.1.0__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.
Files changed (198) hide show
  1. pretensor/__init__.py +50 -0
  2. pretensor/benchmark/__init__.py +54 -0
  3. pretensor/benchmark/cli.py +294 -0
  4. pretensor/benchmark/fixtures.py +84 -0
  5. pretensor/benchmark/l1/__init__.py +23 -0
  6. pretensor/benchmark/l1/metrics.py +141 -0
  7. pretensor/benchmark/l1/pipeline.py +188 -0
  8. pretensor/benchmark/l1/runner.py +245 -0
  9. pretensor/benchmark/l2/__init__.py +27 -0
  10. pretensor/benchmark/l2/gold.py +236 -0
  11. pretensor/benchmark/l2/metrics.py +146 -0
  12. pretensor/benchmark/l2/pipeline.py +124 -0
  13. pretensor/benchmark/l2/runner.py +530 -0
  14. pretensor/benchmark/l3/__init__.py +73 -0
  15. pretensor/benchmark/l3/agent.py +316 -0
  16. pretensor/benchmark/l3/db.py +188 -0
  17. pretensor/benchmark/l3/gold.py +85 -0
  18. pretensor/benchmark/l3/llm_client.py +395 -0
  19. pretensor/benchmark/l3/mcp_client.py +357 -0
  20. pretensor/benchmark/l3/pretensor_runner.py +456 -0
  21. pretensor/benchmark/l3/prompt.py +132 -0
  22. pretensor/benchmark/l3/runner.py +358 -0
  23. pretensor/benchmark/l3/sql_equivalence.py +176 -0
  24. pretensor/benchmark/release_gate.py +448 -0
  25. pretensor/benchmark/results.py +298 -0
  26. pretensor/benchmark/runner.py +109 -0
  27. pretensor/cli/__init__.py +1 -0
  28. pretensor/cli/commands/_source_runner.py +147 -0
  29. pretensor/cli/commands/analyze.py +201 -0
  30. pretensor/cli/commands/connections/__init__.py +7 -0
  31. pretensor/cli/commands/connections/add_remove.py +126 -0
  32. pretensor/cli/commands/connections/register.py +12 -0
  33. pretensor/cli/commands/export.py +131 -0
  34. pretensor/cli/commands/index.py +559 -0
  35. pretensor/cli/commands/list.py +76 -0
  36. pretensor/cli/commands/quickstart.py +207 -0
  37. pretensor/cli/commands/reindex.py +646 -0
  38. pretensor/cli/commands/semantic.py +190 -0
  39. pretensor/cli/commands/serve.py +144 -0
  40. pretensor/cli/commands/sync_grants.py +149 -0
  41. pretensor/cli/commands/validate.py +176 -0
  42. pretensor/cli/config_file.py +442 -0
  43. pretensor/cli/constants.py +10 -0
  44. pretensor/cli/dbt_enrichment.py +96 -0
  45. pretensor/cli/main.py +109 -0
  46. pretensor/cli/paths.py +43 -0
  47. pretensor/cli/plugin.py +52 -0
  48. pretensor/config.py +226 -0
  49. pretensor/connectors/__init__.py +29 -0
  50. pretensor/connectors/base.py +165 -0
  51. pretensor/connectors/bigquery.py +468 -0
  52. pretensor/connectors/inspect.py +321 -0
  53. pretensor/connectors/lineage_sqlglot.py +97 -0
  54. pretensor/connectors/models.py +130 -0
  55. pretensor/connectors/mysql.py +402 -0
  56. pretensor/connectors/pg_array_parse.py +53 -0
  57. pretensor/connectors/postgres.py +938 -0
  58. pretensor/connectors/registry.py +93 -0
  59. pretensor/connectors/snapshot.py +244 -0
  60. pretensor/connectors/snowflake.py +908 -0
  61. pretensor/core/__init__.py +1 -0
  62. pretensor/core/builder.py +307 -0
  63. pretensor/core/dsn_crypto.py +51 -0
  64. pretensor/core/graph_schema_manager.py +246 -0
  65. pretensor/core/graph_store.py +1226 -0
  66. pretensor/core/ids.py +101 -0
  67. pretensor/core/portable_export.py +276 -0
  68. pretensor/core/query_runner.py +67 -0
  69. pretensor/core/registry.py +209 -0
  70. pretensor/core/schema.py +473 -0
  71. pretensor/core/secure_io.py +93 -0
  72. pretensor/core/store.py +469 -0
  73. pretensor/enrichment/__init__.py +1 -0
  74. pretensor/enrichment/analyze/__init__.py +0 -0
  75. pretensor/enrichment/analyze/classify.py +49 -0
  76. pretensor/enrichment/analyze/extract_python.py +196 -0
  77. pretensor/enrichment/analyze/parse.py +141 -0
  78. pretensor/enrichment/analyze/pipeline.py +195 -0
  79. pretensor/enrichment/analyze/summary.py +38 -0
  80. pretensor/enrichment/analyze/walker.py +98 -0
  81. pretensor/enrichment/analyze/writers.py +214 -0
  82. pretensor/enrichment/dbt/__init__.py +30 -0
  83. pretensor/enrichment/dbt/lineage.py +100 -0
  84. pretensor/enrichment/dbt/manifest.py +300 -0
  85. pretensor/enrichment/dbt/metadata.py +263 -0
  86. pretensor/enrichment/dbt/pipeline.py +77 -0
  87. pretensor/enrichment/dbt/resolution.py +101 -0
  88. pretensor/enrichment/dbt/signals.py +305 -0
  89. pretensor/entities/__init__.py +27 -0
  90. pretensor/entities/builder.py +63 -0
  91. pretensor/entities/classifier.py +383 -0
  92. pretensor/entities/llm_extract.py +66 -0
  93. pretensor/errors.py +35 -0
  94. pretensor/graph_models/__init__.py +17 -0
  95. pretensor/graph_models/base.py +11 -0
  96. pretensor/graph_models/consumer.py +71 -0
  97. pretensor/graph_models/edge.py +35 -0
  98. pretensor/graph_models/entity.py +21 -0
  99. pretensor/graph_models/node.py +79 -0
  100. pretensor/graph_models/relationship.py +33 -0
  101. pretensor/integrations/__init__.py +42 -0
  102. pretensor/integrations/_base.py +138 -0
  103. pretensor/integrations/google_adk.py +49 -0
  104. pretensor/integrations/langchain.py +55 -0
  105. pretensor/integrations/llamaindex.py +53 -0
  106. pretensor/intelligence/__init__.py +33 -0
  107. pretensor/intelligence/cluster_labeler.py +425 -0
  108. pretensor/intelligence/clustering.py +168 -0
  109. pretensor/intelligence/combining.py +32 -0
  110. pretensor/intelligence/discovery.py +114 -0
  111. pretensor/intelligence/embeddings.py +317 -0
  112. pretensor/intelligence/graph_export.py +200 -0
  113. pretensor/intelligence/heuristic.py +544 -0
  114. pretensor/intelligence/join_paths/__init__.py +130 -0
  115. pretensor/intelligence/join_paths/on_demand.py +516 -0
  116. pretensor/intelligence/join_paths/storage.py +70 -0
  117. pretensor/intelligence/llm_infer.py +78 -0
  118. pretensor/intelligence/llm_runtime.py +62 -0
  119. pretensor/intelligence/metric_templates.py +193 -0
  120. pretensor/intelligence/pipeline.py +364 -0
  121. pretensor/intelligence/role_exemplars.py +263 -0
  122. pretensor/intelligence/schema_classification.py +360 -0
  123. pretensor/intelligence/scoring.py +76 -0
  124. pretensor/intelligence/semantic.py +240 -0
  125. pretensor/intelligence/shadow_alias.py +101 -0
  126. pretensor/intelligence/statistical.py +50 -0
  127. pretensor/intelligence/steps.py +191 -0
  128. pretensor/intelligence/steps_embedding.py +168 -0
  129. pretensor/introspection/__init__.py +6 -0
  130. pretensor/introspection/inspector.py +5 -0
  131. pretensor/introspection/models/__init__.py +0 -0
  132. pretensor/introspection/models/base.py +5 -0
  133. pretensor/introspection/models/config.py +237 -0
  134. pretensor/introspection/models/dsn.py +550 -0
  135. pretensor/introspection/models/plan.py +116 -0
  136. pretensor/introspection/models/schema.py +10 -0
  137. pretensor/introspection/models/semantic.py +121 -0
  138. pretensor/introspection/models/validation.py +116 -0
  139. pretensor/introspection/snapshot.py +46 -0
  140. pretensor/mcp/__init__.py +16 -0
  141. pretensor/mcp/config_json.py +24 -0
  142. pretensor/mcp/payload_types.py +274 -0
  143. pretensor/mcp/resources/__init__.py +17 -0
  144. pretensor/mcp/resources/markdown.py +314 -0
  145. pretensor/mcp/server.py +285 -0
  146. pretensor/mcp/service.py +49 -0
  147. pretensor/mcp/service_context.py +142 -0
  148. pretensor/mcp/service_registry.py +294 -0
  149. pretensor/mcp/store_cache.py +43 -0
  150. pretensor/mcp/tool_registry.py +136 -0
  151. pretensor/mcp/tools/__init__.py +1 -0
  152. pretensor/mcp/tools/_rank.py +244 -0
  153. pretensor/mcp/tools/_timed.py +26 -0
  154. pretensor/mcp/tools/compile_metric.py +144 -0
  155. pretensor/mcp/tools/consumers.py +161 -0
  156. pretensor/mcp/tools/context.py +1121 -0
  157. pretensor/mcp/tools/cypher.py +509 -0
  158. pretensor/mcp/tools/detect_changes.py +254 -0
  159. pretensor/mcp/tools/impact.py +271 -0
  160. pretensor/mcp/tools/list.py +131 -0
  161. pretensor/mcp/tools/schema.py +170 -0
  162. pretensor/mcp/tools/search.py +316 -0
  163. pretensor/mcp/tools/semantic_search.py +282 -0
  164. pretensor/mcp/tools/traverse.py +1027 -0
  165. pretensor/mcp/tools/validate_sql.py +150 -0
  166. pretensor/observability.py +203 -0
  167. pretensor/py.typed +0 -0
  168. pretensor/quickstart/README.md +29 -0
  169. pretensor/quickstart/__init__.py +6 -0
  170. pretensor/quickstart/docker-compose.yml +18 -0
  171. pretensor/quickstart/pagila_data.sql +63 -0
  172. pretensor/quickstart/pagila_ddl.sql +92 -0
  173. pretensor/search/__init__.py +6 -0
  174. pretensor/search/base.py +80 -0
  175. pretensor/search/index.py +435 -0
  176. pretensor/semantic/__init__.py +24 -0
  177. pretensor/semantic/base.py +123 -0
  178. pretensor/semantic/compiler.py +487 -0
  179. pretensor/semantic/yaml_layer.py +180 -0
  180. pretensor/skills/__init__.py +5 -0
  181. pretensor/skills/generator.py +235 -0
  182. pretensor/staleness/__init__.py +15 -0
  183. pretensor/staleness/graph_patcher.py +355 -0
  184. pretensor/staleness/impact_analyzer.py +162 -0
  185. pretensor/staleness/snapshot_store.py +38 -0
  186. pretensor/validation/__init__.py +9 -0
  187. pretensor/validation/query_validator.py +436 -0
  188. pretensor/visibility/__init__.py +23 -0
  189. pretensor/visibility/config.py +126 -0
  190. pretensor/visibility/filter.py +143 -0
  191. pretensor/visibility/kuzu_helpers.py +32 -0
  192. pretensor/visibility/runtime.py +36 -0
  193. pretensor/visibility/sync_grants.py +188 -0
  194. pretensor-0.1.0.dist-info/METADATA +251 -0
  195. pretensor-0.1.0.dist-info/RECORD +198 -0
  196. pretensor-0.1.0.dist-info/WHEEL +4 -0
  197. pretensor-0.1.0.dist-info/entry_points.txt +2 -0
  198. pretensor-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,207 @@
1
+ """``pretensor quickstart`` — clone-to-running in one command."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ import subprocess
7
+ import time
8
+ from importlib.resources import files
9
+ from pathlib import Path
10
+
11
+ import typer
12
+ from rich.console import Console
13
+
14
+ from pretensor.cli import constants as cli_constants
15
+ from pretensor.cli.commands.index import _run_index
16
+ from pretensor.cli.config_file import get_cli_config
17
+ from pretensor.introspection.models.dsn import connection_config_from_url
18
+ from pretensor.mcp import print_mcp_config
19
+
20
+ QUICKSTART_DSN = "postgresql://postgres:postgres@localhost:55432/pagila"
21
+ QUICKSTART_NAME = "pagila"
22
+ HEALTH_TIMEOUT_SECONDS = 60
23
+
24
+
25
+ def _compose_path() -> Path:
26
+ # The compose file ships inside the wheel as a package data file alongside
27
+ # the pagila SQL fixtures it mounts. Resolving via ``importlib.resources``
28
+ # works in editable installs and in pip-installed wheels alike.
29
+ return Path(str(files("pretensor.quickstart") / "docker-compose.yml"))
30
+
31
+
32
+ _QUICKSTART_ASSET_NAMES = ("docker-compose.yml", "pagila_ddl.sql", "pagila_data.sql")
33
+
34
+
35
+ def _stage_compose_assets(state_dir: Path) -> Path:
36
+ # Snap-confined Docker (the default `snap install docker` on Ubuntu)
37
+ # can't read files under hidden directories in $HOME. A `pipx install`
38
+ # puts the package under ~/.local/pipx/venvs/..., so invoking compose
39
+ # straight against the site-packages copy fails there. Copying the
40
+ # compose file and SQL fixtures next to the state dir sidesteps that
41
+ # (and makes the compose file user-inspectable).
42
+ src_dir = files("pretensor.quickstart")
43
+ dest_dir = state_dir / "quickstart"
44
+ dest_dir.mkdir(parents=True, exist_ok=True)
45
+ for name in _QUICKSTART_ASSET_NAMES:
46
+ (dest_dir / name).write_bytes((src_dir / name).read_bytes())
47
+ return dest_dir / "docker-compose.yml"
48
+
49
+
50
+ def _wait_healthy(console: Console, container: str, timeout: int) -> None:
51
+ deadline = time.monotonic() + timeout
52
+ while time.monotonic() < deadline:
53
+ proc = subprocess.run(
54
+ ["docker", "inspect", "-f", "{{.State.Health.Status}}", container],
55
+ capture_output=True,
56
+ text=True,
57
+ )
58
+ status = proc.stdout.strip()
59
+ if status == "healthy":
60
+ return
61
+ if proc.returncode != 0 and "No such" in proc.stderr:
62
+ raise RuntimeError(f"container {container} not running")
63
+ time.sleep(1)
64
+ raise RuntimeError(
65
+ f"container {container} did not become healthy within {timeout}s"
66
+ )
67
+
68
+
69
+ def register_quickstart_command(app: typer.Typer, *, console: Console) -> None:
70
+ @app.command("quickstart")
71
+ def quickstart_command(
72
+ no_docker: bool = typer.Option(
73
+ False,
74
+ "--no-docker",
75
+ help=(
76
+ "Skip the docker compose step; assume Postgres is already "
77
+ f"reachable at {QUICKSTART_DSN}."
78
+ ),
79
+ ),
80
+ down: bool = typer.Option(
81
+ False,
82
+ "--down",
83
+ help="Tear down the quickstart container and exit.",
84
+ ),
85
+ state_dir: Path = typer.Option(
86
+ cli_constants.DEFAULT_STATE_DIR,
87
+ "--state-dir",
88
+ help="Directory for registry.json and graph files.",
89
+ file_okay=False,
90
+ dir_okay=True,
91
+ writable=True,
92
+ resolve_path=True,
93
+ ),
94
+ ctx: typer.Context = typer.Option(None, hidden=True),
95
+ ) -> None:
96
+ """Spin up a sample Postgres, index it, and print MCP config — one command."""
97
+ cli_config = get_cli_config(ctx)
98
+ compose_file = _compose_path()
99
+
100
+ if down:
101
+ staged_compose = _stage_compose_assets(state_dir)
102
+ _compose_down(console, staged_compose)
103
+ return
104
+
105
+ if not no_docker:
106
+ if shutil.which("docker") is None:
107
+ console.print(
108
+ "[red]`docker` is not on PATH.[/red]\n"
109
+ "Install Docker Desktop, or pass --no-docker if you have "
110
+ "Postgres reachable at the quickstart DSN already."
111
+ )
112
+ raise typer.Exit(1)
113
+ if not compose_file.is_file():
114
+ console.print(
115
+ f"[red]Compose file not found:[/red] {compose_file}\n"
116
+ "Run `pretensor quickstart` from a clone of the pretensor repo."
117
+ )
118
+ raise typer.Exit(1)
119
+ staged_compose = _stage_compose_assets(state_dir)
120
+ _compose_up(console, staged_compose)
121
+ try:
122
+ _wait_healthy(
123
+ console, "pretensor-quickstart-db", HEALTH_TIMEOUT_SECONDS
124
+ )
125
+ except RuntimeError as e:
126
+ console.print(f"[red]Postgres did not start:[/red] {e}")
127
+ raise typer.Exit(1) from e
128
+ console.print("[green]Postgres is up.[/green]")
129
+
130
+ try:
131
+ config = connection_config_from_url(QUICKSTART_DSN, QUICKSTART_NAME)
132
+ except ValueError as e:
133
+ console.print(f"[red]Invalid quickstart DSN:[/red] {e}")
134
+ raise typer.Exit(1) from e
135
+
136
+ from pretensor.intelligence.embeddings import resolve_embeddings_auto
137
+
138
+ _run_index(
139
+ console=console,
140
+ cli_config=cli_config,
141
+ dsn=QUICKSTART_DSN,
142
+ connection_name=QUICKSTART_NAME,
143
+ config=config,
144
+ state_dir=state_dir,
145
+ unified=False,
146
+ # AUTO, same as `pretensor index`: on iff the [embeddings]
147
+ # extra is installed and the kill switch is unset.
148
+ embeddings=resolve_embeddings_auto(None),
149
+ skills_target="claude",
150
+ visibility_file=None,
151
+ profile=None,
152
+ dbt_manifest=None,
153
+ dbt_sources=None,
154
+ )
155
+
156
+ console.print("\n[bold]MCP server config[/bold] (paste into your client):")
157
+ print_mcp_config(state_dir)
158
+ console.print(
159
+ "\n[bold green]Done.[/bold green] Try a query: "
160
+ f"`pretensor list` or start the server with `pretensor serve "
161
+ f"--state-dir {state_dir}`."
162
+ )
163
+
164
+
165
+ def _print_permission_hint_if_relevant(console: Console, output: str) -> None:
166
+ if "permission denied" in output.lower():
167
+ console.print(
168
+ "[yellow]Hint:[/yellow] snap-confined Docker (the default "
169
+ "`snap install docker` on Ubuntu) can't read files under hidden "
170
+ "directories in $HOME. That includes the staged state dir when "
171
+ "quickstart runs from $HOME itself (~/.pretensor/...) or from "
172
+ "any dotfile-prefixed path. Rerun from a non-hidden project "
173
+ "directory (e.g. `mkdir ~/pretensor-demo && cd ~/pretensor-demo`), "
174
+ "or install Docker from apt/a PPA instead of the snap."
175
+ )
176
+
177
+
178
+ def _compose_up(console: Console, compose_file: Path) -> None:
179
+ console.print(f"[bold blue]Starting Postgres[/bold blue] via {compose_file}...")
180
+ proc = subprocess.run(
181
+ ["docker", "compose", "-f", str(compose_file), "up", "-d"],
182
+ capture_output=True,
183
+ text=True,
184
+ )
185
+ if proc.returncode != 0:
186
+ output = proc.stderr or proc.stdout
187
+ console.print(f"[red]docker compose up failed:[/red]\n{output}")
188
+ _print_permission_hint_if_relevant(console, output)
189
+ raise typer.Exit(1)
190
+
191
+
192
+ def _compose_down(console: Console, compose_file: Path) -> None:
193
+ if not compose_file.is_file():
194
+ console.print(f"[yellow]Compose file not found:[/yellow] {compose_file}")
195
+ raise typer.Exit(1)
196
+ console.print(f"[bold blue]Tearing down[/bold blue] {compose_file}...")
197
+ proc = subprocess.run(
198
+ ["docker", "compose", "-f", str(compose_file), "down", "-v"],
199
+ capture_output=True,
200
+ text=True,
201
+ )
202
+ if proc.returncode != 0:
203
+ output = proc.stderr or proc.stdout
204
+ console.print(f"[red]docker compose down failed:[/red]\n{output}")
205
+ _print_permission_hint_if_relevant(console, output)
206
+ raise typer.Exit(1)
207
+ console.print("[green]Quickstart container removed.[/green]")