sqlmesh.cli.main API documentation

Edit on GitHub

# sqlmesh.cli.main

View Source

      1from __future__ import annotations
      2
      3import os
      4import sys
      5import typing as t
      6
      7import click
      8
      9from sqlmesh.cli import error_handler
     10from sqlmesh.cli import options as opt
     11from sqlmesh.cli.example_project import ProjectTemplate, init_example_project
     12from sqlmesh.core.context import Context
     13from sqlmesh.utils.date import TimeLike
     14
     15
     16@click.group(no_args_is_help=True)
     17@opt.path
     18@opt.config
     19@click.option(
     20    "--connection",
     21    type=str,
     22    help="The name of the connection.",
     23)
     24@click.option(
     25    "--test-connection",
     26    type=str,
     27    help="The name of the connection to use for tests.",
     28)
     29@click.pass_context
     30@error_handler
     31def cli(
     32    ctx: click.Context,
     33    path: str,
     34    config: t.Optional[str] = None,
     35    connection: t.Optional[str] = None,
     36    test_connection: t.Optional[str] = None,
     37) -> None:
     38    """SQLMesh command line tool."""
     39    if ctx.invoked_subcommand == "version":
     40        return
     41
     42    path = os.path.abspath(path)
     43    if ctx.invoked_subcommand == "init":
     44        ctx.obj = path
     45        return
     46
     47    # Delegates the execution of the --help option to the corresponding subcommand
     48    if "--help" in sys.argv:
     49        return
     50
     51    context = Context(
     52        path=path,
     53        config=config,
     54        connection=connection,
     55        test_connection=test_connection,
     56    )
     57
     58    if not context.models:
     59        raise click.ClickException(
     60            f"`{path}` doesn't seem to have any models... cd into the proper directory or specify the path with --path."
     61        )
     62
     63    ctx.obj = context
     64
     65
     66@cli.command("init")
     67@click.option(
     68    "-t",
     69    "--template",
     70    type=str,
     71    help="Project template. Support values: airflow, default.",
     72)
     73@click.pass_context
     74@error_handler
     75def init(ctx: click.Context, template: t.Optional[str] = None) -> None:
     76    """Create a new SQLMesh repository."""
     77    try:
     78        project_template = ProjectTemplate(template.lower() if template else "default")
     79    except ValueError:
     80        raise click.ClickException(f"Invalid project template '{template}'")
     81    init_example_project(ctx.obj, template=project_template)
     82
     83
     84@cli.command("render")
     85@click.argument("model")
     86@opt.start_time
     87@opt.end_time
     88@opt.latest_time
     89@opt.expand
     90@click.pass_context
     91@error_handler
     92def render(
     93    ctx: click.Context,
     94    model: str,
     95    start: TimeLike,
     96    end: TimeLike,
     97    latest: t.Optional[TimeLike] = None,
     98    expand: t.Optional[t.Union[bool, t.Iterable[str]]] = None,
     99) -> None:
    100    """Renders a model's query, optionally expanding referenced models."""
    101    snapshot = ctx.obj.snapshots.get(model)
    102
    103    if not snapshot:
    104        raise click.ClickException(f"Model `{model}` not found.")
    105
    106    rendered = ctx.obj.render(
    107        snapshot,
    108        start=start,
    109        end=end,
    110        latest=latest,
    111        expand=expand,
    112    )
    113
    114    sql = rendered.sql(pretty=True, dialect=ctx.obj.dialect)
    115    ctx.obj.console.show_sql(sql)
    116
    117
    118@cli.command("evaluate")
    119@click.argument("model")
    120@opt.start_time
    121@opt.end_time
    122@opt.latest_time
    123@click.option(
    124    "--limit",
    125    type=int,
    126    help="The number of rows which the query should be limited to.",
    127)
    128@click.pass_context
    129@error_handler
    130def evaluate(
    131    ctx: click.Context,
    132    model: str,
    133    start: TimeLike,
    134    end: TimeLike,
    135    latest: t.Optional[TimeLike] = None,
    136    limit: t.Optional[int] = None,
    137) -> None:
    138    """Evaluate a model and return a dataframe with a default limit of 1000."""
    139    df = ctx.obj.evaluate(
    140        model,
    141        start=start,
    142        end=end,
    143        latest=latest,
    144        limit=limit,
    145    )
    146    ctx.obj.console.log_success(df)
    147
    148
    149@cli.command("format")
    150@click.pass_context
    151@error_handler
    152def format(ctx: click.Context) -> None:
    153    """Format all models in a given directory."""
    154    ctx.obj.format()
    155
    156
    157@cli.command("diff")
    158@click.argument("environment")
    159@click.pass_context
    160@error_handler
    161def diff(ctx: click.Context, environment: t.Optional[str] = None) -> None:
    162    """Show the diff between the current context and a given environment."""
    163    ctx.obj.diff(environment)
    164
    165
    166@cli.command("plan")
    167@click.argument("environment", required=False)
    168@opt.start_time
    169@opt.end_time
    170@click.option(
    171    "--create-from",
    172    type=str,
    173    help="The environment to create the target environment from if it doesn't exist. Default: prod.",
    174)
    175@click.option(
    176    "--skip-tests",
    177    help="Skip tests prior to generating the plan if they are defined.",
    178)
    179@click.option(
    180    "--restate-model",
    181    "-r",
    182    type=str,
    183    multiple=True,
    184    help="Restate data for specified models and models downstream from the one specified. For production environment, all related model versions will have their intervals wiped, but only the current versions will be backfilled. For development environment, only the current model versions will be affected.",
    185)
    186@click.option(
    187    "--no-gaps",
    188    is_flag=True,
    189    help="Ensure that new snapshots have no data gaps when comparing to existing snapshots for matching models in the target environment.",
    190)
    191@click.option(
    192    "--skip-backfill",
    193    is_flag=True,
    194    help="Skip the backfill step.",
    195)
    196@click.option(
    197    "--forward-only",
    198    is_flag=True,
    199    help="Create a plan for forward-only changes.",
    200)
    201@click.option(
    202    "--no-prompts",
    203    is_flag=True,
    204    help="Disable interactive prompts for the backfill time range. Please note that if this flag is set and there are uncategorized changes, plan creation will fail.",
    205)
    206@click.option(
    207    "--auto-apply",
    208    is_flag=True,
    209    help="Automatically apply the new plan after creation.",
    210)
    211@click.option(
    212    "--no-auto-categorization",
    213    is_flag=True,
    214    help="Disable automatic change categorization.",
    215    default=None,
    216)
    217@click.pass_context
    218@error_handler
    219def plan(ctx: click.Context, environment: t.Optional[str] = None, **kwargs: t.Any) -> None:
    220    """Plan a migration of the current context's models with the given environment."""
    221    context = ctx.obj
    222    restate_models = kwargs.pop("restate_model", None)
    223    context.plan(environment, restate_models=restate_models, **kwargs)
    224
    225
    226@cli.command("run")
    227@click.argument("environment", required=False)
    228@opt.start_time
    229@opt.end_time
    230@click.option("--skip-janitor", is_flag=True, help="Skip the jantitor task.")
    231@click.pass_context
    232@error_handler
    233def run(ctx: click.Context, environment: t.Optional[str] = None, **kwargs: t.Any) -> None:
    234    """Evaluates the DAG of models using the built-in scheduler."""
    235    context = ctx.obj
    236    context.run(environment, **kwargs)
    237
    238
    239@cli.command("dag")
    240@opt.file
    241@click.pass_context
    242@error_handler
    243def dag(ctx: click.Context, file: str) -> None:
    244    """
    245    Renders the dag using graphviz.
    246
    247    This command requires a manual install of both the python and system graphviz package.
    248    """
    249    ctx.obj.render_dag(file)
    250
    251
    252@cli.command("test")
    253@opt.match_pattern
    254@opt.verbose
    255@click.argument("tests", nargs=-1)
    256@click.pass_obj
    257@error_handler
    258def test(obj: Context, k: t.List[str], verbose: bool, tests: t.List[str]) -> None:
    259    """Run model unit tests."""
    260    # Set Python unittest verbosity level
    261    result = obj.test(match_patterns=k, tests=tests, verbose=verbose)
    262    if not result.wasSuccessful():
    263        exit(1)
    264
    265
    266@cli.command("audit")
    267@click.option(
    268    "--model",
    269    "models",
    270    multiple=True,
    271    help="A model to audit. Multiple models can be audited.",
    272)
    273@opt.start_time
    274@opt.end_time
    275@opt.latest_time
    276@click.pass_obj
    277@error_handler
    278def audit(
    279    obj: Context,
    280    models: t.Iterator[str],
    281    start: TimeLike,
    282    end: TimeLike,
    283    latest: t.Optional[TimeLike] = None,
    284) -> None:
    285    """Run audits."""
    286    obj.audit(models=models, start=start, end=end, latest=latest)
    287
    288
    289@cli.command("fetchdf")
    290@click.argument("sql")
    291@click.pass_context
    292@error_handler
    293def fetchdf(ctx: click.Context, sql: str) -> None:
    294    """Runs a sql query and displays the results."""
    295    context = ctx.obj
    296    context.console.log_success(context.fetchdf(sql))
    297
    298
    299@cli.command("version")
    300@error_handler
    301def version() -> None:
    302    """Print version."""
    303    try:
    304        from sqlmesh import __version__
    305
    306        print(__version__)
    307    except ImportError:
    308        print("Version is not available")
    309
    310
    311if __name__ == "__main__":
    312    cli()

cli = <Group cli>

SQLMesh command line tool.

init = <Command init>

Create a new SQLMesh repository.

render = <Command render>

Renders a model's query, optionally expanding referenced models.

evaluate = <Command evaluate>

Evaluate a model and return a dataframe with a default limit of 1000.

format = <Command format>

Format all models in a given directory.

diff = <Command diff>

Show the diff between the current context and a given environment.

plan = <Command plan>

Plan a migration of the current context's models with the given environment.

run = <Command run>

Evaluates the DAG of models using the built-in scheduler.

dag = <Command dag>

Renders the dag using graphviz.

This command requires a manual install of both the python and system graphviz package.

test = <Command test>

Run model unit tests.

audit = <Command audit>

Run audits.

fetchdf = <Command fetchdf>

Runs a sql query and displays the results.

version = <Command version>

Print version.