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.
- pretensor/__init__.py +50 -0
- pretensor/benchmark/__init__.py +54 -0
- pretensor/benchmark/cli.py +294 -0
- pretensor/benchmark/fixtures.py +84 -0
- pretensor/benchmark/l1/__init__.py +23 -0
- pretensor/benchmark/l1/metrics.py +141 -0
- pretensor/benchmark/l1/pipeline.py +188 -0
- pretensor/benchmark/l1/runner.py +245 -0
- pretensor/benchmark/l2/__init__.py +27 -0
- pretensor/benchmark/l2/gold.py +236 -0
- pretensor/benchmark/l2/metrics.py +146 -0
- pretensor/benchmark/l2/pipeline.py +124 -0
- pretensor/benchmark/l2/runner.py +530 -0
- pretensor/benchmark/l3/__init__.py +73 -0
- pretensor/benchmark/l3/agent.py +316 -0
- pretensor/benchmark/l3/db.py +188 -0
- pretensor/benchmark/l3/gold.py +85 -0
- pretensor/benchmark/l3/llm_client.py +395 -0
- pretensor/benchmark/l3/mcp_client.py +357 -0
- pretensor/benchmark/l3/pretensor_runner.py +456 -0
- pretensor/benchmark/l3/prompt.py +132 -0
- pretensor/benchmark/l3/runner.py +358 -0
- pretensor/benchmark/l3/sql_equivalence.py +176 -0
- pretensor/benchmark/release_gate.py +448 -0
- pretensor/benchmark/results.py +298 -0
- pretensor/benchmark/runner.py +109 -0
- pretensor/cli/__init__.py +1 -0
- pretensor/cli/commands/_source_runner.py +147 -0
- pretensor/cli/commands/analyze.py +201 -0
- pretensor/cli/commands/connections/__init__.py +7 -0
- pretensor/cli/commands/connections/add_remove.py +126 -0
- pretensor/cli/commands/connections/register.py +12 -0
- pretensor/cli/commands/export.py +131 -0
- pretensor/cli/commands/index.py +559 -0
- pretensor/cli/commands/list.py +76 -0
- pretensor/cli/commands/quickstart.py +207 -0
- pretensor/cli/commands/reindex.py +646 -0
- pretensor/cli/commands/semantic.py +190 -0
- pretensor/cli/commands/serve.py +144 -0
- pretensor/cli/commands/sync_grants.py +149 -0
- pretensor/cli/commands/validate.py +176 -0
- pretensor/cli/config_file.py +442 -0
- pretensor/cli/constants.py +10 -0
- pretensor/cli/dbt_enrichment.py +96 -0
- pretensor/cli/main.py +109 -0
- pretensor/cli/paths.py +43 -0
- pretensor/cli/plugin.py +52 -0
- pretensor/config.py +226 -0
- pretensor/connectors/__init__.py +29 -0
- pretensor/connectors/base.py +165 -0
- pretensor/connectors/bigquery.py +468 -0
- pretensor/connectors/inspect.py +321 -0
- pretensor/connectors/lineage_sqlglot.py +97 -0
- pretensor/connectors/models.py +130 -0
- pretensor/connectors/mysql.py +402 -0
- pretensor/connectors/pg_array_parse.py +53 -0
- pretensor/connectors/postgres.py +938 -0
- pretensor/connectors/registry.py +93 -0
- pretensor/connectors/snapshot.py +244 -0
- pretensor/connectors/snowflake.py +908 -0
- pretensor/core/__init__.py +1 -0
- pretensor/core/builder.py +307 -0
- pretensor/core/dsn_crypto.py +51 -0
- pretensor/core/graph_schema_manager.py +246 -0
- pretensor/core/graph_store.py +1226 -0
- pretensor/core/ids.py +101 -0
- pretensor/core/portable_export.py +276 -0
- pretensor/core/query_runner.py +67 -0
- pretensor/core/registry.py +209 -0
- pretensor/core/schema.py +473 -0
- pretensor/core/secure_io.py +93 -0
- pretensor/core/store.py +469 -0
- pretensor/enrichment/__init__.py +1 -0
- pretensor/enrichment/analyze/__init__.py +0 -0
- pretensor/enrichment/analyze/classify.py +49 -0
- pretensor/enrichment/analyze/extract_python.py +196 -0
- pretensor/enrichment/analyze/parse.py +141 -0
- pretensor/enrichment/analyze/pipeline.py +195 -0
- pretensor/enrichment/analyze/summary.py +38 -0
- pretensor/enrichment/analyze/walker.py +98 -0
- pretensor/enrichment/analyze/writers.py +214 -0
- pretensor/enrichment/dbt/__init__.py +30 -0
- pretensor/enrichment/dbt/lineage.py +100 -0
- pretensor/enrichment/dbt/manifest.py +300 -0
- pretensor/enrichment/dbt/metadata.py +263 -0
- pretensor/enrichment/dbt/pipeline.py +77 -0
- pretensor/enrichment/dbt/resolution.py +101 -0
- pretensor/enrichment/dbt/signals.py +305 -0
- pretensor/entities/__init__.py +27 -0
- pretensor/entities/builder.py +63 -0
- pretensor/entities/classifier.py +383 -0
- pretensor/entities/llm_extract.py +66 -0
- pretensor/errors.py +35 -0
- pretensor/graph_models/__init__.py +17 -0
- pretensor/graph_models/base.py +11 -0
- pretensor/graph_models/consumer.py +71 -0
- pretensor/graph_models/edge.py +35 -0
- pretensor/graph_models/entity.py +21 -0
- pretensor/graph_models/node.py +79 -0
- pretensor/graph_models/relationship.py +33 -0
- pretensor/integrations/__init__.py +42 -0
- pretensor/integrations/_base.py +138 -0
- pretensor/integrations/google_adk.py +49 -0
- pretensor/integrations/langchain.py +55 -0
- pretensor/integrations/llamaindex.py +53 -0
- pretensor/intelligence/__init__.py +33 -0
- pretensor/intelligence/cluster_labeler.py +425 -0
- pretensor/intelligence/clustering.py +168 -0
- pretensor/intelligence/combining.py +32 -0
- pretensor/intelligence/discovery.py +114 -0
- pretensor/intelligence/embeddings.py +317 -0
- pretensor/intelligence/graph_export.py +200 -0
- pretensor/intelligence/heuristic.py +544 -0
- pretensor/intelligence/join_paths/__init__.py +130 -0
- pretensor/intelligence/join_paths/on_demand.py +516 -0
- pretensor/intelligence/join_paths/storage.py +70 -0
- pretensor/intelligence/llm_infer.py +78 -0
- pretensor/intelligence/llm_runtime.py +62 -0
- pretensor/intelligence/metric_templates.py +193 -0
- pretensor/intelligence/pipeline.py +364 -0
- pretensor/intelligence/role_exemplars.py +263 -0
- pretensor/intelligence/schema_classification.py +360 -0
- pretensor/intelligence/scoring.py +76 -0
- pretensor/intelligence/semantic.py +240 -0
- pretensor/intelligence/shadow_alias.py +101 -0
- pretensor/intelligence/statistical.py +50 -0
- pretensor/intelligence/steps.py +191 -0
- pretensor/intelligence/steps_embedding.py +168 -0
- pretensor/introspection/__init__.py +6 -0
- pretensor/introspection/inspector.py +5 -0
- pretensor/introspection/models/__init__.py +0 -0
- pretensor/introspection/models/base.py +5 -0
- pretensor/introspection/models/config.py +237 -0
- pretensor/introspection/models/dsn.py +550 -0
- pretensor/introspection/models/plan.py +116 -0
- pretensor/introspection/models/schema.py +10 -0
- pretensor/introspection/models/semantic.py +121 -0
- pretensor/introspection/models/validation.py +116 -0
- pretensor/introspection/snapshot.py +46 -0
- pretensor/mcp/__init__.py +16 -0
- pretensor/mcp/config_json.py +24 -0
- pretensor/mcp/payload_types.py +274 -0
- pretensor/mcp/resources/__init__.py +17 -0
- pretensor/mcp/resources/markdown.py +314 -0
- pretensor/mcp/server.py +285 -0
- pretensor/mcp/service.py +49 -0
- pretensor/mcp/service_context.py +142 -0
- pretensor/mcp/service_registry.py +294 -0
- pretensor/mcp/store_cache.py +43 -0
- pretensor/mcp/tool_registry.py +136 -0
- pretensor/mcp/tools/__init__.py +1 -0
- pretensor/mcp/tools/_rank.py +244 -0
- pretensor/mcp/tools/_timed.py +26 -0
- pretensor/mcp/tools/compile_metric.py +144 -0
- pretensor/mcp/tools/consumers.py +161 -0
- pretensor/mcp/tools/context.py +1121 -0
- pretensor/mcp/tools/cypher.py +509 -0
- pretensor/mcp/tools/detect_changes.py +254 -0
- pretensor/mcp/tools/impact.py +271 -0
- pretensor/mcp/tools/list.py +131 -0
- pretensor/mcp/tools/schema.py +170 -0
- pretensor/mcp/tools/search.py +316 -0
- pretensor/mcp/tools/semantic_search.py +282 -0
- pretensor/mcp/tools/traverse.py +1027 -0
- pretensor/mcp/tools/validate_sql.py +150 -0
- pretensor/observability.py +203 -0
- pretensor/py.typed +0 -0
- pretensor/quickstart/README.md +29 -0
- pretensor/quickstart/__init__.py +6 -0
- pretensor/quickstart/docker-compose.yml +18 -0
- pretensor/quickstart/pagila_data.sql +63 -0
- pretensor/quickstart/pagila_ddl.sql +92 -0
- pretensor/search/__init__.py +6 -0
- pretensor/search/base.py +80 -0
- pretensor/search/index.py +435 -0
- pretensor/semantic/__init__.py +24 -0
- pretensor/semantic/base.py +123 -0
- pretensor/semantic/compiler.py +487 -0
- pretensor/semantic/yaml_layer.py +180 -0
- pretensor/skills/__init__.py +5 -0
- pretensor/skills/generator.py +235 -0
- pretensor/staleness/__init__.py +15 -0
- pretensor/staleness/graph_patcher.py +355 -0
- pretensor/staleness/impact_analyzer.py +162 -0
- pretensor/staleness/snapshot_store.py +38 -0
- pretensor/validation/__init__.py +9 -0
- pretensor/validation/query_validator.py +436 -0
- pretensor/visibility/__init__.py +23 -0
- pretensor/visibility/config.py +126 -0
- pretensor/visibility/filter.py +143 -0
- pretensor/visibility/kuzu_helpers.py +32 -0
- pretensor/visibility/runtime.py +36 -0
- pretensor/visibility/sync_grants.py +188 -0
- pretensor-0.1.0.dist-info/METADATA +251 -0
- pretensor-0.1.0.dist-info/RECORD +198 -0
- pretensor-0.1.0.dist-info/WHEEL +4 -0
- pretensor-0.1.0.dist-info/entry_points.txt +2 -0
- 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]")
|