Move error handling to common

This commit is contained in:
Dima Gerasimov 2019-12-21 10:58:45 +00:00
parent 0415ea2560
commit 522d3bc5d9
3 changed files with 30 additions and 43 deletions

View file

@ -4,9 +4,11 @@ from typing import Iterable, NamedTuple, Optional
from itertools import chain from itertools import chain
import porg import porg
from kython import listify from .common import listify
from ..error import Res, echain
from kython.org import parse_org_date from kython.org import parse_org_date
from kython.kerror import Res, echain
from mycfg import paths from mycfg import paths

View file

@ -1,23 +1,20 @@
from typing import Union, TypeVar, Iterator, Callable, Iterable, List, Tuple, Type """
Various error handling helpers
See https://beepb00p.xyz/mypy-error-handling.html#kiss for more detail
"""
from itertools import tee
from typing import Union, TypeVar, Iterable, List, Tuple, Type
T = TypeVar('T') T = TypeVar('T')
E = TypeVar('E', bound=Exception) E = TypeVar('E', bound=Exception) # TODO make covariant?
ResT = Union[T, E] ResT = Union[T, E]
Res = ResT[T, Exception] Res = ResT[T, Exception]
# TODO make it a bit more typed??
def is_error(res: Res[T]) -> bool:
return isinstance(res, Exception)
def is_ok(res: Res[T]) -> bool:
return not is_error(res)
def unwrap(res: Res[T]) -> T: def unwrap(res: Res[T]) -> T:
if isinstance(res, Exception): if isinstance(res, Exception):
raise res raise res
@ -25,38 +22,26 @@ def unwrap(res: Res[T]) -> T:
return res return res
def split_errors(l: Iterable[ResT[T, E]], ET=Exception) -> Tuple[List[T], List[E]]:
rl: List[T] = []
el: List[E] = []
for x in l:
if isinstance(x, ET):
el.append(x)
else:
rl.append(x) # type: ignore
return rl, el
def ytry(cb) -> Iterator[Exception]:
try:
cb()
except Exception as e:
yield e
# TODO experimental, not sure if I like it
def echain(ex: E, cause: Exception) -> E: def echain(ex: E, cause: Exception) -> E:
ex.__cause__ = cause ex.__cause__ = cause
# TODO assert cause is none?
# TODO copy??
return ex return ex
# try:
# # TODO is there a awy to get around raise from?
# raise ex from cause def split_errors(l: Iterable[ResT[T, E]], ET: Type[E]) -> Tuple[Iterable[T], Iterable[E]]:
# except Exception as e: # TODO would be nice to have ET=Exception default?
# if isinstance(e, type(ex)): vit, eit = tee(l)
# return e # TODO ugh, not sure if I can reconcile type checking and runtime and convince mypy that ET and E are the same type?
# else: values: Iterable[T] = (
# raise e r # type: ignore[misc]
for r in vit
if not isinstance(r, ET))
errors: Iterable[E] = (
r
for r in eit
if isinstance(r, ET))
# TODO would be interesting to be able to have yield statement anywehere in code
# so there are multiple 'entry points' to the return value
return (values, errors)
def sort_res_by(items: Iterable[ResT], key) -> List[ResT]: def sort_res_by(items: Iterable[ResT], key) -> List[ResT]:

View file

@ -9,7 +9,7 @@ import pytz
from ..common import setup_logger from ..common import setup_logger
from ..kython.kerror import ResT, echain, unwrap, sort_res_by from ..error import ResT, echain, unwrap, sort_res_by
from ..kython.konsume import wrap, zoom, ignore from ..kython.konsume import wrap, zoom, ignore