diff --git a/pyresult/result.py b/pyresult/result.py index 9145fa1..8934534 100644 --- a/pyresult/result.py +++ b/pyresult/result.py @@ -1,14 +1,80 @@ # -*- coding: utf-8 -*- '''Result pattern implementation''' -import collections +from collections import namedtuple from toolz import curry OK = 'Ok' ERROR = 'Error' -Result = collections.namedtuple('Result', ('status', 'value')) + +class Result(namedtuple('Result', ('status', 'value'))): + '''Result''' + __slots__ = () + + def __and__(self, other): + '''Calculate the AND of two results. + + :param other: Result e a + :returns: Result e a + + >>> from pyresult import ok, error + + >>> ok(1) & ok(2) + Result(status='Ok', value=[1, 2]) + + >>> ok(1) & error(2) + Result(status='Error', value=[2]) + + >>> error(1) & ok(2) + Result(status='Error', value=[1]) + + >>> error(1) & error(2) + Result(status='Error', value=[1, 2]) + + ''' + cond = (is_ok(self), is_ok(other)) + + if cond == (True, True): + return ok([self.value, other.value]) + elif cond == (True, False): + return error([other.value]) + elif cond == (False, True): + return error([self.value]) + elif cond == (False, False): # pragma: no branch + return error([self.value, other.value]) + + def __or__(self, other): + '''Calculate the OR of two results. + + :param other: Result e a + :returns: Result e a + + >>> from pyresult import ok, error + + >>> ok(1) | ok(2) + Result(status='Ok', value=[1, 2]) + + >>> ok(1) | error(2) + Result(status='Ok', value=[1]) + + >>> error(1) | ok(2) + Result(status='Ok', value=[2]) + + >>> error(1) | error(2) + Result(status='Error', value=[1, 2]) + ''' + cond = (is_ok(self), is_ok(other)) + + if cond == (True, True): + return ok([self.value, other.value]) + elif cond == (True, False): + return ok([self.value]) + elif cond == (False, True): + return ok([other.value]) + elif cond == (False, False): # pragma: no branch + return error([self.value, other.value]) class ResultError(Exception): diff --git a/setup.cfg b/setup.cfg index e7eae87..d425d32 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,19 +23,22 @@ exclude = urls.py,runtests.py,conf.py ignore = E501,E402 [tool:pytest] -addopts = -vvl -norecursedirs = .* requirements docs node_modules +addopts = -vvl --doctest-glob='*.rst' --doctest-modules --ignore=setup.py +norecursedirs = .* requirements node_modules +doctest_optionflags = ALLOW_UNICODE ELLIPSIS [coverage:run] branch = true [coverage:report] -omit = +omit = + *docs* *site-packages* *tests* *.tox* *conftest* *virtuals* *migrations* + *setup.py show_missing = True