Skip to content

Commit a412110

Browse files
authored
chore: make _path optional and more representative (#4303)
1 parent 701efe7 commit a412110

File tree

17 files changed

+85
-50
lines changed

17 files changed

+85
-50
lines changed

sqlmesh/core/context.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -948,10 +948,12 @@ def config_for_path(self, path: Path) -> t.Tuple[Config, Path]:
948948

949949
def config_for_node(self, node: str | Model | Audit) -> Config:
950950
if isinstance(node, str):
951-
return self.config_for_path(self.get_snapshot(node, raise_if_missing=True).node._path)[
952-
0
953-
] # type: ignore
954-
return self.config_for_path(node._path)[0] # type: ignore
951+
path = self.get_snapshot(node, raise_if_missing=True).node._path
952+
else:
953+
path = node._path
954+
if path is None:
955+
return self.config
956+
return self.config_for_path(path)[0] # type: ignore
955957

956958
@property
957959
def models(self) -> MappingProxyType[str, Model]:

sqlmesh/core/macros.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def __init__(
171171
resolve_tables: t.Optional[t.Callable[[exp.Expression], exp.Expression]] = None,
172172
snapshots: t.Optional[t.Dict[str, Snapshot]] = None,
173173
default_catalog: t.Optional[str] = None,
174-
path: Path = Path(),
174+
path: t.Optional[Path] = None,
175175
environment_naming_info: t.Optional[EnvironmentNamingInfo] = None,
176176
model_fqn: t.Optional[str] = None,
177177
):
@@ -1384,7 +1384,7 @@ def normalize_macro_name(name: str) -> str:
13841384
def call_macro(
13851385
func: t.Callable,
13861386
dialect: DialectType,
1387-
path: Path,
1387+
path: t.Optional[Path],
13881388
provided_args: t.Tuple[t.Any, ...],
13891389
provided_kwargs: t.Dict[str, t.Any],
13901390
**optional_kwargs: t.Any,
@@ -1431,7 +1431,7 @@ def _coerce(
14311431
expr: t.Any,
14321432
typ: t.Any,
14331433
dialect: DialectType,
1434-
path: Path,
1434+
path: t.Optional[Path] = None,
14351435
strict: bool = False,
14361436
) -> t.Any:
14371437
"""Coerces the given expression to the specified type on a best-effort basis."""

sqlmesh/core/model/definition.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,8 @@ def is_seed(self) -> bool:
16481648
def seed_path(self) -> Path:
16491649
seed_path = Path(self.kind.path)
16501650
if not seed_path.is_absolute():
1651+
if self._path is None:
1652+
raise SQLMeshError(f"Seed model '{self.name}' has no path")
16511653
return self._path.parent / seed_path
16521654
return seed_path
16531655

@@ -2022,7 +2024,7 @@ def load_sql_based_model(
20222024
expressions: t.List[exp.Expression],
20232025
*,
20242026
defaults: t.Optional[t.Dict[str, t.Any]] = None,
2025-
path: Path = Path(),
2027+
path: t.Optional[Path] = None,
20262028
module_path: Path = Path(),
20272029
time_column_format: str = c.DEFAULT_TIME_COLUMN_FORMAT,
20282030
macros: t.Optional[MacroRegistry] = None,
@@ -2173,6 +2175,8 @@ def load_sql_based_model(
21732175
# The name of the model will be inferred from its path relative to `models/`, if it's not explicitly specified
21742176
name = meta_fields.pop("name", "")
21752177
if not name and infer_names:
2178+
if path is None:
2179+
raise ValueError(f"Model {name} must have a name")
21762180
name = get_model_name(path)
21772181

21782182
if not name:
@@ -2251,7 +2255,7 @@ def create_seed_model(
22512255
name: TableName,
22522256
seed_kind: SeedKind,
22532257
*,
2254-
path: Path = Path(),
2258+
path: t.Optional[Path] = None,
22552259
module_path: Path = Path(),
22562260
**kwargs: t.Any,
22572261
) -> Model:
@@ -2270,7 +2274,12 @@ def create_seed_model(
22702274
seed_path = module_path.joinpath(*subdirs)
22712275
seed_kind.path = str(seed_path)
22722276
elif not seed_path.is_absolute():
2273-
seed_path = path / seed_path if path.is_dir() else path.parent / seed_path
2277+
if path is None:
2278+
seed_path = seed_path
2279+
elif path.is_dir():
2280+
seed_path = path / seed_path
2281+
else:
2282+
seed_path = path.parent / seed_path
22742283

22752284
seed = create_seed(seed_path)
22762285

@@ -2405,7 +2414,7 @@ def _create_model(
24052414
name: TableName,
24062415
*,
24072416
defaults: t.Optional[t.Dict[str, t.Any]] = None,
2408-
path: Path = Path(),
2417+
path: t.Optional[Path] = None,
24092418
time_column_format: str = c.DEFAULT_TIME_COLUMN_FORMAT,
24102419
jinja_macros: t.Optional[JinjaMacroRegistry] = None,
24112420
jinja_macro_references: t.Optional[t.Set[MacroReference]] = None,
@@ -2593,7 +2602,7 @@ def _create_model(
25932602

25942603
def _split_sql_model_statements(
25952604
expressions: t.List[exp.Expression],
2596-
path: Path,
2605+
path: t.Optional[Path],
25972606
dialect: t.Optional[str] = None,
25982607
) -> t.Tuple[
25992608
t.Optional[exp.Expression],
@@ -2714,7 +2723,7 @@ def _refs_to_sql(values: t.Any) -> exp.Expression:
27142723
def render_meta_fields(
27152724
fields: t.Dict[str, t.Any],
27162725
module_path: Path,
2717-
path: Path,
2726+
path: t.Optional[Path],
27182727
jinja_macros: t.Optional[JinjaMacroRegistry],
27192728
macros: t.Optional[MacroRegistry],
27202729
dialect: DialectType,
@@ -2801,7 +2810,7 @@ def render_field_value(value: t.Any) -> t.Any:
28012810
def render_model_defaults(
28022811
defaults: t.Dict[str, t.Any],
28032812
module_path: Path,
2804-
path: Path,
2813+
path: t.Optional[Path],
28052814
jinja_macros: t.Optional[JinjaMacroRegistry],
28062815
macros: t.Optional[MacroRegistry],
28072816
dialect: DialectType,
@@ -2851,7 +2860,7 @@ def parse_defaults_properties(
28512860
def render_expression(
28522861
expression: exp.Expression,
28532862
module_path: Path,
2854-
path: Path,
2863+
path: t.Optional[Path],
28552864
jinja_macros: t.Optional[JinjaMacroRegistry] = None,
28562865
macros: t.Optional[MacroRegistry] = None,
28572866
dialect: DialectType = None,

sqlmesh/core/node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class _Node(PydanticModel):
199199
interval_unit_: t.Optional[IntervalUnit] = Field(alias="interval_unit", default=None)
200200
tags: t.List[str] = []
201201
stamp: t.Optional[str] = None
202-
_path: Path = Path()
202+
_path: t.Optional[Path] = None
203203
_data_hash: t.Optional[str] = None
204204
_metadata_hash: t.Optional[str] = None
205205

sqlmesh/core/renderer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __init__(
4343
expression: exp.Expression,
4444
dialect: DialectType,
4545
macro_definitions: t.List[d.MacroDef],
46-
path: Path = Path(),
46+
path: t.Optional[Path] = None,
4747
jinja_macro_registry: t.Optional[JinjaMacroRegistry] = None,
4848
python_env: t.Optional[t.Dict[str, Executable]] = None,
4949
only_execution_time: bool = False,

sqlmesh/core/snapshot/definition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2198,7 +2198,7 @@ def check_ready_intervals(
21982198
context: ExecutionContext,
21992199
python_env: t.Dict[str, Executable],
22002200
dialect: DialectType = None,
2201-
path: Path = Path(),
2201+
path: t.Optional[Path] = None,
22022202
kwargs: t.Optional[t.Dict] = None,
22032203
) -> Intervals:
22042204
checked_intervals: Intervals = []

sqlmesh/dbt/converter/convert.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ def _convert_models(
207207

208208
if model.kind.is_seed:
209209
# this will produce the original seed file, eg "items.csv"
210+
if model._path is None:
211+
raise ValueError(f"Unhandled model path for model {model_name}")
210212
seed_filename = model._path.relative_to(input_paths.seeds)
211213

212214
# seed definition - rename "items.csv" -> "items.sql"
@@ -219,6 +221,8 @@ def _convert_models(
219221
assert isinstance(model.kind, SeedKind)
220222
model.kind.path = str(Path("../seeds", seed_filename))
221223
else:
224+
if model._path is None:
225+
raise ValueError(f"Unhandled model path for model {model_name}")
222226
if input_paths.models in model._path.parents:
223227
model_filename = model._path.relative_to(input_paths.models)
224228
elif input_paths.snapshots in model._path.parents:
@@ -290,6 +294,8 @@ def _convert_standalone_audits(
290294

291295
audit_definition_string = ";\n".join(stringified)
292296

297+
if audit._path is None:
298+
continue
293299
audit_filename = audit._path.relative_to(input_paths.tests)
294300
audit_output_path = output_paths.audits / audit_filename
295301
audit_output_path.write_text(audit_definition_string)

sqlmesh/lsp/reference.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ def get_model_definitions_for_a_path(
164164
else:
165165
return []
166166

167+
if file_path is None:
168+
return []
169+
167170
# Find all possible references
168171
references: t.List[Reference] = []
169172

@@ -246,6 +249,8 @@ def get_model_definitions_for_a_path(
246249
if referenced_model is None:
247250
continue
248251
referenced_model_path = referenced_model._path
252+
if referenced_model_path is None:
253+
continue
249254
# Check whether the path exists
250255
if not referenced_model_path.is_file():
251256
continue
@@ -372,6 +377,9 @@ def get_macro_definitions_for_a_path(
372377
else:
373378
return []
374379

380+
if file_path is None:
381+
return []
382+
375383
references = []
376384
_, config_path = lsp_context.context.config_for_path(
377385
file_path,

sqlmesh/magics.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@ def model(self, context: Context, line: str, sql: t.Optional[str] = None) -> Non
287287
if loaded.name == args.model:
288288
model = loaded
289289
else:
290-
with open(model._path, "r", encoding="utf-8") as file:
291-
expressions = parse(file.read(), default_dialect=config.dialect)
290+
if model._path:
291+
with open(model._path, "r", encoding="utf-8") as file:
292+
expressions = parse(file.read(), default_dialect=config.dialect)
292293

293294
formatted = format_model_expressions(
294295
expressions,
@@ -307,8 +308,9 @@ def model(self, context: Context, line: str, sql: t.Optional[str] = None) -> Non
307308
replace=True,
308309
)
309310

310-
with open(model._path, "w", encoding="utf-8") as file:
311-
file.write(formatted)
311+
if model._path:
312+
with open(model._path, "w", encoding="utf-8") as file:
313+
file.write(formatted)
312314

313315
if sql:
314316
context.console.log_success(f"Model `{args.model}` updated")

tests/core/test_model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,7 +3290,7 @@ def runtime_macro(evaluator, **kwargs) -> None:
32903290
model = load_sql_based_model(expressions)
32913291
with pytest.raises(
32923292
ConfigError,
3293-
match=r"Dependencies must be provided explicitly for models that can be rendered only at runtime at.*",
3293+
match=r"Dependencies must be provided explicitly for models that can be rendered only at runtime",
32943294
):
32953295
model.validate_definition()
32963296

@@ -8324,7 +8324,7 @@ def test_physical_version():
83248324

83258325
with pytest.raises(
83268326
ConfigError,
8327-
match=r"Pinning a physical version is only supported for forward only models at.*",
8327+
match=r"Pinning a physical version is only supported for forward only models( at.*)?",
83288328
):
83298329
load_sql_based_model(
83308330
d.parse(

0 commit comments

Comments
 (0)