Skip to content

Commit 4c3c157

Browse files
committed
Add second level of verbosity
1 parent 5fd3c2a commit 4c3c157

11 files changed

Lines changed: 152 additions & 50 deletions

File tree

sqlmesh/cli/main.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from sqlmesh.cli.example_project import ProjectTemplate, init_example_project
1414
from sqlmesh.core.analytics import cli_analytics
1515
from sqlmesh.core.console import configure_console, get_console
16+
from sqlmesh.core.constants import Verbosity
1617
from sqlmesh.core.config import load_configs
1718
from sqlmesh.core.context import Context
1819
from sqlmesh.utils.date import TimeLike
@@ -438,19 +439,27 @@ def diff(ctx: click.Context, environment: t.Optional[str] = None) -> None:
438439
help="Output text differences for the rendered versions of the models and standalone audits",
439440
)
440441
@opt.verbose
442+
@opt.very_verbose
441443
@click.pass_context
442444
@error_handler
443445
@cli_analytics
444446
def plan(
445-
ctx: click.Context, verbose: bool, environment: t.Optional[str] = None, **kwargs: t.Any
447+
ctx: click.Context,
448+
verbose: bool,
449+
very_verbose: bool,
450+
environment: t.Optional[str] = None,
451+
**kwargs: t.Any,
446452
) -> None:
447453
"""Apply local changes to the target environment."""
448454
context = ctx.obj
449455
restate_models = kwargs.pop("restate_model") or None
450456
select_models = kwargs.pop("select_model") or None
451457
allow_destructive_models = kwargs.pop("allow_destructive_model") or None
452458
backfill_models = kwargs.pop("backfill_model") or None
453-
setattr(get_console(), "verbose", verbose)
459+
460+
verbosity = Verbosity.VERBOSE if verbose else Verbosity.DEFAULT
461+
verbosity = Verbosity.VERY_VERBOSE if very_verbose else verbosity
462+
setattr(get_console(), "verbosity", verbosity)
454463
context.plan(
455464
environment,
456465
restate_models=restate_models,
@@ -630,6 +639,7 @@ def create_test(
630639
@cli.command("test")
631640
@opt.match_pattern
632641
@opt.verbose
642+
@opt.very_verbose
633643
@click.option(
634644
"--preserve-fixtures",
635645
is_flag=True,
@@ -644,14 +654,18 @@ def test(
644654
obj: Context,
645655
k: t.List[str],
646656
verbose: bool,
657+
very_verbose: bool,
647658
preserve_fixtures: bool,
648659
tests: t.List[str],
649660
) -> None:
650661
"""Run model unit tests."""
662+
verbosity = Verbosity.VERBOSE if verbose else Verbosity.DEFAULT
663+
verbosity = Verbosity.VERY_VERBOSE if very_verbose else verbosity
664+
651665
result = obj.test(
652666
match_patterns=k,
653667
tests=tests,
654-
verbose=verbose,
668+
verbosity=verbosity,
655669
preserve_fixtures=preserve_fixtures,
656670
)
657671
if not result.wasSuccessful():
@@ -700,16 +714,20 @@ def fetchdf(ctx: click.Context, sql: str) -> None:
700714
help="Skip the connection test.",
701715
)
702716
@opt.verbose
717+
@opt.very_verbose
703718
@click.pass_obj
704719
@error_handler
705720
@cli_analytics
706-
def info(obj: Context, skip_connection: bool, verbose: bool) -> None:
721+
def info(obj: Context, skip_connection: bool, verbose: bool, very_verbose: bool) -> None:
707722
"""
708723
Print information about a SQLMesh project.
709724
710725
Includes counts of project models and macros and connection tests for the data warehouse.
711726
"""
712-
obj.print_info(skip_connection=skip_connection, verbose=verbose)
727+
verbosity = Verbosity.VERBOSE if verbose else Verbosity.DEFAULT
728+
verbosity = Verbosity.VERY_VERBOSE if very_verbose else verbosity
729+
730+
obj.print_info(skip_connection=skip_connection, verbosity=verbosity)
713731

714732

715733
@cli.command("ui")
@@ -900,22 +918,31 @@ def rewrite(obj: Context, sql: str, read: str = "", write: str = "") -> None:
900918
default=0.7,
901919
)
902920
@opt.verbose
921+
@opt.very_verbose
903922
@click.pass_context
904923
@error_handler
905924
@cli_analytics
906925
def prompt(
907-
ctx: click.Context, prompt: str, evaluate: bool, temperature: float, verbose: bool
926+
ctx: click.Context,
927+
prompt: str,
928+
evaluate: bool,
929+
temperature: float,
930+
verbose: bool,
931+
very_verbose: bool,
908932
) -> None:
909933
"""Uses LLM to generate a SQL query from a prompt."""
910934
from sqlmesh.integrations.llm import LLMIntegration
911935

936+
verbosity = Verbosity.VERBOSE if verbose else Verbosity.DEFAULT
937+
verbosity = Verbosity.VERY_VERBOSE if very_verbose else verbosity
938+
912939
context = ctx.obj
913940

914941
llm_integration = LLMIntegration(
915942
context.models.values(),
916943
context.engine_adapter.dialect,
917944
temperature=temperature,
918-
verbose=verbose,
945+
verbosity=verbosity,
919946
)
920947
query = llm_integration.query(prompt)
921948

sqlmesh/cli/options.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,10 @@
5454
is_flag=True,
5555
help="Verbose output.",
5656
)
57+
58+
very_verbose = click.option(
59+
"-vv",
60+
"--very-verbose",
61+
is_flag=True,
62+
help="Very verbose output.",
63+
)

