Skip to content

Commit

Permalink
Improved error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
cknv committed Apr 6, 2016
1 parent 605aedc commit 215d867
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 22 deletions.
5 changes: 5 additions & 0 deletions envargs/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
class BaseError(Exception):
"""Base Error for when envparse fails."""

def __init__(self, message, **extra):
"""Make a new error."""
self.message = message
self.extra = extra


class ParseError(BaseError):
"""Specific Error for when a raw value cannot be parsed."""
Expand Down
9 changes: 9 additions & 0 deletions envargs/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""Smaller helper functions for taking care of repeated things."""


def callables(potential_callables):
"""Ensure that the callables are in fact a sequence."""
if callable(potential_callables):
return [potential_callables]

return potential_callables
26 changes: 12 additions & 14 deletions envargs/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Everthing about vars."""
from . import errors
from . import helpers


class Var:
Expand All @@ -11,7 +12,7 @@ class Var:
def __init__(self, use, validate=None, load_from=None, default=None, err_msg=None):
"""Return a new instance."""
self.use = use
self.validate_with = validate
self.validate_with = helpers.callables(validate)
self.load_from = load_from
self.default = default
self.err_msg = err_msg
Expand All @@ -25,29 +26,26 @@ def __repr__(self):
self.default,
)

def parse(self, value):
def parse(self, value, location):
"""Return the parsed value."""
try:
return self.use(value)
except Exception as err:
raise errors.ParseError(
'Could not parse value.'
'Parsing failed.',
value=value,
location=location,
) from err

def validate(self, value):
def validate(self, value, location):
"""Validate the parsed value."""
if self.validate_with is None:
return

if callable(self.validate_with):
if self.validate_with(value) is False:
for validator in self.validate_with:
if validator(value) is False:
raise errors.ValidationError(
self.err_msg or 'Validation failed.'
self.err_msg or 'Validation failed.',
value=value,
location=location,
)

elif isinstance(self.validate_with, (list, set, tuple)):
for validator in self.validate_with:
if validator(value) is False:
raise errors.ValidationError(
self.err_msg or 'Validation failed.'
)
5 changes: 3 additions & 2 deletions envargs/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ def _load_values(values, fields):
if value is None:
raise errors.ParseError(
'Required field missing.',
location=location,
)

value = field.parse(value)
field.validate(value)
value = field.parse(value, location)
field.validate(value, location)
yield dest, value


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='envargs',
version='0.1.0',
version='0.1.1',

description='Parsing and validation of environment variables',
long_description=long_description,
Expand Down
31 changes: 26 additions & 5 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ def test_parse_fail():
'A_VAR': 'abc',
}

with raises(errors.ParseError):
with raises(errors.ParseError) as err:
parse_dict(values, args)

assert err.value.extra == {
'location': 'A_VAR',
'value': 'abc',
}


def test_validation_with_lambda_fail():
"""Simple case that fails to validate."""
Expand All @@ -37,9 +42,14 @@ def test_validation_with_lambda_fail():
'A_VAR': '1',
}

with raises(errors.ValidationError):
with raises(errors.ValidationError) as err:
parse_dict(values, args)

assert err.value.extra == {
'value': 1,
'location': 'A_VAR',
}


def test_missing_value():
"""Test case that fails because of a missing value."""
Expand All @@ -53,15 +63,22 @@ def test_missing_value():

values = {}

with raises(errors.ParseError):
with raises(errors.ParseError) as err:
parse_dict(values, args)

assert err.value.extra == {
'location': 'A_VAR',
}


def test_fancy_validation_function():
"""Test that fails to validate with a real function."""
def validation_function(value):
if value == 1:
raise errors.ValidationError
raise errors.ValidationError(
'Value not 1',
value=value,
)

args = {
'a_var': Var(
Expand All @@ -75,5 +92,9 @@ def validation_function(value):
'A_VAR': '1',
}

with raises(errors.ValidationError):
with raises(errors.ValidationError) as err:
parse_dict(values, args)

assert err.value.extra == {
'value': 1,
}

0 comments on commit 215d867

Please sign in to comment.