Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":
pydantic version: 1.6.1
pydantic compiled: True
install path: /home/sven/miniconda3/envs/mathub/lib/python3.7/site-packages/pydantic
python version: 3.7.7 (default, May 7 2020, 21:25:33) [GCC 7.3.0]
platform: Linux-4.15.0-122-generic-x86_64-with-debian-buster-sid
optional deps. installed: ['typing-extensions']
from pydantic import BaseModel
from typing import Callable
class Person(BaseModel):
firstname: str = "Joe"
lastname: str = "Kennedy"
fullname: str = property(lambda self: self.firstname + " " + self.lastname)
p1 = Person()
p2 = Person(firstname="Rose")
p3 = Person(firstname="John", fullname="John F Kennedy")
print(p1.fullname, p2.fullname, p3.fullname)
>>> Joe Kennedy Rose Kennedy John Kennedy
Expected the output
>>> .... John F Kennedy
Since I pass fullname="John F Kennedy" when initializing the class, but since I originally defined it as
property(lambda self: ....)
It doesn't seem to want to be overwritten.
Seems like the more generic issue is that a Callable with a default cannot be reassigned a different function.
from pydantic import BaseModel
from typing import Callable
from functools import partial
class Person(BaseModel):
firstname: str = "Joe"
lastname: str = "Kennedy"
fullname: Callable = lambda self: self.firstname + " " + self.lastname
p1 = Person()
p2 = Person(firstname="Rose")
p3 = Person(firstname="John", fullname=lambda:"John F Kennedy")
print(p1.fullname(), p2.fullname(), p3.fullname())
>>> Joe Kennedy Rose Kennedy John Kennedy
That's not a bug.
Pydantic does nothing with instances of FunctionType, property, classmethod, staticmethod or type (all of them defined in pydantic.main.UNTOUCHED_TYPES and can be extended through Config.keep_untouched)
Since fullname never inferred as a field, and just remain normal property object, when you pass fullname key to Person, it's just ignored since by default Config.extra is set to Extra.ignore.
Moreover, that's not how property or even regular methods work in python: you can't overwrite property just on some instance of the class, as properties are defined as descriptors on the class itself.
```py
class Foo:
@property
def a(self):
return 'original'
f = Foo()
f.__dict__['a'] = property(lambda self: 'modified') # this will never work as property
print(f.a) # original (since Foo.a is a descriptor, instance attribute is ignored)
print(f.__dict__['a']) #
Hi @SvenPVoigt
As @MrMrRobat said (thanks for the answer btw!) it's not a bug
An easy workaround could be
from typing import Dict, Optional
from pydantic import BaseModel, validator
class Person(BaseModel):
firstname: str = "Joe"
lastname: str = "Kennedy"
fullname: str = None
@validator('fullname', always=True)
def set_default(cls, v: Optional[str], values: Dict[str, str]) -> str:
if v is None:
return values['firstname'] + ' ' + values['lastname']
return v
p1 = Person()
p2 = Person(firstname="Rose")
p3 = Person(firstname="John", fullname="John F Kennedy")
print(p1.fullname) # Joe Kennedy
print(p2.fullname) # Rose Kennedy
print(p3.fullname) # John F Kennedy
Hope it helps