[docs]defcompose2(a:Callable[[AA],AR],b:Callable[[BA],AA])->Callable[[BA],AR]:""" Returns a function composed from the two given functions ``a`` and ``b`` such that calling ``compose2(a, b)(x)`` is equivalent to calling ``a(b(x))``. >>> compose2("".join, reversed)("!olleH") 'Hello!' """a_name=_name(a)b_name=_name(b)defc(arg:BA)->AR:returna(b(arg))c.__name__=f"{a_name}∘{b_name}"c.__doc__=f"Function composed as {a_name}({b_name}(_))."returnc
A=TypeVar("A")
[docs]defexcepts(exception:tuple[type[Exception],...]|type[Exception],negate:bool=False,)->Callable[[Callable[[A],Any]],Callable[[A],bool]]:""" Turn a unary function that raises an exception into a boolean predicate. >>> def validate_positive(number: int) -> None: ... if number < 0: raise ValueError >>> is_positive = excepts(ValueError)(validate_positive) >>> is_positive(0), is_positive(-1) (True, False) """defdecorator(fn:Callable[[A],Any])->Callable[[A],bool]:@functools.wraps(fn)defwrapper(arg:A)->bool:try:fn(arg)exceptexception:returnnegatereturnnotnegatereturnwrapperreturndecorator