Skip to content

Commit b7be02d

Browse files
committed
chore: make path optional
- more correctly represent path being optional
1 parent a9ef531 commit b7be02d

12 files changed

Lines changed: 60 additions & 29 deletions

File tree

sqlmesh/core/context.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -929,10 +929,15 @@ def config_for_path(self, path: Path) -> t.Tuple[Config, Path]:
929929

930930
def config_for_node(self, node: str | Model | Audit) -> Config:
931931
if isinstance(node, str):
932-
return self.config_for_path(self.get_snapshot(node, raise_if_missing=True).node._path)[
933-
0
934-
] # type: ignore
935-
return self.config_for_path(node._path)[0] # type: ignore
932+
path = self.get_snapshot(node, raise_if_missing=True).node._path
933+
if path is None:
934+
return self.config
935+
config = self.config_for_path(path)
936+
return config[0]
937+
path = node._path
938+
if path is None:
939+
return self.config
940+
return self.config_for_path(path)[0] # type: ignore
936941

937942
@property
938943
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
@@ -1638,6 +1638,8 @@ def is_seed(self) -> bool:
16381638
def seed_path(self) -> Path:
16391639
seed_path = Path(self.kind.path)
16401640
if not seed_path.is_absolute():
1641+
if self._path is None:
1642+
raise SQLMeshError(f"Seed model '{self.name}' has no path")
16411643
return self._path.parent / seed_path
16421644
return seed_path
16431645

