Skip to content

Commit

Permalink
Validate by regexp/Validate with a custom error (#132)
Browse files Browse the repository at this point in the history
* Validate by regexp

* Add validate

* Fix tests

* More tests
  • Loading branch information
Pliner authored Sep 28, 2023
1 parent ccca39a commit 0a8442b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 17 deletions.
7 changes: 4 additions & 3 deletions marshmallow_recipe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from .naming_case import CAMEL_CASE, CAPITAL_CAMEL_CASE, CamelCase, CapitalCamelCase, NamingCase
from .options import NoneValueHandling, options
from .serialization import EmptySchema, dump, dump_many, load, load_many, schema
from .validator import ValidationError, ValidationFunc
from .validation import ValidationFunc, regexp_validate, validate

__all__: tuple[str, ...] = (
# bake.py
Expand Down Expand Up @@ -85,9 +85,10 @@
"dump_many",
"schema",
"EmptySchema",
# validator.py
"ValidationError",
# validation.py
"ValidationFunc",
"regexp_validate",
"validate",
)

__version__ = "0.0.31"
Expand Down
2 changes: 1 addition & 1 deletion marshmallow_recipe/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import marshmallow as m
import marshmallow.validate

from .validator import ValidationFunc
from .validation import ValidationFunc

_MARSHMALLOW_VERSION_MAJOR = int(m.__version__.split(".")[0])

Expand Down
2 changes: 1 addition & 1 deletion marshmallow_recipe/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any, TypeGuard, final

from .missing import MISSING
from .validator import ValidationFunc
from .validation import ValidationFunc


@final
Expand Down
24 changes: 24 additions & 0 deletions marshmallow_recipe/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import collections.abc
import re
from typing import Any

import marshmallow.validate

ValidationFunc = collections.abc.Callable[[Any], Any]


def regexp_validate(regexp: re.Pattern | str, *, error: str | None = None) -> ValidationFunc:
return marshmallow.validate.Regexp(regexp, error=error)


def validate(validator: ValidationFunc, *, error: str | None = None) -> ValidationFunc:
if error is None:
return validator

def _validator_with_custom_error(value: Any) -> Any:
result = validator(value)
if result is False:
raise marshmallow.ValidationError(error)
return result

return _validator_with_custom_error
11 changes: 0 additions & 11 deletions marshmallow_recipe/validator.py

This file was deleted.

35 changes: 34 additions & 1 deletion tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import datetime
import decimal
import uuid
from typing import cast
from typing import Annotated, cast

import marshmallow as m
import pytest
Expand Down Expand Up @@ -245,3 +245,36 @@ class IntContainer:

with pytest.raises(m.ValidationError):
mr.dump(IntContainer(int_field=cast(int, "invalid")))


def test_regexp_validate() -> None:
@dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
class StrContainer:
value1: Annotated[str, mr.str_meta(validate=mr.regexp_validate(r"^[a-z]+$"))]
value2: Annotated[
str, mr.str_meta(validate=mr.regexp_validate(r"^[a-z]+$", error="String does not match ^[a-z]+$."))
]

with pytest.raises(m.ValidationError) as exc_info:
mr.dump(StrContainer(value1="42", value2="100500"))

assert exc_info.value.messages == {
"value1": ["String does not match expected pattern."],
"value2": ["String does not match ^[a-z]+$."],
}


def test_validate() -> None:
@dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
class IntContainer:
value: Annotated[
int,
mr.str_meta(
validate=mr.validate(lambda x: x < 0, error="Should be negative."),
),
]

with pytest.raises(m.ValidationError) as exc_info:
mr.dump(IntContainer(value=42))

assert exc_info.value.messages == {"value": ["Should be negative."]}

0 comments on commit 0a8442b

Please sign in to comment.