Skip to content

Commit

Permalink
add strict and context support to validate_assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
PrettyWood committed Aug 4, 2022
1 parent 3b48166 commit 265f8c5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 5 deletions.
4 changes: 3 additions & 1 deletion pydantic_core/_pydantic_core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class SchemaValidator:
def isinstance_json(
self, input: 'str | bytes | bytearray', strict: 'bool | None' = None, context: Any = None
) -> bool: ...
def validate_assignment(self, field: str, input: Any, data: 'dict[str, Any]') -> 'dict[str, Any]': ...
def validate_assignment(
self, field: str, input: Any, data: 'dict[str, Any]', strict: 'bool | None' = None, context: Any = None
) -> 'dict[str, Any]': ...

class SchemaError(Exception):
pass
Expand Down
14 changes: 11 additions & 3 deletions src/validators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,20 @@ impl SchemaValidator {
}
}

pub fn validate_assignment(&self, py: Python, field: String, input: &PyAny, data: &PyDict) -> PyResult<PyObject> {
pub fn validate_assignment(
&self,
py: Python,
field: String,
input: &PyAny,
data: &PyDict,
strict: Option<bool>,
context: Option<&PyAny>,
) -> PyResult<PyObject> {
let extra = Extra {
data: Some(data),
field: Some(field.as_str()),
strict: None,
context: None,
strict,
context,
};
let r = self
.validator
Expand Down
48 changes: 47 additions & 1 deletion tests/validators/test_typed_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def test_validate_assignment():
assert v.validate_assignment('field_a', b'abc', {'field_a': 'test'}) == ({'field_a': 'abc'}, {'field_a'})


def test_validate_assignment_strict():
def test_validate_assignment_strict_field():
v = SchemaValidator(
{
'type': 'typed-dict',
Expand Down Expand Up @@ -354,6 +354,52 @@ def test_validate_assignment_allow_extra_validate():
]


def test_validate_assignment_with_strict():
v = SchemaValidator(
{'type': 'typed-dict', 'fields': {'x': {'schema': {'type': 'str'}}, 'y': {'schema': {'type': 'int'}}}}
)

r = v.validate_python({'x': 'a', 'y': '123'})
assert r == {'x': 'a', 'y': 123}

assert v.validate_assignment('y', '124', r) == {'x': 'a', 'y': 124}

with pytest.raises(ValidationError) as exc_info:
v.validate_assignment('y', '124', r, True)

assert exc_info.value.errors() == [
{'kind': 'int_type', 'loc': ['y'], 'message': 'Input should be a valid integer', 'input_value': '124'}
]


# TODO: move to tests/test_validation_context.py
# once https://github.com/samuelcolvin/pydantic-core/pull/220 is merged
def test_validate_assignment_with_context():
def f1(input_value, *, context, **kwargs):
context['f1'] = input_value
return input_value + f'| context: {context}'

def f2(input_value, *, context, **kwargs):
context['f2'] = input_value
return input_value + f'| context: {context}'

v = SchemaValidator(
{
'type': 'typed-dict',
'fields': {
'f1': {'schema': {'type': 'function', 'mode': 'plain', 'function': f1}},
'f2': {'schema': {'type': 'function', 'mode': 'plain', 'function': f2}},
},
}
)

m1 = v.validate_python({'f1': '1', 'f2': '2'}, None, {'x': 'y'})
assert m1 == {'f1': "1| context: {'x': 'y', 'f1': '1'}", 'f2': "2| context: {'x': 'y', 'f1': '1', 'f2': '2'}"}

m2 = v.validate_assignment('f1', '3', m1, None, {'x': 'y'})
assert m2 == {'f1': "3| context: {'x': 'y', 'f1': '3'}", 'f2': "2| context: {'x': 'y', 'f1': '1', 'f2': '2'}"}


def test_json_error():
v = SchemaValidator(
{'type': 'typed-dict', 'fields': {'field_a': {'schema': {'type': 'list', 'items_schema': 'int'}}}}
Expand Down

0 comments on commit 265f8c5

Please sign in to comment.