dbdocs 0.0.0__tar.gz → 1.0.0__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 (34) hide show
  1. {dbdocs-0.0.0 → dbdocs-1.0.0}/PKG-INFO +2 -2
  2. {dbdocs-0.0.0 → dbdocs-1.0.0}/README.md +1 -1
  3. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/_sqlglot_lineage.py +40 -20
  4. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/column_lineage.py +7 -2
  5. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/builder.py +3 -1
  6. {dbdocs-0.0.0 → dbdocs-1.0.0}/pyproject.toml +5 -2
  7. {dbdocs-0.0.0 → dbdocs-1.0.0}/.gitignore +0 -0
  8. {dbdocs-0.0.0 → dbdocs-1.0.0}/LICENSE +0 -0
  9. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/__init__.py +0 -0
  10. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/__main__.py +0 -0
  11. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/cli/__init__.py +0 -0
  12. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/cli/main.py +0 -0
  13. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/core/__init__.py +0 -0
  14. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/core/artifacts.py +0 -0
  15. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/core/config.py +0 -0
  16. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/core/exceptions.py +0 -0
  17. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/core/log.py +0 -0
  18. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/__init__.py +0 -0
  19. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/erd.py +0 -0
  20. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/erd_json.py +0 -0
  21. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/graph.py +0 -0
  22. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/extract/nodes.py +0 -0
  23. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/main.py +0 -0
  24. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/__init__.py +0 -0
  25. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/app.js +0 -0
  26. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/favicon.svg +0 -0
  27. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/graph/index.css +0 -0
  28. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/graph/index.js +0 -0
  29. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/style.css +0 -0
  30. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/vendor/marked.min.js +0 -0
  31. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/assets/vendor/minisearch.min.js +0 -0
  32. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/bundle/index.html +0 -0
  33. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/deploy.py +0 -0
  34. {dbdocs-0.0.0 → dbdocs-1.0.0}/dbdocs/site/inject.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbdocs
3
- Version: 0.0.0
3
+ Version: 1.0.0
4
4
  Summary: Alternative dbt docs site: Catalog + ERD + column-level lineage
5
5
  Project-URL: Homepage, https://github.com/datnguye/dbt-docs
6
6
  Project-URL: Repository, https://github.com/datnguye/dbt-docs
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
27
27
  <p align="center"><b>An alternative dbt docs site — catalog + ERD + column-level lineage, baked into one file.</b></p>
28
28
 
29
29
  <p align="center">
30
- <a href="https://dbdocs.datnguye.me/demo/"><img src="https://img.shields.io/badge/live-demo-FF694A?style=flat&logo=rocket&logoColor=white" alt="live demo"></a>
30
+ <a href="https://dbdocs.datnguye.me/latest/demo/"><img src="https://img.shields.io/badge/live-demo-FF694A?style=flat&logo=rocket&logoColor=white" alt="live demo"></a>
31
31
  <a href="https://dbdocs.datnguye.me/"><img src="https://img.shields.io/badge/docs-visit%20site-blue?style=flat&logo=gitbook&logoColor=white" alt="docs"></a>
32
32
  <a href="https://pypi.org/project/dbdocs/"><img src="https://badge.fury.io/py/dbdocs.svg" alt="PyPI version"></a>
33
33
  <img src="https://img.shields.io/badge/CLI-Python-FFCE3E?labelColor=14354C&logo=python&logoColor=white" alt="python-cli">
@@ -5,7 +5,7 @@
5
5
  <p align="center"><b>An alternative dbt docs site — catalog + ERD + column-level lineage, baked into one file.</b></p>
6
6
 
7
7
  <p align="center">
8
- <a href="https://dbdocs.datnguye.me/demo/"><img src="https://img.shields.io/badge/live-demo-FF694A?style=flat&logo=rocket&logoColor=white" alt="live demo"></a>
8
+ <a href="https://dbdocs.datnguye.me/latest/demo/"><img src="https://img.shields.io/badge/live-demo-FF694A?style=flat&logo=rocket&logoColor=white" alt="live demo"></a>
9
9
  <a href="https://dbdocs.datnguye.me/"><img src="https://img.shields.io/badge/docs-visit%20site-blue?style=flat&logo=gitbook&logoColor=white" alt="docs"></a>
10
10
  <a href="https://pypi.org/project/dbdocs/"><img src="https://badge.fury.io/py/dbdocs.svg" alt="PyPI version"></a>
11
11
  <img src="https://img.shields.io/badge/CLI-Python-FFCE3E?labelColor=14354C&logo=python&logoColor=white" alt="python-cli">
@@ -44,19 +44,19 @@ class Node:
44
44
  yield from d.walk()
45
45
 
46
46
 
47
- def lineage(
48
- column: str | exp.Column,
47
+ def prepare_scope(
49
48
  sql: str | exp.Expression,
50
49
  schema: dict | Schema | None = None,
51
50
  sources: t.Mapping[str, str | exp.Query] | None = None,
52
51
  dialect: DialectType = None,
53
- scope: Scope | None = None,
54
- trim_selects: bool = True,
55
52
  **kwargs,
56
- ) -> Node:
57
- """Build the lineage graph for a column of a SQL query."""
53
+ ) -> Scope:
54
+ """Parse, qualify, and build the optimizer scope for a SQL query once.
55
+
56
+ The expensive half of :func:`lineage`. Callers tracing many columns of one
57
+ query build the scope here and reuse it across :func:`lineage` calls.
58
+ """
58
59
  expression = maybe_parse(sql, dialect=dialect)
