Fix field of a type that has a default value (#880)

* fix type field

* update changes

* add testcase

* separate test for type fields
This commit is contained in:
Koudai Aono
2019-10-09 22:06:15 +09:00
committed by Samuel Colvin
parent 6a0e5313cb
commit 46db1efdfc
3 changed files with 48 additions and 8 deletions
+1
View File
@@ -0,0 +1 @@
Fix field of a type that has a default value.
+6 -2
View File
@@ -18,7 +18,7 @@ from .parse import Protocol, load_file, load_str_bytes
from .schema import model_schema
from .types import PyObject, StrBytes
from .typing import AnyCallable, AnyType, ForwardRef, is_classvar, resolve_annotations, update_field_forward_refs
from .utils import GetterDict, ValueItems, truncate, validate_field_name
from .utils import GetterDict, ValueItems, lenient_issubclass, truncate, validate_field_name
if TYPE_CHECKING:
from .class_validators import ValidatorListDict
@@ -175,7 +175,11 @@ class ModelMetaclass(ABCMeta):
elif is_valid_field(ann_name):
validate_field_name(bases, ann_name)
value = namespace.get(ann_name, ...)
if isinstance(value, untouched_types) and ann_type != PyObject:
if (
isinstance(value, untouched_types)
and ann_type != PyObject
and not lenient_issubclass(getattr(ann_type, '__origin__', None), Type)
):
continue
fields[ann_name] = ModelField.infer(
name=ann_name,
+41 -6
View File
@@ -1,7 +1,7 @@
import re
from decimal import Decimal
from enum import Enum
from typing import Any, Dict, List, Optional, Set, Tuple, Union
from typing import Any, Dict, List, Optional, Set, Tuple, Type, Union
import pytest
@@ -957,15 +957,50 @@ def test_init_inspection():
Foobar(x=1)
def test_ignored_type():
def foobar():
def test_type_on_annotation():
class FooBar:
pass
class Model(BaseModel):
a: int = foobar
b: int
a: int = int
b: Type[int]
c: Type[int] = int
d: FooBar = FooBar
e: Type[FooBar]
f: Type[FooBar] = FooBar
assert Model.__fields__.keys() == {'b'}
assert Model.__fields__.keys() == {'b', 'c', 'e', 'f'}
def test_assign_type():
class Parent:
def echo(self):
return 'parent'
class Child(Parent):
def echo(self):
return 'child'
class Different:
def echo(self):
return 'different'
class Model(BaseModel):
v: Type[Parent] = Parent
assert Model(v=Parent).v().echo() == 'parent'
assert Model().v().echo() == 'parent'
assert Model(v=Child).v().echo() == 'child'
with pytest.raises(ValidationError) as exc_info:
Model(v=Different)
assert exc_info.value.errors() == [
{
'loc': ('v',),
'msg': 'subclass of Parent expected',
'type': 'type_error.subclass',
'ctx': {'expected_class': 'Parent'},
}
]
def test_optional_subfields():