fix: support plain typing.Tuple (#2133)

closes #2132
This commit is contained in:
Eric Jolibois
2020-11-30 18:59:46 +01:00
committed by GitHub
parent c0ac53b757
commit 4169b1e2fa
3 changed files with 22 additions and 12 deletions
+1
View File
@@ -0,0 +1 @@
Support plain `typing.Tuple` type
+15 -9
View File
@@ -346,7 +346,6 @@ class ModelField(Representation):
Note: this method is **not** idempotent (because _type_analysis is not idempotent),
e.g. calling it it multiple times may modify the field and configure it incorrectly.
"""
self._set_default_and_type()
if self.type_.__class__ == ForwardRef:
# self.type_ is currently a ForwardRef and there's nothing we can do now,
@@ -448,14 +447,19 @@ class ModelField(Representation):
return
if issubclass(origin, Tuple): # type: ignore
self.shape = SHAPE_TUPLE
self.sub_fields = []
for i, t in enumerate(get_args(self.type_)):
if t is Ellipsis:
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_TUPLE_ELLIPSIS
return
self.sub_fields.append(self._create_sub_type(t, f'{self.name}_{i}'))
# origin == Tuple without item type
if not get_args(self.type_):
self.type_ = Any
self.shape = SHAPE_TUPLE_ELLIPSIS
else:
self.shape = SHAPE_TUPLE
self.sub_fields = []
for i, t in enumerate(get_args(self.type_)):
if t is Ellipsis:
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_TUPLE_ELLIPSIS
return
self.sub_fields.append(self._create_sub_type(t, f'{self.name}_{i}'))
return
if issubclass(origin, List):
@@ -605,6 +609,8 @@ class ModelField(Representation):
e: errors_.PydanticTypeError
if self.shape == SHAPE_LIST:
e = errors_.ListError()
elif self.shape in (SHAPE_TUPLE, SHAPE_TUPLE_ELLIPSIS):
e = errors_.TupleError()
elif self.shape == SHAPE_SET:
e = errors_.SetError()
elif self.shape == SHAPE_FROZENSET:
+6 -3
View File
@@ -2341,21 +2341,24 @@ def test_generic_without_params():
class Model(BaseModel):
generic_list: List
generic_dict: Dict
generic_tuple: Tuple
m = Model(generic_list=[0, 'a'], generic_dict={0: 'a', 'a': 0})
assert m.dict() == {'generic_list': [0, 'a'], 'generic_dict': {0: 'a', 'a': 0}}
m = Model(generic_list=[0, 'a'], generic_dict={0: 'a', 'a': 0}, generic_tuple=(1, 'q'))
assert m.dict() == {'generic_list': [0, 'a'], 'generic_dict': {0: 'a', 'a': 0}, 'generic_tuple': (1, 'q')}
def test_generic_without_params_error():
class Model(BaseModel):
generic_list: List
generic_dict: Dict
generic_tuple: Tuple
with pytest.raises(ValidationError) as exc_info:
Model(generic_list=0, generic_dict=0)
Model(generic_list=0, generic_dict=0, generic_tuple=0)
assert exc_info.value.errors() == [
{'loc': ('generic_list',), 'msg': 'value is not a valid list', 'type': 'type_error.list'},
{'loc': ('generic_dict',), 'msg': 'value is not a valid dict', 'type': 'type_error.dict'},
{'loc': ('generic_tuple',), 'msg': 'value is not a valid tuple', 'type': 'type_error.tuple'},
]