ripple-sql 0.1.1__tar.gz → 0.1.2__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.
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/CHANGELOG.md +7 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/PKG-INFO +1 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/pyproject.toml +1 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/dbt.py +5 -2
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/dbt_config.py +3 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/sqldir.py +2 -2
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/types.py +7 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/lookml.py +2 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/semantic.py +2 -1
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/.gitignore +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/LICENSE +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/README.md +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/__init__.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/answer.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/answer_page.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/cache.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/ci.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/ci_signature.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/cli.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/doctor.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/__init__.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/budget.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/column_lineage.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/column_ref.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/cte_tracing.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dependencies.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dialect.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dispatch.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/extraction.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/jinja.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/json_sources.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/macro_source.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/pipeline.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/preprocess.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/safe_gen.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/schema_qualification.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/scope.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/select_sources.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/sql_script.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/statement.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tech_debt.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_catalog.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_scalar_vars.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_tvf.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_xml.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/types.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/unused_deps.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/validation.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/graph.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/home.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/__init__.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/identity.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/sidecar.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/mcp_server.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/names.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/project.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/py.typed +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/render.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/render_shims.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/schemas.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/server.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/sourcefiles.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/star_resolution.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer.css +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer.html +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer_twin.js +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/explore.js +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/__init__.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/cli.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/collect.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/discover.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/ingest.py +0 -0
- {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/report.py +0 -0
|
@@ -6,6 +6,11 @@ Notable changes to Ripple. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.2] - 2026-09-09
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- A symlink whose target is gone matched the SQL, YAML, LookML, macro, and seed globs and crashed the load with a traceback on the first real folder the published build ran in. One helper, `files_under`, now serves every project glob and keeps regular files only.
|
|
13
|
+
|
|
9
14
|
## [0.1.1] - 2026-09-09
|
|
10
15
|
|
|
11
16
|
### Changed
|
|
@@ -230,6 +235,7 @@ First public release.
|
|
|
230
235
|
### Removed
|
|
231
236
|
- The dark whole-graph canvas that `ripple serve` used to open (`static/index.html`). Every surface now draws one answer.
|
|
232
237
|
|
|
233
|
-
[Unreleased]: https://github.com/bteh/ripple/compare/v0.1.
|
|
238
|
+
[Unreleased]: https://github.com/bteh/ripple/compare/v0.1.2...HEAD
|
|
239
|
+
[0.1.2]: https://github.com/bteh/ripple/releases/tag/v0.1.2
|
|
234
240
|
[0.1.1]: https://github.com/bteh/ripple/releases/tag/v0.1.1
|
|
235
241
|
[0.1.0]: https://github.com/bteh/ripple/releases/tag/v0.1.0
|
|
@@ -24,6 +24,7 @@ from ripple.loaders.types import (
|
|
|
24
24
|
DEFAULT_DIALECT,
|
|
25
25
|
Model,
|
|
26
26
|
Project,
|
|
27
|
+
files_under,
|
|
27
28
|
relative_posix,
|
|
28
29
|
)
|
|
29
30
|
|
|
@@ -124,7 +125,7 @@ def _seed_tables(root: Path) -> list[Model]:
|
|
|
124
125
|
|
|
125
126
|
seeds: list[Model] = []
|
|
126
127
|
for seed_dir in _seed_dirs(root):
|
|
127
|
-
for path in
|
|
128
|
+
for path in files_under(seed_dir, "*.csv"):
|
|
128
129
|
try:
|
|
129
130
|
with open(path, newline="", encoding="utf-8", errors="replace") as f:
|
|
130
131
|
header = next(csv.reader(f), [])
|
|
@@ -257,7 +258,9 @@ def _load_dbt_raw(root: Path, dialect: str | None) -> Project:
|
|
|
257
258
|
"run 'dbt compile' for exact lineage."
|
|
258
259
|
]
|
|
259
260
|
model_dirs = _dbt_model_dirs(root)
|
|
260
|
-
pairs = sorted(
|
|
261
|
+
pairs = sorted(
|
|
262
|
+
((d, p) for d in model_dirs for p in files_under(d, "*.sql")), key=lambda t: t[1]
|
|
263
|
+
)
|
|
261
264
|
# a slice of every model, the same sample the sql-dir loader sniffs
|
|
262
265
|
sample = "\n".join(p.read_text(errors="replace", encoding="utf-8")[:4000] for _, p in pairs)[
|
|
263
266
|
:200000
|
|
@@ -5,6 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
import re
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
+
from ripple.loaders.types import files_under
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
def _project_vars(root: Path) -> dict:
|
|
10
12
|
"""Declared vars from dbt_project.yml. A sub-dict scoped under the
|
|
@@ -236,7 +238,7 @@ def _macro_sources(root: Path) -> list[tuple[str | None, str]]:
|
|
|
236
238
|
macros_dir = base / dir_name
|
|
237
239
|
if not macros_dir.is_dir():
|
|
238
240
|
continue
|
|
239
|
-
for macro_file in
|
|
241
|
+
for macro_file in files_under(macros_dir, "*.sql"):
|
|
240
242
|
resolved = macro_file.resolve()
|
|
241
243
|
if resolved in seen_files:
|
|
242
244
|
continue
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
from ripple.engine.budget import TIMED_OUT, budget_seconds, max_sql_bytes, run_within_budget
|
|
8
8
|
from ripple.loaders.identity import directory_identity
|
|
9
|
-
from ripple.loaders.types import IGNORE_DIRS, Model, Project, relative_posix
|
|
9
|
+
from ripple.loaders.types import IGNORE_DIRS, Model, Project, files_under, relative_posix
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def _iter_sql_files(root: Path, exclude: list[Path] | None = None) -> tuple[list[Path], int]:
|
|
@@ -19,7 +19,7 @@ def _iter_sql_files(root: Path, exclude: list[Path] | None = None) -> tuple[list
|
|
|
19
19
|
kept: list[Path] = []
|
|
20
20
|
skipped = 0
|
|
21
21
|
excluded = [d.resolve() for d in (exclude or [])]
|
|
22
|
-
for path in
|
|
22
|
+
for path in files_under(root, "*.sql"):
|
|
23
23
|
dirs = path.relative_to(root).parts[:-1]
|
|
24
24
|
if any(part in IGNORE_DIRS or part.startswith(".") for part in dirs):
|
|
25
25
|
skipped += 1
|
|
@@ -218,3 +218,10 @@ def whole_machine(path: Path) -> bool:
|
|
|
218
218
|
would read every file the user owns."""
|
|
219
219
|
here = Path(path).resolve()
|
|
220
220
|
return here == Path.home().resolve() or here == Path(here.anchor)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def files_under(root: Path, pattern: str) -> list[Path]:
|
|
224
|
+
"""The regular files matching a glob under root, sorted. A symlink whose
|
|
225
|
+
target is gone matches the glob and is not a file; reading it raised a
|
|
226
|
+
traceback on the first real folder this ran in."""
|
|
227
|
+
return sorted(p for p in root.rglob(pattern) if p.is_file())
|
|
@@ -16,6 +16,7 @@ from pathlib import Path
|
|
|
16
16
|
|
|
17
17
|
import yaml
|
|
18
18
|
|
|
19
|
+
from ripple.loaders.types import files_under
|
|
19
20
|
from ripple.project import IGNORE_DIRS
|
|
20
21
|
from ripple.semantic import DownstreamEdge
|
|
21
22
|
|
|
@@ -133,7 +134,7 @@ def load_lookml_downstream(root: Path) -> list[DownstreamEdge]:
|
|
|
133
134
|
return []
|
|
134
135
|
|
|
135
136
|
edges: list[DownstreamEdge] = []
|
|
136
|
-
for path in
|
|
137
|
+
for path in files_under(root, "*.lkml"):
|
|
137
138
|
parts = path.relative_to(root).parts[:-1]
|
|
138
139
|
if any(p in IGNORE_DIRS or p.startswith(".") for p in parts):
|
|
139
140
|
continue
|
|
@@ -19,6 +19,7 @@ from pathlib import Path
|
|
|
19
19
|
|
|
20
20
|
import yaml
|
|
21
21
|
|
|
22
|
+
from ripple.loaders.types import files_under
|
|
22
23
|
from ripple.project import IGNORE_DIRS
|
|
23
24
|
|
|
24
25
|
_REF = re.compile(r"ref\(\s*['\"]([^'\"]+)['\"]\s*(?:,\s*['\"]([^'\"]+)['\"])?\s*\)")
|
|
@@ -47,7 +48,7 @@ def _ref_model(value) -> str | None:
|
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
def _iter_schema_docs(root: Path):
|
|
50
|
-
for path in
|
|
51
|
+
for path in files_under(root, "*.yml") + files_under(root, "*.yaml"):
|
|
51
52
|
parts = path.relative_to(root).parts[:-1]
|
|
52
53
|
if any(p in IGNORE_DIRS or p.startswith(".") for p in parts):
|
|
53
54
|
continue
|
|
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
|