Currently, errors are raised (exclusively?) as Err exceptions (parallel to Rust's Err variant of its Result type), and the caller must pick them apart manually using isinstance() or similar:
try:
result=await_request(pending_request)
exceptErrasexc:
ifisinstance(exc.value, Error_OptionalNone):
# There were no more requests within the timeout.breakelse:
# Something truly went wrong.raiseelse:
# Do the no-error case.
This should be shortenable to:
try:
result=await_request(pending_request)
exceptNoRequestErrorasexc:
breakelse:
# Do the no-error case.
(This may not be the most motivating example, since await_request() should perhaps return None when there is no request. However, it serves to illustrate the form.)
Result is currently defined as Union[Ok[T], Err[E]]. It seems to me that we can achieve an idiomatic and lossless mapping onto Python's result/exception duality by having Result-returning functions raise E xor return T.
Note that currently we raise the entire Err(E), not merely E, necessitating further unpacking. I don't think it brings any benefit, since E is the only thing in the Err:
@dataclass(frozen=True)classErr(Generic[E], Exception):
value: E
A notable speed bump is that the current error classes are root classes, not subclasses of BaseException, as is required for catching them.
@dataclassclassError_OptionalNone:
pass
However, it appears the binding generator is aware those are errors…
Error=Union[Error_GenericError, Error_InvalidArgument, Error_BadHandle, Error_BufferLen, Error_Unsupported, Error_HttpInvalid, Error_HttpUser, Error_HttpIncomplete, Error_OptionalNone, Error_HttpHeadTooLarge, Error_HttpInvalidStatus, Error_LimitExceeded]
…so perhaps the fix is straightforward.
For completeness and in case fixing it closer to the source proves intractable: decorating Result-returning functions with one that catches any Err, unpacks it, and re-raises its E would domesticate them sufficiently. (The BaseException speed bump would still need to be solved first.)
Currently, errors are raised (exclusively?) as
Errexceptions (parallel to Rust'sErrvariant of itsResulttype), and the caller must pick them apart manually usingisinstance()or similar:This should be shortenable to:
(This may not be the most motivating example, since
await_request()should perhaps returnNonewhen there is no request. However, it serves to illustrate the form.)Resultis currently defined asUnion[Ok[T], Err[E]]. It seems to me that we can achieve an idiomatic and lossless mapping onto Python's result/exception duality by havingResult-returning functions raiseExor returnT.Note that currently we raise the entire
Err(E), not merelyE, necessitating further unpacking. I don't think it brings any benefit, sinceEis the only thing in theErr:A notable speed bump is that the current error classes are root classes, not subclasses of
BaseException, as is required for catching them.However, it appears the binding generator is aware those are errors…
…so perhaps the fix is straightforward.
For completeness and in case fixing it closer to the source proves intractable: decorating
Result-returning functions with one that catches anyErr, unpacks it, and re-raises itsEwould domesticate them sufficiently. (TheBaseExceptionspeed bump would still need to be solved first.)