From a66058b0958d89fa728e9245caeab05d8514b711 Mon Sep 17 00:00:00 2001 From: Blair Bonnett Date: Tue, 2 Dec 2025 17:33:13 +0100 Subject: [PATCH 1/3] Typehint and documentation for Future.status --- distributed/client.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/distributed/client.py b/distributed/client.py index 415394ab179..623f73f3b7c 100644 --- a/distributed/client.py +++ b/distributed/client.py @@ -302,13 +302,13 @@ class Future(TaskRef, Generic[_T]): # Make sure this stays unique even across multiple processes or hosts _uid = uuid.uuid4().hex - def __init__(self, key, client=None, state=None, _id=None): + def __init__(self, key: str | tuple, client=None, state=None, _id=None): self.key = key self._cleared = False self._client = client self._id = _id or (Future._uid, next(Future._counter)) self._input_state = state - self._state = None + self._state: FutureState | None = None self._bind_late() @property @@ -358,13 +358,17 @@ def executor(self): return self.client @property - def status(self): - """Returns the status + def status( + self, + ) -> Literal["cancelled", "error", "finished", "lost", "pending"] | None: + """The status of the future. Returns ------- - str - The status + {"cancelled", "error", "finished", "lost", "pending"} + The current status. This may be None if the future has not been + bound to a client. + """ if self._state: return self._state.status @@ -641,6 +645,8 @@ class FutureState: __slots__ = ("_event", "key", "status", "type", "exception", "traceback") + status: Literal["cancelled", "error", "finished", "lost", "pending"] + def __init__(self, key: str): self._event = None self.key = key From c51d8705f55ae45c534928a5eb5526a07dd5e012 Mon Sep 17 00:00:00 2001 From: crusaderky Date: Sun, 3 May 2026 17:01:40 +0100 Subject: [PATCH 2/3] More annotations --- distributed/client.py | 46 +++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/distributed/client.py b/distributed/client.py index 6de5fde01f7..11809d4bb31 100644 --- a/distributed/client.py +++ b/distributed/client.py @@ -151,11 +151,11 @@ class FutureCancelledError(CancelledError): - key: str + key: Key reason: str msg: str | None - def __init__(self, key: str, reason: str | None, msg: str | None = None): + def __init__(self, key: Key, reason: str | None, msg: str | None = None): self.key = key self.reason = reason if reason else "unknown" self.msg = msg @@ -163,12 +163,9 @@ def __init__(self, key: str, reason: str | None, msg: str | None = None): def __str__(self) -> str: result = f"{self.key} cancelled for reason: {self.reason}." if self.msg: - result = "\n".join([result, self.msg]) + result += f"\n{self.msg}" return result - def __reduce__(self): - return self.__class__, (self.key, self.reason, self.msg) - class FuturesCancelledError(CancelledError): error_groups: list[CancelledFuturesGroup] @@ -295,21 +292,35 @@ class Future(TaskRef, Generic[_T]): Client: Creates futures """ + key: Key + _client: Client | None + _input_state: FutureState | None + _state: FutureState | None + _id: tuple[str, int] + _cleared: bool + _is_finalizing: staticmethod[[], bool] = staticmethod(sys.is_finalizing) + _cb_executor: ClassVar[ThreadPoolExecutor | None] = None + _cb_executor_pid: ClassVar[int | None] = None - _cb_executor = None - _cb_executor_pid = None - _counter = itertools.count() - # Make sure this stays unique even across multiple processes or hosts - _uid = uuid.uuid4().hex + # Generate _id of Future instances as (_uid, next(_counter)) + # Make sure _uid stays unique even across multiple processes or hosts + _uid: ClassVar[str] = uuid.uuid4().hex + _counter: ClassVar[itertools.count[int]] = itertools.count() - def __init__(self, key: str | tuple, client=None, state=None, _id=None): + def __init__( + self, + key: Key, + client: Client | None = None, + state: FutureState | None = None, + _id: tuple[str, int] | None = None, + ): self.key = key - self._cleared = False self._client = client - self._id = _id or (Future._uid, next(Future._counter)) self._input_state = state - self._state: FutureState | None = None + self._state = None + self._id = _id or (Future._uid, next(Future._counter)) + self._cleared = False self._bind_late() @property @@ -651,9 +662,10 @@ class FutureState: __slots__ = ("_event", "key", "status", "type", "exception", "traceback") - status: Literal["cancelled", "error", "finished", "lost", "pending"] + key: Key + status: Literal["pending", "cancelled", "finished", "lost", "error"] - def __init__(self, key: str): + def __init__(self, key: Key): self._event = None self.key = key self.exception = None From a612f3283bccbffb17d42a76504352eae596d8ff Mon Sep 17 00:00:00 2001 From: crusaderky Date: Sun, 3 May 2026 18:03:15 +0100 Subject: [PATCH 3/3] revert --- distributed/client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/distributed/client.py b/distributed/client.py index 11809d4bb31..3667bb46fb6 100644 --- a/distributed/client.py +++ b/distributed/client.py @@ -166,6 +166,10 @@ def __str__(self) -> str: result += f"\n{self.msg}" return result + # Workaround to tblib <3.2.1 + def __reduce__(self): + return self.__class__, (self.key, self.reason, self.msg) + class FuturesCancelledError(CancelledError): error_groups: list[CancelledFuturesGroup]