Skip to content

Commit

Permalink
Fix seeds in dependencies
Browse files Browse the repository at this point in the history
Modified a test to cover the bug
Update the FilePath definition
Add a new attribute to seeds (seed_file_path)
Test fixes
Added --no-version-check flag to dbt seed
  • Loading branch information
Jacob Beck committed Sep 27, 2019
1 parent 78a199f commit d246bab
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 93 deletions.
11 changes: 7 additions & 4 deletions core/dbt/clients/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@ def find_matching(root_path,
for local_file in local_files:
absolute_path = os.path.join(current_path, local_file)
relative_path = os.path.relpath(
absolute_path, absolute_path_to_search)
absolute_path, absolute_path_to_search
)

if fnmatch.fnmatch(local_file, file_pattern):
matching.append({
'searched_path': relative_path_to_search,
'absolute_path': absolute_path,
'relative_path': relative_path,
'searched_path': os.path.normcase(
relative_path_to_search
),
'absolute_path': os.path.normcase(absolute_path),
'relative_path': os.path.normcase(relative_path),
})

return matching
Expand Down
10 changes: 8 additions & 2 deletions core/dbt/context/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import agate
import json
import os
from typing import Union, Callable

from dbt.adapters.factory import get_adapter
from dbt.node_types import NodeType
Expand All @@ -8,6 +10,8 @@

import dbt.clients.jinja
import dbt.clients.agate_helper
from dbt.contracts.graph.compiled import CompiledSeedNode
from dbt.contracts.graph.parsed import ParsedSeedNode
import dbt.exceptions
import dbt.flags
import dbt.tracking
Expand Down Expand Up @@ -353,9 +357,11 @@ def generate_config_context(cli_vars):
return _add_tracking(context)


def _build_load_agate_table(model):
def _build_load_agate_table(
model: Union[ParsedSeedNode, CompiledSeedNode]
) -> Callable[[], agate.Table]:
def load_agate_table():
path = model.original_file_path
path = model.seed_file_path
try:
table = dbt.clients.agate_helper.from_csv(path)
except ValueError as e:
Expand Down
10 changes: 9 additions & 1 deletion core/dbt/contracts/graph/compiled.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
)
from dbt.node_types import NodeType
from dbt.contracts.util import Replaceable
from dbt.exceptions import InternalException

from hologram import JsonSchemaMixin
from dataclasses import dataclass, field
Expand Down Expand Up @@ -87,6 +88,13 @@ class CompiledRPCNode(CompiledNode):
@dataclass
class CompiledSeedNode(CompiledNode):
resource_type: NodeType = field(metadata={'restrict': [NodeType.Seed]})
seed_file_path: str = ''

def __post_init__(self):
if self.seed_file_path == '':
raise InternalException(
'Seeds should always have a seed_file_path'
)

@property
def empty(self):
Expand Down Expand Up @@ -191,7 +199,7 @@ def parsed_instance_for(compiled: CompiledNode) -> ParsedNode:
raise ValueError('invalid resource_type: {}'
.format(compiled.resource_type))

# validate=False to allow extra keys from copmiling
# validate=False to allow extra keys from compiling
return cls.from_dict(compiled.to_dict(), validate=False)


Expand Down
25 changes: 20 additions & 5 deletions core/dbt/contracts/graph/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,31 @@
class FilePath(JsonSchemaMixin):
searched_path: str
relative_path: str
absolute_path: str
project_root: str

@property
def search_key(self):
# TODO: should this be project root + original_file_path?
def search_key(self) -> str:
# TODO: should this be project name + path relative to project root?
return self.absolute_path

@property
def original_file_path(self):
return os.path.join(self.searched_path, self.relative_path)
def full_path(self) -> str:
# useful for symlink preservation
return os.path.normcase(os.path.join(
self.project_root, self.searched_path, self.relative_path
))

@property
def absolute_path(self) -> str:
return os.path.normcase(os.path.abspath(self.full_path))

@property
def original_file_path(self) -> str:
# this is mostly used for reporting errors. It doesn't show the project
# name, should it?
return os.path.join(
self.searched_path, self.relative_path
)


@dataclass
Expand Down
7 changes: 7 additions & 0 deletions core/dbt/contracts/graph/parsed.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,13 @@ class ParsedRPCNode(ParsedNode):
@dataclass
class ParsedSeedNode(ParsedNode):
resource_type: NodeType = field(metadata={'restrict': [NodeType.Seed]})
seed_file_path: str = ''

def __post_init__(self):
if self.seed_file_path == '':
raise dbt.exceptions.InternalException(
'Seeds should always have a seed_file_path'
)

