Skip to content

Commit

Permalink
Fix #6497: Support global flags passed in after subcommands (#8670)
Browse files Browse the repository at this point in the history
  • Loading branch information
aranke authored and jtcohen6 committed Sep 28, 2023
1 parent 4875c31 commit 1b70a35
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 43 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Fixes-20230919-140514.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Fixes
body: Support global flags passed in after subcommands
time: 2023-09-19T14:05:14.600303+01:00
custom:
Author: aranke
Issue: "6497"
98 changes: 58 additions & 40 deletions core/dbt/cli/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import functools
from copy import copy
from dataclasses import dataclass
from typing import Callable, List, Optional, Union
Expand Down Expand Up @@ -118,6 +119,42 @@ def invoke(self, args: List[str], **kwargs) -> dbtRunnerResult:
)


# approach from https://github.com/pallets/click/issues/108#issuecomment-280489786
def global_flags(func):
@p.cache_selected_only
@p.debug
@p.deprecated_print
@p.enable_legacy_logger
@p.fail_fast
@p.log_cache_events
@p.log_file_max_bytes
@p.log_format_file
@p.log_level
@p.log_level_file
@p.log_path
@p.macro_debugging
@p.partial_parse
@p.populate_cache
@p.print
@p.printer_width
@p.quiet
@p.record_timing_info
@p.send_anonymous_usage_stats
@p.single_threaded
@p.static_parser
@p.use_colors
@p.use_colors_file
@p.use_experimental_parser
@p.version
@p.version_check
@p.write_json
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)

return wrapper


# dbt
@click.group(
context_settings={"help_option_names": ["-h", "--help"]},
Expand All @@ -126,36 +163,10 @@ def invoke(self, args: List[str], **kwargs) -> dbtRunnerResult:
epilog="Specify one of these sub-commands and you can find more help from there.",
)
@click.pass_context
@p.cache_selected_only
@p.debug
@p.deprecated_print
@p.enable_legacy_logger
@p.fail_fast
@p.log_cache_events
@p.log_file_max_bytes
@p.log_format
@p.log_format_file
@p.log_level
@p.log_level_file
@p.log_path
@p.macro_debugging
@p.partial_parse
@p.populate_cache
@p.print
@p.printer_width
@p.quiet
@p.record_timing_info
@p.send_anonymous_usage_stats
@p.single_threaded
@p.static_parser
@p.use_colors
@p.use_colors_file
@p.use_experimental_parser
@p.version
@p.version_check
@global_flags
@p.warn_error
@p.warn_error_options
@p.write_json
@p.log_format
def cli(ctx, **kwargs):
"""An ELT tool for managing your SQL transformations and data models.
For more documentation on these commands, visit: docs.getdbt.com
Expand All @@ -165,10 +176,10 @@ def cli(ctx, **kwargs):
# dbt build
@cli.command("build")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.exclude
@p.fail_fast
@p.favor_state
@p.deprecated_favor_state
@p.full_refresh
Expand All @@ -187,7 +198,6 @@ def cli(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -210,6 +220,7 @@ def build(ctx, **kwargs):
# dbt clean
@cli.command("clean")
@click.pass_context
@global_flags
@p.profile
@p.profiles_dir
@p.project_dir
Expand All @@ -232,13 +243,15 @@ def clean(ctx, **kwargs):
# dbt docs
@cli.group()
@click.pass_context
@global_flags
def docs(ctx, **kwargs):
"""Generate or serve the documentation website for your project"""


# dbt docs generate
@docs.command("generate")
@click.pass_context
@global_flags
@p.compile_docs
@p.defer
@p.deprecated_defer
Expand All @@ -256,7 +269,6 @@ def docs(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -279,6 +291,7 @@ def docs_generate(ctx, **kwargs):
# dbt docs serve
@docs.command("serve")
@click.pass_context
@global_flags
@p.browser
@p.port
@p.profile
Expand Down Expand Up @@ -307,6 +320,7 @@ def docs_serve(ctx, **kwargs):
# dbt compile
@cli.command("compile")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.exclude
Expand All @@ -328,7 +342,6 @@ def docs_serve(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -352,6 +365,7 @@ def compile(ctx, **kwargs):
# dbt show
@cli.command("show")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.exclude
Expand All @@ -374,7 +388,6 @@ def compile(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -398,13 +411,13 @@ def show(ctx, **kwargs):
# dbt debug
@cli.command("debug")
@click.pass_context
@global_flags
@p.config_dir
@p.profile
@p.profiles_dir_exists_false
@p.project_dir
@p.target
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
def debug(ctx, **kwargs):
Expand All @@ -423,6 +436,7 @@ def debug(ctx, **kwargs):
# dbt deps
@cli.command("deps")
@click.pass_context
@global_flags
@p.profile
@p.profiles_dir_exists_false
@p.project_dir
Expand All @@ -443,6 +457,7 @@ def deps(ctx, **kwargs):
# dbt init
@cli.command("init")
@click.pass_context
@global_flags
# for backwards compatibility, accept 'project_name' as an optional positional argument
@click.argument("project_name", required=False)
@p.profile
Expand All @@ -465,6 +480,7 @@ def init(ctx, **kwargs):
# dbt list
@cli.command("list")
@click.pass_context
@global_flags
@p.exclude
@p.indirect_selection
@p.models
Expand Down Expand Up @@ -509,14 +525,14 @@ def list(ctx, **kwargs):
# dbt parse
@cli.command("parse")
@click.pass_context
@global_flags
@p.profile
@p.profiles_dir
@p.project_dir
@p.target
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -533,12 +549,12 @@ def parse(ctx, **kwargs):
# dbt run
@cli.command("run")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.favor_state
@p.deprecated_favor_state
@p.exclude
@p.fail_fast
@p.full_refresh
@p.profile
@p.profiles_dir
Expand All @@ -551,7 +567,6 @@ def parse(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -574,6 +589,7 @@ def run(ctx, **kwargs):
# dbt run operation
@cli.command("run-operation")
@click.pass_context
@global_flags
@click.argument("macro")
@p.args
@p.profile
Expand Down Expand Up @@ -604,6 +620,7 @@ def run_operation(ctx, **kwargs):
# dbt seed
@cli.command("seed")
@click.pass_context
@global_flags
@p.exclude
@p.full_refresh
@p.profile
Expand All @@ -618,7 +635,6 @@ def run_operation(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand All @@ -640,6 +656,7 @@ def seed(ctx, **kwargs):
# dbt snapshot
@cli.command("snapshot")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.exclude
Expand Down Expand Up @@ -678,13 +695,15 @@ def snapshot(ctx, **kwargs):
# dbt source
@cli.group()
@click.pass_context
@global_flags
def source(ctx, **kwargs):
"""Manage your project's sources"""


