annotation only fields first

This commit is contained in:
Samuel Colvin
2017-07-08 18:50:59 +01:00
parent 044fd42f4f
commit 5efa54d80d
6 changed files with 36 additions and 36 deletions
+1
View File
@@ -10,6 +10,7 @@ v0.4.0 (2017-XX-XX)
* simplify error display
* use unicode ellipsis in ``truncate``
* add ``parse_obj``, ``parse_raw`` and ``parse_file`` helper functions #58
* switch annotation only fields to come first in fields list not last
v0.3.0 (2017-06-21)
...................
+9 -9
View File
@@ -10,9 +10,9 @@ class TestPydantic:
def __init__(self, allow_extra):
class Model(BaseModel):
id: int = ...
client_name: constr(max_length=255) = ...
sort_index: float = ...
id: int
client_name: constr(max_length=255)
sort_index: float
# client_email: EmailStr = None
client_phone: constr(max_length=255) = None
@@ -23,15 +23,15 @@ class TestPydantic:
contractor: PositiveInt = None
upstream_http_referrer: constr(max_length=1023) = None
grecaptcha_response: constr(min_length=20, max_length=1000) = ...
grecaptcha_response: constr(min_length=20, max_length=1000)
last_updated: datetime = None
class Skill(BaseModel):
subject: str = ...
subject_id: int = ...
category: str = ...
qual_level: str = ...
qual_level_id: int = ...
subject: str
subject_id: int
category: str
qual_level: str
qual_level_id: int
qual_level_ranking: float = 0
skills: List[Skill] = []
+3 -3
View File
@@ -234,7 +234,7 @@ The ellipsis notation ``...`` will not work with mypy, you need to use annotatio
.. warning::
Be aware that using annotation only fields will alter the order of your fields in metadata and errors:
annotation only fields will always come last, but still in the order they were defined.
annotation only fields will always come first, but still in the order they were defined.
To get round this you can use the ``Required`` (via ``from pydantic import Required``) field as an alias for
ellipses or annotation only.
@@ -247,8 +247,8 @@ a model.
.. warning::
However be warned: immutability in python is never strict. If developers are determined/stupid they can always
modify a so called "immutable" object
Immutability in python is never strict. If developers are determined/stupid they can always
modify a so-called "immutable" object.
.. literalinclude:: examples/mutation.py
+17 -18
View File
@@ -48,29 +48,18 @@ class MetaModel(type):
fields.update(base.__fields__)
config = inherit_config(base.config, config)
annotations = namespace.get('__annotations__')
config = inherit_config(namespace.get('Config'), config)
class_validators = {n: f for n, f in namespace.items()
if n.startswith('validate_') and isinstance(f, FunctionType)}
class_validators = {
n: f for n, f in namespace.items() if n.startswith('validate_') and isinstance(f, FunctionType)
}
for f in fields.values():
f.set_config(config)
for var_name, value in namespace.items():
if var_name.startswith('_') or isinstance(value, TYPE_BLACKLIST):
continue
fields[var_name] = Field.infer(
name=var_name,
value=value,
annotation=annotations.pop(var_name, None) if annotations else None,
class_validators=class_validators,
config=config,
)
if annotations:
for ann_name, ann_type in annotations.items():
if ann_name.startswith('_'):
continue
annotations = namespace.get('__annotations__', {})
# annotation only fields need to come first in fields
for ann_name, ann_type in annotations.items():
if not ann_name.startswith('_') and ann_name not in namespace:
fields[ann_name] = Field.infer(
name=ann_name,
value=...,
@@ -79,6 +68,16 @@ class MetaModel(type):
config=config,
)
for var_name, value in namespace.items():
if not var_name.startswith('_') and not isinstance(value, TYPE_BLACKLIST):
fields[var_name] = Field.infer(
name=var_name,
value=value,
annotation=annotations.get(var_name),
class_validators=class_validators,
config=config,
)
new_namespace = {
'config': config,
'__fields__': fields,
+5 -5
View File
@@ -397,16 +397,16 @@ _a:
def test_annotation_config():
class Model(BaseModel):
a: float
b: int = 10
b: float
a: int = 10
_c: str
class Config:
fields = {'a': 'foobar'}
fields = {'b': 'foobar'}
assert list(Model.__fields__.keys()) == ['b', 'a']
assert [f.alias for f in Model.__fields__.values()] == ['b', 'foobar']
assert Model(foobar='123').a == 123.0
assert [f.alias for f in Model.__fields__.values()] == ['foobar', 'a']
assert Model(foobar='123').b == 123.0
def test_success_values_include():
+1 -1
View File
@@ -285,7 +285,7 @@ def test_field_order():
d: dict = {}
# fields are ordered as defined except annotation-only fields come last
assert list(Model.__fields__.keys()) == ['b', 'd', 'c', 'a']
assert list(Model.__fields__.keys()) == ['c', 'a', 'b', 'd']
def test_required():