If you’re saying that I must handle an exception in my code rather than crash because my “fail early, fail often” design choices offend your religious preferences… then keep it to yourself and out of PEPs.
If you’re saying that I must handle an exception in my code rather than crash because my “fail early, fail often” design choices offend your religious preferences… then keep it to yourself and out of PEPs.
def wrapper():
try:
return handler()
except Exception:
logger.exception("unknown exception")
webserver.status = 500
the type system needs to be able to determine that "f doesn't raise an exception". For example, one way to do this can be that all functions by default raise exception and we type: def handler() -> T: ...
def wrapper() -> NeverRaises[T]: ...
then we have webserver_add('GET', '/handler', wrapper)
so that def webserver_add(method: str, path: str, handle_func: Callable[[], NeverRaises[T]]) -> None: ...
which is type safer.Of course, here we need to specially handle `KeyboardInterrupt`, signals and exceptions returned by `logger` etc. I would personally recommend ignoring `KeyboardInterrupt`, and signals and type annotating `logger.exception` as `NeverRaises`. 95% is still better than 0%.
I disagree, in part because “handles all exceptions” is a lie; exceptions can occur at any point, including in exception-hnadling code.
It is not possible to have a Python function which provides the guarantee you want, so it makes no sense to have a Python type system which expressed it: it will either be never used or a lie.
If you think you need this guarantee, you need to step back and ask what the functional requirement actually is and find a different way of meeting it.