Package: aevent
aeventlets you call boring synchronous Python from async code.
Without blocking or splattingasyncandawaitonto it.
Ideally, this works without modifying the synchronous code.Put another way,aeventis togeventwhatanyiois togreenlet.That is, it replaces standard Python functions with calls toanyioinstead ofgevent.Some limitations apply.UsageBefore any other imports, insert this code block into your main code:import aevent
aevent.setup('trio')  # or asyncio, if you mustThis will annoy various code checkers, but that can’t be helped.Start your main loopusingaevent.run, or callawait aevent.per_task()in the task(s) that need to use patched code.Theaevent.nativeandaevent.patchedcontext managers can be used to
temporarily disable or re-enableaevent’s patches.Support functionsaeventmonkey-patchesanyio’sTaskGroup.spawnin two ways.the child task is instrumented to supportgreenback.spawnreturns a cancel scope. You can use it to cancel the new task.Callaevent.per_taskin your child task if you start tasks some other way.ThreadingThreads are translated to tasks. In order for that to work, you must start
your program withaevent.run, or run the sync code in question within anaevent.runnerasync context manager. Runners may be nested.Supported modulestimesleepthreadingqueueatexitsocketselectpollNot yet supportedselectanything elsednsosreadwritesslsubprocesssignalSubclassing patched classesDirectly subclassing one of the classes patched byaeventdoes not
work and requires special consideration. Consider this code:class my_thread(threading.Thread):
   def run(self):
       ...For use withaeventyou can choose the originalThreadimplementation:orig_Thread = getattr(threading.Thread, "_aevent_orig", threading.Thread)
class my_thread(orig_Thread):
  ...or theaevent-ified version:new_Thread = threading.Thread._aevent_new # fails when aevent is not loaded
class my_thread(new_Thread):
  ...or you might want to create two separate implementations, and switch based
on the aevent context:class _orig_my_thread(threading.Thread._aevent_orig):
   ...
class _new_my_thread(threading.Thread._aevent_new):
   ...
my_thread = aevent.patch__new_my_thread, name="my_thread", orig=_orig_my_thread)If you generate local subclasses on the fly, you can simplify this to:def some_code():
    class my_thread(threading.Thread._aevent_select()):
        def run(self):
            ...
    job = my_tread()
    my_thread.start()Other affected modulesYou need to import any module which requires non-patched code before
importingaevent.Modules which are known to be affected:multiprocessingInternalsaevent’s monkey patching is done mainly on the module/class level.geventprefers to patch individual methods. This may cause some
reduced compatibility compared togevent.aeventworks by prepending its local_monkeydirectory to the import path.
These modules try to afford the same public interface as the ones they’re
replacing while calling the correspondinganyiofunctions throughgreenback_.Context switching back to async-flavored code is done by way ofgreenback.aeventruns on Python 3.7 ff.TestingThe test suite runs withtrioas backend. Due toaevent’s monkeypatching,
switching backends around is not supported. However, you can set the
environment variableAEVENT_BACKENDtoasyncioto run the test
suite with that.The test suite pulls in a copy ofpyroute2(no changes, other than fixing
bugs unrelated toaevent) and tests against its test suite, thereby
(mostly) ensuring that this particular package works withaevent.