@@ -2003,7 +2005,7 @@ def load_sql_based_model(
20032005
expressions: t.List[exp.Expression],
20042006
*,
20052007
defaults: t.Optional[t.Dict[str, t.Any]] = None,
2006-
path: Path = Path(),
2008+
path: t.Optional[Path] = None,
20072009
module_path: Path = Path(),
20082010
time_column_format: str = c.DEFAULT_TIME_COLUMN_FORMAT,
20092011
macros: t.Optional[MacroRegistry] = None,
@@ -2153,6 +2155,8 @@ def load_sql_based_model(
21532155
# The name of the model will be inferred from its path relative to `models/`, if it's not explicitly specified
21542156
name = meta_fields.pop("name", "")
21552157
if not name and infer_names:
2158+
if path is None:
2159+
raise ValueError("Model must have a name", path)
21562160
name = get_model_name(path)
21572161

21582162
if not name:
@@ -2230,7 +2234,7 @@ def create_seed_model(
22302234
name: TableName,
22312235
seed_kind: SeedKind,
22322236
*,
2233-
path: Path = Path(),
2237+
path: t.Optional[Path] = None,
22342238
module_path: Path = Path(),
22352239
**kwargs: t.Any,
22362240
) -> Model:
@@ -2249,7 +2253,12 @@ def create_seed_model(
22492253
seed_path = module_path.joinpath(*subdirs)
22502254
seed_kind.path = str(seed_path)
22512255
elif not seed_path.is_absolute():
2252-
seed_path = path / seed_path if path.is_dir() else path.parent / seed_path
2256+
if path is None:
2257+
seed_path = seed_path
2258+
elif path.is_dir():
2259+
seed_path = path / seed_path
2260+
else:
2261+
seed_path = path.parent / seed_path
22532262

22542263
seed = create_seed(seed_path)
22552264

@@ -2384,7 +2393,7 @@ def _create_model(
23842393
name: TableName,
23852394
*,
23862395
defaults: t.Optional[t.Dict[str, t.Any]] = None,
2387-
path: Path = Path(),
2396+
path: t.Optional[Path] = None,
23882397
time_column_format: str = c.DEFAULT_TIME_COLUMN_FORMAT,
23892398
jinja_macros: t.Optional[JinjaMacroRegistry] = None,
23902399
jinja_macro_references: t.Optional[t.Set[MacroReference]] = None,
@@ -2553,7 +2562,7 @@ def _create_model(
25532562

25542563
def _split_sql_model_statements(
25552564
expressions: t.List[exp.Expression],
2556-
path: Path,
2565+
path: t.Optional[Path],
25572566
dialect: t.Optional[str] = None,
25582567
) -> t.Tuple[
25592568
t.Optional[exp.Expression],
@@ -2674,7 +2683,7 @@ def _refs_to_sql(values: t.Any) -> exp.Expression:
26742683
def render_meta_fields(
26752684
fields: t.Dict[str, t.Any],
26762685
module_path: Path,
2677-
path: Path,
2686+
path: t.Optional[Path],
26782687
jinja_macros: t.Optional[JinjaMacroRegistry],
26792688
macros: t.Optional[MacroRegistry],
26802689
dialect: DialectType,
@@ -2758,7 +2767,7 @@ def render_field_value(value: t.Any) -> t.Any:
27582767
def render_model_defaults(
27592768
defaults: t.Dict[str, t.Any],
27602769
module_path: Path,
2761-
path: Path,
2770+
path: t.Optional[Path],
27622771
jinja_macros: t.Optional[JinjaMacroRegistry],
27632772
macros: t.Optional[MacroRegistry],
27642773
dialect: DialectType,
@@ -2808,7 +2817,7 @@ def parse_defaults_properties(
28082817
def render_expression(
28092818
expression: exp.Expression,
28102819
module_path: Path,
2811-
path: Path,
2820+
path: t.Optional[Path],
28122821
jinja_macros: t.Optional[JinjaMacroRegistry] = None,
28132822
macros: t.Optional[MacroRegistry] = None,
28142823
dialect: DialectType = None,

sqlmesh/core/node.py

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

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
@@ -2168,7 +2168,7 @@ def _check_ready_intervals(
21682168
context: ExecutionContext,
21692169
python_env: t.Dict[str, Executable],
21702170
dialect: DialectType = None,
2171-
path: Path = Path(),
2171+
path: t.Optional[Path] = None,
21722172
kwargs: t.Optional[t.Dict] = None,
21732173
) -> Intervals:
21742174
checked_intervals: Intervals = []

sqlmesh/lsp/reference.py

Lines changed: 9 additions & 1 deletion
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

@@ -235,8 +238,10 @@ def get_model_definitions_for_a_path(
235238
if referenced_model is None:
236239
continue
237240
referenced_model_path = referenced_model._path
241+
if referenced_model_path is None:
242+
continue
238243
# Check whether the path exists
239-
if not referenced_model_path.is_file():
244+
if referenced_model_path is None or not referenced_model_path.is_file():
240245
continue
241246
referenced_model_uri = URI.from_path(referenced_model_path)
242247

@@ -336,6 +341,9 @@ def get_macro_definitions_for_a_path(
336341
else:
337342
return []
338343

344+
if file_path is None:
345+
return []
346+
339347
references = []
340348
_, config_path = lsp_context.context.config_for_path(
341349
file_path,

sqlmesh/magics.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ def model(self, context: Context, line: str, sql: t.Optional[str] = None) -> Non
235235
if loaded.name == args.model:
236236
model = loaded
237237
else:
238-
with open(model._path, "r", encoding="utf-8") as file:
239-
expressions = parse(file.read(), default_dialect=config.dialect)
238+
if model._path:
239+
with open(model._path, "r", encoding="utf-8") as file:
240+
expressions = parse(file.read(), default_dialect=config.dialect)
240241

241242
formatted = format_model_expressions(
242243
expressions,
@@ -255,8 +256,9 @@ def model(self, context: Context, line: str, sql: t.Optional[str] = None) -> Non
255256
replace=True,
256257
)
257258

258-
with open(model._path, "w", encoding="utf-8") as file:
259-
file.write(formatted)
259+
if model._path:
260+
with open(model._path, "w", encoding="utf-8") as file:
261+
file.write(formatted)
260262

261263
if sql:
262264
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
@@ -3282,7 +3282,7 @@ def runtime_macro(evaluator, **kwargs) -> None:
32823282
model = load_sql_based_model(expressions)
32833283
with pytest.raises(
32843284
ConfigError,
3285-
match=r"Dependencies must be provided explicitly for models that can be rendered only at runtime at.*",
3285+
match=r"Dependencies must be provided explicitly for models that can be rendered only at runtime",
32863286
):
32873287
model.validate_definition()
32883288

@@ -8014,7 +8014,7 @@ def test_physical_version():
80148014

80158015
with pytest.raises(
80168016
ConfigError,
8017-
match=r"Pinning a physical version is only supported for forward only models at.*",
8017+
match=r"Pinning a physical version is only supported for forward only models( at.*)?",
80188018
):
80198019
load_sql_based_model(
80208020
d.parse(

tests/integrations/github/cicd/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _make_function(username: str, state: str, **kwargs) -> PullRequestReview:
4949
github_client.requester,
5050
{},
5151
{
52-
# Name is whatever they provide in their GitHub profile or login as fallback. Always use login.
52+
# Name is whatever they provide in their GitHub profile or login as a fallback. Always use login.
5353
"user": AttributeDict(name="Unrelated", login=username),
5454
"state": state,
5555
**kwargs,

0 commit comments

Comments
 (0)