Skip to content

Re-raise errors stemming from iteration#121

Merged
calgray merged 1 commit into
calgray:mainfrom
rtobar:raise-errors-from-iteration
Jul 8, 2026
Merged

Re-raise errors stemming from iteration#121
calgray merged 1 commit into
calgray:mainfrom
rtobar:raise-errors-from-iteration

Conversation

@rtobar

@rtobar rtobar commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

No tests/docs yet, but it hopefully shows the shortcoming that needed fixing. I thought I could be more careful and try/catch next(self._iterator) more specifically, but it doesn't seem to be worth the effort -- I think any exception needs to be re-raised anyway.

Signed-off-by: Rodrigo Tobar <rtobar@icrar.org>
@calgray
calgray self-requested a review July 7, 2026 09:25

@calgray calgray left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the MR ✨ It seems I've mostly up until this point been looking at exceptions raised from async loops being able to cancel the background thread context, but not so much exceptions raised from the the worker thread propagating up to async/main thread. Monad results through the queue is nice type-safe approach to handling it.

I might need to change some repo setting to get this MR to run pre-commit before approval

@dataclasses.dataclass
class _Result(Generic[_T]):
value: _T | None
error: Exception | None

@calgray calgray Jul 7, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires a cast below as this monad doesn't enforce it must contain either value or error.

Rust std::Result<T, E> and C++ std::expected<T, E> use a compact type union to achieve this (but not perfectly compact, they must allocate descriminator bit). Python objects fortunately carry the runtime type, a tiny equivalent monad that handles the T == E edge case is the following (until Python adds standard monads):

_T = TypeVar("_T")
_E = TypeVar("_E")

class _Ok(Generic[T]):
    def __init__(self, value: T):
        self.value = value

class _Err(Generic[E]):
    def __init__(self, error: E):
        self.error = error

# from python 3.12 onwards
# type _Result[T, E] = _Ok[T] | _Err[E]

These thin wrappers then allow:

if isinstance(result, _Err):
    raise result.error
return result.value

@calgray
calgray self-requested a review July 7, 2026 10:30
calgray
calgray previously approved these changes Jul 7, 2026
@calgray
calgray dismissed their stale review July 7, 2026 10:36

"Approve workflows to run" button missing

@calgray
calgray self-requested a review July 8, 2026 06:08
@calgray
calgray merged commit 8561556 into calgray:main Jul 8, 2026
@rtobar
rtobar deleted the raise-errors-from-iteration branch July 8, 2026 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants