sqlmesh 0.205.1.dev7__py3-none-any.whl → 0.205.1.dev8__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.
- sqlmesh/_version.py +2 -2
- sqlmesh/core/linter/helpers.py +19 -13
- sqlmesh/core/linter/rules/builtin.py +76 -4
- sqlmesh/lsp/completions.py +1 -1
- sqlmesh/lsp/main.py +10 -6
- sqlmesh/lsp/reference.py +42 -376
- sqlmesh/lsp/rename.py +2 -2
- sqlmesh/utils/lineage.py +404 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/METADATA +1 -1
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/RECORD +14 -14
- sqlmesh/lsp/description.py +0 -29
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/WHEEL +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev8.dist-info}/top_level.txt +0 -0
sqlmesh/utils/lineage.py
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import typing as t
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
|
|
6
|
+
from sqlmesh.core.dialect import normalize_model_name
|
|
7
|
+
from sqlmesh.core.linter.helpers import (
|
|
8
|
+
TokenPositionDetails,
|
|
9
|
+
)
|
|
10
|
+
from sqlmesh.core.linter.rule import Range, Position
|
|
11
|
+
from sqlmesh.core.model.definition import SqlModel, ExternalModel, PythonModel, SeedModel
|
|
12
|
+
from sqlglot import exp
|
|
13
|
+
from sqlglot.optimizer.scope import build_scope
|
|
14
|
+
|
|
15
|
+
from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
|
|
16
|
+
from ruamel.yaml import YAML
|
|
17
|
+
|
|
18
|
+
from sqlmesh.utils.pydantic import PydanticModel
|
|
19
|
+
|
|
20
|
+
if t.TYPE_CHECKING:
|
|
21
|
+
from sqlmesh.core.context import Context
|
|
22
|
+
from sqlmesh.core.context import GenericContext
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ModelReference(PydanticModel):
|
|
26
|
+
"""A reference to a model, excluding external models."""
|
|
27
|
+
|
|
28
|
+
type: t.Literal["model"] = "model"
|
|
29
|
+
path: Path
|
|
30
|
+
range: Range
|
|
31
|
+
markdown_description: t.Optional[str] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ExternalModelReference(PydanticModel):
|
|
35
|
+
"""A reference to an external model."""
|
|
36
|
+
|
|
37
|
+
type: t.Literal["external_model"] = "external_model"
|
|
38
|
+
range: Range
|
|
39
|
+
target_range: t.Optional[Range] = None
|
|
40
|
+
path: t.Optional[Path] = None
|
|
41
|
+
"""The path of the external model, typically a YAML file, it is optional because
|
|
42
|
+
external models can be unregistered and so the path is not available."""
|
|
43
|
+
|
|
44
|
+
markdown_description: t.Optional[str] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class CTEReference(PydanticModel):
|
|
48
|
+
"""A reference to a CTE."""
|
|
49
|
+
|
|
50
|
+
type: t.Literal["cte"] = "cte"
|
|
51
|
+
path: Path
|
|
52
|
+
range: Range
|
|
53
|
+
target_range: Range
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MacroReference(PydanticModel):
|
|
57
|
+
"""A reference to a macro."""
|
|
58
|
+
|
|
59
|
+
type: t.Literal["macro"] = "macro"
|
|
60
|
+
path: Path
|
|
61
|
+
range: Range
|
|
62
|
+
target_range: Range
|
|
63
|
+
markdown_description: t.Optional[str] = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
Reference = t.Annotated[
|
|
67
|
+
t.Union[ModelReference, CTEReference, MacroReference, ExternalModelReference],
|
|
68
|
+
Field(discriminator="type"),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def extract_references_from_query(
|
|
73
|
+
query: exp.Expression,
|
|
74
|
+
context: t.Union["Context", "GenericContext[t.Any]"],
|
|
75
|
+
document_path: Path,
|
|
76
|
+
read_file: t.List[str],
|
|
77
|
+
depends_on: t.Set[str],
|
|
78
|
+
dialect: t.Optional[str] = None,
|
|
79
|
+
) -> t.List[Reference]:
|
|
80
|
+
# Build a scope tree to properly handle nested CTEs
|
|
81
|
+
try:
|
|
82
|
+
query = normalize_identifiers(query.copy(), dialect=dialect)
|
|
83
|
+
root_scope = build_scope(query)
|
|
84
|
+
except Exception:
|
|
85
|
+
root_scope = None
|
|
86
|
+
|
|
87
|
+
references: t.List[Reference] = []
|
|
88
|
+
if not root_scope:
|
|
89
|
+
return references
|
|
90
|
+
|
|
91
|
+
# Traverse all scopes to find CTE definitions and table references
|
|
92
|
+
for scope in root_scope.traverse():
|
|
93
|
+
for table in scope.tables:
|
|
94
|
+
table_name = table.name
|
|
95
|
+
|
|
96
|
+
# Check if this table reference is a CTE in the current scope
|
|
97
|
+
if cte_scope := scope.cte_sources.get(table_name):
|
|
98
|
+
cte = cte_scope.expression.parent
|
|
99
|
+
alias = cte.args["alias"]
|
|
100
|
+
if isinstance(alias, exp.TableAlias):
|
|
101
|
+
identifier = alias.this
|
|
102
|
+
if isinstance(identifier, exp.Identifier):
|
|
103
|
+
target_range_sqlmesh = TokenPositionDetails.from_meta(
|
|
104
|
+
identifier.meta
|
|
105
|
+
).to_range(read_file)
|
|
106
|
+
table_range_sqlmesh = TokenPositionDetails.from_meta(
|
|
107
|
+
table.this.meta
|
|
108
|
+
).to_range(read_file)
|
|
109
|
+
|
|
110
|
+
references.append(
|
|
111
|
+
CTEReference(
|
|
112
|
+
path=document_path, # Same file
|
|
113
|
+
range=table_range_sqlmesh,
|
|
114
|
+
target_range=target_range_sqlmesh,
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
column_references = _process_column_references(
|
|
119
|
+
scope=scope,
|
|
120
|
+
reference_name=table.name,
|
|
121
|
+
read_file=read_file,
|
|
122
|
+
referenced_model_path=document_path,
|
|
123
|
+
description="",
|
|
124
|
+
reference_type="cte",
|
|
125
|
+
cte_target_range=target_range_sqlmesh,
|
|
126
|
+
)
|
|
127
|
+
references.extend(column_references)
|
|
128
|
+
continue
|
|
129
|
+
|
|
130
|
+
# For non-CTE tables, process these as before (external model references)
|
|
131
|
+
# Normalize the table reference
|
|
132
|
+
unaliased = table.copy()
|
|
133
|
+
if unaliased.args.get("alias") is not None:
|
|
134
|
+
unaliased.set("alias", None)
|
|
135
|
+
reference_name = unaliased.sql(dialect=dialect)
|
|
136
|
+
try:
|
|
137
|
+
normalized_reference_name = normalize_model_name(
|
|
138
|
+
reference_name,
|
|
139
|
+
default_catalog=context.default_catalog,
|
|
140
|
+
dialect=dialect,
|
|
141
|
+
)
|
|
142
|
+
if normalized_reference_name not in depends_on:
|
|
143
|
+
continue
|
|
144
|
+
except Exception:
|
|
145
|
+
# Skip references that cannot be normalized
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
# Get the referenced model uri
|
|
149
|
+
referenced_model = context.get_model(
|
|
150
|
+
model_or_snapshot=normalized_reference_name, raise_if_missing=False
|
|
151
|
+
)
|
|
152
|
+
if referenced_model is None:
|
|
153
|
+
# Extract metadata for positioning
|
|
154
|
+
table_meta = TokenPositionDetails.from_meta(table.this.meta)
|
|
155
|
+
table_range_sqlmesh = table_meta.to_range(read_file)
|
|
156
|
+
start_pos_sqlmesh = table_range_sqlmesh.start
|
|
157
|
+
end_pos_sqlmesh = table_range_sqlmesh.end
|
|
158
|
+
|
|
159
|
+
# If there's a catalog or database qualifier, adjust the start position
|
|
160
|
+
catalog_or_db = table.args.get("catalog") or table.args.get("db")
|
|
161
|
+
if catalog_or_db is not None:
|
|
162
|
+
catalog_or_db_meta = TokenPositionDetails.from_meta(catalog_or_db.meta)
|
|
163
|
+
catalog_or_db_range_sqlmesh = catalog_or_db_meta.to_range(read_file)
|
|
164
|
+
start_pos_sqlmesh = catalog_or_db_range_sqlmesh.start
|
|
165
|
+
|
|
166
|
+
references.append(
|
|
167
|
+
ExternalModelReference(
|
|
168
|
+
range=Range(
|
|
169
|
+
start=start_pos_sqlmesh,
|
|
170
|
+
end=end_pos_sqlmesh,
|
|
171
|
+
),
|
|
172
|
+
markdown_description="Unregistered external model",
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
continue
|
|
176
|
+
referenced_model_path = referenced_model._path
|
|
177
|
+
if referenced_model_path is None:
|
|
178
|
+
continue
|
|
179
|
+
# Check whether the path exists
|
|
180
|
+
if not referenced_model_path.is_file():
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
# Extract metadata for positioning
|
|
184
|
+
table_meta = TokenPositionDetails.from_meta(table.this.meta)
|
|
185
|
+
table_range_sqlmesh = table_meta.to_range(read_file)
|
|
186
|
+
start_pos_sqlmesh = table_range_sqlmesh.start
|
|
187
|
+
end_pos_sqlmesh = table_range_sqlmesh.end
|
|
188
|
+
|
|
189
|
+
# If there's a catalog or database qualifier, adjust the start position
|
|
190
|
+
catalog_or_db = table.args.get("catalog") or table.args.get("db")
|
|
191
|
+
if catalog_or_db is not None:
|
|
192
|
+
catalog_or_db_meta = TokenPositionDetails.from_meta(catalog_or_db.meta)
|
|
193
|
+
catalog_or_db_range_sqlmesh = catalog_or_db_meta.to_range(read_file)
|
|
194
|
+
start_pos_sqlmesh = catalog_or_db_range_sqlmesh.start
|
|
195
|
+
|
|
196
|
+
description = generate_markdown_description(referenced_model)
|
|
197
|
+
|
|
198
|
+
# For external models in YAML files, find the specific model block
|
|
199
|
+
if isinstance(referenced_model, ExternalModel):
|
|
200
|
+
yaml_target_range: t.Optional[Range] = None
|
|
201
|
+
if (
|
|
202
|
+
referenced_model_path.suffix in (".yaml", ".yml")
|
|
203
|
+
and referenced_model_path.is_file()
|
|
204
|
+
):
|
|
205
|
+
yaml_target_range = _get_yaml_model_range(
|
|
206
|
+
referenced_model_path, referenced_model.name
|
|
207
|
+
)
|
|
208
|
+
references.append(
|
|
209
|
+
ExternalModelReference(
|
|
210
|
+
path=referenced_model_path,
|
|
211
|
+
range=Range(
|
|
212
|
+
start=start_pos_sqlmesh,
|
|
213
|
+
end=end_pos_sqlmesh,
|
|
214
|
+
),
|
|
215
|
+
markdown_description=description,
|
|
216
|
+
target_range=yaml_target_range,
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
column_references = _process_column_references(
|
|
221
|
+
scope=scope,
|
|
222
|
+
reference_name=normalized_reference_name,
|
|
223
|
+
read_file=read_file,
|
|
224
|
+
referenced_model_path=referenced_model_path,
|
|
225
|
+
description=description,
|
|
226
|
+
yaml_target_range=yaml_target_range,
|
|
227
|
+
reference_type="external_model",
|
|
228
|
+
default_catalog=context.default_catalog,
|
|
229
|
+
dialect=dialect,
|
|
230
|
+
)
|
|
231
|
+
references.extend(column_references)
|
|
232
|
+
else:
|
|
233
|
+
references.append(
|
|
234
|
+
ModelReference(
|
|
235
|
+
path=referenced_model_path,
|
|
236
|
+
range=Range(
|
|
237
|
+
start=start_pos_sqlmesh,
|
|
238
|
+
end=end_pos_sqlmesh,
|
|
239
|
+
),
|
|
240
|
+
markdown_description=description,
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
column_references = _process_column_references(
|
|
245
|
+
scope=scope,
|
|
246
|
+
reference_name=normalized_reference_name,
|
|
247
|
+
read_file=read_file,
|
|
248
|
+
referenced_model_path=referenced_model_path,
|
|
249
|
+
description=description,
|
|
250
|
+
reference_type="model",
|
|
251
|
+
default_catalog=context.default_catalog,
|
|
252
|
+
dialect=dialect,
|
|
253
|
+
)
|
|
254
|
+
references.extend(column_references)
|
|
255
|
+
|
|
256
|
+
return references
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def generate_markdown_description(
|
|
260
|
+
model: t.Union[SqlModel, ExternalModel, PythonModel, SeedModel],
|
|
261
|
+
) -> t.Optional[str]:
|
|
262
|
+
description = model.description
|
|
263
|
+
columns = model.columns_to_types
|
|
264
|
+
column_descriptions = model.column_descriptions
|
|
265
|
+
|
|
266
|
+
if columns is None:
|
|
267
|
+
return description or None
|
|
268
|
+
|
|
269
|
+
columns_table = "\n".join(
|
|
270
|
+
[
|
|
271
|
+
f"| {column} | {column_type} | {column_descriptions.get(column, '')} |"
|
|
272
|
+
for column, column_type in columns.items()
|
|
273
|
+
]
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
table_header = "| Column | Type | Description |\n|--------|------|-------------|\n"
|
|
277
|
+
columns_text = table_header + columns_table
|
|
278
|
+
return f"{description}\n\n{columns_text}" if description else columns_text
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _process_column_references(
|
|
282
|
+
scope: t.Any,
|
|
283
|
+
reference_name: str,
|
|
284
|
+
read_file: t.List[str],
|
|
285
|
+
referenced_model_path: Path,
|
|
286
|
+
description: t.Optional[str] = None,
|
|
287
|
+
yaml_target_range: t.Optional[Range] = None,
|
|
288
|
+
reference_type: t.Literal["model", "external_model", "cte"] = "model",
|
|
289
|
+
default_catalog: t.Optional[str] = None,
|
|
290
|
+
dialect: t.Optional[str] = None,
|
|
291
|
+
cte_target_range: t.Optional[Range] = None,
|
|
292
|
+
) -> t.List[Reference]:
|
|
293
|
+
"""
|
|
294
|
+
Process column references for a given table and create appropriate reference objects.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
scope: The SQL scope to search for columns
|
|
298
|
+
reference_name: The full reference name (may include database/catalog)
|
|
299
|
+
read_file: The file content as list of lines
|
|
300
|
+
referenced_model_path: Path of the referenced model
|
|
301
|
+
description: Markdown description for the reference
|
|
302
|
+
yaml_target_range: Target range for external models (YAML files)
|
|
303
|
+
reference_type: Type of reference - "model", "external_model", or "cte"
|
|
304
|
+
default_catalog: Default catalog for normalization
|
|
305
|
+
dialect: SQL dialect for normalization
|
|
306
|
+
cte_target_range: Target range for CTE references
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
List of table references for column usages
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
references: t.List[Reference] = []
|
|
313
|
+
for column in scope.find_all(exp.Column):
|
|
314
|
+
if column.table:
|
|
315
|
+
if reference_type == "cte":
|
|
316
|
+
if column.table == reference_name:
|
|
317
|
+
table_range = _get_column_table_range(column, read_file)
|
|
318
|
+
references.append(
|
|
319
|
+
CTEReference(
|
|
320
|
+
path=referenced_model_path,
|
|
321
|
+
range=table_range,
|
|
322
|
+
target_range=cte_target_range,
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
else:
|
|
326
|
+
table_parts = [part.sql(dialect) for part in column.parts[:-1]]
|
|
327
|
+
table_ref = ".".join(table_parts)
|
|
328
|
+
normalized_reference_name = normalize_model_name(
|
|
329
|
+
table_ref,
|
|
330
|
+
default_catalog=default_catalog,
|
|
331
|
+
dialect=dialect,
|
|
332
|
+
)
|
|
333
|
+
if normalized_reference_name == reference_name:
|
|
334
|
+
table_range = _get_column_table_range(column, read_file)
|
|
335
|
+
if reference_type == "external_model":
|
|
336
|
+
references.append(
|
|
337
|
+
ExternalModelReference(
|
|
338
|
+
path=referenced_model_path,
|
|
339
|
+
range=table_range,
|
|
340
|
+
markdown_description=description,
|
|
341
|
+
target_range=yaml_target_range,
|
|
342
|
+
)
|
|
343
|
+
)
|
|
344
|
+
else:
|
|
345
|
+
references.append(
|
|
346
|
+
ModelReference(
|
|
347
|
+
path=referenced_model_path,
|
|
348
|
+
range=table_range,
|
|
349
|
+
markdown_description=description,
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
return references
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def _get_column_table_range(column: exp.Column, read_file: t.List[str]) -> Range:
|
|
357
|
+
"""
|
|
358
|
+
Get the range for a column's table reference, handling both simple and qualified table names.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
column: The column expression
|
|
362
|
+
read_file: The file content as list of lines
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
The Range covering the table reference in the column
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
table_parts = column.parts[:-1]
|
|
369
|
+
|
|
370
|
+
start_range = TokenPositionDetails.from_meta(table_parts[0].meta).to_range(read_file)
|
|
371
|
+
end_range = TokenPositionDetails.from_meta(table_parts[-1].meta).to_range(read_file)
|
|
372
|
+
|
|
373
|
+
return Range(
|
|
374
|
+
start=start_range.start,
|
|
375
|
+
end=end_range.end,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _get_yaml_model_range(path: Path, model_name: str) -> t.Optional[Range]:
|
|
380
|
+
"""
|
|
381
|
+
Find the range of a specific model block in a YAML file.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
yaml_path: Path to the YAML file
|
|
385
|
+
model_name: Name of the model to find
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
The Range of the model block in the YAML file, or None if not found
|
|
389
|
+
"""
|
|
390
|
+
yaml = YAML()
|
|
391
|
+
with path.open("r", encoding="utf-8") as f:
|
|
392
|
+
data = yaml.load(f)
|
|
393
|
+
|
|
394
|
+
if not isinstance(data, list):
|
|
395
|
+
return None
|
|
396
|
+
|
|
397
|
+
for item in data:
|
|
398
|
+
if isinstance(item, dict) and item.get("name") == model_name:
|
|
399
|
+
# Get size of block by taking the earliest line/col in the items block and the last line/col of the block
|
|
400
|
+
position_data = item.lc.data["name"] # type: ignore
|
|
401
|
+
start = Position(line=position_data[2], character=position_data[3])
|
|
402
|
+
end = Position(line=position_data[2], character=position_data[3] + len(item["name"]))
|
|
403
|
+
return Range(start=start, end=end)
|
|
404
|
+
return None
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
sqlmesh/__init__.py,sha256=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
|
|
2
|
-
sqlmesh/_version.py,sha256=
|
|
2
|
+
sqlmesh/_version.py,sha256=O6HKB0GOTs35eNzv7mkEhoR0RKzZ0ghQEUat1MqXvj4,528
|
|
3
3
|
sqlmesh/magics.py,sha256=bEzYqXHcM0P3CjyUZ1O9arlmXAdLAhoglKbQ29fD9AE,41842
|
|
4
4
|
sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -77,10 +77,10 @@ sqlmesh/core/engine_adapter/spark.py,sha256=sYkVOPS0X43UPbI0z7Hh_EpKlI36qkOcr4NN
|
|
|
77
77
|
sqlmesh/core/engine_adapter/trino.py,sha256=Tws3GxqnC6BmXFohqru1TDxsgPH-21qV6Oky7FaaLpE,15908
|
|
78
78
|
sqlmesh/core/linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
79
|
sqlmesh/core/linter/definition.py,sha256=JDJTkhByUw4Tr3nF-BOHKFAx_eASQqEqzX6AUVQUz8I,5659
|
|
80
|
-
sqlmesh/core/linter/helpers.py,sha256=
|
|
80
|
+
sqlmesh/core/linter/helpers.py,sha256=HNNSiuKB2o4Z2AGbwgrGr9hE0lQnIR7VHQfj8D8M_Jw,5202
|
|
81
81
|
sqlmesh/core/linter/rule.py,sha256=cyGoAz9HuhBYRfbgow_MZhzmDvQE7NK1gzzKsAN0cwY,3694
|
|
82
82
|
sqlmesh/core/linter/rules/__init__.py,sha256=gevzfb67vFqckTCoVAe_TBGf6hQ-YtE1_YuGuXyh1L0,77
|
|
83
|
-
sqlmesh/core/linter/rules/builtin.py,sha256=
|
|
83
|
+
sqlmesh/core/linter/rules/builtin.py,sha256=rOZoNGB-TOuUgOXLdxhhHbSe-0CU4XG5iGY-UeFJyu0,8069
|
|
84
84
|
sqlmesh/core/metric/__init__.py,sha256=H1HmoD5IwN4YWe9iJXyueLYNmTQFZwok5nSWNJcZIBQ,237
|
|
85
85
|
sqlmesh/core/metric/definition.py,sha256=Yd5aVgsZCDPJ43aGP7WqtzZOuuSUtB8uJGVA6Jw9x9M,7201
|
|
86
86
|
sqlmesh/core/metric/rewriter.py,sha256=GiSTHfn2kinqCfNPYgZPRk93JFLzVaaejHtHDQ0yXZI,7326
|
|
@@ -164,16 +164,15 @@ sqlmesh/integrations/github/cicd/command.py,sha256=w3oWhvR4utEurB5UABXj4iVBIojkC
|
|
|
164
164
|
sqlmesh/integrations/github/cicd/config.py,sha256=n4KyNv65y1gpys82iLAQZUb6g2pnzywyV_7cOrQXsnI,3669
|
|
165
165
|
sqlmesh/integrations/github/cicd/controller.py,sha256=XZIh8y7527sBcTMCyXyVxulieFGa90Uz5Uq0wfLPjOY,54857
|
|
166
166
|
sqlmesh/lsp/api.py,sha256=_lA_buSPZFIoLJuINbS53LbNOOaHp3orb0uFTE3aCqI,2328
|
|
167
|
-
sqlmesh/lsp/completions.py,sha256=
|
|
167
|
+
sqlmesh/lsp/completions.py,sha256=7Lhboh6xyoMJ3kkHG3aZz1xVbDwKiXeQKdIRj5xlUOA,6674
|
|
168
168
|
sqlmesh/lsp/context.py,sha256=7zkDu1J4OyeFgWM_q96_zSqI057Ei_dExx-zcBVADNs,14850
|
|
169
169
|
sqlmesh/lsp/custom.py,sha256=3gfN_z9IXKOhTGkaZX7V5I8WUmI4z1GWe1sViOo92pw,3980
|
|
170
|
-
sqlmesh/lsp/description.py,sha256=PjguwyVw5YeYSgT0JMhkf5U1Jry-sDPLvQ2caIR9JPQ,856
|
|
171
170
|
sqlmesh/lsp/errors.py,sha256=3NMim_5J00Eypz7t8b7XbkBfy8gIsRkeq-VcjD4COtc,1489
|
|
172
171
|
sqlmesh/lsp/helpers.py,sha256=EFc1u3-b7kSv5-tNwmKUDxId72RCLDBnN2lLTgRSzzQ,1020
|
|
173
172
|
sqlmesh/lsp/hints.py,sha256=j-blccBUil94yRoDjWfkSM0HqMmsKD6hP2TaWdWWVk4,3734
|
|
174
|
-
sqlmesh/lsp/main.py,sha256=
|
|
175
|
-
sqlmesh/lsp/reference.py,sha256
|
|
176
|
-
sqlmesh/lsp/rename.py,sha256=
|
|
173
|
+
sqlmesh/lsp/main.py,sha256=IW6Om8yGWBkKywBjKxFYhGe4UXa-iWlKcPCkyOgYKD0,42460
|
|
174
|
+
sqlmesh/lsp/reference.py,sha256=-TTT5NIIGDQoEDCzH8RNgEINt0p9DYclzEn4rBjreRI,18475
|
|
175
|
+
sqlmesh/lsp/rename.py,sha256=AFj-zJGWiBgHSj1jx1rOx4yJmmw1QpEcob648epM8gk,4668
|
|
177
176
|
sqlmesh/lsp/tests_ranges.py,sha256=YO5w534J5_y2NWxj9t637wHLbFDJdXBvM7i5F4C-P0I,2308
|
|
178
177
|
sqlmesh/lsp/uri.py,sha256=mvSLbZGmMTHPpliThOtVWiFcHnfJzp1w39q9l-xD2SI,802
|
|
179
178
|
sqlmesh/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -278,6 +277,7 @@ sqlmesh/utils/errors.py,sha256=8FE33Eo3KN3Y4s5EZM5t92jZi9BAVGzkr3QCGlrLeDk,5679
|
|
|
278
277
|
sqlmesh/utils/git.py,sha256=v1MD4Zwn52UBn_tTfoKn8SAPJVGC6SEFrJ4WEJFbgF0,1868
|
|
279
278
|
sqlmesh/utils/hashing.py,sha256=nZRKvLNQ83tLG4IoXshVJZf-MbDrXC1HOeNw8Ji-tMM,578
|
|
280
279
|
sqlmesh/utils/jinja.py,sha256=zulSPIICdFOjN__xkAiMpxbCS7S0--xAFK9d8VG0KvU,27844
|
|
280
|
+
sqlmesh/utils/lineage.py,sha256=r8bmemlZpGq-g2jlEPUnG3qNrg1RCdHC0I8k8x8QvKM,15578
|
|
281
281
|
sqlmesh/utils/metaprogramming.py,sha256=yDWS3_tkm6Yd5TNHgii2x_VdZ2pVM0vL6oFuwFMMs0A,23554
|
|
282
282
|
sqlmesh/utils/migration.py,sha256=R7Ck6FX-LfcujGy7sgS0kDWlK-xAEBODr3gqIQ8gC08,835
|
|
283
283
|
sqlmesh/utils/pandas.py,sha256=FytTSLcRNtO0-YMvpoDBkkut3yoQJR9mBSKpif8lxug,2497
|
|
@@ -286,7 +286,7 @@ sqlmesh/utils/pydantic.py,sha256=o_NsXbIpDqNpUA1Uc5xF0ZzoXQYYB0DfHwdRxBwXPNk,120
|
|
|
286
286
|
sqlmesh/utils/rich.py,sha256=cwQ5nJ6sgz64xHtoh6_ec7ReV5YpsOGhMtUJnwoRfEI,3549
|
|
287
287
|
sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
|
|
288
288
|
sqlmesh/utils/yaml.py,sha256=hvo5lmybYLcIx4p6CQwufS8X4MbwS60lEBnCmYJCXmU,2336
|
|
289
|
-
sqlmesh-0.205.1.
|
|
289
|
+
sqlmesh-0.205.1.dev8.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
|
|
290
290
|
web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
291
291
|
web/client/dist/index.html,sha256=SXykdSRNgrT1k6I2dPZPEfpxPjIsi8-yVFijt-naSA4,5472
|
|
292
292
|
web/client/dist/assets/Audits-Jm353fhk.js,sha256=ry6b5IKT3hLAfD5C3T2BqxulfauEV0n0YZ2vsP4eQ_U,1041
|
|
@@ -404,8 +404,8 @@ web/server/api/endpoints/models.py,sha256=kwj0s7uve3iZSMfmjkoPVMFMeY1sD0peTeyrWf
|
|
|
404
404
|
web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
|
|
405
405
|
web/server/api/endpoints/plan.py,sha256=bbbY50W_2MsZSTxOHWMKz0tbIm75nsRSlPy8GI2fg9Q,9306
|
|
406
406
|
web/server/api/endpoints/table_diff.py,sha256=SCy3-pr5x6bEEiOaZGCDbiHQhpgxwmnz3Acqa2Ie6jI,2090
|
|
407
|
-
sqlmesh-0.205.1.
|
|
408
|
-
sqlmesh-0.205.1.
|
|
409
|
-
sqlmesh-0.205.1.
|
|
410
|
-
sqlmesh-0.205.1.
|
|
411
|
-
sqlmesh-0.205.1.
|
|
407
|
+
sqlmesh-0.205.1.dev8.dist-info/METADATA,sha256=6LQWBfLHBvtcA5WdLBE9jJ5zBPxCpYxt_AqZYw9y0_M,26678
|
|
408
|
+
sqlmesh-0.205.1.dev8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
409
|
+
sqlmesh-0.205.1.dev8.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
|
|
410
|
+
sqlmesh-0.205.1.dev8.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
|
|
411
|
+
sqlmesh-0.205.1.dev8.dist-info/RECORD,,
|
sqlmesh/lsp/description.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from sqlmesh.core.model.definition import (
|
|
2
|
-
ExternalModel,
|
|
3
|
-
PythonModel,
|
|
4
|
-
SeedModel,
|
|
5
|
-
SqlModel,
|
|
6
|
-
)
|
|
7
|
-
import typing as t
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def generate_markdown_description(
|
|
11
|
-
model: t.Union[SqlModel, ExternalModel, PythonModel, SeedModel],
|
|
12
|
-
) -> t.Optional[str]:
|
|
13
|
-
description = model.description
|
|
14
|
-
columns = model.columns_to_types
|
|
15
|
-
column_descriptions = model.column_descriptions
|
|
16
|
-
|
|
17
|
-
if columns is None:
|
|
18
|
-
return description or None
|
|
19
|
-
|
|
20
|
-
columns_table = "\n".join(
|
|
21
|
-
[
|
|
22
|
-
f"| {column} | {column_type} | {column_descriptions.get(column, '')} |"
|
|
23
|
-
for column, column_type in columns.items()
|
|
24
|
-
]
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
table_header = "| Column | Type | Description |\n|--------|------|-------------|\n"
|
|
28
|
-
columns_text = table_header + columns_table
|
|
29
|
-
return f"{description}\n\n{columns_text}" if description else columns_text
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|