@property
def empty(self):
Expand Down
4 changes: 2 additions & 2 deletions core/dbt/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,16 +823,16 @@ def parse_args(args):
compile_sub = _build_compile_subparser(subs, base_subparser)
generate_sub = _build_docs_generate_subparser(docs_subs, base_subparser)
test_sub = _build_test_subparser(subs, base_subparser)
seed_sub = _build_seed_subparser(subs, base_subparser)
# --threads, --no-version-check
_add_common_arguments(run_sub, compile_sub, generate_sub, test_sub,
rpc_sub)
rpc_sub, seed_sub)
# --models, --exclude
_add_selection_arguments(run_sub, compile_sub, generate_sub, test_sub)
_add_selection_arguments(snapshot_sub, models_name='select')
# --full-refresh
_add_table_mutability_arguments(run_sub, compile_sub)

_build_seed_subparser(subs, base_subparser)
_build_docs_serve_subparser(docs_subs, base_subparser)
_build_source_snapshot_freshness_subparser(source_subs, base_subparser)
_build_run_operation_subparser(subs, base_subparser)
Expand Down
12 changes: 3 additions & 9 deletions core/dbt/parser/hooks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
from dataclasses import dataclass
from typing import Iterable, Iterator, Union, List, Tuple

Expand Down Expand Up @@ -71,16 +70,11 @@ class HookParser(SimpleParser[HookBlock, ParsedHookNode]):
def transform(self, node):
return node

def get_paths(self):
searched_path = '.'
relative_path = 'dbt_project.yml'
absolute_path = os.path.normcase(os.path.abspath(os.path.join(
self.project.project_root, searched_path, relative_path
)))
def get_paths(self) -> List[FilePath]:
path = FilePath(
project_root=self.project.project_root,
searched_path='.',
relative_path='relative_path',
absolute_path=absolute_path,
relative_path='dbt_project.yml',
)
return [path]

Expand Down
14 changes: 10 additions & 4 deletions core/dbt/parser/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from dbt.clients.system import find_matching
from dbt.config import Project
from dbt.contracts.graph.manifest import SourceFile, FilePath
from dbt.exceptions import CompilationException
from dbt.exceptions import CompilationException, InternalException


@dataclass
Expand Down Expand Up @@ -70,9 +70,15 @@ def __iter__(self) -> Iterator[FilePath]:
root = self.project.project_root

for result in find_matching(root, self.relative_dirs, ext):
file_match = FilePath(**{
k: os.path.normcase(v) for k, v in result.items()
})
if 'searched_path' not in result or 'relative_path' not in result:
raise InternalException(
'Invalid result from find_matching: {}'.format(result)
)
file_match = FilePath(
searched_path=result['searched_path'],
relative_path=result['relative_path'],
project_root=root,
)
yield file_match


Expand Down
16 changes: 16 additions & 0 deletions core/dbt/parser/seeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,19 @@ def render_with_context(

def load_file(self, match: FilePath) -> SourceFile:
return SourceFile.seed(match)

def _create_parsetime_node(
self,
block: FileBlock,
path: str,
config: SourceConfig,
name=None,
**kwargs,
) -> ParsedSeedNode:
return super()._create_parsetime_node(
block=block,
path=path,
config=config,
name=name,
seed_file_path=block.path.full_path,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
id
1
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@


select 1 as id
select * from {{ ref('seed') }}
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class TestSimpleDependency(BaseDependencyTest):

@property
def schema(self):
return "local_dependency_006"
return 'local_dependency_006'

@property
def models(self):
return "local_models"
return 'local_models'

def base_schema(self):
return self.unique_schema()
Expand All @@ -51,8 +51,9 @@ def configured_schema(self):

@use_profile('postgres')
def test_postgres_local_dependency(self):
self.run_dbt(["deps"])
results = self.run_dbt(["run"])
self.run_dbt(['deps'])
self.run_dbt(['seed'])
results = self.run_dbt(['run'])
self.assertEqual(len(results), 3)
self.assertEqual({r.node.schema for r in results},
{self.base_schema(), self.configured_schema()})
Expand Down Expand Up @@ -103,6 +104,11 @@ def configured_schema(self):
def test_postgres_local_dependency_out_of_date(self, mock_get):
mock_get.return_value = dbt.semver.VersionSpecifier.from_version_string('0.0.1')
self.run_dbt(['deps'])
# check seed
with self.assertRaises(dbt.exceptions.DbtProjectError) as exc:
self.run_dbt(['seed'])
self.assertIn('--no-version-check', str(exc.exception))
# check run too
with self.assertRaises(dbt.exceptions.DbtProjectError) as exc:
self.run_dbt(['run'])
self.assertIn('--no-version-check', str(exc.exception))
Expand All @@ -112,6 +118,7 @@ def test_postgres_local_dependency_out_of_date(self, mock_get):
def test_postgres_local_dependency_out_of_date_no_check(self, mock_get):
mock_get.return_value = dbt.semver.VersionSpecifier.from_version_string('0.0.1')
self.run_dbt(['deps'])
self.run_dbt(['seed', '--no-version-check'])
results = self.run_dbt(['run', '--no-version-check'])
self.assertEqual(len(results), 3)

Expand Down
Loading

0 comments on commit d246bab

Please sign in to comment.