mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
simplify Union field choice
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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] = ...
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user