sqlmesh/core/console.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from rich.syntax import Syntax
2525
from rich.table import Table
2626
from rich.tree import Tree
27-
27+
from sqlmesh.core.constants import Verbosity
2828
from sqlmesh.core.environment import EnvironmentNamingInfo
2929
from sqlmesh.core.linter.rule import RuleViolation
3030
from sqlmesh.core.model import Model
@@ -310,10 +310,13 @@ def show_row_diff(
310310
def print_environments(self, environments_summary: t.Dict[str, int]) -> None:
311311
"""Prints all environment names along with expiry datetime."""
312312

313-
def _limit_model_names(self, tree: Tree, verbose: bool = False) -> Tree:
313+
def _limit_model_names(self, tree: Tree, verbosity: Verbosity = Verbosity.DEFAULT) -> Tree:
314314
"""Trim long indirectly modified model lists below threshold."""
315315
modified_length = len(tree.children)
316-
if not verbose and modified_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD:
316+
if (
317+
verbosity < Verbosity.VERY_VERBOSE
318+
and modified_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD
319+
):
317320
tree.children = [
318321
tree.children[0],
319322
Tree(f".... {modified_length-2} more ...."),
@@ -516,7 +519,7 @@ class TerminalConsole(Console):
516519
def __init__(
517520
self,
518521
console: t.Optional[RichConsole] = None,
519-
verbose: bool = False,
522+
verbosity: Verbosity = Verbosity.DEFAULT,
520523
dialect: DialectType = None,
521524
ignore_warnings: bool = False,
522525
**kwargs: t.Any,
@@ -548,7 +551,7 @@ def __init__(
548551

549552
self.loading_status: t.Dict[uuid.UUID, Status] = {}
550553

551-
self.verbose = verbose
554+
self.verbosity = verbosity
552555
self.dialect = dialect
553556
self.ignore_warnings = ignore_warnings
554557

@@ -673,7 +676,7 @@ def start_creation_progress(
673676
def update_creation_progress(self, snapshot: SnapshotInfoLike) -> None:
674677
"""Update the snapshot creation progress."""
675678
if self.creation_progress is not None and self.creation_task is not None:
676-
if self.verbose:
679+
if self.verbosity >= Verbosity.VERBOSE:
677680
self.creation_progress.live.console.print(
678681
f"{snapshot.display_name(self.environment_naming_info, self.default_catalog, dialect=self.dialect)} [green]created[/green]"
679682
)
@@ -749,7 +752,7 @@ def start_promotion_progress(
749752
def update_promotion_progress(self, snapshot: SnapshotInfoLike, promoted: bool) -> None:
750753
"""Update the snapshot promotion progress."""
751754
if self.promotion_progress is not None and self.promotion_task is not None:
752-
if self.verbose:
755+
if self.verbosity >= Verbosity.VERBOSE:
753756
action_str = "[green]promoted[/green]" if promoted else "[yellow]demoted[/yellow]"
754757
self.promotion_progress.live.console.print(
755758
f"{snapshot.display_name(self.environment_naming_info, self.default_catalog, dialect=self.dialect)} {action_str}"
@@ -971,15 +974,15 @@ def _show_summary_tree_for(
971974
added_tree.add(
972975
f"[added]{snapshot.display_name(environment_naming_info, default_catalog, dialect=self.dialect)}"
973976
)
974-
tree.add(self._limit_model_names(added_tree, self.verbose))
977+
tree.add(self._limit_model_names(added_tree, self.verbosity))
975978
if removed_snapshot_ids:
976979
removed_tree = Tree("[bold][removed]Removed:")
977980
for s_id in sorted(removed_snapshot_ids):
978981
snapshot_table_info = context_diff.removed_snapshots[s_id]
979982
removed_tree.add(
980983
f"[removed]{snapshot_table_info.display_name(environment_naming_info, default_catalog, dialect=self.dialect)}"
981984
)
982-
tree.add(self._limit_model_names(removed_tree, self.verbose))
985+
tree.add(self._limit_model_names(removed_tree, self.verbosity))
983986
if modified_snapshot_ids:
984987
direct = Tree("[bold][direct]Directly Modified:")
985988
indirect = Tree("[bold][indirect]Indirectly Modified:")
@@ -1007,7 +1010,7 @@ def _show_summary_tree_for(
10071010
if direct.children:
10081011
tree.add(direct)
10091012
if indirect.children:
1010-
tree.add(self._limit_model_names(indirect, self.verbose))
1013+
tree.add(self._limit_model_names(indirect, self.verbosity))
10111014
if metadata.children:
10121015
tree.add(metadata)
10131016
self._print(tree)
@@ -1077,7 +1080,7 @@ def _prompt_categorize(
10771080
f"[indirect]{child_snapshot.display_name(plan.environment_naming_info, default_catalog, dialect=self.dialect)}"
10781081
)
10791082
if indirect_tree:
1080-
indirect_tree = self._limit_model_names(indirect_tree, self.verbose)
1083+
indirect_tree = self._limit_model_names(indirect_tree, self.verbosity)
10811084

10821085
self._print(tree)
10831086
if not no_prompts:
@@ -1107,7 +1110,7 @@ def _show_categorized_snapshots(self, plan: Plan, default_catalog: t.Optional[st
11071110
f"[indirect]{child_snapshot.display_name(plan.environment_naming_info, default_catalog, dialect=self.dialect)} ({child_category_str})"
11081111
)
11091112
if indirect_tree:
1110-
indirect_tree = self._limit_model_names(indirect_tree, self.verbose)
1113+
indirect_tree = self._limit_model_names(indirect_tree, self.verbosity)
11111114
elif context_diff.metadata_updated(snapshot.name):
11121115
tree = Tree(
11131116
f"\n[bold][metadata]Metadata Updated: {snapshot.display_name(plan.environment_naming_info, default_catalog, dialect=self.dialect)}"
@@ -1144,7 +1147,7 @@ def _show_missing_dates(self, plan: Plan, default_catalog: t.Optional[str]) -> N
11441147
)
11451148

11461149
if backfill:
1147-
backfill = self._limit_model_names(backfill, self.verbose)
1150+
backfill = self._limit_model_names(backfill, self.verbosity)
11481151
self._print(backfill)
11491152

11501153
def _prompt_effective_from(
@@ -1993,7 +1996,10 @@ def show_model_difference_summary(
19931996
self._print("\n**Added Models:**")
19941997
added_models = sorted(added_snapshot_models)
19951998
list_length = len(added_models)
1996-
if not self.verbose and list_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD:
1999+
if (
2000+
self.verbosity < Verbosity.VERY_VERBOSE
2001+
and list_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD
2002+
):
19972003
self._print(added_models[0])
19982004
self._print(f"- `.... {list_length-2} more ....`\n")
19992005
self._print(added_models[-1])
@@ -2017,7 +2023,10 @@ def show_model_difference_summary(
20172023
self._print("\n**Removed Models:**")
20182024
removed_models = sorted(removed_model_snapshot_table_infos)
20192025
list_length = len(removed_models)
2020-
if not self.verbose and list_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD:
2026+
if (
2027+
self.verbosity < Verbosity.VERY_VERBOSE
2028+
and list_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD
2029+
):
20212030
self._print(removed_models[0])
20222031
self._print(f"- `.... {list_length-2} more ....`\n")
20232032
self._print(removed_models[-1])
@@ -2062,7 +2071,7 @@ def show_model_difference_summary(
20622071
indirectly_modified = sorted(indirectly_modified)
20632072
modified_length = len(indirectly_modified)
20642073
if (
2065-
not self.verbose
2074+
self.verbosity < Verbosity.VERY_VERBOSE
20662075
and modified_length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD
20672076
):
20682077
self._print(
@@ -2106,7 +2115,10 @@ def _show_missing_dates(self, plan: Plan, default_catalog: t.Optional[str]) -> N
21062115
)
21072116

21082117
length = len(snapshots)
2109-
if not self.verbose and length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD:
2118+
if (
2119+
self.verbosity < Verbosity.VERY_VERBOSE
2120+
and length > self.INDIRECTLY_MODIFIED_DISPLAY_THRESHOLD
2121+
):
21102122
self._print(snapshots[0])
21112123
self._print(f"- `.... {length-2} more ....`\n")
21122124
self._print(snapshots[-1])
@@ -2135,7 +2147,7 @@ def _show_categorized_snapshots(self, plan: Plan, default_catalog: t.Optional[st
21352147
f"[indirect]{child_snapshot.display_name(plan.environment_naming_info, default_catalog, dialect=self.dialect)} ({child_category_str})"
21362148
)
21372149
if indirect_tree:
2138-
indirect_tree = self._limit_model_names(indirect_tree, self.verbose)
2150+
indirect_tree = self._limit_model_names(indirect_tree, self.verbosity)
21392151
elif context_diff.metadata_updated(snapshot.name):
21402152
tree = Tree(
21412153
f"[bold][metadata]Metadata Updated: {snapshot.display_name(plan.environment_naming_info, default_catalog, dialect=self.dialect)}"
@@ -2364,7 +2376,7 @@ def __init__(
23642376
) -> None:
23652377
self.console: RichConsole = console or srich.console
23662378
self.dialect = dialect
2367-
self.verbose = False
2379+
self.verbosity = Verbosity.DEFAULT
23682380
self.ignore_warnings = ignore_warnings
23692381

23702382
def _write(self, msg: t.Any, *args: t.Any, **kwargs: t.Any) -> None:

sqlmesh/core/constants.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import typing as t
77
from pathlib import Path
8+
from enum import IntEnum
89

910
SQLMESH = "sqlmesh"
1011
SQLMESH_PATH = Path.home() / ".sqlmesh"
@@ -91,3 +92,9 @@
9192
HYBRID = "hybrid"
9293

9394
DISABLE_SQLMESH_STATE_MIGRATION = "SQLMESH__AIRFLOW__DISABLE_STATE_MIGRATION"
95+
96+
97+
class Verbosity(IntEnum):
98+
DEFAULT = 1
99+
VERBOSE = 2
100+
VERY_VERBOSE = 3

sqlmesh/core/context.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
from sqlglot import Dialect, exp
5252
from sqlglot.helper import first
5353
from sqlglot.lineage import GraphHTML
54-
54+
from sqlmesh.core.constants import Verbosity
5555
from sqlmesh.core import analytics
5656
from sqlmesh.core import constants as c
5757
from sqlmesh.core.analytics import python_api_analytics
@@ -1741,16 +1741,13 @@ def test(
17411741
self,
17421742
match_patterns: t.Optional[t.List[str]] = None,
17431743
tests: t.Optional[t.List[str]] = None,
1744-
verbose: bool = False,
1744+
verbosity: Verbosity = Verbosity.DEFAULT,
17451745
preserve_fixtures: bool = False,
17461746
stream: t.Optional[t.TextIO] = None,
17471747
) -> ModelTextTestResult:
17481748
"""Discover and run model tests"""
1749-
if verbose:
1749+
if verbosity >= Verbosity.VERBOSE:
17501750
pd.set_option("display.max_columns", None)
1751-
verbosity = 2
1752-
else:
1753-
verbosity = 1
17541751

17551752
if tests:
17561753
result = run_model_tests(
@@ -1954,15 +1951,17 @@ def create_external_models(self, strict: bool = False) -> None:
19541951
)
19551952

19561953
@python_api_analytics
1957-
def print_info(self, skip_connection: bool = False, verbose: bool = False) -> None:
1954+
def print_info(
1955+
self, skip_connection: bool = False, verbosity: Verbosity = Verbosity.DEFAULT
1956+
) -> None:
19581957
"""Prints information about connections, models, macros, etc. to the console."""
19591958
self.console.log_status_update(f"Models: {len(self.models)}")
19601959
self.console.log_status_update(f"Macros: {len(self._macros) - len(macro.get_registry())}")
19611960

19621961
if skip_connection:
19631962
return
19641963

1965-
if verbose:
1964+
if verbosity >= Verbosity.VERBOSE:
19661965
self.console.log_status_update("")
19671966
print_config(self.config.get_connection(self.gateway), self.console, "Connection")
19681967
print_config(
@@ -2072,9 +2071,11 @@ def clear_caches(self) -> None:
20722071
for path in self.configs:
20732072
rmtree(path / c.CACHE)
20742073

2075-
def _run_tests(self, verbose: bool = False) -> t.Tuple[unittest.result.TestResult, str]:
2074+
def _run_tests(
2075+
self, verbosity: Verbosity = Verbosity.DEFAULT
2076+
) -> t.Tuple[unittest.result.TestResult, str]:
20762077
test_output_io = StringIO()
2077-
result = self.test(stream=test_output_io, verbose=verbose)
2078+
result = self.test(stream=test_output_io, verbosity=verbosity)
20782079
return result, test_output_io.getvalue()
20792080

20802081
def _run_plan_tests(

0 commit comments

Comments
 (0)