diff --git a/changes/1999-me-ransh.md b/changes/1999-me-ransh.md new file mode 100644 index 0000000..236886f --- /dev/null +++ b/changes/1999-me-ransh.md @@ -0,0 +1,2 @@ +Call validator with the correct `values` parameter type in `BaseModel.__setattr__`, +when `validate_assignment = True` in model config. diff --git a/pydantic/main.py b/pydantic/main.py index e55d61c..02e27d1 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -365,8 +365,10 @@ class BaseModel(Representation, metaclass=ModelMetaclass): known_field = self.__fields__.get(name, None) if known_field: - value, error_ = known_field.validate(value, self.dict(exclude={name}), loc=name, cls=self.__class__) + original_value = self.__dict__.pop(name) + value, error_ = known_field.validate(value, self.__dict__, loc=name, cls=self.__class__) if error_: + self.__dict__[name] = original_value raise ValidationError([error_], self.__class__) new_values[name] = value diff --git a/tests/test_validators.py b/tests/test_validators.py index 9e3f4dc..44ca23c 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -199,6 +199,30 @@ def test_validating_assignment_dict(): ] +def test_validating_assignment_values_dict(): + class ModelOne(BaseModel): + a: int + + class ModelTwo(BaseModel): + m: ModelOne + b: int + + @validator('b') + def validate_b(cls, b, values): + if 'm' in values: + return b + values['m'].a # this fails if values['m'] is a dict + else: + return b + + class Config: + validate_assignment = True + + model = ModelTwo(m=ModelOne(a=1), b=2) + assert model.b == 3 + model.b = 3 + assert model.b == 4 + + def test_validate_multiple(): # also test TypeError class Model(BaseModel):