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
import porg
from kython import listify
from .common import listify
from ..error import Res, echain
from kython.org import parse_org_date
from kython.kerror import Res, echain
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')
E = TypeVar('E', bound=Exception)
E = TypeVar('E', bound=Exception) # TODO make covariant?
ResT = Union[T, E]
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:
if isinstance(res, Exception):
raise res
@ -25,38 +22,26 @@ def unwrap(res: Res[T]) -> T:
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:
ex.__cause__ = cause
# TODO assert cause is none?
# TODO copy??
return ex
# try:
# # TODO is there a awy to get around raise from?
# raise ex from cause
# except Exception as e:
# if isinstance(e, type(ex)):
# return e
# else:
# raise e
def split_errors(l: Iterable[ResT[T, E]], ET: Type[E]) -> Tuple[Iterable[T], Iterable[E]]:
# TODO would be nice to have ET=Exception default?
vit, eit = tee(l)
# TODO ugh, not sure if I can reconcile type checking and runtime and convince mypy that ET and E are the same type?
values: Iterable[T] = (
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]:

View file

@ -9,7 +9,7 @@ import pytz
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