Make model dump/load symmetric for aliased fields (#160)

* Make dump/load symmetric for aliased fields

* Only populate model fields by alias if enabled

* Document Config.allow_population_by_alias

* Update history

* Fix doc formatting

* Fix doc errors
This commit is contained in:
Ben Demaree
2018-05-24 10:46:03 -05:00
committed by Samuel Colvin
parent 31683f8dc4
commit 62d39d90a7
4 changed files with 35 additions and 0 deletions
+4
View File
@@ -3,6 +3,10 @@
History
-------
v0.9.2 (2018-XX-XX)
...................
* add ``Config.allow_population_by_alias`` #160, thanks @bendemaree
v0.9.1 (2018-05-10)
...................
* allow custom ``get_field_config`` on config classes #159
+13
View File
@@ -262,6 +262,19 @@ Options:
rather than the raw enum - useful if you want to serialise ``model.dict()`` later (default: ``False``)
:fields: extra information on each field, currently just "alias" is allowed (default: ``None``)
:validate_assignment: whether to perform validation on assignment to attributes or not (default: ``False``)
:allow_population_by_alias: whether or not an aliased field may be populated by its name as given by the model
attribute, rather than strictly the alias; please be sure to read the warning below before enabling this (default:
``False``)
.. warning::
Think twice before enabling ``allow_population_by_alias``! Enabling it could cause previously correct code to become
subtly incorrect. As an example, say you have a field named ``card_number`` with the alias ``cardNumber``. With
population by alias disabled (the default), trying to parse an object with only the key ``card_number`` will fail.
However, if you enable population by alias, the ``card_number`` field can now be populated from ``cardNumber``
**or** ``card_number``, and the previously-invalid example object would now be valid. This may be desired for some
use cases, but in others (like the one given here, perhaps!), relaxing strictness with respect to aliases could
introduce bugs.
.. literalinclude:: examples/config.py
+4
View File
@@ -24,6 +24,7 @@ class BaseConfig:
ignore_extra = True
allow_extra = False
allow_mutation = True
allow_population_by_alias = False
use_enum_values = False
fields = {}
validate_assignment = False
@@ -265,6 +266,9 @@ class BaseModel(metaclass=MetaModel):
for name, field in self.__fields__.items():
value = input_data.get(field.alias, MISSING)
if value is MISSING and self.__config__.allow_population_by_alias and field.alt_alias:
value = input_data.get(field.name, MISSING)
if value is MISSING:
if self.__config__.validate_all or field.validate_always:
value = field.default
+14
View File
@@ -292,6 +292,20 @@ def test_alias():
assert Model(_a='different').dict() == {'a': 'different'}
def test_population_by_alias():
class Model(BaseModel):
a: str
class Config:
allow_population_by_alias = True
fields = {
'a': {'alias': '_a'}
}
assert Model(a='different').a == 'different'
assert Model(a='different').dict() == {'a': 'different'}
def test_field_order():
class Model(BaseModel):
c: float