pretensor 0.1.0a0__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/cli/__init__.py +1 -0
- pretensor/cli/commands/connections/__init__.py +7 -0
- pretensor/cli/commands/connections/add_remove.py +122 -0
- pretensor/cli/commands/connections/register.py +12 -0
- pretensor/cli/commands/export.py +120 -0
- pretensor/cli/commands/index.py +551 -0
- pretensor/cli/commands/list.py +65 -0
- pretensor/cli/commands/quickstart.py +171 -0
- pretensor/cli/commands/reindex.py +581 -0
- pretensor/cli/commands/semantic.py +190 -0
- pretensor/cli/commands/serve.py +129 -0
- pretensor/cli/commands/sync_grants.py +149 -0
- pretensor/cli/commands/validate.py +156 -0
- pretensor/cli/config_file.py +412 -0
- pretensor/cli/constants.py +10 -0
- pretensor/cli/dbt_enrichment.py +96 -0
- pretensor/cli/main.py +81 -0
- pretensor/cli/paths.py +43 -0
- pretensor/cli/plugin.py +52 -0
- pretensor/config.py +145 -0
- pretensor/connectors/SKILL.md +16 -0
- pretensor/connectors/__init__.py +29 -0
- pretensor/connectors/base.py +165 -0
- pretensor/connectors/bigquery.py +463 -0
- pretensor/connectors/inspect.py +321 -0
- pretensor/connectors/lineage_sqlglot.py +91 -0
- pretensor/connectors/models.py +130 -0
- pretensor/connectors/pg_array_parse.py +53 -0
- pretensor/connectors/postgres.py +921 -0
- pretensor/connectors/registry.py +51 -0
- pretensor/connectors/snapshot.py +244 -0
- pretensor/connectors/snowflake.py +840 -0
- pretensor/core/__init__.py +1 -0
- pretensor/core/builder.py +268 -0
- pretensor/core/dsn_crypto.py +40 -0
- pretensor/core/ids.py +68 -0
- pretensor/core/portable_export.py +253 -0
- pretensor/core/registry.py +204 -0
- pretensor/core/schema.py +368 -0
- pretensor/core/store.py +1343 -0
- pretensor/enrichment/__init__.py +1 -0
- pretensor/enrichment/dbt/__init__.py +30 -0
- pretensor/enrichment/dbt/lineage.py +100 -0
- pretensor/enrichment/dbt/manifest.py +298 -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 +359 -0
- pretensor/entities/llm_extract.py +66 -0
- pretensor/graph_models/__init__.py +14 -0
- pretensor/graph_models/base.py +11 -0
- pretensor/graph_models/edge.py +35 -0
- pretensor/graph_models/entity.py +21 -0
- pretensor/graph_models/node.py +75 -0
- pretensor/graph_models/relationship.py +27 -0
- pretensor/intelligence/__init__.py +33 -0
- pretensor/intelligence/cluster_labeler.py +335 -0
- pretensor/intelligence/clustering.py +162 -0
- pretensor/intelligence/combining.py +32 -0
- pretensor/intelligence/discovery.py +114 -0
- pretensor/intelligence/embeddings.py +198 -0
- pretensor/intelligence/graph_export.py +139 -0
- pretensor/intelligence/heuristic.py +540 -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 +60 -0
- pretensor/intelligence/metric_templates.py +193 -0
- pretensor/intelligence/pipeline.py +254 -0
- pretensor/intelligence/schema_classification.py +306 -0
- pretensor/intelligence/scoring.py +66 -0
- pretensor/intelligence/shadow_alias.py +101 -0
- pretensor/intelligence/statistical.py +50 -0
- pretensor/intelligence/steps.py +161 -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 +236 -0
- pretensor/introspection/models/dsn.py +442 -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 +248 -0
- pretensor/mcp/resources/__init__.py +19 -0
- pretensor/mcp/resources/markdown.py +420 -0
- pretensor/mcp/server.py +723 -0
- pretensor/mcp/service.py +47 -0
- pretensor/mcp/service_context.py +126 -0
- pretensor/mcp/service_registry.py +242 -0
- pretensor/mcp/tool_registry.py +126 -0
- pretensor/mcp/tools/__init__.py +1 -0
- pretensor/mcp/tools/compile_metric.py +87 -0
- pretensor/mcp/tools/context.py +894 -0
- pretensor/mcp/tools/cypher.py +333 -0
- pretensor/mcp/tools/detect_changes.py +226 -0
- pretensor/mcp/tools/impact.py +165 -0
- pretensor/mcp/tools/list.py +110 -0
- pretensor/mcp/tools/schema.py +128 -0
- pretensor/mcp/tools/search.py +108 -0
- pretensor/mcp/tools/traverse.py +753 -0
- pretensor/mcp/tools/validate_sql.py +74 -0
- pretensor/observability.py +203 -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 +346 -0
- pretensor/semantic/yaml_layer.py +182 -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.0a0.dist-info/METADATA +175 -0
- pretensor-0.1.0a0.dist-info/RECORD +138 -0
- pretensor-0.1.0a0.dist-info/WHEEL +4 -0
- pretensor-0.1.0a0.dist-info/entry_points.txt +2 -0
- pretensor-0.1.0a0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,171 @@
|
|
|
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 pathlib import Path
|
|
9
|
+
|
|
10
|
+
import typer
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
|
|
13
|
+
from pretensor.cli import constants as cli_constants
|
|
14
|
+
from pretensor.cli.commands.index import _run_index
|
|
15
|
+
from pretensor.cli.config_file import get_cli_config
|
|
16
|
+
from pretensor.introspection.models.dsn import connection_config_from_url
|
|
17
|
+
from pretensor.mcp import print_mcp_config
|
|
18
|
+
|
|
19
|
+
QUICKSTART_DSN = "postgresql://postgres:postgres@localhost:55432/pagila"
|
|
20
|
+
QUICKSTART_NAME = "pagila"
|
|
21
|
+
COMPOSE_REL_PATH = Path("docker/quickstart/docker-compose.yml")
|
|
22
|
+
HEALTH_TIMEOUT_SECONDS = 60
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _repo_root() -> Path:
|
|
26
|
+
# src/pretensor/cli/commands/quickstart.py → repo root is 4 levels up.
|
|
27
|
+
return Path(__file__).resolve().parents[4]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _compose_path() -> Path:
|
|
31
|
+
return _repo_root() / COMPOSE_REL_PATH
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _wait_healthy(console: Console, container: str, timeout: int) -> None:
|
|
35
|
+
deadline = time.monotonic() + timeout
|
|
36
|
+
while time.monotonic() < deadline:
|
|
37
|
+
proc = subprocess.run(
|
|
38
|
+
["docker", "inspect", "-f", "{{.State.Health.Status}}", container],
|
|
39
|
+
capture_output=True,
|
|
40
|
+
text=True,
|
|
41
|
+
)
|
|
42
|
+
status = proc.stdout.strip()
|
|
43
|
+
if status == "healthy":
|
|
44
|
+
return
|
|
45
|
+
if proc.returncode != 0 and "No such" in proc.stderr:
|
|
46
|
+
raise RuntimeError(f"container {container} not running")
|
|
47
|
+
time.sleep(1)
|
|
48
|
+
raise RuntimeError(
|
|
49
|
+
f"container {container} did not become healthy within {timeout}s"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def register_quickstart_command(app: typer.Typer, *, console: Console) -> None:
|
|
54
|
+
@app.command("quickstart")
|
|
55
|
+
def quickstart_command(
|
|
56
|
+
no_docker: bool = typer.Option(
|
|
57
|
+
False,
|
|
58
|
+
"--no-docker",
|
|
59
|
+
help=(
|
|
60
|
+
"Skip the docker compose step; assume Postgres is already "
|
|
61
|
+
f"reachable at {QUICKSTART_DSN}."
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
down: bool = typer.Option(
|
|
65
|
+
False,
|
|
66
|
+
"--down",
|
|
67
|
+
help="Tear down the quickstart container and exit.",
|
|
68
|
+
),
|
|
69
|
+
state_dir: Path = typer.Option(
|
|
70
|
+
cli_constants.DEFAULT_STATE_DIR,
|
|
71
|
+
"--state-dir",
|
|
72
|
+
help="Directory for registry.json and graph files.",
|
|
73
|
+
file_okay=False,
|
|
74
|
+
dir_okay=True,
|
|
75
|
+
writable=True,
|
|
76
|
+
resolve_path=True,
|
|
77
|
+
),
|
|
78
|
+
ctx: typer.Context = typer.Option(None, hidden=True),
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Spin up a sample Postgres, index it, and print MCP config — one command."""
|
|
81
|
+
cli_config = get_cli_config(ctx)
|
|
82
|
+
compose_file = _compose_path()
|
|
83
|
+
|
|
84
|
+
if down:
|
|
85
|
+
_compose_down(console, compose_file)
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
if not no_docker:
|
|
89
|
+
if shutil.which("docker") is None:
|
|
90
|
+
console.print(
|
|
91
|
+
"[red]`docker` is not on PATH.[/red]\n"
|
|
92
|
+
"Install Docker Desktop, or pass --no-docker if you have "
|
|
93
|
+
"Postgres reachable at the quickstart DSN already."
|
|
94
|
+
)
|
|
95
|
+
raise typer.Exit(1)
|
|
96
|
+
if not compose_file.is_file():
|
|
97
|
+
console.print(
|
|
98
|
+
f"[red]Compose file not found:[/red] {compose_file}\n"
|
|
99
|
+
"Run `pretensor quickstart` from a clone of the pretensor repo."
|
|
100
|
+
)
|
|
101
|
+
raise typer.Exit(1)
|
|
102
|
+
_compose_up(console, compose_file)
|
|
103
|
+
try:
|
|
104
|
+
_wait_healthy(
|
|
105
|
+
console, "pretensor-quickstart-db", HEALTH_TIMEOUT_SECONDS
|
|
106
|
+
)
|
|
107
|
+
except RuntimeError as e:
|
|
108
|
+
console.print(f"[red]Postgres did not start:[/red] {e}")
|
|
109
|
+
raise typer.Exit(1) from e
|
|
110
|
+
console.print("[green]Postgres is up.[/green]")
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
config = connection_config_from_url(QUICKSTART_DSN, QUICKSTART_NAME)
|
|
114
|
+
except ValueError as e:
|
|
115
|
+
console.print(f"[red]Invalid quickstart DSN:[/red] {e}")
|
|
116
|
+
raise typer.Exit(1) from e
|
|
117
|
+
|
|
118
|
+
_run_index(
|
|
119
|
+
console=console,
|
|
120
|
+
cli_config=cli_config,
|
|
121
|
+
dsn=QUICKSTART_DSN,
|
|
122
|
+
connection_name=QUICKSTART_NAME,
|
|
123
|
+
config=config,
|
|
124
|
+
state_dir=state_dir,
|
|
125
|
+
unified=False,
|
|
126
|
+
skills_target="claude",
|
|
127
|
+
visibility_file=None,
|
|
128
|
+
profile=None,
|
|
129
|
+
dbt_manifest=None,
|
|
130
|
+
dbt_sources=None,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
console.print("\n[bold]MCP server config[/bold] (paste into your client):")
|
|
134
|
+
print_mcp_config(state_dir)
|
|
135
|
+
console.print(
|
|
136
|
+
"\n[bold green]Done.[/bold green] Try a query: "
|
|
137
|
+
f"`pretensor list` or start the server with `pretensor serve "
|
|
138
|
+
f"--graph-dir {state_dir}`."
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _compose_up(console: Console, compose_file: Path) -> None:
|
|
143
|
+
console.print(f"[bold blue]Starting Postgres[/bold blue] via {compose_file}...")
|
|
144
|
+
proc = subprocess.run(
|
|
145
|
+
["docker", "compose", "-f", str(compose_file), "up", "-d"],
|
|
146
|
+
capture_output=True,
|
|
147
|
+
text=True,
|
|
148
|
+
)
|
|
149
|
+
if proc.returncode != 0:
|
|
150
|
+
console.print(
|
|
151
|
+
f"[red]docker compose up failed:[/red]\n{proc.stderr or proc.stdout}"
|
|
152
|
+
)
|
|
153
|
+
raise typer.Exit(1)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _compose_down(console: Console, compose_file: Path) -> None:
|
|
157
|
+
if not compose_file.is_file():
|
|
158
|
+
console.print(f"[yellow]Compose file not found:[/yellow] {compose_file}")
|
|
159
|
+
raise typer.Exit(1)
|
|
160
|
+
console.print(f"[bold blue]Tearing down[/bold blue] {compose_file}...")
|
|
161
|
+
proc = subprocess.run(
|
|
162
|
+
["docker", "compose", "-f", str(compose_file), "down", "-v"],
|
|
163
|
+
capture_output=True,
|
|
164
|
+
text=True,
|
|
165
|
+
)
|
|
166
|
+
if proc.returncode != 0:
|
|
167
|
+
console.print(
|
|
168
|
+
f"[red]docker compose down failed:[/red]\n{proc.stderr or proc.stdout}"
|
|
169
|
+
)
|
|
170
|
+
raise typer.Exit(1)
|
|
171
|
+
console.print("[green]Quickstart container removed.[/green]")
|