Skip to content

Commit 0039108

Browse files
committed
Merge branch 'main' into add-linter-rule
2 parents 88235cc + 2dd01a4 commit 0039108

File tree

216 files changed

+8692
-1853
lines changed

Some content is hidden

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

216 files changed

+8692
-1853
lines changed

.circleci/continue_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ jobs:
148148
command: ./.circleci/test_migration.sh sushi "--gateway duckdb_persistent"
149149
- run:
150150
name: Run the migration test - sushi_dbt
151-
command: ./.circleci/test_migration.sh sushi_dbt "--config migration_test_config"
151+
command: ./.circleci/test_migration.sh sushi_dbt "--config migration_test_config"
152152

153153
ui_style:
154154
docker:

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ dmypy.json
138138
*~
139139
*#
140140

141+
# Vim
142+
*.swp
143+
*.swo
144+
.null-ls*
145+
146+
141147
*.duckdb
142148
*.duckdb.wal
143149

@@ -158,3 +164,4 @@ spark-warehouse/
158164

159165
# claude
160166
.claude/
167+

docs/reference/configuration.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,10 @@ Formatting settings for the `sqlmesh format` command and UI.
125125

126126
Configuration for the `sqlmesh janitor` command.
127127

128-
| Option | Description | Type | Required |
129-
|--------------------------|----------------------------------------------------------------------------------------------------------------------------|:-------:|:--------:|
130-
| `warn_on_delete_failure` | Whether to warn instead of erroring if the janitor fails to delete the expired environment schema / views (Default: False) | boolean | N |
128+
| Option | Description | Type | Required |
129+
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------|:-------:|:--------:|
130+
| `warn_on_delete_failure` | Whether to warn instead of erroring if the janitor fails to delete the expired environment schema / views (Default: False) | boolean | N |
131+
| `expired_snapshots_batch_size` | Maximum number of expired snapshots to clean in a single batch (Default: 200) | int | N |
131132

132133

133134
## UI

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.20.0",
27+
"sqlglot[rs]~=27.24.2",
2828
"tenacity",
2929
"time-machine",
3030
"json-stream"

sqlmesh/__init__.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ def is_cicd_environment() -> bool:
126126

127127

128128
def is_interactive_environment() -> bool:
129+
if sys.stdin is None or sys.stdout is None:
130+
return False
129131
return sys.stdin.isatty() and sys.stdout.isatty()
130132

131133

@@ -186,15 +188,23 @@ def configure_logging(
186188
write_to_file: bool = True,
187189
log_file_dir: t.Optional[t.Union[str, Path]] = None,
188190
ignore_warnings: bool = False,
191+
log_level: t.Optional[t.Union[str, int]] = None,
189192
) -> None:
190193
# Remove noisy grpc logs that are not useful for users
191194
os.environ["GRPC_VERBOSITY"] = os.environ.get("GRPC_VERBOSITY", "NONE")
192195

193196
logger = logging.getLogger()
194197
debug = force_debug or debug_mode_enabled()
195198

196-
# base logger needs to be the lowest level that we plan to log
197-
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+
198208
logger.setLevel(level)
199209

200210
if debug:

sqlmesh/cli/project_init.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,15 @@ def _gen_config(
116116
- invalidselectstarexpansion
117117
- noambiguousprojections
118118
""",
119-
ProjectTemplate.DBT: f"""# --- Virtual Data Environment Mode ---
119+
ProjectTemplate.DBT: f"""# --- DBT-specific options ---
120+
dbt:
121+
# This configuration ensures that each dbt target gets its own isolated state.
122+
# The inferred state schemas are named "sqlmesh_state_<profile name>_<target schema>", eg "sqlmesh_state_jaffle_shop_dev"
123+
# If this is undesirable, you may manually configure the gateway to use a specific state schema name
124+
# https://sqlmesh.readthedocs.io/en/stable/integrations/dbt/#selecting-a-different-state-connection
125+
infer_state_schema_name: True
126+
127+
# --- Virtual Data Environment Mode ---
120128
# Enable Virtual Data Environments (VDE) for *development* environments.
121129
# Note that the production environment in dbt projects is not virtual by default to maintain compatibility with existing tooling.
122130
# https://sqlmesh.readthedocs.io/en/stable/guides/configuration/#virtual-data-environment-modes

sqlmesh/core/_typing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
SessionProperties = t.Dict[str, t.Union[exp.Expression, str, int, float, bool]]
1212
CustomMaterializationProperties = t.Dict[str, t.Union[exp.Expression, str, int, float, bool]]
1313

14+
1415
if sys.version_info >= (3, 11):
1516
from typing import Self as Self
1617
else:

sqlmesh/core/config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@
3636
from sqlmesh.core.config.naming import NameInferenceConfig as NameInferenceConfig
3737
from sqlmesh.core.config.linter import LinterConfig as LinterConfig
3838
from sqlmesh.core.config.plan import PlanConfig as PlanConfig
39-
from sqlmesh.core.config.root import Config as Config
39+
from sqlmesh.core.config.root import Config as Config, DbtConfig as DbtConfig
4040
from sqlmesh.core.config.run import RunConfig as RunConfig
4141
from sqlmesh.core.config.scheduler import BuiltInSchedulerConfig as BuiltInSchedulerConfig

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):

0 commit comments

Comments
 (0)