59
- column = normalize_identifiers.normalize_identifiers(column, dialect=dialect).name
60
60
 
61
61
  if sources:
62
62
  expression = exp.expand(
@@ -65,22 +65,42 @@ def lineage(
65
65
  dialect=dialect,
66
66
  )
67
67
 
68
+ expression = qualify.qualify(
69
+ expression,
70
+ dialect=dialect,
71
+ schema=schema,
72
+ **{
73
+ "validate_qualify_columns": False,
74
+ "identify": False,
75
+ "allow_partial_qualification": True,
76
+ **kwargs,
77
+ },
78
+ )
79
+ scope = build_scope(expression)
68
80
  if not scope:
69
- expression = qualify.qualify(
70
- expression,
71
- dialect=dialect,
72
- schema=schema,
73
- **{
74
- "validate_qualify_columns": False,
75
- "identify": False,
76
- "allow_partial_qualification": True,
77
- **kwargs,
78
- },
79
- )
80
- scope = build_scope(expression)
81
+ raise SqlglotError("Cannot build lineage, sql must be SELECT")
82
+ return scope
83
+
84
+
85
+ def lineage(
86
+ column: str | exp.Column,
87
+ sql: str | exp.Expression,
88
+ schema: dict | Schema | None = None,
89
+ sources: t.Mapping[str, str | exp.Query] | None = None,
90
+ dialect: DialectType = None,
91
+ scope: Scope | None = None,
92
+ trim_selects: bool = True,
93
+ **kwargs,
94
+ ) -> Node:
95
+ """Build the lineage graph for a column of a SQL query.
96
+
97
+ Pass a prebuilt ``scope`` (from :func:`prepare_scope`) to skip the per-call
98
+ parse/qualify/build_scope when tracing many columns of the same query.
99
+ """
100
+ column = normalize_identifiers.normalize_identifiers(column, dialect=dialect).name
81
101
 
82
102
  if not scope:
83
- raise SqlglotError("Cannot build lineage, sql must be SELECT")
103
+ scope = prepare_scope(sql, schema=schema, sources=sources, dialect=dialect, **kwargs)
84
104
 
85
105
  select_names_original = {select.alias_or_name for select in scope.expression.selects}
86
106
  select_names_lower = {name.lower(): name for name in select_names_original}
@@ -20,7 +20,7 @@ from sqlglot.errors import SqlglotError
20
20
  from dbdocs.core.artifacts import db_schema, node_name
21
21
  from dbdocs.core.exceptions import LineageError
22
22
  from dbdocs.core.log import logger
23
- from dbdocs.extract._sqlglot_lineage import Node, lineage
23
+ from dbdocs.extract._sqlglot_lineage import Node, lineage, prepare_scope
24
24
 
25
25
  #: dbt adapter_type → sqlglot dialect, when the names differ. Most match 1:1.
26
26
  _DIALECT_ALIASES = {
@@ -80,9 +80,14 @@ class ColumnLineageExtractor:
80
80
  output_columns = (
81
81
  list(getattr(catalog_node, "columns", {}) or {}) if catalog_node else []
82
82
  )
83
+ if not output_columns:
84
+ return
85
+ # Build the scope once per model, then trace each column against it —
86
+ # qualify is the expensive part and is identical for every column.
87
+ scope = prepare_scope(compiled, schema=self.schema, dialect=self.dialect)
83
88
  for column in output_columns:
84
89
  try:
85
- root = lineage(column, compiled, schema=self.schema, dialect=self.dialect)
90
+ root = lineage(column, compiled, dialect=self.dialect, scope=scope)
86
91
  except SqlglotError:
87
92
  # One unresolvable column shouldn't drop the rest of the model.
88
93
  continue
@@ -115,8 +115,10 @@ class ReportBuilder:
115
115
  data = self.build_data()
116
116
  index = out / "index.html"
117
117
  index.write_text(inject(index.read_text(encoding="utf-8"), data), encoding="utf-8")
118
+ # Compact, not indented — keeps the debug dump cheap on large projects.
118
119
  (out / "dbdocs-data.json").write_text(
119
- json.dumps(data, indent=2, default=self._json_default), encoding="utf-8"
120
+ json.dumps(data, separators=(",", ":"), default=self._json_default),
121
+ encoding="utf-8",
120
122
  )
121
123
 
122
124
  logger.info(
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dbdocs"
3
- version = "0.0.0"
3
+ dynamic = ["version"]
4
4
  description = "Alternative dbt docs site: Catalog + ERD + column-level lineage"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -29,9 +29,12 @@ Repository = "https://github.com/datnguye/dbt-docs"
29
29
  dbdocs = "dbdocs.main:main"
30
30
 
31
31
  [build-system]
32
- requires = ["hatchling"]
32
+ requires = ["hatchling", "hatch-vcs"]
33
33
  build-backend = "hatchling.build"
34
34
 
35
+ [tool.hatch.version]
36
+ source = "vcs"
37
+
35
38
  [tool.hatch.build.targets.wheel]
36
39
  packages = ["dbdocs"]
37
40
  artifacts = [
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