diff --git a/core/dbt/config/project.py b/core/dbt/config/project.py index 184c2629397..fd3d6696826 100644 --- a/core/dbt/config/project.py +++ b/core/dbt/config/project.py @@ -435,7 +435,11 @@ def from_project_config( seeds = cfg.seeds snapshots = cfg.snapshots sources = cfg.sources - vars_value = V2VarProvider(cfg.vars) + if cfg.vars is None: + vars_dict: Dict[str, Any] = {} + else: + vars_dict = cfg.vars + vars_value = V2VarProvider(vars_dict) else: raise ValidationError( f'Got unsupported config_version={cfg.config_version}' diff --git a/core/dbt/config/runtime.py b/core/dbt/config/runtime.py index fd501bdf0b3..b9e7c31c95c 100644 --- a/core/dbt/config/runtime.py +++ b/core/dbt/config/runtime.py @@ -229,6 +229,12 @@ def _get_v2_config_paths( ) -> PathSet: for key, value in config.items(): if isinstance(value, dict) and not key.startswith('+'): + if key == 'vars': + warn_or_error( + f'Found a "vars" dictionary in a config block for a ' + f'dbt_project.yml file with config-version 2 ' + f'({self.project_root}/dbt_project.yml)' + ) self._get_v2_config_paths(value, path + (key,), paths) else: paths.add(path) @@ -278,6 +284,7 @@ def get_resource_config_paths(self) -> Dict[str, PathSet]: 'models': self._get_config_paths(self.models), 'seeds': self._get_config_paths(self.seeds), 'snapshots': self._get_config_paths(self.snapshots), + 'sources': self._get_config_paths(self.sources), } def get_unused_resource_config_paths( diff --git a/core/dbt/context/context_config.py b/core/dbt/context/context_config.py index 3bf5e039d4a..a33be3357e4 100644 --- a/core/dbt/context/context_config.py +++ b/core/dbt/context/context_config.py @@ -137,7 +137,6 @@ def _update_from_config( validate=validate ) - # TODO: is fqn[0] always the project name? def calculate_node_config( self, config_calls: List[Dict[str, Any]], diff --git a/core/dbt/context/providers.py b/core/dbt/context/providers.py index 0ab5a19d00a..e7c26ea7e53 100644 --- a/core/dbt/context/providers.py +++ b/core/dbt/context/providers.py @@ -315,6 +315,7 @@ def resolve( self.model, target_name, target_package, + disabled=isinstance(target_model, Disabled), ) self.validate(target_model, target_name, target_package) return self.create_relation(target_model, target_name) @@ -385,7 +386,7 @@ def resolve(self, source_name: str, table_name: str): self.model.package_name, ) - if target_source is None: + if target_source is None or isinstance(target_source, Disabled): source_target_not_found( self.model, source_name, diff --git a/core/dbt/contracts/graph/manifest.py b/core/dbt/contracts/graph/manifest.py index 2404cd49352..28f2a9b1af7 100644 --- a/core/dbt/contracts/graph/manifest.py +++ b/core/dbt/contracts/graph/manifest.py @@ -14,8 +14,8 @@ from hologram import JsonSchemaMixin from dbt.contracts.graph.parsed import ( - ParsedNode, ParsedMacro, ParsedDocumentation, ParsedNodePatch, - ParsedMacroPatch, ParsedSourceDefinition + ParsedMacro, ParsedDocumentation, ParsedNodePatch, ParsedMacroPatch, + ParsedSourceDefinition ) from dbt.contracts.graph.compiled import CompileResultNode, NonSourceNode from dbt.contracts.util import Writable, Replaceable @@ -383,9 +383,24 @@ def search(self, haystack: Iterable[N]) -> Optional[N]: return None +D = TypeVar('D') + + @dataclass -class Disabled: - target: ParsedNode +class Disabled(Generic[D]): + target: D + + +MaybeParsedSource = Optional[Union[ + ParsedSourceDefinition, + Disabled[ParsedSourceDefinition], +]] + + +MaybeNonSource = Optional[Union[ + NonSourceNode, + Disabled[NonSourceNode] +]] @dataclass @@ -396,7 +411,7 @@ class Manifest: macros: MutableMapping[str, ParsedMacro] docs: MutableMapping[str, ParsedDocumentation] generated_at: datetime - disabled: List[ParsedNode] + disabled: List[CompileResultNode] files: MutableMapping[str, SourceFile] metadata: ManifestMetadata = field(default_factory=ManifestMetadata) flat_graph: Dict[str, Any] = field(default_factory=dict) @@ -448,13 +463,23 @@ def build_flat_graph(self): def find_disabled_by_name( self, name: str, package: Optional[str] = None - ) -> Optional[ParsedNode]: + ) -> Optional[NonSourceNode]: searcher: NameSearcher = NameSearcher( name, package, NodeType.refable() ) result = searcher.search(self.disabled) + return result + + def find_disabled_source_by_name( + self, source_name: str, table_name: str, package: Optional[str] = None + ) -> Optional[ParsedSourceDefinition]: + search_name = f'{source_name}.{table_name}' + searcher: NameSearcher = NameSearcher( + search_name, package, [NodeType.Source] + ) + result = searcher.search(self.disabled) if result is not None: - assert isinstance(result, ParsedNode) + assert isinstance(result, ParsedSourceDefinition) return result def find_docs_by_name( @@ -597,9 +622,7 @@ def find_materialization_macro_by_name( def get_resource_fqns(self) -> Mapping[str, PathSet]: resource_fqns: Dict[str, Set[Tuple[str, ...]]] = {} for unique_id, node in self.nodes.items(): - if node.resource_type == NodeType.Source: - continue # sources have no FQNs and can't be configured - resource_type_plural = node.resource_type + 's' + resource_type_plural = node.resource_type.pluralize() if resource_type_plural not in resource_fqns: resource_fqns[resource_type_plural] = set() resource_fqns[resource_type_plural].add(tuple(node.fqn)) @@ -761,14 +784,14 @@ def resolve_ref( target_model_package: Optional[str], current_project: str, node_package: str, - ) -> Optional[Union[NonSourceNode, Disabled]]: + ) -> MaybeNonSource: if target_model_package is not None: return self.find_refable_by_name( target_model_name, target_model_package) - target_model = None - disabled_target = None + target_model: Optional[NonSourceNode] = None + disabled_target: Optional[NonSourceNode] = None # first pass: look for models in the current_project # second pass: look for models in the node's package @@ -801,9 +824,12 @@ def resolve_source( target_table_name: str, current_project: str, node_package: str - ) -> Optional[ParsedSourceDefinition]: + ) -> MaybeParsedSource: candidate_targets = [current_project, node_package, None] - target_source = None + + target_source: Optional[ParsedSourceDefinition] = None + disabled_target: Optional[ParsedSourceDefinition] = None + for candidate in candidate_targets: target_source = self.find_source_by_name( target_source_name, @@ -813,6 +839,13 @@ def resolve_source( if target_source is not None and target_source.config.enabled: return target_source + if disabled_target is None: + disabled_target = self.find_disabled_source_by_name( + target_source_name, target_table_name, candidate + ) + + if disabled_target is not None: + return Disabled(disabled_target) return None def resolve_doc( @@ -861,7 +894,7 @@ class WritableManifest(JsonSchemaMixin, Writable): 'The docs defined in the dbt project and its dependencies' )) ) - disabled: Optional[List[ParsedNode]] = field(metadata=dict( + disabled: Optional[List[CompileResultNode]] = field(metadata=dict( description='A list of the disabled nodes in the target' )) generated_at: datetime = field(metadata=dict( diff --git a/core/dbt/contracts/graph/searcher.py b/core/dbt/contracts/graph/searcher.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/dbt/contracts/project.py b/core/dbt/contracts/project.py index 27a14eb2aed..d028a11fbf1 100644 --- a/core/dbt/contracts/project.py +++ b/core/dbt/contracts/project.py @@ -203,8 +203,8 @@ class ProjectV2(HyphenatedJsonSchemaMixin, Replaceable): snapshots: Dict[str, Any] = field(default_factory=dict) analyses: Dict[str, Any] = field(default_factory=dict) sources: Dict[str, Any] = field(default_factory=dict) - vars: Dict[str, Any] = field( - default_factory=dict, + vars: Optional[Dict[str, Any]] = field( + default=None, metadata=dict( description='map project names to their vars override dicts', ), diff --git a/core/dbt/deprecations.py b/core/dbt/deprecations.py index baeffd79b53..443f74e9bf2 100644 --- a/core/dbt/deprecations.py +++ b/core/dbt/deprecations.py @@ -99,6 +99,8 @@ class DbtProjectYamlDeprecation(DBTDeprecation): has been upgraded to config version 2. A future version of dbt will remove support for the existing ("version 1") format. + dbt found a version 1 dbt_project.yml in the project "{project_name}" + Documentation for dbt_project.yml version 2 can be found here: DOCS LINK GOES HERE diff --git a/core/dbt/exceptions.py b/core/dbt/exceptions.py index 6b4f2f5ed72..cc5c8e90fd7 100644 --- a/core/dbt/exceptions.py +++ b/core/dbt/exceptions.py @@ -462,8 +462,10 @@ def doc_target_not_found( raise_compiler_error(msg, model) -def _get_target_failure_msg(model, target_model_name, target_model_package, - include_path, reason): +def _get_target_failure_msg( + model, target_name: str, target_model_package: Optional[str], + include_path: bool, reason: str, target_kind: str +) -> str: target_package_string = '' if target_model_package is not None: target_package_string = "in package '{}' ".format(target_model_package) @@ -472,52 +474,73 @@ def _get_target_failure_msg(model, target_model_name, target_model_package, if include_path: source_path_string = ' ({})'.format(model.original_file_path) - return "{} '{}'{} depends on a node named '{}' {}which {}".format( + return "{} '{}'{} depends on a {} named '{}' {}which {}".format( model.resource_type.title(), model.unique_id, source_path_string, - target_model_name, + target_kind, + target_name, target_package_string, reason ) -def get_target_disabled_msg(model, target_model_name, target_model_package): - return _get_target_failure_msg(model, target_model_name, - target_model_package, include_path=True, - reason='is disabled') - - -def get_target_not_found_msg(model, target_model_name, target_model_package): - return _get_target_failure_msg(model, target_model_name, - target_model_package, include_path=True, - reason='was not found') - - -def get_target_not_found_or_disabled_msg(model, target_model_name, - target_model_package): - return _get_target_failure_msg(model, target_model_name, - target_model_package, include_path=False, - reason='was not found or is disabled') +def get_target_not_found_or_disabled_msg( + model, target_model_name: str, target_model_package: Optional[str], + disabled: Optional[bool] = None, +) -> str: + if disabled is None: + reason = 'was not found or is disabled' + elif disabled is True: + reason = 'is disabled' + else: + reason = 'was not found' + return _get_target_failure_msg( + model, target_model_name, target_model_package, include_path=True, + reason=reason, target_kind='node' + ) -def ref_target_not_found(model, target_model_name, target_model_package): - msg = get_target_not_found_or_disabled_msg(model, target_model_name, - target_model_package) +def ref_target_not_found( + model, + target_model_name: str, + target_model_package: Optional[str], + disabled: Optional[bool] = None, +) -> NoReturn: + msg = get_target_not_found_or_disabled_msg( + model, target_model_name, target_model_package, disabled + ) raise_compiler_error(msg, model) -def source_disabled_message(model, target_name, target_table_name): - return ("{} '{}' ({}) depends on source '{}.{}' which was not found" - .format(model.resource_type.title(), - model.unique_id, - model.original_file_path, - target_name, - target_table_name)) +def get_source_not_found_or_disabled_msg( + model, + target_name: str, + target_table_name: str, + disabled: Optional[bool] = None, +) -> str: + full_name = f'{target_name}.{target_table_name}' + if disabled is None: + reason = 'was not found or is disabled' + elif disabled is True: + reason = 'is disabled' + else: + reason = 'was not found' + return _get_target_failure_msg( + model, full_name, None, include_path=True, + reason=reason, target_kind='source' + ) -def source_target_not_found(model, target_name, target_table_name) -> NoReturn: - msg = source_disabled_message(model, target_name, target_table_name) +def source_target_not_found( + model, + target_name: str, + target_table_name: str, + disabled: Optional[bool] = None +) -> NoReturn: + msg = get_source_not_found_or_disabled_msg( + model, target_name, target_table_name, disabled + ) raise_compiler_error(msg, model) diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index 490ef47f6b1..f9edfd1de5a 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -334,7 +334,10 @@ def load_all( projects = root_config.load_dependencies() for project in projects.values(): if project.config_version == 1: - deprecations.warn('dbt-project-yaml-v1') + deprecations.warn( + 'dbt-project-yaml-v1', + project_name=project.project_name, + ) loader = cls(root_config, projects, macro_hook) loader.load(internal_manifest=internal_manifest) loader.write_parse_results() @@ -545,7 +548,7 @@ def process_refs(manifest: Manifest, current_project: str): def _process_sources_for_node( manifest: Manifest, current_project: str, node: NonSourceNode ): - target_source = None + target_source: Optional[Union[Disabled, ParsedSourceDefinition]] = None for source_name, table_name in node.sources: target_source = manifest.resolve_source( source_name, @@ -554,13 +557,15 @@ def _process_sources_for_node( node.package_name, ) - if target_source is None: + if target_source is None or isinstance(target_source, Disabled): # this folows the same pattern as refs node.config.enabled = False dbt.utils.invalid_source_fail_unless_test( node, source_name, - table_name) + table_name, + disabled=(isinstance(target_source, Disabled)) + ) continue target_source_id = target_source.unique_id node.depends_on.nodes.append(target_source_id) diff --git a/core/dbt/parser/results.py b/core/dbt/parser/results.py index 7aeab74aa9d..16227bd0798 100644 --- a/core/dbt/parser/results.py +++ b/core/dbt/parser/results.py @@ -6,6 +6,7 @@ from dbt.contracts.graph.manifest import ( SourceFile, RemoteFile, FileHash, MacroKey ) +from dbt.contracts.graph.compiled import CompileResultNode from dbt.contracts.graph.parsed import ( HasUniqueID, ParsedAnalysisNode, @@ -15,7 +16,6 @@ ParsedMacro, ParsedMacroPatch, ParsedModelNode, - ParsedNode, ParsedNodePatch, ParsedRPCNode, ParsedSeedNode, @@ -73,7 +73,7 @@ class ParseResult(JsonSchemaMixin, Writable, Replaceable): macro_patches: MutableMapping[MacroKey, ParsedMacroPatch] = dict_field() patches: MutableMapping[str, ParsedNodePatch] = dict_field() files: MutableMapping[str, SourceFile] = dict_field() - disabled: MutableMapping[str, List[ParsedNode]] = dict_field() + disabled: MutableMapping[str, List[CompileResultNode]] = dict_field() dbt_version: str = __version__ def get_file(self, source_file: SourceFile) -> SourceFile: @@ -98,7 +98,7 @@ def add_node(self, source_file: SourceFile, node: ManifestNodes): self.nodes[node.unique_id] = node self.get_file(source_file).nodes.append(node.unique_id) - def add_disabled(self, source_file: SourceFile, node: ParsedNode): + def add_disabled(self, source_file: SourceFile, node: CompileResultNode): if node.unique_id in self.disabled: self.disabled[node.unique_id].append(node) else: @@ -160,7 +160,7 @@ def _get_disabled( self, unique_id: str, match_file: SourceFile, - ) -> List[ParsedNode]: + ) -> List[CompileResultNode]: if unique_id not in self.disabled: raise InternalException( 'called _get_disabled with id={}, but it does not exist' diff --git a/core/dbt/parser/schemas.py b/core/dbt/parser/schemas.py index ac7f8c97f0b..b71224f57aa 100644 --- a/core/dbt/parser/schemas.py +++ b/core/dbt/parser/schemas.py @@ -634,7 +634,15 @@ def parse_patch( tags=tags, config=config, ) - self.results.add_source(self.yaml.file, result) + self.add_result_source(block, result) + + def add_result_source( + self, block: FileBlock, source: ParsedSourceDefinition + ): + if source.config.enabled: + self.results.add_source(block.file, source) + else: + self.results.add_disabled(block.file, source) class NonSourceParser( diff --git a/core/dbt/task/base.py b/core/dbt/task/base.py index d70ac8f9817..bd03e17a520 100644 --- a/core/dbt/task/base.py +++ b/core/dbt/task/base.py @@ -134,7 +134,10 @@ class ConfiguredTask(BaseTask): def __init__(self, args, config): if config.config_version == 1: - deprecations.warn('dbt-project-yaml-v1') + deprecations.warn( + 'dbt-project-yaml-v1', + project_name=config.project_name, + ) super().__init__(args, config) register_adapter(self.config) diff --git a/core/dbt/utils.py b/core/dbt/utils.py index b2cb02a5a5e..152dbf0ece8 100644 --- a/core/dbt/utils.py +++ b/core/dbt/utils.py @@ -308,44 +308,44 @@ def __get__(self, obj, objtype): return functools.partial(self.__call__, obj) -def invalid_ref_test_message(node, target_model_name, target_model_package, - disabled): - if disabled: - msg = dbt.exceptions.get_target_disabled_msg( - node, target_model_name, target_model_package - ) - else: - msg = dbt.exceptions.get_target_not_found_msg( - node, target_model_name, target_model_package - ) - return 'WARNING: {}'.format(msg) - - def invalid_ref_fail_unless_test(node, target_model_name, target_model_package, disabled): if node.resource_type == NodeType.Test: - msg = invalid_ref_test_message(node, target_model_name, - target_model_package, disabled) + msg = dbt.exceptions.get_target_not_found_or_disabled_msg( + node, target_model_name, target_model_package, disabled + ) if disabled: - logger.debug(msg) + logger.debug(f'WARNING: {msg}') else: - dbt.exceptions.warn_or_error(msg) + dbt.exceptions.warn_or_error(msg, log_fmt='WARNING: {}') else: dbt.exceptions.ref_target_not_found( node, target_model_name, - target_model_package) + target_model_package, + disabled=disabled, + ) -def invalid_source_fail_unless_test(node, target_name, target_table_name): +def invalid_source_fail_unless_test( + node, target_name, target_table_name, disabled +): if node.resource_type == NodeType.Test: - msg = dbt.exceptions.source_disabled_message(node, target_name, - target_table_name) - dbt.exceptions.warn_or_error(msg, log_fmt='WARNING: {}') + msg = dbt.exceptions.get_source_not_found_or_disabled_msg( + node, target_name, target_table_name, disabled + ) + if disabled: + logger.debug(f'WARNING: {msg}') + else: + dbt.exceptions.warn_or_error(msg, log_fmt='WARNING: {}') else: - dbt.exceptions.source_target_not_found(node, target_name, - target_table_name) + dbt.exceptions.source_target_not_found( + node, + target_name, + target_table_name, + disabled=disabled + ) def parse_cli_vars(var_string: str) -> Dict[str, Any]: diff --git a/plugins/bigquery/dbt/adapters/bigquery/impl.py b/plugins/bigquery/dbt/adapters/bigquery/impl.py index d3b862115c5..a11af60b72a 100644 --- a/plugins/bigquery/dbt/adapters/bigquery/impl.py +++ b/plugins/bigquery/dbt/adapters/bigquery/impl.py @@ -83,7 +83,6 @@ class BigqueryConfig(AdapterConfig): partition_by: Optional[Dict[str, Any]] = None kms_key_name: Optional[str] = None labels: Optional[Dict[str, str]] = None - # TODO: should this accept `str` and `int`, too? partitions: Optional[List[str]] = None diff --git a/test/integration/011_invalid_model_tests/models-not-found/dependent.sql b/test/integration/011_invalid_model_tests/models-not-found/dependent.sql new file mode 100644 index 00000000000..3f871f8ffb6 --- /dev/null +++ b/test/integration/011_invalid_model_tests/models-not-found/dependent.sql @@ -0,0 +1,2 @@ +-- view does not exist +select * from {{ ref('view_model') }} diff --git a/test/integration/011_invalid_model_tests/sources-disabled/model.sql b/test/integration/011_invalid_model_tests/sources-disabled/model.sql new file mode 100644 index 00000000000..55bbcba67b4 --- /dev/null +++ b/test/integration/011_invalid_model_tests/sources-disabled/model.sql @@ -0,0 +1 @@ +select * from {{ source('test_source', 'test_table') }} diff --git a/test/integration/011_invalid_model_tests/sources-disabled/sources.yml b/test/integration/011_invalid_model_tests/sources-disabled/sources.yml new file mode 100644 index 00000000000..b6755f4bb2c --- /dev/null +++ b/test/integration/011_invalid_model_tests/sources-disabled/sources.yml @@ -0,0 +1,7 @@ +version: 2 +sources: + - name: test_source + schema: "{{ target.schema }}" + tables: + - name: test_table + identifier: seed diff --git a/test/integration/011_invalid_model_tests/sources-missing/model.sql b/test/integration/011_invalid_model_tests/sources-missing/model.sql new file mode 100644 index 00000000000..55bbcba67b4 --- /dev/null +++ b/test/integration/011_invalid_model_tests/sources-missing/model.sql @@ -0,0 +1 @@ +select * from {{ source('test_source', 'test_table') }} diff --git a/test/integration/011_invalid_model_tests/test_invalid_models.py b/test/integration/011_invalid_model_tests/test_invalid_models.py index de574df7059..3170e6be509 100644 --- a/test/integration/011_invalid_model_tests/test_invalid_models.py +++ b/test/integration/011_invalid_model_tests/test_invalid_models.py @@ -25,7 +25,7 @@ def test_postgres_view_with_incremental_attributes(self): self.assertIn('enabled', str(exc.exception)) -class TestInvalidModelReference(DBTIntegrationTest): +class TestDisabledModelReference(DBTIntegrationTest): def setUp(self): DBTIntegrationTest.setUp(self) @@ -40,6 +40,23 @@ def schema(self): def models(self): return "models-3" + @use_profile('postgres') + def test_postgres_view_with_incremental_attributes(self): + with self.assertRaises(RuntimeError) as exc: + self.run_dbt() + + self.assertIn('which is disabled', str(exc.exception)) + + +class TestMissingModelReference(DBTIntegrationTest): + @property + def schema(self): + return "invalid_models_011" + + @property + def models(self): + return "models-not-found" + @use_profile('postgres') def test_postgres_view_with_incremental_attributes(self): with self.assertRaises(RuntimeError) as exc: @@ -73,9 +90,61 @@ def test_postgres_call_invalid(self): with self.assertRaises(Exception) as exc: self.run_dbt(['compile']) - macro_path = os.path.join('bad-macros', 'macros.sql') model_path = os.path.join('models-4', 'bad_macro.sql') self.assertIn(f'> in macro some_macro ({macro_path})', str(exc.exception)) self.assertIn(f'> called by model bad_macro ({model_path})', str(exc.exception)) + + +class TestInvalidDisabledSource(DBTIntegrationTest): + def setUp(self): + super().setUp() + self.run_sql_file("seed.sql") + + @property + def schema(self): + return "invalid_models_011" + + @property + def models(self): + return 'sources-disabled' + + @property + def project_config(self): + return { + 'config-version': 2, + 'sources': { + 'test': { + 'enabled': False, + } + } + } + + @use_profile('postgres') + def test_postgres_source_disabled(self): + with self.assertRaises(RuntimeError) as exc: + self.run_dbt() + + self.assertIn('which is disabled', str(exc.exception)) + + +class TestInvalidMissingSource(DBTIntegrationTest): + def setUp(self): + super().setUp() + self.run_sql_file("seed.sql") + + @property + def schema(self): + return "invalid_models_011" + + @property + def models(self): + return 'sources-missing' + + @use_profile('postgres') + def test_postgres_source_missing(self): + with self.assertRaises(RuntimeError) as exc: + self.run_dbt() + + self.assertIn('which was not found', str(exc.exception)) diff --git a/test/integration/039_config_test/test_configs.py b/test/integration/039_config_test/test_configs.py index a0369f2fdca..b680241c773 100644 --- a/test/integration/039_config_test/test_configs.py +++ b/test/integration/039_config_test/test_configs.py @@ -2,6 +2,7 @@ import shutil from test.integration.base import DBTIntegrationTest, use_profile +from dbt.exceptions import CompilationException class TestConfigs(DBTIntegrationTest): @@ -120,3 +121,77 @@ def models(self): def test_postgres_disable_seed_partial_parse(self): self.run_dbt(['--partial-parse', 'seed']) self.run_dbt(['--partial-parse', 'seed']) + + +class TestConfigWithVars(DBTIntegrationTest): + @property + def schema(self): + return "config_039" + + @property + def project_config(self): + return { + 'config-version': 2, + 'data-paths': ['data'], + 'seeds': { + 'quote_columns': False, + 'test': { + 'vars': { + 'something': 100, + }, + }, + }, + } + + @property + def models(self): + return "empty-models" + + @use_profile('postgres') + def test_postgres_embedded_config_with_vars(self): + with self.assertRaises(CompilationException) as exc: + self.run_dbt(['seed']) + + self.assertIn('Found a "vars" dictionary in a config block', str(exc.exception)) + self.run_dbt(['seed'], strict=False) + + +class TestUnusedModelConfigs(DBTIntegrationTest): + @property + def schema(self): + return "config_039" + + @property + def project_config(self): + return { + 'config-version': 2, + 'data-paths': ['data'], + 'models': { + 'test': { + 'enabled': True, + } + }, + 'seeds': { + 'quote_columns': False, + }, + 'sources': { + 'test': { + 'enabled': True, + } + } + } + + @property + def models(self): + return "empty-models" + + @use_profile('postgres') + def test_postgres_warn_unused_configuration_paths(self): + with self.assertRaises(CompilationException) as exc: + self.run_dbt(['seed']) + + self.assertIn('Configuration paths exist', str(exc.exception)) + self.assertIn('- sources.test', str(exc.exception)) + self.assertIn('- models.test', str(exc.exception)) + + self.run_dbt(['seed'], strict=False) diff --git a/test/unit/test_manifest.py b/test/unit/test_manifest.py index 15d55a94192..2ba9743426b 100644 --- a/test/unit/test_manifest.py +++ b/test/unit/test_manifest.py @@ -342,7 +342,7 @@ def test_get_resource_fqns(self): database='dbt', schema='analytics', alias='seed', - resource_type='seed', + resource_type=NodeType.Seed, unique_id='seed.root.seed', fqn=['root', 'seed'], package_name='root',