Skip to content

Commit

Permalink
Fix profile yml error handling (#816) (#820)
Browse files Browse the repository at this point in the history
  • Loading branch information
beckjake authored Jul 5, 2018
1 parent 540631f commit 8aba382
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Changes

- Fix the error handling for profiles.yml validation ([#820](https://github.com/fishtown-analytics/dbt/pull/820))
- Make the `--threads` parameter actually change the number of threads used ([#819](https://github.com/fishtown-analytics/dbt/pull/819))
- Use Mapping instead of dict as the base class for APIObject ([#756](https://github.com/fishtown-analytics/dbt/pull/756))
- Write JSON manifest file to disk during compilation ([#761](https://github.com/fishtown-analytics/dbt/pull/761))
Expand Down
11 changes: 5 additions & 6 deletions dbt/api/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,17 @@ def validate(self):
"""
validator = Draft4Validator(self.SCHEMA)

errors = []
errors = set() # make errors a set to avoid duplicates

for error in validator.iter_errors(self.serialize()):
errors.append('.'.join(
errors.add('.'.join(
list(map(str, error.path)) + [error.message]
))

if errors:
raise ValidationException(
'Invalid arguments passed to "{}" instance: {}'
.format(type(self).__name__,
", ".join(errors)))
msg = ('Invalid arguments passed to "{}" instance: {}'.format(
type(self).__name__, ', '.join(errors)))
raise ValidationException(msg)

# implement the Mapping protocol:
# https://docs.python.org/3/library/collections.abc.html
Expand Down
1 change: 1 addition & 0 deletions dbt/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dbt.compat import basestring
from dbt.logger import GLOBAL_LOGGER as logger
import re


class Exception(BaseException):
Expand Down
10 changes: 1 addition & 9 deletions dbt/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,7 @@ class CredentialsValidator(APIObject):
try:
CredentialsValidator(**target_cfg)
except dbt.exceptions.ValidationException as e:
if 'extra keys not allowed' in str(e):
raise DbtProjectError(
"Extra project configuration '{}' is not recognized"
.format('.'.join(e.path)), self)
else:
# TODO : does this fail if eg. project is missing?
raise DbtProjectError(
"Expected project configuration '{}' was not supplied"
.format('.'.join(e.path)), self)
raise DbtProjectError(str(e), self)

def log_warnings(self):
target_cfg = self.run_environment()
Expand Down
85 changes: 85 additions & 0 deletions test/unit/test_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import unittest

import os
import dbt.project


class ProjectTest(unittest.TestCase):
def setUp(self):
self.profiles = {
'test': {
'outputs': {
'test': {
'type': 'postgres',
'threads': 4,
'host': 'database',
'port': 5432,
'user': 'root',
'pass': 'password',
'dbname': 'dbt',
'schema': 'dbt_test'
}
},
'target': 'test'
}
}
self.cfg = {
'name': 'X',
'version': '0.1',
'profile': 'test',
'project-root': os.path.abspath('.'),
}

def test_profile_validate_success(self):
# Make sure we can instantiate + validate a valid profile

project = dbt.project.Project(
cfg=self.cfg,
profiles=self.profiles,
profiles_dir=None
)

project.validate()

def test_profile_validate_missing(self):
del self.profiles['test']['outputs']['test']['schema']

project = dbt.project.Project(
cfg=self.cfg,
profiles=self.profiles,
profiles_dir=None
)

message = r'.*schema.* is a required property.*'
with self.assertRaisesRegexp(dbt.project.DbtProjectError, message):
project.validate()

def test_profile_validate_extra(self):
self.profiles['test']['outputs']['test']['foo'] = 'bar'

project = dbt.project.Project(
cfg=self.cfg,
profiles=self.profiles,
profiles_dir=None
)

message = r'.*not allowed.*foo.* was unexpected.*'
with self.assertRaisesRegexp(dbt.project.DbtProjectError, message):
project.validate()

def test_profile_validate_missing_and_extra(self):
del self.profiles['test']['outputs']['test']['schema']
self.profiles['test']['outputs']['test']['foo'] = 'bar'

project = dbt.project.Project(
cfg=self.cfg,
profiles=self.profiles,
profiles_dir=None
)

unrecognized = r'not allowed.*foo.* was unexpected'
extra = r'schema.* is a required property'
# fun with regexp ordering: want both, don't care about order
message = '.*({0}.*{1}|{1}.*{0}).*'.format(unrecognized, extra)
with self.assertRaisesRegexp(dbt.project.DbtProjectError, message):
project.validate()

0 comments on commit 8aba382

Please sign in to comment.