Skip to content

Commit 44c7250

Browse files
committed
Add chess.engine.AnalysisResult.get() (niklasf#394)
1 parent 7f19bca commit 44c7250

2 files changed

Lines changed: 39 additions & 14 deletions

File tree

chess/engine.py

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ class EngineTerminatedError(EngineError):
197197
"""The engine process exited unexpectedly."""
198198

199199

200+
class AnalysisComplete(Exception):
201+
"""
202+
Raised when analysis is complete, all information has been consumed, but
203+
further information was requested.
204+
"""
205+
206+
200207
ConfigValue = Union[str, int, bool, None]
201208
ConfigMapping = Mapping[str, ConfigValue]
202209

@@ -2081,32 +2088,43 @@ async def wait(self) -> None:
20812088
"""Waits until the analysis is complete (or stopped)."""
20822089
await self._finished
20832090

2084-
def __aiter__(self) -> "AnalysisResult":
2085-
return self
2086-
2087-
async def next(self) -> Optional[InfoDict]:
2091+
async def get(self) -> Optional[InfoDict]:
20882092
"""
20892093
Waits for the next dictionary of information from the engine and
2090-
returns it. Returns ``None`` if the analysis has been stopped and
2091-
all information has been consumed.
2094+
returns it.
20922095
20932096
It might be more convenient to use ``async for info in analysis: ...``.
2094-
"""
2095-
async for info in self:
2096-
return info
2097-
return None
20982097
2099-
async def __anext__(self) -> InfoDict:
2098+
:raises: :exc:`chess.engine.AnalysisComplete` if the analysis is
2099+
complete (or has been stopped) and all information has been
2100+
consumed. Use :func:`~chess.engine.AnalysisResult.next()` if you
2101+
prefer to get ``None`` instead of an exception.
2102+
"""
21002103
if self._seen_kork:
2101-
raise StopAsyncIteration
2104+
raise AnalysisComplete()
21022105

21032106
info = await self._queue.get()
21042107
if info is KORK:
21052108
self._seen_kork = True
21062109
await self._finished
2107-
raise StopAsyncIteration
2110+
raise AnalysisComplete()
21082111

2109-
return typing.cast(InfoDict, info)
2112+
return info
2113+
2114+
async def next(self) -> Optional[InfoDict]:
2115+
try:
2116+
return await self.get()
2117+
except AnalysisComplete:
2118+
return None
2119+
2120+
def __aiter__(self) -> "AnalysisResult":
2121+
return self
2122+
2123+
async def __anext__(self) -> InfoDict:
2124+
try:
2125+
return await self.get()
2126+
except AnalysisComplete:
2127+
raise StopAsyncIteration
21102128

21112129
def __enter__(self) -> "AnalysisResult":
21122130
return self
@@ -2364,6 +2382,11 @@ def wait(self) -> None:
23642382
future = asyncio.run_coroutine_threadsafe(self.inner.wait(), self.simple_engine.protocol.loop)
23652383
return future.result()
23662384

2385+
def get(self) -> Optional[InfoDict]:
2386+
with self.simple_engine._not_shut_down():
2387+
future = asyncio.run_coroutine_threadsafe(self.inner.get(), self.simple_engine.protocol.loop)
2388+
return future.result()
2389+
23672390
def next(self) -> Optional[InfoDict]:
23682391
with self.simple_engine._not_shut_down():
23692392
future = asyncio.run_coroutine_threadsafe(self.inner.next(), self.simple_engine.protocol.loop)

docs/engine.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ Reference
385385

386386
.. autoclass:: chess.engine.EngineTerminatedError
387387

388+
.. autoclass:: chess.engine.AnalysisComplete
389+
388390
.. autofunction:: chess.engine.popen_uci
389391

390392
.. autofunction:: chess.engine.popen_xboard

0 commit comments

Comments
 (0)