Skip to content

Commit

Permalink
support self argument (pydantic#632)
Browse files Browse the repository at this point in the history
* support self argument, fix pydantic#629

* support self recursively
  • Loading branch information
samuelcolvin authored Jul 6, 2019
1 parent e4b285a commit 34f271e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ v0.30 (unreleased)
* fix unparameterized generic type schema generation, #625 by @dmontagu
* fix schema generation with multiple/circular references to the same model, #621 by @tiangolo and @wongpat
* support custom root types, #628 by @koxudaxi
* support ``self`` as a field name in ``parse_obj``, #632 by @samuelcolvin

v0.29 (2019-06-19)
..................
Expand Down
11 changes: 8 additions & 3 deletions pydantic/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,12 @@ def parse_obj(cls: Type['Model'], obj: Any) -> 'Model':
except (TypeError, ValueError) as e:
exc = TypeError(f'{cls.__name__} expected dict not {type(obj).__name__}')
raise ValidationError([ErrorWrapper(exc, loc='__obj__')]) from e
return cls(**obj)

m = cls.__new__(cls)
values, fields_set, _ = validate_model(m, obj)
object.__setattr__(m, '__values__', values)
object.__setattr__(m, '__fields_set__', fields_set)
return m

@classmethod
def parse_raw(
Expand Down Expand Up @@ -472,14 +477,14 @@ def __get_validators__(cls) -> 'CallableGenerator':
@classmethod
def validate(cls: Type['Model'], value: Any) -> 'Model':
if isinstance(value, dict):
return cls(**value)
return cls.parse_obj(value)
elif isinstance(value, cls):
return value.copy()
elif cls.__config__.orm_mode:
return cls.from_orm(value)
else:
with change_exception(DictError, TypeError, ValueError):
return cls(**dict(value))
return cls.parse_obj(value)

@classmethod
def _decompose_class(cls: Type['Model'], obj: Any) -> GetterDict:
Expand Down
26 changes: 26 additions & 0 deletions tests/test_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,3 +880,29 @@ class Spam(BaseModel):
assert Spam(c=Foo(a='123')).dict() == {'c': {'a': 123}}
with pytest.raises(ValidationError):
Spam(c=Bar(b='123'))


def test_self():
class Model(BaseModel):
self: str

m = Model.parse_obj(dict(self='some value'))
assert m.dict() == {'self': 'some value'}
assert m.self == 'some value'
assert m.schema() == {
'title': 'Model',
'type': 'object',
'properties': {'self': {'title': 'Self', 'type': 'string'}},
'required': ['self'],
}


def test_self_recursive():
class SubModel(BaseModel):
self: int

class Model(BaseModel):
sm: SubModel

m = Model.parse_obj({'sm': {'self': '123'}})
assert m.dict() == {'sm': {'self': 123}}

0 comments on commit 34f271e

Please sign in to comment.