simplify Union field choice

This commit is contained in:
Samuel Colvin
2017-05-08 19:08:16 +01:00
parent 24b9fdcd86
commit 242995beb6
5 changed files with 29 additions and 17 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ def type_json(type_: type):
return str(type_)
Error = namedtuple('Error', ['exc', 'track_type', 'index'])
Error = namedtuple('Error', ['exc', 'track', 'index'])
def jsonify_errors(e):
@@ -20,7 +20,7 @@ def jsonify_errors(e):
elif isinstance(e, Error):
d = {
'error_type': e.exc.__class__.__name__,
'track': type_json(e.track_type),
'track': type_json(e.track),
'index': e.index,
}
if isinstance(e.exc, ValidationError):
+4 -10
View File
@@ -175,20 +175,14 @@ class Field:
return result, None
def _validate_singleton(self, tracks, v, model, index=None):
result, errors = ..., []
errors = []
for track in tracks:
value, exc = track.validate(v, model, self)
if exc:
errors.append(Error(exc, track.type_, index))
elif isinstance(v, track.type_):
# exact match: return immediately
return value, None
else:
result = value
if result is not ...:
return result, None
else:
return v, errors[0] if len(tracks) == 1 else errors
return value, None
return v, errors[0] if len(tracks) == 1 else errors
def __repr__(self):
return f'<Field {self}>'
@@ -233,7 +227,7 @@ class ValidatorRoute:
v = validator(v, model=model, field=field)
else:
v = validator(model, v)
except (ValueError, TypeError, ImportError) as e:
except (ValueError, TypeError) as e:
return v, e
return v, None
+5 -1
View File
@@ -105,7 +105,11 @@ class Module:
@classmethod
def validate(cls, value):
return import_string(value)
try:
return import_string(value)
except ImportError as e:
# errors must be TypeError or ValueError
raise ValueError(str(e)) from e
class DSN(str):
+15 -4
View File
@@ -18,7 +18,7 @@ def test_str_bytes():
)
m = StrBytesModel(v=b'b')
assert m.v == b'b'
assert m.v == 'b'
with pytest.raises(ValidationError) as exc_info:
StrBytesModel(v=None)
@@ -50,7 +50,7 @@ def test_str_bytes_none():
assert m.v == 's'
m = StrBytesModel(v=b'b')
assert m.v == b'b'
assert m.v == 'b'
m = StrBytesModel(v=None)
assert m.v is None
@@ -73,14 +73,14 @@ def test_union_int_str():
assert m.v == 123
m = Model(v='123')
assert m.v == '123'
assert m.v == 123
m = Model(v=b'foobar')
assert m.v == 'foobar'
# here both validators work and it's impossible to work out which value "closer"
m = Model(v=12.2)
assert m.v == '12.2'
assert m.v == 12
with pytest.raises(ValidationError) as exc_info:
Model(v=None)
@@ -104,6 +104,17 @@ def test_union_int_str():
}""" == exc_info.value.json(2)
def test_union_priority():
class ModelOne(BaseModel):
v: Union[int, str] = ...
class ModelTwo(BaseModel):
v: Union[str, int] = ...
assert ModelOne(v='123').v == 123
assert ModelTwo(v='123').v == '123'
def test_typed_list():
class Model(BaseModel):
v: List[int] = ...
+3
View File
@@ -76,6 +76,9 @@ class ModuleModel(BaseModel):
def test_module_import():
m = ModuleModel()
assert m.module == os.path
with pytest.raises(ValidationError) as exc_info:
ModuleModel(module='foobar')
assert '"\\"foobar\\" doesn\'t look like a module path"' in exc_info.value.args[0]
class CheckModel(BaseModel):