Skip to content

Commit 66ac52a

Browse files
authored
Feat: add formatter options to render command (#4753)
1 parent 3e1c1cb commit 66ac52a

7 files changed

Lines changed: 196 additions & 103 deletions

File tree

docs/reference/cli.md

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -419,19 +419,31 @@ Usage: sqlmesh render [OPTIONS] MODEL
419419
Render a model's query, optionally expanding referenced models.
420420
421421
Options:
422-
-s, --start TEXT The start datetime of the interval for which this
423-
command will be applied.
424-
-e, --end TEXT The end datetime of the interval for which this
425-
command will be applied.
426-
--execution-time TEXT The execution time (defaults to now).
427-
--expand TEXT Whether or not to expand materialized models
428-
(defaults to False). If True, all referenced models
429-
are expanded as raw queries. Multiple model names can
430-
also be specified, in which case only they will be
431-
expanded as raw queries.
432-
--dialect TEXT The SQL dialect to render the query as.
433-
--no-format Disable fancy formatting of the query.
434-
--help Show this message and exit.
422+
-s, --start TEXT The start datetime of the interval for which
423+
this command will be applied.
424+
-e, --end TEXT The end datetime of the interval for which this
425+
command will be applied.
426+
--execution-time TEXT The execution time (defaults to now).
427+
--expand TEXT Whether or not to expand materialized models
428+
(defaults to False). If True, all referenced
429+
models are expanded as raw queries. Multiple
430+
model names can also be specified, in which case
431+
only they will be expanded as raw queries.
432+
--dialect TEXT The SQL dialect to render the query as.
433+
--no-format Disable fancy formatting of the query.
434+
--max-text-width INTEGER The max number of characters in a segment before
435+
creating new lines in pretty mode.
436+
--leading-comma Determines whether or not the comma is leading
437+
or trailing in select expressions. Default is
438+
trailing.
439+
--normalize-functions TEXT Whether or not to normalize all function names.
440+
Possible values are: 'upper', 'lower'
441+
--indent INTEGER Determines the indentation size in a formatted
442+
string.
443+
--pad INTEGER Determines the pad size in a formatted string.
444+
--normalize Whether or not to normalize identifiers to
445+
lowercase.
446+
--help Show this message and exit.
435447
```
436448

437449
## rewrite

docs/reference/notebook.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ options:
201201
```
202202
%render [--start START] [--end END] [--execution-time EXECUTION_TIME]
203203
[--expand EXPAND] [--dialect DIALECT] [--no-format]
204+
[--normalize] [--pad PAD] [--indent INDENT]
205+
[--normalize-functions NORMALIZE_FUNCTIONS] [--leading-comma]
206+
[--max-text-width MAX_TEXT_WIDTH]
204207
model
205208
206209
Renders a model's query, optionally expanding referenced models.
@@ -220,6 +223,17 @@ options:
220223
models are expanded as raw queries.
221224
--dialect DIALECT SQL dialect to render.
222225
--no-format Disable fancy formatting of the query.
226+
--normalize Whether or not to normalize identifiers to lowercase.
227+
--pad PAD Determines the pad size in a formatted string.
228+
--indent INDENT Determines the indentation size in a formatted string.
229+
--normalize-functions NORMALIZE_FUNCTIONS
230+
Whether or not to normalize all function names.
231+
Possible values are: 'upper', 'lower'
232+
--leading-comma Determines whether or not the comma is leading or
233+
trailing in select expressions. Default is trailing.
234+
--max-text-width MAX_TEXT_WIDTH
235+
The max number of characters in a segment before
236+
creating new lines in pretty mode.
223237
```
224238

225239
#### dag

sqlmesh/cli/main.py

Lines changed: 20 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ def init(
191191
help="The SQL dialect to render the query as.",
192192
)
193193
@click.option("--no-format", is_flag=True, help="Disable fancy formatting of the query.")
194+
@opt.format_options
194195
@click.pass_context
195196
@error_handler
196197
@cli_analytics
@@ -203,6 +204,7 @@ def render(
203204
expand: t.Optional[t.Union[bool, t.Iterable[str]]] = None,
204205
dialect: t.Optional[str] = None,
205206
no_format: bool = False,
207+
**format_kwargs: t.Any,
206208
) -> None:
207209
"""Render a model's query, optionally expanding referenced models."""
208210
rendered = ctx.obj.render(
@@ -213,7 +215,17 @@ def render(
213215
expand=expand,
214216
)
215217

216-
sql = rendered.sql(pretty=True, dialect=ctx.obj.config.dialect if dialect is None else dialect)
218+
format_config = ctx.obj.config_for_node(model).format
219+
format_kwargs = {
220+
**format_config.generator_options,
221+
**{k: v for k, v in format_kwargs.items() if v is not None},
222+
}
223+
224+
sql = rendered.sql(
225+
pretty=True,
226+
dialect=ctx.obj.config.dialect if dialect is None else dialect,
227+
**format_kwargs,
228+
)
217229
if no_format:
218230
print(sql)
219231
else:
@@ -264,65 +276,30 @@ def evaluate(
264276
help="Transpile project models to the specified dialect.",
265277
)
266278
@click.option(
267-
"--append-newline",
268-
is_flag=True,
269-
help="Include a newline at the end of each file.",
270-
default=None,
271-
)
272-
@click.option(
273-
"--no-rewrite-casts",
274-
is_flag=True,
275-
help="Preserve the existing casts, without rewriting them to use the :: syntax.",
276-
default=None,
277-
)
278-
@click.option(
279-
"--normalize",
279+
"--check",
280280
is_flag=True,
281-
help="Whether or not to normalize identifiers to lowercase.",
281+
help="Whether or not to check formatting (but not actually format anything).",
282282
default=None,
283283
)
284284
@click.option(
285-
"--pad",
286-
type=int,
287-
help="Determines the pad size in a formatted string.",
288-
)
289-
@click.option(
290-
"--indent",
291-
type=int,
292-
help="Determines the indentation size in a formatted string.",
293-
)
294-
@click.option(
295-
"--normalize-functions",
296-
type=str,
297-
help="Whether or not to normalize all function names. Possible values are: 'upper', 'lower'",
298-
)
299-
@click.option(
300-
"--leading-comma",
285+
"--rewrite-casts/--no-rewrite-casts",
301286
is_flag=True,
302-
help="Determines whether or not the comma is leading or trailing in select expressions. Default is trailing.",
287+
help="Rewrite casts to use the :: syntax.",
303288
default=None,
304289
)
305290
@click.option(
306-
"--max-text-width",
307-
type=int,
308-
help="The max number of characters in a segment before creating new lines in pretty mode.",
309-
)
310-
@click.option(
311-
"--check",
291+
"--append-newline",
312292
is_flag=True,
313-
help="Whether or not to check formatting (but not actually format anything).",
314-
default=None,
293+
help="Include a newline at the end of each file.",
315294
)
295+
@opt.format_options
316296
@click.pass_context
317297
@error_handler
318298
@cli_analytics
319299
def format(
320300
ctx: click.Context, paths: t.Optional[t.Tuple[str, ...]] = None, **kwargs: t.Any
321301
) -> None:
322302
"""Format all SQL models and audits."""
323-
if kwargs.pop("no_rewrite_casts", None):
324-
kwargs["rewrite_casts"] = False
325-
326303
if not ctx.obj.format(**{k: v for k, v in kwargs.items() if v is not None}, paths=paths):
327304
ctx.exit(1)
328305

sqlmesh/cli/options.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import os
4+
import typing as t
45

56
import click
67

@@ -54,3 +55,38 @@
5455
count=True,
5556
help="Verbose output. Use -vv for very verbose output.",
5657
)
58+
59+
60+
def format_options(func: t.Callable) -> t.Callable:
61+
"""Decorator to add common format options to CLI commands."""
62+
func = click.option(
63+
"--normalize",
64+
is_flag=True,
65+
help="Whether or not to normalize identifiers to lowercase.",
66+
)(func)
67+
func = click.option(
68+
"--pad",
69+
type=int,
70+
help="Determines the pad size in a formatted string.",
71+
)(func)
72+
func = click.option(
73+
"--indent",
74+
type=int,
75+
help="Determines the indentation size in a formatted string.",
76+
)(func)
77+
func = click.option(
78+
"--normalize-functions",
79+
type=str,
80+
help="Whether or not to normalize all function names. Possible values are: 'upper', 'lower'",
81+
)(func)
82+
func = click.option(
83+
"--leading-comma",
84+
is_flag=True,
85+
help="Determines whether or not the comma is leading or trailing in select expressions. Default is trailing.",
86+
)(func)
87+
func = click.option(
88+
"--max-text-width",
89+
type=int,
90+
help="The max number of characters in a segment before creating new lines in pretty mode.",
91+
)(func)
92+
return func

sqlmesh/magics.py

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,43 @@ def wrapper(self: SQLMeshMagics, *args: t.Any, **kwargs: t.Any) -> None:
9393
return wrapper
9494

9595

96+
def format_arguments(func: t.Callable) -> t.Callable:
97+
"""Decorator to add common format arguments to magic commands."""
98+
func = argument(
99+
"--normalize",
100+
action="store_true",
101+
help="Whether or not to normalize identifiers to lowercase.",
102+
default=None,
103+
)(func)
104+
func = argument(
105+
"--pad",
106+
type=int,
107+
help="Determines the pad size in a formatted string.",
108+
)(func)
109+
func = argument(
110+
"--indent",
111+
type=int,
112+
help="Determines the indentation size in a formatted string.",
113+
)(func)
114+
func = argument(
115+
"--normalize-functions",
116+
type=str,
117+
help="Whether or not to normalize all function names. Possible values are: 'upper', 'lower'",
118+
)(func)
119+
func = argument(
120+
"--leading-comma",
121+
action="store_true",
122+
help="Determines whether or not the comma is leading or trailing in select expressions. Default is trailing.",
123+
default=None,
124+
)(func)
125+
func = argument(
126+
"--max-text-width",
127+
type=int,
128+
help="The max number of characters in a segment before creating new lines in pretty mode.",
129+
)(func)
130+
return func
131+
132+
96133
@magics_class
97134
class SQLMeshMagics(Magics):
98135
@property
@@ -579,23 +616,39 @@ def evaluate(self, context: Context, line: str) -> None:
579616
)
580617
@argument("--dialect", type=str, help="SQL dialect to render.")
581618
@argument("--no-format", action="store_true", help="Disable fancy formatting of the query.")
619+
@format_arguments
582620
@line_magic
583621
@pass_sqlmesh_context
584622
def render(self, context: Context, line: str) -> None:
585623
"""Renders a model's query, optionally expanding referenced models."""
586624
context.refresh()
587-
args = parse_argstring(self.render, line)
625+
render_opts = vars(parse_argstring(self.render, line))
626+
model = render_opts.pop("model")
627+
dialect = render_opts.pop("dialect", None)
588628

589629
query = context.render(
590-
args.model,
591-
start=args.start,
592-
end=args.end,
593-
execution_time=args.execution_time,
594-
expand=args.expand,
630+
model,
631+
start=render_opts.pop("start", None),
632+
end=render_opts.pop("end", None),
633+
execution_time=render_opts.pop("execution_time", None),
634+
expand=render_opts.pop("expand", False),
595635
)
596636

597-
sql = query.sql(pretty=True, dialect=args.dialect or context.config.dialect)
598-
if args.no_format:
637+
no_format = render_opts.pop("no_format", False)
638+
639+
format_config = context.config_for_node(model).format
640+
format_options = {
641+
**format_config.generator_options,
642+
**{k: v for k, v in render_opts.items() if v is not None},
643+
}
644+
645+
sql = query.sql(
646+
pretty=True,
647+
dialect=context.config.dialect if dialect is None else dialect,
648+
**format_options,
649+
)
650+
651+
if no_format:
599652
context.console.log_status_update(sql)
600653
else:
601654
context.console.show_sql(sql)
@@ -853,55 +906,24 @@ def rewrite(self, context: Context, line: str, sql: str) -> None:
853906
help="Transpile project models to the specified dialect.",
854907
)
855908
@argument(
856-
"--append-newline",
857-
action="store_true",
858-
help="Whether or not to append a newline to the end of the file.",
859-
default=None,
860-
)
861-
@argument(
862-
"--no-rewrite-casts",
863-
action="store_true",
864-
help="Whether or not to preserve the existing casts, without rewriting them to use the :: syntax.",
865-
default=None,
866-
)
867-
@argument(
868-
"--normalize",
909+
"--check",
869910
action="store_true",
870-
help="Whether or not to normalize identifiers to lowercase.",
911+
help="Whether or not to check formatting (but not actually format anything).",
871912
default=None,
872913
)
873914
@argument(
874-
"--pad",
875-
type=int,
876-
help="Determines the pad size in a formatted string.",
877-
)
878-
@argument(
879-
"--indent",
880-
type=int,
881-
help="Determines the indentation size in a formatted string.",
882-
)
883-
@argument(
884-
"--normalize-functions",
885-
type=str,
886-
help="Whether or not to normalize all function names. Possible values are: 'upper', 'lower'",
887-
)
888-
@argument(
889-
"--leading-comma",
915+
"--append-newline",
890916
action="store_true",
891-
help="Determines whether or not the comma is leading or trailing in select expressions. Default is trailing.",
917+
help="Include a newline at the end of the output.",
892918
default=None,
893919
)
894920
@argument(
895-
"--max-text-width",
896-
type=int,
897-
help="The max number of characters in a segment before creating new lines in pretty mode.",
898-
)
899-
@argument(
900-
"--check",
921+
"--no-rewrite-casts",
901922
action="store_true",
902-
help="Whether or not to check formatting (but not actually format anything).",
923+
help="Preserve the existing casts, without rewriting them to use the :: syntax.",
903924
default=None,
904925
)
926+
@format_arguments
905927
@line_magic
906928
@pass_sqlmesh_context
907929
def format(self, context: Context, line: str) -> bool:

0 commit comments

Comments
 (0)