# dbt source freshness
@source.command("freshness")
@click.pass_context
@global_flags
@p.exclude
@p.output_path # TODO: Is this ok to re-use? We have three different output params, how much can we consolidate?
@p.profile
Expand Down Expand Up @@ -726,10 +745,10 @@ def freshness(ctx, **kwargs):
# dbt test
@cli.command("test")
@click.pass_context
@global_flags
@p.defer
@p.deprecated_defer
@p.exclude
@p.fail_fast
@p.favor_state
@p.deprecated_favor_state
@p.indirect_selection
Expand All @@ -745,7 +764,6 @@ def freshness(ctx, **kwargs):
@p.target_path
@p.threads
@p.vars
@p.version_check
@requires.postflight
@requires.preflight
@requires.profile
Expand Down
19 changes: 16 additions & 3 deletions tests/unit/test_cli_flags.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pytest

import click
from multiprocessing import get_context
from pathlib import Path
from typing import List, Optional

import click
import pytest

from dbt.cli.exceptions import DbtUsageException
from dbt.cli.main import cli
from dbt.contracts.project import UserConfig
Expand Down Expand Up @@ -352,3 +352,16 @@ def test_duplicate_flags_raises_error(self):

with pytest.raises(DbtUsageException):
Flags(context)

def test_global_flag_at_child_context(self):
parent_context_a = self.make_dbt_context("parent_context_a", ["--no-use-colors"])
child_context_a = self.make_dbt_context("child_context_a", ["run"], parent_context_a)
flags_a = Flags(child_context_a)

parent_context_b = self.make_dbt_context("parent_context_b", ["run"])
child_context_b = self.make_dbt_context(
"child_context_b", ["--no-use-colors"], parent_context_b
)
flags_b = Flags(child_context_b)

assert flags_a.USE_COLORS == flags_b.USE_COLORS

0 comments on commit 1b70a35

Please sign in to comment.