sqlmesh 0.187.6.dev7__py3-none-any.whl → 0.187.6.dev11__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/config/scheduler.py +11 -7
- sqlmesh/core/context.py +75 -42
- sqlmesh/core/selector.py +1 -1
- sqlmesh/integrations/github/cicd/controller.py +1 -1
- sqlmesh/lsp/reference.py +188 -0
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/METADATA +1 -1
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/RECORD +15 -15
- web/server/api/endpoints/commands.py +1 -1
- web/server/api/endpoints/files.py +1 -1
- web/server/utils.py +1 -2
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/WHEEL +0 -0
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.187.6.dev7.dist-info → sqlmesh-0.187.6.dev11.dist-info}/top_level.txt +0 -0
sqlmesh/_version.py
CHANGED
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.187.6.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 187, 6, '
|
|
20
|
+
__version__ = version = '0.187.6.dev11'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 187, 6, 'dev11')
|
sqlmesh/core/config/scheduler.py
CHANGED
|
@@ -47,8 +47,8 @@ class SchedulerConfig(abc.ABC):
|
|
|
47
47
|
"""
|
|
48
48
|
|
|
49
49
|
@abc.abstractmethod
|
|
50
|
-
def
|
|
51
|
-
"""Returns the default catalog for
|
|
50
|
+
def get_default_catalog_per_gateway(self, context: GenericContext) -> t.Dict[str, str]:
|
|
51
|
+
"""Returns the default catalog for each gateway.
|
|
52
52
|
|
|
53
53
|
Args:
|
|
54
54
|
context: The SQLMesh Context.
|
|
@@ -66,7 +66,7 @@ class SchedulerConfig(abc.ABC):
|
|
|
66
66
|
class _EngineAdapterStateSyncSchedulerConfig(SchedulerConfig):
|
|
67
67
|
def create_state_sync(self, context: GenericContext) -> StateSync:
|
|
68
68
|
state_connection = (
|
|
69
|
-
context.config.get_state_connection(context.gateway) or context.
|
|
69
|
+
context.config.get_state_connection(context.gateway) or context.connection_config
|
|
70
70
|
)
|
|
71
71
|
|
|
72
72
|
warehouse_connection = context.config.get_connection(context.gateway)
|
|
@@ -110,7 +110,7 @@ class _EngineAdapterStateSyncSchedulerConfig(SchedulerConfig):
|
|
|
110
110
|
|
|
111
111
|
def state_sync_fingerprint(self, context: GenericContext) -> str:
|
|
112
112
|
state_connection = (
|
|
113
|
-
context.config.get_state_connection(context.gateway) or context.
|
|
113
|
+
context.config.get_state_connection(context.gateway) or context.connection_config
|
|
114
114
|
)
|
|
115
115
|
return md5(
|
|
116
116
|
[
|
|
@@ -132,12 +132,16 @@ class BuiltInSchedulerConfig(_EngineAdapterStateSyncSchedulerConfig, BaseConfig)
|
|
|
132
132
|
state_sync=context.state_sync,
|
|
133
133
|
snapshot_evaluator=context.snapshot_evaluator,
|
|
134
134
|
create_scheduler=context.create_scheduler,
|
|
135
|
-
default_catalog=
|
|
135
|
+
default_catalog=context.default_catalog,
|
|
136
136
|
console=context.console,
|
|
137
137
|
)
|
|
138
138
|
|
|
139
|
-
def
|
|
140
|
-
|
|
139
|
+
def get_default_catalog_per_gateway(self, context: GenericContext) -> t.Dict[str, str]:
|
|
140
|
+
default_catalogs_per_gateway: t.Dict[str, str] = {}
|
|
141
|
+
for gateway, adapter in context.engine_adapters.items():
|
|
142
|
+
if catalog := adapter.default_catalog:
|
|
143
|
+
default_catalogs_per_gateway[gateway] = catalog
|
|
144
|
+
return default_catalogs_per_gateway
|
|
141
145
|
|
|
142
146
|
|
|
143
147
|
SCHEDULER_CONFIG_TO_TYPE = {
|
sqlmesh/core/context.py
CHANGED
|
@@ -62,7 +62,9 @@ from sqlmesh.core.config import (
|
|
|
62
62
|
Config,
|
|
63
63
|
load_configs,
|
|
64
64
|
)
|
|
65
|
+
from sqlmesh.core.config.connection import ConnectionConfig
|
|
65
66
|
from sqlmesh.core.config.loader import C
|
|
67
|
+
from sqlmesh.core.config.root import RegexKeyDict
|
|
66
68
|
from sqlmesh.core.console import get_console
|
|
67
69
|
from sqlmesh.core.context_diff import ContextDiff
|
|
68
70
|
from sqlmesh.core.dialect import (
|
|
@@ -91,6 +93,7 @@ from sqlmesh.core.plan import Plan, PlanBuilder, SnapshotIntervals
|
|
|
91
93
|
from sqlmesh.core.plan.definition import UserProvidedFlags
|
|
92
94
|
from sqlmesh.core.reference import ReferenceGraph
|
|
93
95
|
from sqlmesh.core.scheduler import Scheduler, CompletionStatus
|
|
96
|
+
from sqlmesh.core.schema_diff import SchemaDiffer
|
|
94
97
|
from sqlmesh.core.schema_loader import create_external_models_file
|
|
95
98
|
from sqlmesh.core.selector import Selector
|
|
96
99
|
from sqlmesh.core.snapshot import (
|
|
@@ -367,6 +370,9 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
367
370
|
self._excluded_requirements: t.Set[str] = set()
|
|
368
371
|
self._default_catalog: t.Optional[str] = None
|
|
369
372
|
self._default_catalog_per_gateway: t.Optional[t.Dict[str, str]] = None
|
|
373
|
+
self._engine_adapter: t.Optional[EngineAdapter] = None
|
|
374
|
+
self._connection_config: t.Optional[ConnectionConfig] = None
|
|
375
|
+
self._test_connection_config: t.Optional[ConnectionConfig] = None
|
|
370
376
|
self._linters: t.Dict[str, Linter] = {}
|
|
371
377
|
self._loaded: bool = False
|
|
372
378
|
|
|
@@ -407,24 +413,15 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
407
413
|
for path, config in self.configs.items()
|
|
408
414
|
]
|
|
409
415
|
|
|
410
|
-
self.
|
|
416
|
+
self._concurrent_tasks = concurrent_tasks
|
|
411
417
|
self._state_connection_config = (
|
|
412
|
-
self.config.get_state_connection(self.gateway) or self.
|
|
418
|
+
self.config.get_state_connection(self.gateway) or self.connection_config
|
|
413
419
|
)
|
|
414
|
-
self.concurrent_tasks = concurrent_tasks or self._connection_config.concurrent_tasks
|
|
415
|
-
|
|
416
|
-
self._engine_adapters: t.Dict[str, EngineAdapter] = {
|
|
417
|
-
self.selected_gateway: self._connection_config.create_engine_adapter()
|
|
418
|
-
}
|
|
419
420
|
|
|
420
421
|
self._snapshot_evaluator: t.Optional[SnapshotEvaluator] = None
|
|
421
422
|
|
|
422
423
|
self.console = get_console()
|
|
423
|
-
setattr(self.console, "dialect", self.
|
|
424
|
-
|
|
425
|
-
self._test_connection_config = self.config.get_test_connection(
|
|
426
|
-
self.gateway, self.default_catalog, default_catalog_dialect=self.engine_adapter.DIALECT
|
|
427
|
-
)
|
|
424
|
+
setattr(self.console, "dialect", self.config.dialect)
|
|
428
425
|
|
|
429
426
|
self._provided_state_sync: t.Optional[StateSync] = state_sync
|
|
430
427
|
self._state_sync: t.Optional[StateSync] = None
|
|
@@ -435,14 +432,6 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
435
432
|
self.users = list({user.username: user for user in self.users}.values())
|
|
436
433
|
self._register_notification_targets()
|
|
437
434
|
|
|
438
|
-
if (
|
|
439
|
-
self.config.environment_catalog_mapping
|
|
440
|
-
and not self.engine_adapter.catalog_support.is_multi_catalog_supported
|
|
441
|
-
):
|
|
442
|
-
raise SQLMeshError(
|
|
443
|
-
"Environment catalog mapping is only supported for engine adapters that support multiple catalogs"
|
|
444
|
-
)
|
|
445
|
-
|
|
446
435
|
if load:
|
|
447
436
|
self.load()
|
|
448
437
|
|
|
@@ -453,7 +442,9 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
453
442
|
@property
|
|
454
443
|
def engine_adapter(self) -> EngineAdapter:
|
|
455
444
|
"""Returns the default engine adapter."""
|
|
456
|
-
|
|
445
|
+
if self._engine_adapter is None:
|
|
446
|
+
self._engine_adapter = self.connection_config.create_engine_adapter()
|
|
447
|
+
return self._engine_adapter
|
|
457
448
|
|
|
458
449
|
@property
|
|
459
450
|
def snapshot_evaluator(self) -> SnapshotEvaluator:
|
|
@@ -932,19 +923,22 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
932
923
|
|
|
933
924
|
return snapshot
|
|
934
925
|
|
|
935
|
-
def config_for_path(self, path: Path) -> Config:
|
|
926
|
+
def config_for_path(self, path: Path) -> t.Tuple[Config, Path]:
|
|
927
|
+
"""Returns the config and path of the said project for a given file path."""
|
|
936
928
|
for config_path, config in self.configs.items():
|
|
937
929
|
try:
|
|
938
930
|
path.relative_to(config_path)
|
|
939
|
-
return config
|
|
931
|
+
return config, config_path
|
|
940
932
|
except ValueError:
|
|
941
933
|
pass
|
|
942
|
-
return self.config
|
|
934
|
+
return self.config, self.path
|
|
943
935
|
|
|
944
936
|
def config_for_node(self, node: str | Model | Audit) -> Config:
|
|
945
937
|
if isinstance(node, str):
|
|
946
|
-
return self.config_for_path(self.get_snapshot(node, raise_if_missing=True).node._path)
|
|
947
|
-
|
|
938
|
+
return self.config_for_path(self.get_snapshot(node, raise_if_missing=True).node._path)[
|
|
939
|
+
0
|
|
940
|
+
] # type: ignore
|
|
941
|
+
return self.config_for_path(node._path)[0] # type: ignore
|
|
948
942
|
|
|
949
943
|
@property
|
|
950
944
|
def models(self) -> MappingProxyType[str, Model]:
|
|
@@ -977,8 +971,8 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
977
971
|
|
|
978
972
|
@property
|
|
979
973
|
def default_catalog(self) -> t.Optional[str]:
|
|
980
|
-
if self._default_catalog is None:
|
|
981
|
-
self._default_catalog = self.
|
|
974
|
+
if self._default_catalog is None and self.default_catalog_per_gateway:
|
|
975
|
+
self._default_catalog = self.default_catalog_per_gateway[self.selected_gateway]
|
|
982
976
|
return self._default_catalog
|
|
983
977
|
|
|
984
978
|
@python_api_analytics
|
|
@@ -1535,7 +1529,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1535
1529
|
allow_destructive_models=expanded_destructive_models,
|
|
1536
1530
|
environment_ttl=environment_ttl,
|
|
1537
1531
|
environment_suffix_target=self.config.environment_suffix_target,
|
|
1538
|
-
environment_catalog_mapping=self.
|
|
1532
|
+
environment_catalog_mapping=self.environment_catalog_mapping,
|
|
1539
1533
|
categorizer_config=categorizer_config or self.auto_categorize_changes,
|
|
1540
1534
|
auto_categorization_enabled=not no_auto_categorization,
|
|
1541
1535
|
effective_from=effective_from,
|
|
@@ -1547,7 +1541,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1547
1541
|
),
|
|
1548
1542
|
end_bounded=not run,
|
|
1549
1543
|
ensure_finalized_snapshots=self.config.plan.use_finalized_state,
|
|
1550
|
-
engine_schema_differ=
|
|
1544
|
+
engine_schema_differ=SchemaDiffer(), # TODO: fix to properly handle it
|
|
1551
1545
|
interval_end_per_model=max_interval_end_per_model,
|
|
1552
1546
|
console=self.console,
|
|
1553
1547
|
user_provided_flags=user_provided_flags,
|
|
@@ -1636,7 +1630,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1636
1630
|
self.console.show_model_difference_summary(
|
|
1637
1631
|
context_diff,
|
|
1638
1632
|
EnvironmentNamingInfo.from_environment_catalog_mapping(
|
|
1639
|
-
self.
|
|
1633
|
+
self.environment_catalog_mapping,
|
|
1640
1634
|
name=environment,
|
|
1641
1635
|
suffix_target=self.config.environment_suffix_target,
|
|
1642
1636
|
normalize_name=context_diff.normalize_environment_name,
|
|
@@ -1990,7 +1984,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
1990
1984
|
|
|
1991
1985
|
try:
|
|
1992
1986
|
model_to_test = self.get_model(model, raise_if_missing=True)
|
|
1993
|
-
test_adapter = self.
|
|
1987
|
+
test_adapter = self.test_connection_config.create_engine_adapter(
|
|
1994
1988
|
register_comments_override=False
|
|
1995
1989
|
)
|
|
1996
1990
|
|
|
@@ -2036,7 +2030,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
2036
2030
|
preserve_fixtures=preserve_fixtures,
|
|
2037
2031
|
stream=stream,
|
|
2038
2032
|
default_catalog=self.default_catalog,
|
|
2039
|
-
default_catalog_dialect=self.
|
|
2033
|
+
default_catalog_dialect=self.config.dialect or "",
|
|
2040
2034
|
)
|
|
2041
2035
|
|
|
2042
2036
|
@python_api_analytics
|
|
@@ -2475,7 +2469,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
2475
2469
|
self.console.log_test_results(
|
|
2476
2470
|
result,
|
|
2477
2471
|
test_output,
|
|
2478
|
-
self.
|
|
2472
|
+
self.test_connection_config._engine_adapter.DIALECT,
|
|
2479
2473
|
)
|
|
2480
2474
|
if not result.wasSuccessful():
|
|
2481
2475
|
raise PlanError(
|
|
@@ -2496,7 +2490,7 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
2496
2490
|
if snapshot.version
|
|
2497
2491
|
else snapshot.qualified_view_name.for_environment(
|
|
2498
2492
|
EnvironmentNamingInfo.from_environment_catalog_mapping(
|
|
2499
|
-
self.
|
|
2493
|
+
self.environment_catalog_mapping,
|
|
2500
2494
|
name=c.PROD,
|
|
2501
2495
|
suffix_target=self.config.environment_suffix_target,
|
|
2502
2496
|
)
|
|
@@ -2508,24 +2502,63 @@ class GenericContext(BaseContext, t.Generic[C]):
|
|
|
2508
2502
|
@cached_property
|
|
2509
2503
|
def engine_adapters(self) -> t.Dict[str, EngineAdapter]:
|
|
2510
2504
|
"""Returns all the engine adapters for the gateways defined in the configuration."""
|
|
2505
|
+
adapters: t.Dict[str, EngineAdapter] = {self.selected_gateway: self.engine_adapter}
|
|
2511
2506
|
for gateway_name in self.config.gateways:
|
|
2512
2507
|
if gateway_name != self.selected_gateway:
|
|
2513
2508
|
connection = self.config.get_connection(gateway_name)
|
|
2514
2509
|
adapter = connection.create_engine_adapter(concurrent_tasks=self.concurrent_tasks)
|
|
2515
|
-
|
|
2516
|
-
return
|
|
2510
|
+
adapters[gateway_name] = adapter
|
|
2511
|
+
return adapters
|
|
2517
2512
|
|
|
2518
2513
|
@cached_property
|
|
2519
2514
|
def default_catalog_per_gateway(self) -> t.Dict[str, str]:
|
|
2520
2515
|
"""Returns the default catalogs for each engine adapter."""
|
|
2521
2516
|
if self._default_catalog_per_gateway is None:
|
|
2522
|
-
self._default_catalog_per_gateway =
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
if adapter.default_catalog
|
|
2526
|
-
}
|
|
2517
|
+
self._default_catalog_per_gateway = self._scheduler.get_default_catalog_per_gateway(
|
|
2518
|
+
self
|
|
2519
|
+
)
|
|
2527
2520
|
return self._default_catalog_per_gateway
|
|
2528
2521
|
|
|
2522
|
+
@cached_property
|
|
2523
|
+
def concurrent_tasks(self) -> int:
|
|
2524
|
+
if self._concurrent_tasks is None:
|
|
2525
|
+
self._concurrent_tasks = self.connection_config.concurrent_tasks
|
|
2526
|
+
return self._concurrent_tasks
|
|
2527
|
+
|
|
2528
|
+
@cached_property
|
|
2529
|
+
def connection_config(self) -> ConnectionConfig:
|
|
2530
|
+
if self._connection_config is None:
|
|
2531
|
+
self._connection_config = self.config.get_connection(self.selected_gateway)
|
|
2532
|
+
return self._connection_config
|
|
2533
|
+
|
|
2534
|
+
@cached_property
|
|
2535
|
+
def test_connection_config(self) -> ConnectionConfig:
|
|
2536
|
+
if self._test_connection_config is None:
|
|
2537
|
+
self._test_connection_config = self.config.get_test_connection(
|
|
2538
|
+
self.gateway,
|
|
2539
|
+
self.default_catalog,
|
|
2540
|
+
default_catalog_dialect=self.engine_adapter.DIALECT,
|
|
2541
|
+
)
|
|
2542
|
+
return self._test_connection_config
|
|
2543
|
+
|
|
2544
|
+
@cached_property
|
|
2545
|
+
def environment_catalog_mapping(self) -> RegexKeyDict:
|
|
2546
|
+
engine_adapter = None
|
|
2547
|
+
try:
|
|
2548
|
+
engine_adapter = self.engine_adapter
|
|
2549
|
+
except Exception:
|
|
2550
|
+
pass
|
|
2551
|
+
|
|
2552
|
+
if (
|
|
2553
|
+
self.config.environment_catalog_mapping
|
|
2554
|
+
and engine_adapter
|
|
2555
|
+
and not self.engine_adapter.catalog_support.is_multi_catalog_supported
|
|
2556
|
+
):
|
|
2557
|
+
raise SQLMeshError(
|
|
2558
|
+
"Environment catalog mapping is only supported for engine adapters that support multiple catalogs"
|
|
2559
|
+
)
|
|
2560
|
+
return self.config.environment_catalog_mapping
|
|
2561
|
+
|
|
2529
2562
|
def _get_engine_adapter(self, gateway: t.Optional[str] = None) -> EngineAdapter:
|
|
2530
2563
|
if gateway:
|
|
2531
2564
|
if adapter := self.engine_adapters.get(gateway):
|
sqlmesh/core/selector.py
CHANGED
|
@@ -726,7 +726,7 @@ class GithubController:
|
|
|
726
726
|
self._console.log_test_results(
|
|
727
727
|
result,
|
|
728
728
|
output,
|
|
729
|
-
self._context.
|
|
729
|
+
self._context.test_connection_config._engine_adapter.DIALECT,
|
|
730
730
|
)
|
|
731
731
|
test_summary = self._console.consume_captured_output()
|
|
732
732
|
test_title = "Tests Passed" if result.wasSuccessful() else "Tests Failed"
|
sqlmesh/lsp/reference.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from lsprotocol.types import Range, Position
|
|
2
2
|
import typing as t
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
|
|
5
|
+
from sqlmesh.core.audit import StandaloneAudit
|
|
4
6
|
from sqlmesh.core.dialect import normalize_model_name
|
|
5
7
|
from sqlmesh.core.model.definition import SqlModel
|
|
6
8
|
from sqlmesh.lsp.context import LSPContext, ModelTarget, AuditTarget
|
|
@@ -10,6 +12,10 @@ from sqlglot.optimizer.scope import build_scope
|
|
|
10
12
|
from sqlmesh.lsp.uri import URI
|
|
11
13
|
from sqlmesh.utils.pydantic import PydanticModel
|
|
12
14
|
from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
|
|
15
|
+
import ast
|
|
16
|
+
from sqlmesh.core.model import Model
|
|
17
|
+
from sqlmesh import macro
|
|
18
|
+
import inspect
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
class Reference(PydanticModel):
|
|
@@ -72,6 +78,11 @@ def get_references(
|
|
|
72
78
|
A list of references at the given position
|
|
73
79
|
"""
|
|
74
80
|
references = get_model_definitions_for_a_path(lint_context, document_uri)
|
|
81
|
+
|
|
82
|
+
# Get macro references before filtering by position
|
|
83
|
+
macro_references = get_macro_definitions_for_a_path(lint_context, document_uri)
|
|
84
|
+
references.extend(macro_references)
|
|
85
|
+
|
|
75
86
|
filtered_references = list(filter(by_position(position), references))
|
|
76
87
|
return filtered_references
|
|
77
88
|
|
|
@@ -290,3 +301,180 @@ def _range_from_token_position_details(
|
|
|
290
301
|
start=Position(line=start_line_0, character=start_col_0),
|
|
291
302
|
end=Position(line=end_line_0, character=end_col_0),
|
|
292
303
|
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def get_macro_definitions_for_a_path(
|
|
307
|
+
lsp_context: LSPContext, document_uri: URI
|
|
308
|
+
) -> t.List[Reference]:
|
|
309
|
+
"""
|
|
310
|
+
Get macro references for a given path.
|
|
311
|
+
|
|
312
|
+
This function finds all macro invocations (e.g., @ADD_ONE, @MULTIPLY) in a SQL file
|
|
313
|
+
and creates references to their definitions in the Python macro files.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
lsp_context: The LSP context containing macro definitions
|
|
317
|
+
document_uri: The URI of the document to search for macro invocations
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
A list of Reference objects for each macro invocation found
|
|
321
|
+
"""
|
|
322
|
+
path = document_uri.to_path()
|
|
323
|
+
if path.suffix != ".sql":
|
|
324
|
+
return []
|
|
325
|
+
|
|
326
|
+
# Get the file info from the context map
|
|
327
|
+
if path not in lsp_context.map:
|
|
328
|
+
return []
|
|
329
|
+
|
|
330
|
+
file_info = lsp_context.map[path]
|
|
331
|
+
# Process based on whether it's a model or standalone audit
|
|
332
|
+
if isinstance(file_info, ModelTarget):
|
|
333
|
+
# It's a model
|
|
334
|
+
target: t.Optional[t.Union[Model, StandaloneAudit]] = lsp_context.context.get_model(
|
|
335
|
+
model_or_snapshot=file_info.names[0], raise_if_missing=False
|
|
336
|
+
)
|
|
337
|
+
if target is None or not isinstance(target, SqlModel):
|
|
338
|
+
return []
|
|
339
|
+
query = target.query
|
|
340
|
+
file_path = target._path
|
|
341
|
+
elif isinstance(file_info, AuditTarget):
|
|
342
|
+
# It's a standalone audit
|
|
343
|
+
target = lsp_context.context.standalone_audits.get(file_info.name)
|
|
344
|
+
if target is None:
|
|
345
|
+
return []
|
|
346
|
+
query = target.query
|
|
347
|
+
file_path = target._path
|
|
348
|
+
else:
|
|
349
|
+
return []
|
|
350
|
+
|
|
351
|
+
references = []
|
|
352
|
+
config_for_model, config_path = lsp_context.context.config_for_path(
|
|
353
|
+
file_path,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
with open(file_path, "r", encoding="utf-8") as file:
|
|
357
|
+
read_file = file.readlines()
|
|
358
|
+
|
|
359
|
+
for node in query.find_all(exp.Anonymous):
|
|
360
|
+
macro_name = node.name.lower()
|
|
361
|
+
reference = get_macro_reference(
|
|
362
|
+
node=node,
|
|
363
|
+
target=target,
|
|
364
|
+
read_file=read_file,
|
|
365
|
+
config_path=config_path,
|
|
366
|
+
macro_name=macro_name,
|
|
367
|
+
)
|
|
368
|
+
if reference is not None:
|
|
369
|
+
references.append(reference)
|
|
370
|
+
|
|
371
|
+
return references
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def get_macro_reference(
|
|
375
|
+
target: t.Union[Model, StandaloneAudit],
|
|
376
|
+
read_file: t.List[str],
|
|
377
|
+
config_path: t.Optional[Path],
|
|
378
|
+
node: exp.Expression,
|
|
379
|
+
macro_name: str,
|
|
380
|
+
) -> t.Optional[Reference]:
|
|
381
|
+
# Get the file path where the macro is defined
|
|
382
|
+
try:
|
|
383
|
+
# Get the position of the macro invocation in the source file first
|
|
384
|
+
if hasattr(node, "meta") and node.meta:
|
|
385
|
+
token_details = TokenPositionDetails.from_meta(node.meta)
|
|
386
|
+
macro_range = _range_from_token_position_details(token_details, read_file)
|
|
387
|
+
|
|
388
|
+
# Check if it's a built-in method
|
|
389
|
+
if builtin := get_built_in_macro_reference(macro_name, macro_range):
|
|
390
|
+
return builtin
|
|
391
|
+
else:
|
|
392
|
+
# Skip if we can't get the position
|
|
393
|
+
return None
|
|
394
|
+
|
|
395
|
+
# Find the macro definition information
|
|
396
|
+
macro_def = target.python_env.get(macro_name)
|
|
397
|
+
if macro_def is None:
|
|
398
|
+
return None
|
|
399
|
+
|
|
400
|
+
function_name = macro_def.name
|
|
401
|
+
if not function_name:
|
|
402
|
+
return None
|
|
403
|
+
if not macro_def.path:
|
|
404
|
+
return None
|
|
405
|
+
if not config_path:
|
|
406
|
+
return None
|
|
407
|
+
path = Path(config_path).joinpath(macro_def.path)
|
|
408
|
+
|
|
409
|
+
# Parse the Python file to find the function definition
|
|
410
|
+
with open(path, "r") as f:
|
|
411
|
+
tree = ast.parse(f.read())
|
|
412
|
+
with open(path, "r") as f:
|
|
413
|
+
output_read_line = f.readlines()
|
|
414
|
+
|
|
415
|
+
# Find the function definition by name
|
|
416
|
+
start_line = None
|
|
417
|
+
end_line = None
|
|
418
|
+
get_length_of_end_line = None
|
|
419
|
+
docstring = None
|
|
420
|
+
for ast_node in ast.walk(tree):
|
|
421
|
+
if isinstance(ast_node, ast.FunctionDef) and ast_node.name == function_name:
|
|
422
|
+
start_line = ast_node.lineno
|
|
423
|
+
end_line = ast_node.end_lineno
|
|
424
|
+
get_length_of_end_line = (
|
|
425
|
+
len(output_read_line[end_line - 1])
|
|
426
|
+
if end_line is not None and end_line - 1 < len(read_file)
|
|
427
|
+
else 0
|
|
428
|
+
)
|
|
429
|
+
# Extract docstring if present
|
|
430
|
+
docstring = ast.get_docstring(ast_node)
|
|
431
|
+
break
|
|
432
|
+
|
|
433
|
+
if start_line is None or end_line is None or get_length_of_end_line is None:
|
|
434
|
+
return None
|
|
435
|
+
|
|
436
|
+
# Create a reference to the macro definition
|
|
437
|
+
macro_uri = URI.from_path(path)
|
|
438
|
+
|
|
439
|
+
return Reference(
|
|
440
|
+
uri=macro_uri.value,
|
|
441
|
+
range=macro_range,
|
|
442
|
+
target_range=Range(
|
|
443
|
+
start=Position(line=start_line - 1, character=0),
|
|
444
|
+
end=Position(line=end_line - 1, character=get_length_of_end_line),
|
|
445
|
+
),
|
|
446
|
+
markdown_description=docstring,
|
|
447
|
+
)
|
|
448
|
+
except Exception:
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def get_built_in_macro_reference(macro_name: str, macro_range: Range) -> t.Optional[Reference]:
|
|
453
|
+
"""
|
|
454
|
+
Get a reference to a built-in macro by its name.
|
|
455
|
+
|
|
456
|
+
Args:
|
|
457
|
+
macro_name: The name of the built-in macro (e.g., 'each', 'sql_literal')
|
|
458
|
+
macro_range: The range of the macro invocation in the source file
|
|
459
|
+
"""
|
|
460
|
+
built_in_macros = macro.get_registry()
|
|
461
|
+
built_in_macro = built_in_macros.get(macro_name)
|
|
462
|
+
if built_in_macro is None:
|
|
463
|
+
return None
|
|
464
|
+
|
|
465
|
+
func = built_in_macro.func
|
|
466
|
+
filename = inspect.getfile(func)
|
|
467
|
+
source_lines, line_number = inspect.getsourcelines(func)
|
|
468
|
+
|
|
469
|
+
# Calculate the end line number by counting the number of source lines
|
|
470
|
+
end_line_number = line_number + len(source_lines) - 1
|
|
471
|
+
|
|
472
|
+
return Reference(
|
|
473
|
+
uri=URI.from_path(Path(filename)).value,
|
|
474
|
+
range=macro_range,
|
|
475
|
+
target_range=Range(
|
|
476
|
+
start=Position(line=line_number - 1, character=0),
|
|
477
|
+
end=Position(line=end_line_number - 1, character=0),
|
|
478
|
+
),
|
|
479
|
+
markdown_description=func.__doc__ if func.__doc__ else None,
|
|
480
|
+
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
sqlmesh/__init__.py,sha256=69xw6bTmi4cW90M-sl3g6wLDgxVcLHcKg1q8GS3lqyA,7466
|
|
2
|
-
sqlmesh/_version.py,sha256=
|
|
2
|
+
sqlmesh/_version.py,sha256=i568mvr4ypNSszdDvZr4JgAp-aw-eTdLM_JqGZyZ2ro,530
|
|
3
3
|
sqlmesh/magics.py,sha256=JHorAZNtezf123jmTyNSoUC9yHmv-08hMP205PJmmIo,39750
|
|
4
4
|
sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -13,7 +13,7 @@ sqlmesh/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
13
13
|
sqlmesh/core/_typing.py,sha256=e1f7xO2aZCy38M_3VoDy-XI3shyd99-IFctgIFSgXWM,497
|
|
14
14
|
sqlmesh/core/console.py,sha256=ZAaGLOWBJGBxPzLV7KZZ9akPExgD5m5AboCM8O0Q0nY,150944
|
|
15
15
|
sqlmesh/core/constants.py,sha256=oqt6zjepUhQoWlgapKn_HpG7Pu9mrFwepdX5caNfJUI,2499
|
|
16
|
-
sqlmesh/core/context.py,sha256
|
|
16
|
+
sqlmesh/core/context.py,sha256=-pg6ZTvamwAc1SrAF2WhvAuMDTaOZipXSEVP-EiiDso,116971
|
|
17
17
|
sqlmesh/core/context_diff.py,sha256=s9toP17d4tJfOpFH91LcjGK2CM64PVuB0MPkeFgF4hQ,20415
|
|
18
18
|
sqlmesh/core/dialect.py,sha256=fPTV517IOS0nWMxYznNNQnXkQkFFrPOSKe8ghsQ0o8A,49759
|
|
19
19
|
sqlmesh/core/environment.py,sha256=Fsih6WZ7Tx4ec0XIlmIIspUWcmijPNW5uHPRQSWuhA8,12315
|
|
@@ -27,7 +27,7 @@ sqlmesh/core/renderer.py,sha256=KOr7rQ-RfWiS51cEj2fzdhxCrYbU0A5wNTGwKyeqLt4,2663
|
|
|
27
27
|
sqlmesh/core/scheduler.py,sha256=TB03rSvPyaPMRANOJq_O_cNXvu0fc5rVaDVC9olE5kg,34196
|
|
28
28
|
sqlmesh/core/schema_diff.py,sha256=mE28W51JUQz6q8inSOw2Cds84VPIqPxI6C2ed6xLmrg,29812
|
|
29
29
|
sqlmesh/core/schema_loader.py,sha256=lvrI9k7hr1P4X4E6t3U-KrcuvdQuw0UdNlN90P2s52w,3563
|
|
30
|
-
sqlmesh/core/selector.py,sha256=
|
|
30
|
+
sqlmesh/core/selector.py,sha256=wrjuHZsVwEgTOz14gTPe1h-LfYdUFqcFSk1I3t5qdew,12137
|
|
31
31
|
sqlmesh/core/signal.py,sha256=yVLXewYP6eH0vt-EwaIaI2WwHz6hWsVr-Kb2m4kP1FU,1353
|
|
32
32
|
sqlmesh/core/table_diff.py,sha256=AbTbmbV5aP-rqa-LT4A1MRnm5K-jmDi2F3N5cz-pFXQ,24838
|
|
33
33
|
sqlmesh/core/user.py,sha256=EJ6R4R1iK67n80vBoCCsidF56IR7xEYqiCEO-nrVMso,1660
|
|
@@ -54,7 +54,7 @@ sqlmesh/core/config/naming.py,sha256=KVGaxUgswoQajXR_cHFJvgkmEFcU1V182GkOH1SJxuE
|
|
|
54
54
|
sqlmesh/core/config/plan.py,sha256=Sql_bdO2H_vVrIYosf8rWOTRVoMURciX7mEcbMNFFdg,1389
|
|
55
55
|
sqlmesh/core/config/root.py,sha256=q4yD5S6ZoUvCaDNWkm47rGbvITp0JBfBUC37P1a9I9U,14735
|
|
56
56
|
sqlmesh/core/config/run.py,sha256=rIK0QnN_vArrwps2TXGVEbvao2AnGZgzXo7EliJa42E,852
|
|
57
|
-
sqlmesh/core/config/scheduler.py,sha256=
|
|
57
|
+
sqlmesh/core/config/scheduler.py,sha256=k3BVMpy5ZrC05ZlyE3vec8ZGfTjUjWyfsKZtYgflbyA,7029
|
|
58
58
|
sqlmesh/core/config/ui.py,sha256=jsO-S6_d9NkLZGG5pT4mgKgxMF34KzkDociZAMvCX3U,278
|
|
59
59
|
sqlmesh/core/engine_adapter/__init__.py,sha256=two_WTs4UnSNp-fscJh8vOunJq0Xi37EuDuMjKsKuNE,2281
|
|
60
60
|
sqlmesh/core/engine_adapter/_typing.py,sha256=BAM_U7Vsi0k37XHu_nNnu3whXxuTVDey_uZe3aelKYY,1033
|
|
@@ -154,14 +154,14 @@ sqlmesh/integrations/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
|
154
154
|
sqlmesh/integrations/github/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
155
|
sqlmesh/integrations/github/cicd/command.py,sha256=3toifUNTXpYvvOVXb_BiOAgna8CNOQfFEyUTFuDyK10,11515
|
|
156
156
|
sqlmesh/integrations/github/cicd/config.py,sha256=tRhMZaLf1p6AWXvi67n85Q-lptJNGt1Wk_Jr61ytpiM,2104
|
|
157
|
-
sqlmesh/integrations/github/cicd/controller.py,sha256=
|
|
157
|
+
sqlmesh/integrations/github/cicd/controller.py,sha256=FmOO93RF5auSU6aDU2beiP5LblLs38eAUYgHGWB9jYc,41666
|
|
158
158
|
sqlmesh/lsp/api.py,sha256=LJdECSaEZoPbu_Xl4KscVG-WLt7_g4dY-zKGO68dH14,2162
|
|
159
159
|
sqlmesh/lsp/completions.py,sha256=Uo8lUzPBeoB58Eu2642YoAtNI0pgIFWFSvwmuJALTv4,3583
|
|
160
160
|
sqlmesh/lsp/context.py,sha256=nCWg2uVH28-IJC2uDYuCbiXTh1lUFElSpNu4Q-fDWi4,2918
|
|
161
161
|
sqlmesh/lsp/custom.py,sha256=1YVcQz0y-4cdsvTdOQvlhUQXwOqPBWi3v_u1X2EqQxE,901
|
|
162
162
|
sqlmesh/lsp/description.py,sha256=4QIGC9ix8IzmWF6DVUNhY4m1Crk3sNQA6hZ1RbyqU78,827
|
|
163
163
|
sqlmesh/lsp/main.py,sha256=Lg_XHxXNScStf0aiOUptijZnBLOIjcmmhsFgM5w2rNo,27405
|
|
164
|
-
sqlmesh/lsp/reference.py,sha256
|
|
164
|
+
sqlmesh/lsp/reference.py,sha256=-HkMMzRzq4ike5mSkoWajanYNMAwhQhlPaqw62451ac,16887
|
|
165
165
|
sqlmesh/lsp/uri.py,sha256=mvSLbZGmMTHPpliThOtVWiFcHnfJzp1w39q9l-xD2SI,802
|
|
166
166
|
sqlmesh/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
167
167
|
sqlmesh/migrations/v0001_init.py,sha256=h8FwMYJj9_O8yGpk12guaSaGwX5A3we2GiKeHrXi15o,2048
|
|
@@ -270,7 +270,7 @@ sqlmesh/utils/pydantic.py,sha256=I898jAFqa3qU6lG2uPpRebVFncOUo8ZrLWM_R3K3DHU,116
|
|
|
270
270
|
sqlmesh/utils/rich.py,sha256=xNZyPCqEc4TAlJlsEthg-5eYUWpaizz0QjBzO7a1Yv4,1509
|
|
271
271
|
sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
|
|
272
272
|
sqlmesh/utils/yaml.py,sha256=np-WVcwmwsKghCgAj1OBBMsK1SXSRn4wR-H37cGiFr8,2282
|
|
273
|
-
sqlmesh-0.187.6.
|
|
273
|
+
sqlmesh-0.187.6.dev11.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
|
|
274
274
|
web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
275
275
|
web/client/dist/index.html,sha256=8vySM6CmjEU7pX2XGNeYyHR4PwjYGMsYT_RJn3p8Qt8,5472
|
|
276
276
|
web/client/dist/assets/Audits-C6gUfP0Y.js,sha256=fgwKzn8EkoySQW3vumBtag39Tf7tKZ1CAjrtgiV6nVg,1041
|
|
@@ -373,23 +373,23 @@ web/server/main.py,sha256=9PaDa8sigo1z0AxtI3sQ3fHmDqs6uXwP-_IvoMwkznw,3199
|
|
|
373
373
|
web/server/models.py,sha256=NUI2xqDcav20uuC2BZ9xDL2x0v16-gpVT1Sb-WHfAcg,15518
|
|
374
374
|
web/server/openapi.py,sha256=NOg__YQg7arVdajQv5CvOA5KLTQCfGZFvwnjARuM6iE,586
|
|
375
375
|
web/server/settings.py,sha256=PuWrOmn5LpJMBTymCMQreqMsL93tClTJ6wlcAZXjgCo,3755
|
|
376
|
-
web/server/utils.py,sha256=
|
|
376
|
+
web/server/utils.py,sha256=xqfzyqzsFSZu9Q9QHBCNvULUpAC6viInsznOJwcU6ig,3988
|
|
377
377
|
web/server/watcher.py,sha256=5biJ8gbHmGNUrooMFWRmw00XDVg0bMx6Hub571cs6TI,5246
|
|
378
378
|
web/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
379
379
|
web/server/api/endpoints/__init__.py,sha256=FcXl56-kPqbKgCZKOx0kjE50hn37q1m-nwOCxI9tRcc,932
|
|
380
|
-
web/server/api/endpoints/commands.py,sha256=
|
|
380
|
+
web/server/api/endpoints/commands.py,sha256=MpFiGihTNH074q06-7JyJ6x_kiV2C91Qq4pOWdlDkNg,8366
|
|
381
381
|
web/server/api/endpoints/directories.py,sha256=Aa8U4pTs3Saj5DnJ9TDnX9mZois-EXgpcBm5GpNNM_s,1822
|
|
382
382
|
web/server/api/endpoints/environments.py,sha256=g3YC6j4LLlG_wjJqn-Hrz78BWmgS7vhUhzaycsiez00,2124
|
|
383
383
|
web/server/api/endpoints/events.py,sha256=tjhOhGe9jt7L1mOLLapl5qTvicDRnP5lPZHSq9OnSVI,932
|
|
384
|
-
web/server/api/endpoints/files.py,sha256=
|
|
384
|
+
web/server/api/endpoints/files.py,sha256=H309MNDakLDBG12xtP1_J6URTSN3o2lq2rB9qQA5bRg,6731
|
|
385
385
|
web/server/api/endpoints/lineage.py,sha256=XU99RI-6Q9SidItGM5WLQMje8NhM5nZWHbtWxDwWeFE,6050
|
|
386
386
|
web/server/api/endpoints/meta.py,sha256=QKWWrHewGh5JS8mCSWXTKCIQwXw-TQfaT9tWt_SsNY4,1032
|
|
387
387
|
web/server/api/endpoints/models.py,sha256=ud-lRwriyI_OYg9tZchrBgeiXELiRTLNEodrafB7Ndk,4697
|
|
388
388
|
web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
|
|
389
389
|
web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
|
|
390
390
|
web/server/api/endpoints/table_diff.py,sha256=Wd5YxeKbZB7AkrDvqFgvV9ZQlnKYOF1n5W_w2EHE_Zw,2085
|
|
391
|
-
sqlmesh-0.187.6.
|
|
392
|
-
sqlmesh-0.187.6.
|
|
393
|
-
sqlmesh-0.187.6.
|
|
394
|
-
sqlmesh-0.187.6.
|
|
395
|
-
sqlmesh-0.187.6.
|
|
391
|
+
sqlmesh-0.187.6.dev11.dist-info/METADATA,sha256=Vb0ZE8jBYegqvGr34pW0i9vjhsldtVolMJkP2hdGE6I,26494
|
|
392
|
+
sqlmesh-0.187.6.dev11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
393
|
+
sqlmesh-0.187.6.dev11.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
|
|
394
|
+
sqlmesh-0.187.6.dev11.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
|
|
395
|
+
sqlmesh-0.187.6.dev11.dist-info/RECORD,,
|
|
@@ -159,7 +159,7 @@ async def test(
|
|
|
159
159
|
context.console.log_test_results(
|
|
160
160
|
result,
|
|
161
161
|
test_output.getvalue(),
|
|
162
|
-
context.
|
|
162
|
+
context.test_connection_config._engine_adapter.DIALECT,
|
|
163
163
|
)
|
|
164
164
|
|
|
165
165
|
def _test_path(test: ModelTest) -> t.Optional[str]:
|
|
@@ -60,7 +60,7 @@ async def write_file(
|
|
|
60
60
|
replace_file(settings.project_path / path, settings.project_path / path_or_new_path)
|
|
61
61
|
else:
|
|
62
62
|
full_path = settings.project_path / path
|
|
63
|
-
config = context.config_for_path(Path(path_or_new_path)) if context else None
|
|
63
|
+
config, _ = context.config_for_path(Path(path_or_new_path)) if context else (None, None)
|
|
64
64
|
if (
|
|
65
65
|
config
|
|
66
66
|
and config.ui.format_on_save
|
web/server/utils.py
CHANGED
|
@@ -64,11 +64,10 @@ def validate_path(path: str, settings: Settings = Depends(get_settings)) -> str:
|
|
|
64
64
|
if any(
|
|
65
65
|
full_path.match(pattern)
|
|
66
66
|
for pattern in (
|
|
67
|
-
context.config_for_path(Path(path)).ignore_patterns if context else c.IGNORE_PATTERNS
|
|
67
|
+
context.config_for_path(Path(path))[0].ignore_patterns if context else c.IGNORE_PATTERNS
|
|
68
68
|
)
|
|
69
69
|
):
|
|
70
70
|
raise HTTPException(status_code=HTTP_404_NOT_FOUND)
|
|
71
|
-
|
|
72
71
|
return path
|
|
73
72
|
|
|
74
73
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|