-
-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider adding validators package #258
Comments
Shame on me! Not See https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ |
there is also https://validators.readthedocs.io/en/latest/ which imho fortunately returns errors instead of raising them |
Or we can add |
So, it looks like class Validated(Generic[_ValueType, _ErrorType]):
_inner_value: Iterable[
Callable[[_ValueType], Result[_ValueType, _ErrorType]],
] It should work with all types: |
Take a look at http://hackage.haskell.org/package/these as well. http://hackage.haskell.org/package/these-1.1/docs/Data-These.html#t:These It's |
I am using |
Here is another nice lib for validation: https://github.com/typeable/validationt |
Current validation prototype: from returns.primitives.hkt import KindN, kinded, Kinded
from returns.interfaces.specific.result import ResultLikeN
from returns.primitives.container import BaseContainer
from typing import TypeVar, Sequence, Callable, Iterable, TYPE_CHECKING
from returns._generated.iterable import iterable_kind
# Definitions:
_FirstType = TypeVar('_FirstType')
_SecondType = TypeVar('_SecondType')
_ThirdType = TypeVar('_ThirdType')
_ResultKind = TypeVar('_ResultKind', bound=ResultLikeN)
if not TYPE_CHECKING:
reveal_type = print
# TODO:
def validate(
items: Iterable[
Callable[
[_FirstType],
KindN[_ResultKind, _FirstType, _SecondType, _ThirdType],
]
],
) -> Kinded[Callable[
[_FirstType],
KindN[_ResultKind, _FirstType, Sequence[_SecondType], _ThirdType],
]]:
@kinded
def factory(instance: _FirstType) -> KindN[
_ResultKind,
_FirstType,
Sequence[_SecondType],
_ThirdType,
]:
swapped = [item.swap() for item in items]
return iterable_kind(type(swapped[0]), swapped).swap()
return factory What can be changed / improved?
import attr
from returns.result import Result
from returns.io import IOResult
from returns.context import ReaderResult
@attr.dataclass
class Person(object):
fullname: str
age: int
passport: str
def validate_fullname(person: Person) -> Result[Person, str]:
if not person.fullname:
return Result.from_failure('No fullname specified')
return Result.from_value(person)
def validate_age(person: Person) -> Result[Person, str]:
if person.age < 0:
return Result.from_failure('Negative age')
return Result.from_value(person)
def validate_passport(person: Person) -> IOResult[Person, str]:
"""Impures, calls 3rd party API."""
if not person.passport: # this is not an IO action, just an example
return IOResult.from_failure('Missing passort')
return IOResult.from_value(person)
def validate_with_context(person: Person) -> ReaderResult[Person, str, int]:
"""Requires ``int`` context to actually validate anything."""
def factory(deps: int) -> Result[Person, str]:
if person.age < deps:
return Result.from_failure('Less than minimal {0} age'.format(deps))
return Result.from_value(person)
return ReaderResult(factory)
person = Person('', 28, '')
simple = validate([
validate_fullname,
validate_age,
])(person)
hard = validate([
validate_passport,
])(person)
context = validate([
validate_with_context
])(person)
reveal_type(simple)
reveal_type(hard)
reveal_type(context(35)) Outputs:
So, we need to somehow turn |
We can also add simple types to make validation more meaningful: from returns.validation import Valid, Invalid, Validated
def register_user(user: Valid[User]) -> None:
api.register_user_call(user.value) Where |
Currently a lot of python tools just throw exceptions at us or even uses:
.is_valid()
and.errors
properties. It is not type-safe at all. Sometimes it is hard to explain to people how to really use type-driven design and make invalid states unreachable.My idea is that we need to write thin wrappers around popular typed validation packages: like
pydantic
,cerebrus
,schema
, etc to return really typed things.We also need to think about API to be expressive and recognisable enough.
Related: https://gist.github.com/maksbotan/14b4bebda2acab98cdd158f85a970855
CC @maksbotan
The text was updated successfully, but these errors were encountered: