From 4243163066b0da6ace0d81fad76ad8052e34f041 Mon Sep 17 00:00:00 2001 From: Jacob Beck Date: Thu, 16 Apr 2020 12:45:53 -0600 Subject: [PATCH] Split ConfigRenderer into parts Docs now get the schema.yml parser vars The SchemaParser now renders the entire schema.yml except tests/descriptions --- core/dbt/config/__init__.py | 1 - core/dbt/config/profile.py | 12 +- core/dbt/config/project.py | 17 +- core/dbt/config/renderer.py | 267 ++++++++++++++++++++----------- core/dbt/config/runtime.py | 109 +++++++------ core/dbt/contracts/connection.py | 4 +- core/dbt/deps/resolver.py | 10 +- core/dbt/parser/manifest.py | 2 +- core/dbt/parser/schemas.py | 20 ++- core/dbt/task/debug.py | 20 ++- core/dbt/task/deps.py | 5 +- 11 files changed, 295 insertions(+), 172 deletions(-) diff --git a/core/dbt/config/__init__.py b/core/dbt/config/__init__.py index 35e61970352..9681c880f6e 100644 --- a/core/dbt/config/__init__.py +++ b/core/dbt/config/__init__.py @@ -2,4 +2,3 @@ from .profile import Profile, PROFILES_DIR, read_user_config # noqa from .project import Project # noqa from .runtime import RuntimeConfig, UnsetProfileConfig # noqa -from .renderer import ConfigRenderer # noqa diff --git a/core/dbt/config/profile.py b/core/dbt/config/profile.py index 500257286af..b3c145348ca 100644 --- a/core/dbt/config/profile.py +++ b/core/dbt/config/profile.py @@ -16,7 +16,7 @@ from dbt.logger import GLOBAL_LOGGER as logger from dbt.utils import coerce_dict_str -from .renderer import ConfigRenderer +from .renderer import ProfileRenderer DEFAULT_THREADS = 1 DEFAULT_PROFILES_DIR = os.path.join(os.path.expanduser('~'), '.dbt') @@ -240,7 +240,7 @@ def render_profile( raw_profile: Dict[str, Any], profile_name: str, target_override: Optional[str], - renderer: ConfigRenderer, + renderer: ProfileRenderer, ) -> Tuple[str, Dict[str, Any]]: """This is a containment zone for the hateful way we're rendering profiles. @@ -268,7 +268,7 @@ def render_profile( raw_profile, profile_name, target_name ) - profile_data = renderer.render_profile_data(raw_profile_data) + profile_data = renderer.render_data(raw_profile_data) return target_name, profile_data @classmethod @@ -276,7 +276,7 @@ def from_raw_profile_info( cls, raw_profile: Dict[str, Any], profile_name: str, - renderer: ConfigRenderer, + renderer: ProfileRenderer, user_cfg: Optional[Dict[str, Any]] = None, target_override: Optional[str] = None, threads_override: Optional[int] = None, @@ -330,7 +330,7 @@ def from_raw_profiles( cls, raw_profiles: Dict[str, Any], profile_name: str, - renderer: ConfigRenderer, + renderer: ProfileRenderer, target_override: Optional[str] = None, threads_override: Optional[int] = None, ) -> 'Profile': @@ -380,7 +380,7 @@ def from_raw_profiles( def render_from_args( cls, args: Any, - renderer: ConfigRenderer, + renderer: ProfileRenderer, project_profile_name: Optional[str], ) -> 'Profile': """Given the raw profiles as read from disk and the name of the desired diff --git a/core/dbt/config/project.py b/core/dbt/config/project.py index 918faaa4f90..7203d45b055 100644 --- a/core/dbt/config/project.py +++ b/core/dbt/config/project.py @@ -35,7 +35,7 @@ from hologram import ValidationError -from .renderer import ConfigRenderer +from .renderer import DbtProjectYamlRenderer INVALID_VERSION_ERROR = """\ @@ -191,6 +191,9 @@ def _query_comment_from_cfg( @dataclass class PartialProject: + config_version: int = field(metadata=dict( + description='The version of the configuration file format' + )) profile_name: Optional[str] = field(metadata=dict( description='The unrendered profile name in the project, if set' )) @@ -562,11 +565,12 @@ def render_from_dict( project_root: str, project_dict: Dict[str, Any], packages_dict: Dict[str, Any], - renderer: ConfigRenderer, + renderer: DbtProjectYamlRenderer, ) -> 'Project': - rendered_project = renderer.render_project(project_dict) + rendered_project = renderer.render_data(project_dict) rendered_project['project-root'] = project_root - rendered_packages = renderer.render_packages_data(packages_dict) + package_renderer = renderer.get_package_renderer() + rendered_packages = package_renderer.render_data(packages_dict) return cls.from_project_config(rendered_project, rendered_packages) @classmethod @@ -578,8 +582,10 @@ def partial_load( project_name = project_dict.get('name') profile_name = project_dict.get('profile') + config_version = project_dict.get('config-version', 1) return PartialProject( + config_version=config_version, profile_name=profile_name, project_name=project_name, project_root=project_root, @@ -588,9 +594,10 @@ def partial_load( @classmethod def from_project_root( - cls, project_root: str, renderer: ConfigRenderer + cls, project_root: str, renderer: DbtProjectYamlRenderer ) -> 'Project': partial = cls.partial_load(project_root) + renderer.version = partial.config_version return partial.render(renderer) def hashed_name(self): diff --git a/core/dbt/config/renderer.py b/core/dbt/config/renderer.py index 1b269176be6..7357a3a57bc 100644 --- a/core/dbt/config/renderer.py +++ b/core/dbt/config/renderer.py @@ -1,137 +1,212 @@ -from typing import Dict, Any +from typing import Dict, Any, Tuple, Optional, Union from dbt.clients.jinja import get_rendered -from dbt.exceptions import DbtProfileError from dbt.exceptions import DbtProjectError from dbt.exceptions import RecursionException +from dbt.node_types import NodeType from dbt.utils import deep_map -class ConfigRenderer: - """A renderer provides configuration rendering for a given set of cli - variables and a render type. - """ - def __init__(self, context: Dict[str, Any]): +Keypath = Tuple[Union[str, int], ...] + + +class BaseRenderer: + def __init__(self, context: Dict[str, Any]) -> None: self.context = context - @staticmethod - def _is_deferred_render(keypath): + @property + def name(self): + return 'Rendering' + + def should_render_keypath(self, keypath: Keypath) -> bool: + return True + + def render_entry(self, value: Any, keypath: Keypath) -> Any: + if not self.should_render_keypath(keypath): + return value + + return self.render_value(value, keypath) + + def render_value( + self, value: Any, keypath: Optional[Keypath] = None + ) -> Any: + # keypath is ignored. + # if it wasn't read as a string, ignore it + if not isinstance(value, str): + return value + return str(get_rendered(value, self.context)) + + def render_data( + self, data: Dict[str, Any] + ) -> Dict[str, Any]: + try: + return deep_map(self.render_entry, data) + except RecursionException: + raise DbtProjectError( + f'Cycle detected: {self.name} input has a reference to itself', + project=data + ) + + +class DbtProjectYamlRenderer(BaseRenderer): + def __init__( + self, context: Dict[str, Any], version: Optional[int] = None + ) -> None: + super().__init__(context) + self.version: Optional[int] = version + + @property + def name(self): + 'Project config' + + def get_package_renderer(self) -> BaseRenderer: + return PackageRenderer(self.context) + + def should_render_keypath_v1(self, keypath: Keypath) -> bool: if not keypath: - return False + return True first = keypath[0] # run hooks if first in {'on-run-start', 'on-run-end', 'query-comment'}: - return True + return False # models have two things to avoid - if first in {'seeds', 'models', 'snapshots'}: + if first in {'seeds', 'models', 'snapshots', 'seeds'}: # model-level hooks if 'pre-hook' in keypath or 'post-hook' in keypath: - return True + return False # model-level 'vars' declarations if 'vars' in keypath: - return True + return False - return False + return True - def _render_project_entry(self, value, keypath): - """Render an entry, in case it's jinja. This is meant to be passed to - deep_map. + def should_render_keypath_v2(self, keypath: Keypath) -> bool: + if not keypath: + return True - If the parsed entry is a string and has the name 'port', this will - attempt to cast it to an int, and on failure will return the parsed - string. + first = keypath[0] + # run hooks are not rendered + if first in {'on-run-start', 'on-run-end', 'query-comment'}: + return False - :param value Any: The value to potentially render - :param key str: The key to convert on. - :return Any: The rendered entry. - """ - # the project name is never rendered - if keypath == ('name',): - return value - # query comments and hooks should be treated as raw sql, they'll get - # rendered later. - # Same goes for 'vars' declarations inside 'models'/'seeds' - if self._is_deferred_render(keypath): - return value + # don't render vars blocks until runtime + if first == 'vars': + return False - return self.render_value(value) + if first in {'seeds', 'models', 'snapshots', 'seeds'}: + # model-level hooks + if 'pre-hook' in keypath or 'post-hook' in keypath: + return False + # model-level 'vars' declarations + if 'vars' in keypath: + return False - def render_value(self, value, keypath=None): - # keypath is ignored. - # if it wasn't read as a string, ignore it - if not isinstance(value, str): - return value - return str(get_rendered(value, self.context)) + return True + + def should_render_keypath(self, keypath: Keypath) -> bool: + if self.version == 2: + return self.should_render_keypath_v2(keypath) + else: # could be None + return self.should_render_keypath_v1(keypath) + + def render_data( + self, data: Dict[str, Any] + ) -> Dict[str, Any]: + if self.version is None: + self.version = data.get('current-version') + + try: + return deep_map(self.render_entry, data) + except RecursionException: + raise DbtProjectError( + f'Cycle detected: {self.name} input has a reference to itself', + project=data + ) + + +class ProfileRenderer(BaseRenderer): + @property + def name(self): + 'Profile' + + def render_entry(self, value, keypath): + result = super().render_entry(value, keypath) - def _render_profile_data(self, value, keypath): - result = self.render_value(value) if len(keypath) == 1 and keypath[-1] == 'port': try: - result = int(result) + return int(result) except ValueError: # let the validator or connection handle this pass return result - @staticmethod - def _is_schema_test(keypath) -> bool: - # we got passed an UnparsedSourceDefinition - if len(keypath) > 2 and keypath[0] == 'tables': - if keypath[2] == 'tests': - return True - elif keypath[2] == 'columns': - if len(keypath) > 4 and keypath[4] == 'tests': - return True - return False - def _render_schema_source_data(self, value, keypath): - # things to not render: - # - descriptions - # - test arguments - if len(keypath) > 0 and keypath[-1] == 'description': - return value - elif self._is_schema_test(keypath): - return value +class SchemaYamlRenderer(BaseRenderer): + DOCUMENTABLE_NODES = frozenset( + n.pluralize() for n in NodeType.documentable() + ) - return self.render_value(value) + @property + def name(self): + return 'Rendering yaml' - def render_project(self, as_parsed): - """Render the parsed data, returning a new dict (or whatever was read). + def _is_norender_key(self, keypath: Keypath) -> bool: """ - try: - return deep_map(self._render_project_entry, as_parsed) - except RecursionException: - raise DbtProjectError( - 'Cycle detected: Project input has a reference to itself', - project=as_parsed - ) + models: + - name: blah + - description: blah + tests: ... + - columns: + - name: + - description: blah + tests: ... + + Return True if it's tests or description - those aren't rendered + """ + if len(keypath) >= 2 and keypath[1] in ('tests', 'description'): + return True - def render_profile_data(self, as_parsed): - """Render the chosen profile entry, as it was parsed.""" - try: - return deep_map(self._render_profile_data, as_parsed) - except RecursionException: - raise DbtProfileError( - 'Cycle detected: Profile input has a reference to itself', - project=as_parsed - ) + if ( + len(keypath) >= 4 and + keypath[1] == 'columns' and + keypath[3] in ('tests', 'description') + ): + return True - def render_schema_source(self, as_parsed): - try: - return deep_map(self._render_schema_source_data, as_parsed) - except RecursionException: - raise DbtProfileError( - 'Cycle detected: schema.yml input has a reference to itself', - project=as_parsed - ) + return False - def render_packages_data(self, as_parsed): - try: - return deep_map(self.render_value, as_parsed) - except RecursionException: - raise DbtProfileError( - 'Cycle detected: schema.yml input has a reference to itself', - project=as_parsed - ) + # don't render descriptions or test keyword arguments + def should_render_keypath(self, keypath: Keypath) -> bool: + if len(keypath) < 2: + return True + + if keypath[0] not in self.DOCUMENTABLE_NODES: + return True + + if len(keypath) < 3: + return True + + if keypath[0] == NodeType.Source.pluralize(): + if keypath[2] == 'description': + return False + if keypath[2] == 'tables': + if self._is_norender_key(keypath[3:]): + return False + elif keypath[0] == NodeType.Macro.pluralize(): + if keypath[2] == 'arguments': + if self._is_norender_key(keypath[3:]): + return False + elif self._is_norender_key(keypath[1:]): + return False + else: # keypath[0] in self.DOCUMENTABLE_NODES: + if self._is_norender_key(keypath[1:]): + return False + return True + + +class PackageRenderer(BaseRenderer): + @property + def name(self): + return 'Packages config' diff --git a/core/dbt/config/runtime.py b/core/dbt/config/runtime.py index 0a2a25c529a..515063cf5ca 100644 --- a/core/dbt/config/runtime.py +++ b/core/dbt/config/runtime.py @@ -10,7 +10,7 @@ from .profile import Profile from .project import Project -from .renderer import ConfigRenderer +from .renderer import DbtProjectYamlRenderer, ProfileRenderer from dbt import tracking from dbt.adapters.factory import get_relation_class_by_name from dbt.helper_types import FQNPath, PathSet @@ -42,7 +42,7 @@ class RuntimeConfig(Project, Profile, AdapterRequiredConfig): args: Any profile_name: str cli_vars: Dict[str, Any] - dependencies: Optional[Mapping[str, Project]] = None + dependencies: Optional[Mapping[str, 'RuntimeConfig']] = None def __post_init__(self): self.validate() @@ -53,7 +53,7 @@ def from_parts( project: Project, profile: Profile, args: Any, - dependencies: Optional[Mapping[str, Project]] = None, + dependencies: Optional[Mapping[str, 'RuntimeConfig']] = None, ) -> 'RuntimeConfig': """Instantiate a RuntimeConfig from its components. @@ -121,7 +121,7 @@ def new_project(self, project_root: str) -> 'RuntimeConfig': profile.validate() # load the new project and its packages. Don't pass cli variables. - renderer = ConfigRenderer(generate_target_context(profile, {})) + renderer = DbtProjectYamlRenderer(generate_target_context(profile, {})) project = Project.from_project_root(project_root, renderer) @@ -162,31 +162,51 @@ def validate(self): self.validate_version() @classmethod - def from_args(cls, args: Any) -> 'RuntimeConfig': - """Given arguments, read in dbt_project.yml from the current directory, - read in packages.yml if it exists, and use them to find the profile to - load. + def _get_rendered_profile( + cls, + args: Any, + profile_renderer: ProfileRenderer, + profile_name: Optional[str], + ) -> Profile: + return Profile.render_from_args( + args, profile_renderer, profile_name + ) - :param args: The arguments as parsed from the cli. - :raises DbtProjectError: If the project is invalid or missing. - :raises DbtProfileError: If the profile is invalid or missing. - :raises ValidationException: If the cli variables are invalid. - """ + @classmethod + def collect_parts( + cls: Type['RuntimeConfig'], args: Any + ) -> Tuple[Project, Profile]: # profile_name from the project partial = Project.partial_load(os.getcwd()) # build the profile using the base renderer and the one fact we know cli_vars: Dict[str, Any] = parse_cli_vars(getattr(args, 'vars', '{}')) - renderer = ConfigRenderer(generate_base_context(cli_vars=cli_vars)) - profile_name = partial.render_profile_name(renderer) - profile = Profile.render_from_args( - args, renderer, profile_name + profile_renderer = ProfileRenderer(generate_base_context(cli_vars)) + profile_name = partial.render_profile_name(profile_renderer) + + profile = cls._get_rendered_profile( + args, profile_renderer, profile_name ) # get a new renderer using our target information and render the # project - renderer = ConfigRenderer(generate_target_context(profile, cli_vars)) - project = partial.render(renderer) + ctx = generate_target_context(profile, cli_vars) + project_renderer = DbtProjectYamlRenderer(ctx, partial.config_version) + project = partial.render(project_renderer) + return (project, profile) + + @classmethod + def from_args(cls, args: Any) -> 'RuntimeConfig': + """Given arguments, read in dbt_project.yml from the current directory, + read in packages.yml if it exists, and use them to find the profile to + load. + + :param args: The arguments as parsed from the cli. + :raises DbtProjectError: If the project is invalid or missing. + :raises DbtProfileError: If the profile is invalid or missing. + :raises ValidationException: If the cli variables are invalid. + """ + project, profile = cls.collect_parts(args) return cls.from_parts( project=project, @@ -432,7 +452,7 @@ def from_parts( project: Project, profile: Profile, args: Any, - dependencies: Optional[Mapping[str, Project]] = None, + dependencies: Optional[Mapping[str, 'RuntimeConfig']] = None, ) -> 'RuntimeConfig': """Instantiate a RuntimeConfig from its components. @@ -481,29 +501,16 @@ def from_parts( ) @classmethod - def from_args(cls: Type[RuntimeConfig], args: Any) -> 'RuntimeConfig': - """Given arguments, read in dbt_project.yml from the current directory, - read in packages.yml if it exists, and use them to find the profile to - load. - - :param args: The arguments as parsed from the cli. - :raises DbtProjectError: If the project is invalid or missing. - :raises DbtProfileError: If the profile is invalid or missing. - :raises ValidationException: If the cli variables are invalid. - """ - # profile_name from the project - partial = Project.partial_load(os.getcwd()) - - # build the profile using the base renderer and the one fact we know - cli_vars: Dict[str, Any] = parse_cli_vars(getattr(args, 'vars', '{}')) - renderer = ConfigRenderer(generate_base_context(cli_vars=cli_vars)) - profile_name = partial.render_profile_name(renderer) - + def _get_rendered_profile( + cls, + args: Any, + profile_renderer: ProfileRenderer, + profile_name: Optional[str], + ) -> Profile: try: profile = Profile.render_from_args( - args, renderer, profile_name + args, profile_renderer, profile_name ) - cls = RuntimeConfig # we can return a real runtime config, do that except (DbtProjectError, DbtProfileError) as exc: logger.debug( 'Profile not loaded due to error: {}', exc, exc_info=True @@ -516,16 +523,28 @@ def from_args(cls: Type[RuntimeConfig], args: Any) -> 'RuntimeConfig': profile = UnsetProfile() # disable anonymous usage statistics tracking.do_not_track() + return profile - # get a new renderer using our target information and render the - # project - renderer = ConfigRenderer(generate_target_context(profile, cli_vars)) - project = partial.render(renderer) + @classmethod + def from_args(cls: Type[RuntimeConfig], args: Any) -> 'RuntimeConfig': + """Given arguments, read in dbt_project.yml from the current directory, + read in packages.yml if it exists, and use them to find the profile to + load. + + :param args: The arguments as parsed from the cli. + :raises DbtProjectError: If the project is invalid or missing. + :raises DbtProfileError: If the profile is invalid or missing. + :raises ValidationException: If the cli variables are invalid. + """ + project, profile = cls.collect_parts(args) + if not isinstance(profile, UnsetProfile): + # if it's a real profile, return a real config + cls = RuntimeConfig return cls.from_parts( project=project, profile=profile, - args=args, + args=args ) diff --git a/core/dbt/contracts/connection.py b/core/dbt/contracts/connection.py index e786cf5f748..afc9b57ed24 100644 --- a/core/dbt/contracts/connection.py +++ b/core/dbt/contracts/connection.py @@ -2,7 +2,9 @@ import itertools from dataclasses import dataclass, field from typing import ( - Any, ClassVar, Dict, Tuple, Iterable, Optional, NewType, List, Callable) + Any, ClassVar, Dict, Tuple, Iterable, Optional, NewType, List, Callable, + TypeVar +) from typing_extensions import Protocol from hologram import JsonSchemaMixin diff --git a/core/dbt/deps/resolver.py b/core/dbt/deps/resolver.py index 8f571d35712..f810bab981c 100644 --- a/core/dbt/deps/resolver.py +++ b/core/dbt/deps/resolver.py @@ -4,7 +4,8 @@ from dbt.exceptions import raise_dependency_error, InternalException from dbt.context.target import generate_target_context -from dbt.config import Project, ConfigRenderer, RuntimeConfig +from dbt.config import Project, RuntimeConfig +from dbt.config.renderer import DbtProjectYamlRenderer from dbt.deps.base import BasePackage, PinnedPackage, UnpinnedPackage from dbt.deps.local import LocalUnpinnedPackage from dbt.deps.git import GitUnpinnedPackage @@ -97,7 +98,9 @@ def __iter__(self) -> Iterator[UnpinnedPackage]: def _check_for_duplicate_project_names( - final_deps: List[PinnedPackage], config: Project, renderer: ConfigRenderer + final_deps: List[PinnedPackage], + config: Project, + renderer: DbtProjectYamlRenderer, ): seen: Set[str] = set() for package in final_deps: @@ -123,7 +126,8 @@ def resolve_packages( pending = PackageListing.from_contracts(packages) final = PackageListing() - renderer = ConfigRenderer(generate_target_context(config, config.cli_vars)) + ctx = generate_target_context(config, config.cli_vars) + renderer = DbtProjectYamlRenderer(ctx, config.config_version) while pending: next_pending = PackageListing() diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index b5a6b8ae489..ecfe2f3b7d3 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -597,7 +597,7 @@ def process_node( def load_internal_projects(config): - return dict(config.load_projects(internal_project_names())) + return dict(_load_projects(config, internal_project_names())) def load_internal_manifest(config: RuntimeConfig) -> Manifest: diff --git a/core/dbt/parser/schemas.py b/core/dbt/parser/schemas.py index a45942c8323..ac7f8c97f0b 100644 --- a/core/dbt/parser/schemas.py +++ b/core/dbt/parser/schemas.py @@ -11,7 +11,8 @@ from dbt.adapters.factory import get_adapter from dbt.clients.jinja import get_rendered, add_rendered_test_kwargs from dbt.clients.yaml_helper import load_yaml_text -from dbt.config import RuntimeConfig, ConfigRenderer +from dbt.config import RuntimeConfig +from dbt.config.renderer import SchemaYamlRenderer from dbt.context.context_config import ( ContextConfigType, ContextConfigGenerator, @@ -124,6 +125,15 @@ class SchemaParser(SimpleParser[SchemaTestBlock, ParsedSchemaTestNode]): any refs/descriptions, and return a parsed entity with the appropriate information. """ + def __init__( + self, results, project, root_project, macro_manifest, + ) -> None: + super().__init__(results, project, root_project, macro_manifest) + ctx = generate_target_context( + self.root_project, self.root_project.cli_vars + ) + self.raw_renderer = SchemaYamlRenderer(ctx) + @classmethod def get_compiled_path(cls, block: FileBlock) -> str: # should this raise an error? @@ -323,6 +333,7 @@ def parse_file(self, block: FileBlock) -> None: # mark the file as seen, even if there are no macros in it self.results.get_file(block.file) if dct: + dct = self.raw_renderer.render_data(dct) yaml_block = YamlBlock.from_file_block(block, dct) self._parse_format_version(yaml_block) @@ -520,7 +531,7 @@ def parse_patch( class SourceParser(YamlDocsReader[SourceTarget, ParsedSourceDefinition]): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self._renderer = ConfigRenderer( + self._renderer = SchemaYamlRenderer( generate_target_context( self.root_project, self.root_project.cli_vars ) @@ -536,7 +547,6 @@ def get_unparsed_target(self) -> Iterable[SourceTarget]: for data in self.get_key_dicts(): try: data = self.project.credentials.translate_aliases(data) - data = self._renderer.render_schema_source(data) source = UnparsedSourceDefinition.from_dict(data) except (ValidationError, JSONValidationException) as exc: msg = error_context(path, self.key, data, exc) @@ -586,7 +596,9 @@ def parse_patch( # make sure we don't do duplicate tags from source + table tags = sorted(set(itertools.chain(source.tags, table.tags))) - fqn = [self.project.project_name, source.name, table.name] + # the FQN is project name / path elements... /source_name /table_name + fqn = self.schema_parser.get_fqn_prefix(block.path.relative_path) + fqn.extend([source.name, table.name]) config = self.config_generator.calculate_node_config( config_calls=[], diff --git a/core/dbt/task/debug.py b/core/dbt/task/debug.py index e9204fccf99..14b374e13a6 100644 --- a/core/dbt/task/debug.py +++ b/core/dbt/task/debug.py @@ -12,7 +12,8 @@ from dbt.links import ProfileConfigDocs from dbt.adapters.factory import get_adapter, register_adapter from dbt.version import get_installed_version -from dbt.config import Project, Profile, ConfigRenderer +from dbt.config import Project, Profile +from dbt.config.renderer import DbtProjectYamlRenderer, ProfileRenderer from dbt.context.base import generate_base_context from dbt.context.target import generate_target_context from dbt.clients.yaml_helper import load_yaml_text @@ -142,11 +143,12 @@ def _load_project(self): else: ctx = generate_target_context(self.profile, self.cli_vars) - renderer = ConfigRenderer(ctx) + renderer = DbtProjectYamlRenderer(ctx) try: - self.project = Project.from_project_root(self.project_dir, - renderer) + self.project = Project.from_project_root( + self.project_dir, renderer + ) except dbt.exceptions.DbtConfigError as exc: self.project_fail_details = str(exc) return red('ERROR invalid') @@ -185,7 +187,9 @@ def _choose_profile_names(self) -> Optional[List[str]]: partial = Project.partial_load( os.path.dirname(self.project_path) ) - renderer = ConfigRenderer(generate_base_context(self.cli_vars)) + renderer = DbtProjectYamlRenderer( + generate_base_context(self.cli_vars) + ) project_profile = partial.render_profile_name(renderer) except dbt.exceptions.DbtProjectError: pass @@ -226,7 +230,7 @@ def _choose_target_name(self, profile_name: str): assert self.raw_profile_data is not None raw_profile = self.raw_profile_data[profile_name] - renderer = ConfigRenderer(generate_base_context(self.cli_vars)) + renderer = ProfileRenderer(generate_base_context(self.cli_vars)) target_name, _ = Profile.render_profile( raw_profile=raw_profile, @@ -256,7 +260,7 @@ def _load_profile(self): profile_errors = [] profile_names = self._choose_profile_names() - renderer = ConfigRenderer(generate_base_context(self.cli_vars)) + renderer = ProfileRenderer(generate_base_context(self.cli_vars)) for profile_name in profile_names: try: profile: Profile = QueryCommentedProfile.render_from_args( @@ -372,7 +376,7 @@ def validate_connection(cls, target_dict): raw_profile=profile_data, profile_name='', target_override=target_name, - renderer=ConfigRenderer(generate_base_context({})), + renderer=ProfileRenderer(generate_base_context({})), ) result = cls.attempt_connection(profile) if result is not None: diff --git a/core/dbt/task/deps.py b/core/dbt/task/deps.py index f0f4bd8d165..94522e588b6 100644 --- a/core/dbt/task/deps.py +++ b/core/dbt/task/deps.py @@ -2,7 +2,8 @@ import dbt.deprecations import dbt.exceptions -from dbt.config import UnsetProfileConfig, ConfigRenderer +from dbt.config import UnsetProfileConfig +from dbt.config.renderer import DbtProjectYamlRenderer from dbt.context.target import generate_target_context from dbt.deps.base import downloads_directory from dbt.deps.resolver import resolve_packages @@ -43,7 +44,7 @@ def run(self): with downloads_directory(): final_deps = resolve_packages(packages, self.config) - renderer = ConfigRenderer(generate_target_context( + renderer = DbtProjectYamlRenderer(generate_target_context( self.config, self.config.cli_vars ))