Skip to content

Commit 40ec146

Browse files
authored
Merge branch 'main' into fabric_alter_table_no_op
2 parents 7cdbf81 + 15d2cd0 commit 40ec146

File tree

130 files changed

+2611
-1066
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+2611
-1066
lines changed

pnpm-lock.yaml

Lines changed: 19 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies = [
2424
"requests",
2525
"rich[jupyter]",
2626
"ruamel.yaml",
27-
"sqlglot[rs]~=27.24.2",
27+
"sqlglot[rs]~=27.28.0",
2828
"tenacity",
2929
"time-machine",
3030
"json-stream"

sqlmesh/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,23 @@ def configure_logging(
188188
write_to_file: bool = True,
189189
log_file_dir: t.Optional[t.Union[str, Path]] = None,
190190
ignore_warnings: bool = False,
191+
log_level: t.Optional[t.Union[str, int]] = None,
191192
) -> None:
192193
# Remove noisy grpc logs that are not useful for users
193194
os.environ["GRPC_VERBOSITY"] = os.environ.get("GRPC_VERBOSITY", "NONE")
194195

195196
logger = logging.getLogger()
196197
debug = force_debug or debug_mode_enabled()
197198

198-
# base logger needs to be the lowest level that we plan to log
199-
level = logging.DEBUG if debug else logging.INFO
199+
if log_level is not None:
200+
if isinstance(log_level, str):
201+
level = logging._nameToLevel.get(log_level.upper()) or logging.INFO
202+
else:
203+
level = log_level
204+
else:
205+
# base logger needs to be the lowest level that we plan to log
206+
level = logging.DEBUG if debug else logging.INFO
207+
200208
logger.setLevel(level)
201209

202210
if debug:

sqlmesh/core/config/connection.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"clickhouse",
5959
}
6060
MOTHERDUCK_TOKEN_REGEX = re.compile(r"(\?|\&)(motherduck_token=)(\S*)")
61+
PASSWORD_REGEX = re.compile(r"(password=)(\S+)")
6162

6263

6364
def _get_engine_import_validator(
@@ -479,13 +480,13 @@ def create_engine_adapter(
479480
adapter = BaseDuckDBConnectionConfig._data_file_to_adapter.get(key)
480481
if adapter is not None:
481482
logger.info(
482-
f"Using existing DuckDB adapter due to overlapping data file: {self._mask_motherduck_token(key)}"
483+
f"Using existing DuckDB adapter due to overlapping data file: {self._mask_sensitive_data(key)}"
483484
)
484485
return adapter
485486

486487
if data_files:
487488
masked_files = {
488-
self._mask_motherduck_token(file if isinstance(file, str) else file.path)
489+
self._mask_sensitive_data(file if isinstance(file, str) else file.path)
489490
for file in data_files
490491
}
491492
logger.info(f"Creating new DuckDB adapter for data files: {masked_files}")
@@ -507,10 +508,14 @@ def get_catalog(self) -> t.Optional[str]:
507508
return list(self.catalogs)[0]
508509
return None
509510

510-
def _mask_motherduck_token(self, string: str) -> str:
511-
return MOTHERDUCK_TOKEN_REGEX.sub(
512-
lambda m: f"{m.group(1)}{m.group(2)}{'*' * len(m.group(3))}", string
511+
def _mask_sensitive_data(self, string: str) -> str:
512+
# Mask MotherDuck tokens with fixed number of asterisks
513+
result = MOTHERDUCK_TOKEN_REGEX.sub(
514+
lambda m: f"{m.group(1)}{m.group(2)}{'*' * 8 if m.group(3) else ''}", string
513515
)
516+
# Mask PostgreSQL/MySQL passwords with fixed number of asterisks
517+
result = PASSWORD_REGEX.sub(lambda m: f"{m.group(1)}{'*' * 8}", result)
518+
return result
514519

515520

516521
class MotherDuckConnectionConfig(BaseDuckDBConnectionConfig):

sqlmesh/core/config/loader.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ def load_config_from_paths(
178178

179179
dbt_python_config = sqlmesh_config(
180180
project_root=dbt_project_file.parent,
181+
profiles_dir=kwargs.pop("profiles_dir", None),
181182
dbt_profile_name=kwargs.pop("profile", None),
182183
dbt_target_name=kwargs.pop("target", None),
183184
variables=variables,

sqlmesh/core/context.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
)
140140
from sqlmesh.utils.config import print_config
141141
from sqlmesh.utils.jinja import JinjaMacroRegistry
142+
from sqlmesh.utils.windows import IS_WINDOWS, fix_windows_path
142143

143144
if t.TYPE_CHECKING:
144145
import pandas as pd
@@ -153,6 +154,8 @@
153154
)
154155
from sqlmesh.core.snapshot import Node
155156

157+
from sqlmesh.core.snapshot.definition import Intervals
158+
156159
ModelOrSnapshot = t.Union[str, Model, Snapshot]
157160
NodeOrSnapshot = t.Union[str, Model, StandaloneAudit, Snapshot]
158161

@@ -275,6 +278,7 @@ def __init__(
275278
default_dialect: t.Optional[str] = None,
276279
default_catalog: t.Optional[str] = None,
277280
is_restatement: t.Optional[bool] = None,
281+
parent_intervals: t.Optional[Intervals] = None,
278282
variables: t.Optional[t.Dict[str, t.Any]] = None,
279283
blueprint_variables: t.Optional[t.Dict[str, t.Any]] = None,
280284
):
@@ -286,6 +290,7 @@ def __init__(
286290
self._variables = variables or {}
287291
self._blueprint_variables = blueprint_variables or {}
288292
self._is_restatement = is_restatement
293+
self._parent_intervals = parent_intervals
289294

290295
@property
291296
def default_dialect(self) -> t.Optional[str]:
@@ -314,6 +319,10 @@ def gateway(self) -> t.Optional[str]:
314319
def is_restatement(self) -> t.Optional[bool]:
315320
return self._is_restatement
316321

322+
@property
323+
def parent_intervals(self) -> t.Optional[Intervals]:
324+
return self._parent_intervals
325+
317326
def var(self, var_name: str, default: t.Optional[t.Any] = None) -> t.Optional[t.Any]:
318327
"""Returns a variable value."""
319328
return self._variables.get(var_name.lower(), default)
@@ -2590,12 +2599,15 @@ def table_name(
25902599
)
25912600

25922601
def clear_caches(self) -> None:
2593-
for path in self.configs:
2594-
cache_path = path / c.CACHE
2595-
if cache_path.exists():
2596-
rmtree(cache_path)
2597-
if self.cache_dir.exists():
2598-
rmtree(self.cache_dir)
2602+
paths_to_remove = [path / c.CACHE for path in self.configs]
2603+
paths_to_remove.append(self.cache_dir)
2604+
2605+
if IS_WINDOWS:
2606+
paths_to_remove = [fix_windows_path(path) for path in paths_to_remove]
2607+
2608+
for path in paths_to_remove:
2609+
if path.exists():
2610+
rmtree(path)
25992611

26002612
if isinstance(self._state_sync, CachingStateSync):
26012613
self._state_sync.clear_cache()

0 commit comments

Comments
 (0)