Skip to content

Commit

Permalink
add a flag to wrap models/tests in jinja blocks, to see what happens
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Beck committed Apr 17, 2019
1 parent 4dd8056 commit c90ae55
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 6 deletions.
5 changes: 4 additions & 1 deletion core/dbt/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
FULL_REFRESH = False
USE_CACHE = True
WARN_ERROR = False
WRAP_MODELS_IN_TAGS = False


def reset():
global STRICT_MODE, NON_DESTRUCTIVE, FULL_REFRESH, USE_CACHE, WARN_ERROR
global STRICT_MODE, NON_DESTRUCTIVE, FULL_REFRESH, USE_CACHE, WARN_ERROR, \
WRAP_MODELS_IN_TAGS

STRICT_MODE = False
NON_DESTRUCTIVE = False
FULL_REFRESH = False
USE_CACHE = True
WARN_ERROR = False
WRAP_MODELS_IN_TAGS = False
11 changes: 11 additions & 0 deletions core/dbt/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ def update_flags(parsed):
elif arg_full_refresh:
flags.FULL_REFRESH = True

flags.WRAP_MODELS_IN_TAGS = getattr(parsed, 'wrap_models_in_tags', False)


def _build_base_subparser():
base_subparser = argparse.ArgumentParser(add_help=False)
Expand Down Expand Up @@ -637,6 +639,15 @@ def parse_args(args):
help=argparse.SUPPRESS,
)

# if set, wrap all models and tests in '{% model name %}...{% endmodel %}'
# tags, extract them with the jinja block extractor, and verify that we
# got the original input. This is just a sanity check.
p.add_argument(
'--wrap-models-in-tags',
action='store_true',
help=argparse.SUPPRESS
)

subs = p.add_subparsers(title="Available sub-commands")

base_subparser = _build_base_subparser()
Expand Down
40 changes: 40 additions & 0 deletions core/dbt/parser/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,43 @@ def parse_node(self, node, node_path, package_project_config, tags=None,
parsed_node.validate()

return parsed_node

def check_block_parsing(self, name, path, contents):
if not dbt.flags.WRAP_MODELS_IN_TAGS:
return

wrapped = ''.join(
['{% model ', name, ' %}', contents, '{% endmodel %}']
)
blocks = dbt.clients.jinja.extract_toplevel_blocks(wrapped)
if len(blocks) == 0:
raise dbt.exceptions.InternalException(
'Failed to extract node {} ({}) from its wrapped block!'
.format(name, path)
)
elif len(blocks) > 1:
raise dbt.exceptions.InternalException(
'Found multiple blocks when parsing node {} ({}) from its '
'wrapped block, expected 1!'.format(name, path)
)
block = blocks[0]
if block.block_type_name != 'model':
raise dbt.exceptions.InternalException(
'Found invalid block type ("{}") when parsing node {} ({}) '
'from its wrapped block, expected "model"'
.format(block.block_type_name, name, path)
)

if block.block_name != name:
raise dbt.exceptions.InternalException(
'Found invalid block name ("{}") when parsing node {} ({}) '
'from its wrapped block, expected "{}"'
.format(block.block_name, name, path, name)
)

if blocks[0].contents != contents:
raise dbt.exceptions.InternalException(
'Found invalid block contents when parsing node {} ({}) '
'from its wrapped block, expected it to match original file'
.format(name, path)
)
4 changes: 4 additions & 0 deletions core/dbt/parser/base_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from dbt.contracts.graph.unparsed import UnparsedNode
from dbt.parser.base import MacrosKnownParser
from dbt.node_types import NodeType


class BaseSqlParser(MacrosKnownParser):
Expand Down Expand Up @@ -50,6 +51,9 @@ def load_and_parse(self, package_name, root_dir, relative_dirs,
file_match.get('searched_path'),
path)

if resource_type == NodeType.Model:
self.check_block_parsing(name, path, file_contents)

result.append({
'name': name,
'root_path': root_dir,
Expand Down
2 changes: 2 additions & 0 deletions core/dbt/parser/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ def build_test_node(self, test_target, package_name, test, root_dir, path,
full_path = get_pseudo_test_path(full_name, test_path, 'schema_test')
raw_sql = self._build_raw_sql(test_namespace, test_target, test_type,
test_args)

self.check_block_parsing(full_name, test_path, raw_sql)
unparsed = UnparsedNode(
name=full_name,
resource_type=NodeType.Test,
Expand Down
17 changes: 12 additions & 5 deletions test/integration/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,23 @@ def project_config(self):
def profile_config(self):
return {}

def run_dbt(self, args=None, expect_pass=True, strict=True):
def run_dbt(self, args=None, expect_pass=True, strict=True, wrap=True):
if args is None:
args = ["run"]

final_args = []

if strict:
args = ["--strict"] + args
args.append('--log-cache-events')
logger.info("Invoking dbt with {}".format(args))
final_args.append('--strict')
if wrap:
final_args.append('--wrap-models-in-tags')

final_args.extend(args)
final_args.append('--log-cache-events')

logger.info("Invoking dbt with {}".format(final_args))

res, success = dbt.handle_and_check(args)
res, success = dbt.handle_and_check(final_args)
self.assertEqual(
success, expect_pass,
"dbt exit state did not match expected")
Expand Down

0 comments on commit c90ae55

Please sign in to comment.