returns
returns copied to clipboard
WIP: Adds validate function
I am not going to merge this PR any time soon. This is just a place for discussion.
TODO:
- [ ] Decide how we can change the final type of an object:
Person -> Validated[Person]orPerson -> ValidatedPerson - [ ] Decide what to do with
container_type, because I don't like to specify it by hands. Maybe we can enforce this function to bedef validate(steps: NonEmpty[Sequence[...]]) -> ...? - [ ] Decide how to join different validation steps together. There might be different strategies for it: run all, fail fast, etc
- [ ] Decide should it be inside the main repo? Or a separate one?
Code to ry this out:
from typing import TYPE_CHECKING, Callable, Iterable, Sequence, TypeVar, cast
import attr
from returns._internal.pipeline.validation import validate
from returns.context import ReaderResult
from returns.io import IOResult
from returns.result import Result
if not TYPE_CHECKING:
reveal_type = print
@attr.dataclass
class Person(object):
fullname: str
age: int
passport: str
class ValidatedPerson(Person):
...
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('N', 28, '')
simple = validate(Result, [
validate_fullname,
validate_age,
])(person)
hard = validate(IOResult, [
validate_passport,
])(person)
context = validate(ReaderResult, [
validate_with_context
])(person)
reveal_type(simple)
reveal_type(hard)
reveal_type(context(35))
Related https://github.com/zio/zio-prelude/pull/233
Related https://blog.drewolson.org/declarative-validation
Related #258