Skip to content

Commit 46f937f

Browse files
authored
Improvements to loop lifecycle (#152)
1 parent cd9f56b commit 46f937f

File tree

13 files changed

+753
-144
lines changed

13 files changed

+753
-144
lines changed

rendercanvas/_coreutils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,45 @@ def asyncio_is_running():
292292
return loop is not None
293293

294294

295+
# %% Async generators
296+
297+
298+
# Taken from trio._util.py
299+
def name_asyncgen(agen) -> str:
300+
"""Return the fully-qualified name of the async generator function
301+
that produced the async generator iterator *agen*.
302+
"""
303+
if not hasattr(agen, "ag_code"): # pragma: no cover
304+
return repr(agen)
305+
try:
306+
module = agen.ag_frame.f_globals["__name__"]
307+
except (AttributeError, KeyError):
308+
module = f"<{agen.ag_code.co_filename}>"
309+
try:
310+
qualname = agen.__qualname__
311+
except AttributeError:
312+
qualname = agen.ag_code.co_name
313+
return f"{module}.{qualname}"
314+
315+
316+
def close_agen(agen):
317+
"""Try to sync-close an async generator."""
318+
closer = agen.aclose()
319+
try:
320+
# If the next thing is a yield, this will raise RuntimeError which we allow to propagate
321+
closer.send(None)
322+
except StopIteration:
323+
pass
324+
else:
325+
# If the next thing is an await, we get here.
326+
# Give a nicer error than the default "async generator ignored GeneratorExit"
327+
agen_name = name_asyncgen(agen)
328+
logger.error(
329+
f"Async generator {agen_name!r} awaited something during finalization, "
330+
"so we could not clean it up. Wrap it in 'async with aclosing(...):'",
331+
)
332+
333+
295334
# %% Linux window managers
296335

297336

rendercanvas/_enums.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ class EventType(BaseEnum):
167167
UpdateModeEnum = Literal["manual", "ondemand", "continuous", "fastest"]
168168

169169

170+
class LoopState(BaseEnum):
171+
off = None #: The loop is in the 'off' state.
172+
ready = None #: The loop is likely to be used, and is ready to start running.
173+
active = None #: The loop is active, but we don't know how.
174+
interactive = None #: The loop is in interactive mode, e.g. in an IDE or notebook.
175+
running = None #: The loop is running via our ``loop.run()``.
176+
177+
170178
class UpdateMode(BaseEnum):
171179
"""The UpdateMode enum specifies the different modes to schedule draws for the canvas."""
172180

0 commit comments

Comments
 (0)