#!/usr/bin/env python3
-# © Copyright 2021-2022, Scott Gasch
+# © Copyright 2021-2023, Scott Gasch
"""
A :class:`Future` that can be treated as a substutute for the result
Results from :class:`parallelize.parallelize` are returned wrapped
in :class:`SmartFuture` instances.
+
+Also contains some utilility code for waiting for one/many futures.
"""
from __future__ import annotations
logger = logging.getLogger(__name__)
-T = TypeVar('T')
+T = TypeVar("T")
def wait_any(
futures completes
log_exceptions: Should we log (warning + exception) any
underlying exceptions raised during future processing or
- silently ignore then?
+ silently ignore them?
timeout: invoke callback with a periodicity of timeout while
awaiting futures
if log_exceptions and not f.cancelled():
exception = f.exception()
if exception is not None:
- logger.warning(
- 'Future 0x%x raised an unhandled exception and exited.',
+ logger.exception(
+ "Future 0x%x raised an unhandled exception and exited.",
id(f),
+ exc_info=exception,
)
- logger.exception(exception)
raise exception
yield smart_future_by_real_future[f]
- except TimeoutError:
+ except concurrent.futures.TimeoutError:
if callback is not None:
callback()
if callback is not None:
futures: A collection of futures that we're waiting for
log_exceptions: Should we log (warning + exception) any
underlying exceptions raised during future processing or
- silently ignore then?
+ silently ignore them?
Returns:
Only when all futures in the input list are ready. Blocks
if not f.cancelled():
exception = f.exception()
if exception is not None:
- logger.warning(
- 'Future 0x%x raised an unhandled exception and exited.', id(f)
+ logger.exception(
+ "Future 0x%x raised an unhandled exception and exited.",
+ id(f),
+ exc_info=exception,
)
- logger.exception(exception)
raise exception
assert len(done) == len(real_futures)
assert len(not_done) == 0
wrapped_future: a normal Python :class:`concurrent.Future`
object that we are wrapping.
"""
+ super().__init__(set(["id", "wrapped_future", "get_id", "is_ready"]))
assert isinstance(wrapped_future, fut.Future)
self.wrapped_future = wrapped_future
self.id = id_generator.get("smart_future_id")
+ # Note: if you are adding any settable properties to this
+ # class, go add them to the set in DeferredOperand.__setattr__()
+
def get_id(self) -> int:
"""
Returns: