Skip to content

Commit

Permalink
Merge pull request #1232 from austinpgraham/fix-unchanging-field-when…
Browse files Browse the repository at this point in the history
…-validate-assignment-true

Fix unchanging field bug when validate assignment true
  • Loading branch information
vitalik authored Jul 15, 2024
2 parents 8a49992 + 5bca360 commit b75ada8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
10 changes: 7 additions & 3 deletions ninja/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,13 @@ class Config:
def _run_root_validator(
cls, values: Any, handler: ModelWrapValidatorHandler[S], info: ValidationInfo
) -> Any:
# when extra is "forbid" we need to perform default pydantic validation
# as DjangoGetter does not act as dict and pydantic will not be able to validate it
if cls.model_config.get("extra") == "forbid":
# If Pydantic intends to validate against the __dict__ of the immediate Schema
# object, then we need to call `handler` directly on `values` before the conversion
# to DjangoGetter, since any checks or modifications on DjangoGetter's __dict__
# will not persist to the original object.
forbids_extra = cls.model_config.get("extra") == "forbid"
should_validate_assignment = cls.model_config.get("validate_assignment", False)
if forbids_extra or should_validate_assignment:
handler(values)

values = DjangoGetter(values, cls, info.context)
Expand Down
26 changes: 19 additions & 7 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional
from typing import List, Optional, Union
from unittest.mock import Mock

import pytest
Expand Down Expand Up @@ -197,21 +197,33 @@ class Somechema(Schema):
assert repr(dg) == "<DjangoGetter: {'i': 1}>"


def test_django_getter_validates_assignment():
def test_schema_validates_assignment_and_reassigns_the_value():
class ValidateAssignmentSchema(Schema):
str_var: str

model_config = {"validate_assignment": True}

schema_inst = ValidateAssignmentSchema(str_var="test_value")

# Validate we can re-assign the value, this is a test for
# a bug where validate_assignment would cause an AttributeError
# for __dict__ on the target schema.
schema_inst.str_var = "reassigned_value"
assert schema_inst.str_var == "reassigned_value"
try:
schema_inst.str_var = 5
raise AssertionError()
except ValidationError:
# We expect this error, all is okay
pass


@pytest.mark.parametrize("test_validate_assignment", [False, None])
def test_schema_skips_validation_when_validate_assignment_False(
test_validate_assignment: Union[bool, None],
):
class ValidateAssignmentSchema(Schema):
str_var: str
model_config = {"validate_assignment": test_validate_assignment}

schema_inst = ValidateAssignmentSchema(str_var="test_value")
try:
schema_inst.str_var = 5
assert schema_inst.str_var == 5
except ValidationError as ve:
raise AssertionError() from ve

0 comments on commit b75ada8

Please sign in to comment.