Skip to content

Commit

Permalink
Bug fix: excludes skipped for aliased nested fields when by_alias=True (
Browse files Browse the repository at this point in the history
#1398)

* Typo in test function name, fix #1397

* Always use a field's real name for includes/excludes

* Add changes.md file
  • Loading branch information
AlexECX committed Apr 18, 2020
1 parent 161a12a commit 92b0bbc
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 9 deletions.
1 change: 1 addition & 0 deletions changes/1397-AlexECX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Always use a field's real name with includes/excludes in `model._iter()`, regardless of `by_alias`.
18 changes: 10 additions & 8 deletions pydantic/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,27 +690,29 @@ def _iter(
value_exclude = ValueItems(self, exclude) if exclude else None
value_include = ValueItems(self, include) if include else None

for k, v in self.__dict__.items():
for field_key, v in self.__dict__.items():
if (
(allowed_keys is not None and k not in allowed_keys)
(allowed_keys is not None and field_key not in allowed_keys)
or (exclude_none and v is None)
or (exclude_defaults and self.__field_defaults__.get(k, _missing) == v)
or (exclude_defaults and self.__field_defaults__.get(field_key, _missing) == v)
):
continue
if by_alias and k in self.__fields__:
k = self.__fields__[k].alias
if by_alias and field_key in self.__fields__:
dict_key = self.__fields__[field_key].alias
else:
dict_key = field_key
if to_dict or value_include or value_exclude:
v = self._get_value(
v,
to_dict=to_dict,
by_alias=by_alias,
include=value_include and value_include.for_element(k),
exclude=value_exclude and value_exclude.for_element(k),
include=value_include and value_include.for_element(field_key),
exclude=value_exclude and value_exclude.for_element(field_key),
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
)
yield k, v
yield dict_key, v

def _calculate_keys(
self,
Expand Down
30 changes: 29 additions & 1 deletion tests/test_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,35 @@ class Model(BaseModel):
assert m.dict(exclude={'e': ..., 'f': {'d'}}) == {'f': {'c': 'foo'}}


def test_advanced_value_inclide():
def test_advanced_exclude_by_alias():
class SubSubModel(BaseModel):
a: str
aliased_b: str = Field(..., alias='b_alias')

class SubModel(BaseModel):
aliased_c: str = Field(..., alias='c_alias')
aliased_d: List[SubSubModel] = Field(..., alias='d_alias')

class Model(BaseModel):
aliased_e: str = Field(..., alias='e_alias')
aliased_f: SubModel = Field(..., alias='f_alias')

m = Model(
e_alias='e',
f_alias=SubModel(c_alias='foo', d_alias=[SubSubModel(a='a', b_alias='b'), SubSubModel(a='c', b_alias='e')]),
)

excludes = {'aliased_f': {'aliased_c': ..., 'aliased_d': {-1: {'a'}}}}
assert m.dict(exclude=excludes, by_alias=True) == {
'e_alias': 'e',
'f_alias': {'d_alias': [{'a': 'a', 'b_alias': 'b'}, {'b_alias': 'e'}]},
}

excludes = {'aliased_e': ..., 'aliased_f': {'aliased_d'}}
assert m.dict(exclude=excludes, by_alias=True) == {'f_alias': {'c_alias': 'foo'}}


def test_advanced_value_include():
class SubSubModel(BaseModel):
a: str
b: str
Expand Down

0 comments on commit 92b0bbc

Please sign in to comment.