diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08b22ce399e..6070168905d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -246,9 +246,6 @@ jobs: with: python-version: '3.10' - - name: upgrade pip - run: pip install -U pip setuptools wheel - - name: install run: make install-testing diff --git a/changes/3641-PrettyWood.md b/changes/3641-PrettyWood.md new file mode 100644 index 00000000000..d0338c66369 --- /dev/null +++ b/changes/3641-PrettyWood.md @@ -0,0 +1 @@ +`Config.copy_on_model_validation` does a deep copy and not a shallow one \ No newline at end of file diff --git a/pydantic/main.py b/pydantic/main.py index eea8abcbbe8..1dcda9efd55 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -666,7 +666,7 @@ def __get_validators__(cls) -> 'CallableGenerator': def validate(cls: Type['Model'], value: Any) -> 'Model': if isinstance(value, cls): if cls.__config__.copy_on_model_validation: - return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=False) + return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=True) else: return value diff --git a/tests/test_main.py b/tests/test_main.py index c00d70688cb..f4d3844c4aa 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1561,12 +1561,28 @@ class Config: assert t.user is not my_user assert t.user.hobbies == ['scuba diving'] - assert t.user.hobbies is my_user.hobbies # `Config.copy_on_model_validation` only does a shallow copy + assert t.user.hobbies is not my_user.hobbies # `Config.copy_on_model_validation` does a deep copy assert t.user._priv == 13 assert t.user.password.get_secret_value() == 'hashedpassword' assert t.dict() == {'id': '1234567890', 'user': {'id': 42, 'hobbies': ['scuba diving']}} +def test_validation_deep_copy(): + """By default, Config.copy_on_model_validation should do a deep copy""" + + class A(BaseModel): + name: str + + class B(BaseModel): + list_a: List[A] + + a = A(name='a') + b = B(list_a=[a]) + assert b.list_a == [A(name='a')] + a.name = 'b' + assert b.list_a == [A(name='a')] + + @pytest.mark.parametrize( 'kinds', [