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.
Files changed (73) hide show
  1. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/CHANGELOG.md +7 -1
  2. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/PKG-INFO +1 -1
  3. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/pyproject.toml +1 -1
  4. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/dbt.py +5 -2
  5. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/dbt_config.py +3 -1
  6. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/sqldir.py +2 -2
  7. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/types.py +7 -0
  8. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/lookml.py +2 -1
  9. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/semantic.py +2 -1
  10. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/.gitignore +0 -0
  11. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/LICENSE +0 -0
  12. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/README.md +0 -0
  13. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/__init__.py +0 -0
  14. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/answer.py +0 -0
  15. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/answer_page.py +0 -0
  16. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/cache.py +0 -0
  17. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/ci.py +0 -0
  18. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/ci_signature.py +0 -0
  19. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/cli.py +0 -0
  20. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/doctor.py +0 -0
  21. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/__init__.py +0 -0
  22. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/budget.py +0 -0
  23. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/column_lineage.py +0 -0
  24. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/column_ref.py +0 -0
  25. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/cte_tracing.py +0 -0
  26. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dependencies.py +0 -0
  27. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dialect.py +0 -0
  28. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/dispatch.py +0 -0
  29. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/extraction.py +0 -0
  30. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/jinja.py +0 -0
  31. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/json_sources.py +0 -0
  32. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/macro_source.py +0 -0
  33. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/pipeline.py +0 -0
  34. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/preprocess.py +0 -0
  35. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/safe_gen.py +0 -0
  36. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/schema_qualification.py +0 -0
  37. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/scope.py +0 -0
  38. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/select_sources.py +0 -0
  39. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/sql_script.py +0 -0
  40. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/statement.py +0 -0
  41. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tech_debt.py +0 -0
  42. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_catalog.py +0 -0
  43. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_scalar_vars.py +0 -0
  44. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_tvf.py +0 -0
  45. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/tsql_xml.py +0 -0
  46. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/types.py +0 -0
  47. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/unused_deps.py +0 -0
  48. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/engine/validation.py +0 -0
  49. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/graph.py +0 -0
  50. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/home.py +0 -0
  51. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/__init__.py +0 -0
  52. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/identity.py +0 -0
  53. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/loaders/sidecar.py +0 -0
  54. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/mcp_server.py +0 -0
  55. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/names.py +0 -0
  56. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/project.py +0 -0
  57. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/py.typed +0 -0
  58. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/render.py +0 -0
  59. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/render_shims.py +0 -0
  60. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/schemas.py +0 -0
  61. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/server.py +0 -0
  62. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/sourcefiles.py +0 -0
  63. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/star_resolution.py +0 -0
  64. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer.css +0 -0
  65. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer.html +0 -0
  66. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/answer_twin.js +0 -0
  67. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/static/explore.js +0 -0
  68. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/__init__.py +0 -0
  69. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/cli.py +0 -0
  70. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/collect.py +0 -0
  71. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/discover.py +0 -0
  72. {ripple_sql-0.1.1 → ripple_sql-0.1.2}/src/ripple/usage/ingest.py +0 -0
  73. {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.1...HEAD
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ripple-sql
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Offline column-level SQL lineage. See what breaks before you merge.
5
5
  Project-URL: Homepage, https://github.com/bteh/ripple
6
6
  Project-URL: Repository, https://github.com/bteh/ripple
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ripple-sql"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Offline column-level SQL lineage. See what breaks before you merge."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -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 sorted(seed_dir.rglob("*.csv")):
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(((d, p) for d in model_dirs for p in d.rglob("*.sql")), key=lambda t: t[1])
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 sorted(macros_dir.rglob("*.sql")):
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 sorted(root.rglob("*.sql")):
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 sorted(root.rglob("*.lkml")):
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 sorted(root.rglob("*.yml")) + sorted(root.rglob("*.yaml")):
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