Open tomprince opened 3 years ago
Just for context, that code was originally written by @exarkun and I don't actually quite understand it, though I'm sure I could with some effort.
Some options:
Cooperator
that has a context-per-iterator using contextvars
(https://docs.python.org/3/library/contextvars.html). Eliot automatically derives its own context from that, e.g. for asyncio, so it should Just Work.My preference is item 2, since making generic context system is what contextvars
is for, and I imagine it might be more broadly useful as a feature. And it's probably only a few lines of code:
Context
per iterator.__next__
is called on iterator, wrap it with context.run()
.Something like:
from contextvars import Context
from twisted.internet.task import Cooperator
class IteratorWrapper:
def __init__(self, it):
self.it = it
self.context = Context()
def __next__(self):
return self.context.run(self.it.__next__)
class CooperatorWithContext:
def __init__(self):
self._coop = Cooperator()
def coiterate(self, iterator):
return self._coop.coiterate(IteratorWrapper(iterator))
# ... wrap other methods too ...
Other notes:
There is the private
eliot_friendly_generator_function
, which is almost what I need, but it initializes the context on the first call ofnext
/send
, rather than on creation.My use cases is wrapping a generator provided to twisted's
Cooperator
.