23
23
from sqlmesh .core .metric import Metric , MetricMeta , expand_metrics , load_metric_ddl
24
24
from sqlmesh .core .model import (
25
25
Model ,
26
- ExternalModel ,
27
26
ModelCache ,
28
27
SeedModel ,
29
28
create_external_model ,
@@ -59,6 +58,14 @@ class LoadedProject:
59
58
user_rules : RuleSet
60
59
61
60
61
+ class CacheBase (abc .ABC ):
62
+ @abc .abstractmethod
63
+ def get_or_load_models (
64
+ self , target_path : Path , loader : t .Callable [[], t .List [Model ]]
65
+ ) -> t .List [Model ]:
66
+ """Get or load all models from cache."""
67
+
68
+
62
69
class Loader (abc .ABC ):
63
70
"""Abstract base class to load macros and models for a context"""
64
71
@@ -192,6 +199,7 @@ def _load_metrics(self) -> UniqueKeyDict[str, MetricMeta]:
192
199
def _load_external_models (
193
200
self ,
194
201
audits : UniqueKeyDict [str , ModelAudit ],
202
+ cache : CacheBase ,
195
203
gateway : t .Optional [str ] = None ,
196
204
) -> UniqueKeyDict [str , Model ]:
197
205
models : UniqueKeyDict [str , Model ] = UniqueKeyDict ("models" )
@@ -208,32 +216,39 @@ def _load_external_models(
208
216
if external_models_path .exists () and external_models_path .is_dir ():
209
217
paths_to_load .extend (self ._glob_paths (external_models_path , extension = ".yaml" ))
210
218
219
+ def _load () -> t .List [Model ]:
220
+ try :
221
+ with open (path , "r" , encoding = "utf-8" ) as file :
222
+ return [
223
+ create_external_model (
224
+ defaults = self .config .model_defaults .dict (),
225
+ path = path ,
226
+ project = self .config .project ,
227
+ audit_definitions = audits ,
228
+ ** {
229
+ "dialect" : self .config .model_defaults .dialect ,
230
+ "default_catalog" : self .context .default_catalog ,
231
+ ** row ,
232
+ },
233
+ )
234
+ for row in YAML ().load (file .read ())
235
+ ]
236
+ except Exception as ex :
237
+ raise ConfigError (f"Failed to load model definition at '{ path } '.\n { ex } " )
238
+
211
239
for path in paths_to_load :
212
240
self ._track_file (path )
213
241
214
- with open (path , "r" , encoding = "utf-8" ) as file :
215
- external_models : t .List [ExternalModel ] = []
216
- for row in YAML ().load (file .read ()):
217
- model = create_external_model (
218
- defaults = self .config .model_defaults .dict (),
219
- path = path ,
220
- project = self .config .project ,
221
- audit_definitions = audits ,
222
- ** {
223
- "dialect" : self .config .model_defaults .dialect ,
224
- "default_catalog" : self .context .default_catalog ,
225
- ** row ,
226
- },
227
- )
228
- external_models .append (model )
229
-
230
- # external models with no explicit gateway defined form the base set
231
- for model in (e for e in external_models if e .gateway is None ):
242
+ external_models = cache .get_or_load_models (path , _load )
243
+ # external models with no explicit gateway defined form the base set
244
+ for model in external_models :
245
+ if model .gateway is None :
232
246
models [model .fqn ] = model
233
247
234
- # however, if there is a gateway defined, gateway-specific models take precedence
235
- if gateway :
236
- for model in (e for e in external_models if e .gateway == gateway ):
248
+ # however, if there is a gateway defined, gateway-specific models take precedence
249
+ if gateway :
250
+ for model in external_models :
251
+ if model .gateway == gateway :
237
252
models .update ({model .fqn : model })
238
253
239
254
return models
@@ -396,8 +411,9 @@ def _load_models(
396
411
Loads all of the models within the model directory with their associated
397
412
audits into a Dict and creates the dag
398
413
"""
399
- sql_models = self ._load_sql_models (macros , jinja_macros , audits , signals )
400
- external_models = self ._load_external_models (audits , gateway )
414
+ cache = SqlMeshLoader ._Cache (self , self .config_path )
415
+ sql_models = self ._load_sql_models (macros , jinja_macros , audits , signals , cache )
416
+ external_models = self ._load_external_models (audits , cache , gateway )
401
417
python_models = self ._load_python_models (macros , jinja_macros , audits , signals )
402
418
403
419
all_model_names = list (sql_models ) + list (external_models ) + list (python_models )
@@ -413,10 +429,10 @@ def _load_sql_models(
413
429
jinja_macros : JinjaMacroRegistry ,
414
430
audits : UniqueKeyDict [str , ModelAudit ],
415
431
signals : UniqueKeyDict [str , signal ],
432
+ cache : CacheBase ,
416
433
) -> UniqueKeyDict [str , Model ]:
417
434
"""Loads the sql models into a Dict"""
418
435
models : UniqueKeyDict [str , Model ] = UniqueKeyDict ("models" )
419
- cache = SqlMeshLoader ._Cache (self , self .config_path )
420
436
421
437
for path in self ._glob_paths (
422
438
self .config_path / c .MODELS ,
@@ -662,7 +678,7 @@ def _load_linting_rules(self) -> RuleSet:
662
678
663
679
return RuleSet (user_rules .values ())
664
680
665
- class _Cache :
681
+ class _Cache ( CacheBase ) :
666
682
def __init__ (self , loader : SqlMeshLoader , config_path : Path ):
667
683
self ._loader = loader
668
684
self .config_path = config_path
0 commit comments