From 2687fae6e99c026aef4e1b1c2b0e0507bd5dc61f Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Wed, 6 Jun 2018 16:36:40 +0100 Subject: [PATCH] copy defaults to values, fix #154 (#192) --- HISTORY.rst | 1 + pydantic/main.py | 15 +++++++++------ tests/test_main.py | 11 ++++++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 141bb12..d0d391a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -10,6 +10,7 @@ v0.10.0 (2018-XX-XX) * **breaking change**: removed ``Config.min_number_size`` and ``Config.max_number_size`` #183 * added error context and ability to redefine error message templates using ``Config.error_msg_templates`` #183 * fix typo in validator exception #150 +* copy defaults to model values, so different models don't share objects #154 v0.9.1 (2018-05-10) ................... diff --git a/pydantic/main.py b/pydantic/main.py index 94a1020..e9b57a0 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -137,6 +137,9 @@ class MetaModel(ABCMeta): return super().__new__(mcs, name, bases, new_namespace) +_missing = object() + + class BaseModel(metaclass=MetaModel): # populated by the metaclass, defined here to help IDEs only __fields__ = {} @@ -261,18 +264,18 @@ class BaseModel(metaclass=MetaModel): errors = [] for name, field in self.__fields__.items(): - value = input_data.get(field.alias, ...) - if value is ... and self.__config__.allow_population_by_alias and field.alt_alias: - value = input_data.get(field.name, ...) + 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 ...: + if value is _missing: if self.__config__.validate_all or field.validate_always: - value = field.default + value = deepcopy(field.default) else: if field.required: errors.append(ErrorWrapper(MissingError(), loc=field.alias, config=self.__config__)) else: - values[name] = field.default + values[name] = deepcopy(field.default) continue v_, errors_ = field.validate(value, values, loc=field.alias, cls=self.__class__) diff --git a/tests/test_main.py b/tests/test_main.py index 157e49f..5867912 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Any +from typing import Any, List import pytest @@ -452,3 +452,12 @@ def test_set_tuple_values(): assert m.foo == {'a', 'b'} assert m.bar == ('c', 'd') assert m.dict() == {'foo': {'a', 'b'}, 'bar': ('c', 'd')} + + +def test_default_copy(): + class User(BaseModel): + friends: List[int] = [] + + u1 = User() + u2 = User() + assert u1.friends is not u2.friends