mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
Merge pull request #712 from MrMrRobat/__dict__-instead-of-__values__
Rename BaseModel.__values__ to BaseModel.__dict__
This commit is contained in:
+2
-1
@@ -3,10 +3,11 @@
|
||||
History
|
||||
-------
|
||||
|
||||
|
||||
v0.32 (unreleased)
|
||||
..................
|
||||
* add model name to ``ValidationError`` error message, #676 by @dmontagu
|
||||
* **breaking change**: remove ``__getattr__`` and rename ``__values__`` to ``__dict__`` on ``BaseModel``,
|
||||
deprecation warning on use ``__values__`` attr, attributes access speed increased up to 14 times, #712 by @MrMrRobat
|
||||
|
||||
v0.31.1 (2019-07-31)
|
||||
....................
|
||||
|
||||
+19
-26
@@ -266,24 +266,17 @@ class BaseModel(metaclass=MetaModel):
|
||||
_custom_root_type: bool = False
|
||||
|
||||
Config = BaseConfig
|
||||
__slots__ = ('__values__', '__fields_set__')
|
||||
__slots__ = ('__dict__', '__fields_set__')
|
||||
|
||||
def __init__(__pydantic_self__, **data: Any) -> None:
|
||||
# Uses something other than `self` the first arg to allow "self" as a settable attribute
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
__pydantic_self__.__values__: Dict[str, Any] = {}
|
||||
__pydantic_self__.__dict__: Dict[str, Any] = {}
|
||||
__pydantic_self__.__fields_set__: 'SetStr' = set()
|
||||
values, fields_set, _ = validate_model(__pydantic_self__, data)
|
||||
object.__setattr__(__pydantic_self__, '__values__', values)
|
||||
object.__setattr__(__pydantic_self__, '__dict__', values)
|
||||
object.__setattr__(__pydantic_self__, '__fields_set__', fields_set)
|
||||
|
||||
@no_type_check
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self.__values__[name]
|
||||
except KeyError:
|
||||
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
|
||||
|
||||
@no_type_check
|
||||
def __setattr__(self, name, value):
|
||||
if self.__config__.extra is not Extra.allow and name not in self.__fields__:
|
||||
@@ -295,17 +288,17 @@ class BaseModel(metaclass=MetaModel):
|
||||
if error_:
|
||||
raise ValidationError([error_], type(self))
|
||||
else:
|
||||
self.__values__[name] = value_
|
||||
self.__dict__[name] = value_
|
||||
self.__fields_set__.add(name)
|
||||
else:
|
||||
self.__values__[name] = value
|
||||
self.__dict__[name] = value
|
||||
self.__fields_set__.add(name)
|
||||
|
||||
def __getstate__(self) -> 'DictAny':
|
||||
return {'__values__': self.__values__, '__fields_set__': self.__fields_set__}
|
||||
return {'__dict__': self.__dict__, '__fields_set__': self.__fields_set__}
|
||||
|
||||
def __setstate__(self, state: 'DictAny') -> None:
|
||||
object.__setattr__(self, '__values__', state['__values__'])
|
||||
object.__setattr__(self, '__dict__', state['__dict__'])
|
||||
object.__setattr__(self, '__fields_set__', state['__fields_set__'])
|
||||
|
||||
def dict(
|
||||
@@ -413,18 +406,18 @@ class BaseModel(metaclass=MetaModel):
|
||||
obj = cls._decompose_class(obj)
|
||||
m = cls.__new__(cls)
|
||||
values, fields_set, _ = validate_model(m, obj)
|
||||
object.__setattr__(m, '__values__', values)
|
||||
object.__setattr__(m, '__dict__', values)
|
||||
object.__setattr__(m, '__fields_set__', fields_set)
|
||||
return m
|
||||
|
||||
@classmethod
|
||||
def construct(cls: Type['Model'], values: 'DictAny', fields_set: 'SetStr') -> 'Model':
|
||||
"""
|
||||
Creates a new model and set __values__ without any validation, thus values should already be trusted.
|
||||
Creates a new model and set __dict__ without any validation, thus values should already be trusted.
|
||||
Chances are you don't want to use this method directly.
|
||||
"""
|
||||
m = cls.__new__(cls)
|
||||
object.__setattr__(m, '__values__', values)
|
||||
object.__setattr__(m, '__dict__', values)
|
||||
object.__setattr__(m, '__fields_set__', fields_set)
|
||||
return m
|
||||
|
||||
@@ -448,11 +441,11 @@ class BaseModel(metaclass=MetaModel):
|
||||
"""
|
||||
if include is None and exclude is None and update is None:
|
||||
# skip constructing values if no arguments are passed
|
||||
v = self.__values__
|
||||
v = self.__dict__
|
||||
else:
|
||||
allowed_keys = self._calculate_keys(include=include, exclude=exclude, skip_defaults=False, update=update)
|
||||
if allowed_keys is None:
|
||||
v = {**self.__values__, **(update or {})}
|
||||
v = {**self.__dict__, **(update or {})}
|
||||
else:
|
||||
v = {
|
||||
**dict(
|
||||
@@ -595,7 +588,7 @@ class BaseModel(metaclass=MetaModel):
|
||||
value_exclude = ValueItems(self, exclude) if exclude else None
|
||||
value_include = ValueItems(self, include) if include else None
|
||||
|
||||
for k, v in self.__values__.items():
|
||||
for k, v in self.__dict__.items():
|
||||
if allowed_keys is None or k in allowed_keys:
|
||||
yield k, self._get_value(
|
||||
v,
|
||||
@@ -619,7 +612,7 @@ class BaseModel(metaclass=MetaModel):
|
||||
if skip_defaults:
|
||||
keys = self.__fields_set__.copy()
|
||||
else:
|
||||
keys = set(self.__values__.keys())
|
||||
keys = set(self.__dict__.keys())
|
||||
|
||||
if include is not None:
|
||||
if isinstance(include, dict):
|
||||
@@ -652,16 +645,16 @@ class BaseModel(metaclass=MetaModel):
|
||||
return '{}{}{}'.format(
|
||||
self.__class__.__name__,
|
||||
divider,
|
||||
divider.join('{}={}'.format(k, truncate(v)) for k, v in self.__values__.items()),
|
||||
divider.join('{}={}'.format(k, truncate(v)) for k, v in self.__dict__.items()),
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.to_string()
|
||||
|
||||
def __dir__(self) -> 'ListStr':
|
||||
ret = list(object.__dir__(self))
|
||||
ret.extend(self.__values__.keys())
|
||||
return ret
|
||||
@property
|
||||
def __values__(self) -> 'DictStrAny':
|
||||
warnings.warn('`__values__` attribute is deprecated, use `__dict__` instead', DeprecationWarning)
|
||||
return self.__dict__
|
||||
|
||||
|
||||
def create_model(
|
||||
|
||||
@@ -995,3 +995,25 @@ def test_nested_init(model):
|
||||
assert m.self == 'Top Model'
|
||||
assert m.nest.self == 'Nested Model'
|
||||
assert m.nest.modified_number == 1
|
||||
|
||||
|
||||
def test_values_attr_deprecation():
|
||||
class Model(BaseModel):
|
||||
foo: int
|
||||
bar: str
|
||||
|
||||
m = Model(foo=4, bar='baz')
|
||||
with pytest.warns(DeprecationWarning, match='`__values__` attribute is deprecated, use `__dict__` instead'):
|
||||
assert m.__values__ == m.__dict__
|
||||
|
||||
|
||||
def test_init_inspection():
|
||||
class Foobar(BaseModel):
|
||||
x: int
|
||||
|
||||
def __init__(self, **data) -> None:
|
||||
with pytest.raises(AttributeError):
|
||||
assert self.x
|
||||
super().__init__(**data)
|
||||
|
||||
Foobar(x=1)
|
||||
|
||||
Reference in New Issue
Block a user