Gpotato is a python library that implements a PEP 3156 interface for the GLib main event loop. It is designed to be used together with the asyncio module.
The code needs to be thoroughly tested, it should be considered as unstable for the moment.
This is a fork of the gbulb project.
Apache 2.0
https://github.com/astronouth7303/gpotato
import asyncio, gpotato
asyncio.set_event_loop_policy(gpotato.GLibEventLoopPolicy())
import asyncio, gpotato
asyncio.set_event_loop_policy(gpotato.GtkEventLoopPolicy())
import asyncio, gpotato
asyncio.set_event_loop_policy(gpotato.GApplicationEventLoopPolicy())
loop = asyncio.get_event_loop()
loop.run_forever(application = my_gapplication_object)
In GLib, the concept of event loop is split in two classes: GLib.MainContext
and GLib.MainLoop
.
The thing is mostly implemented by MainContext
. MainLoop
is just a wrapper
that implements the run()
and quit()
functions. MainLoop.run()
atomically
acquires a MainContext
and repeatedly calls MainContext.iteration()
until
MainLoop.quit()
is called.
A MainContext
is not bound to a particular thread, however is cannot be used
by multiple threads concurrently. If the context is owned by another thread,
then MainLoop.run()
will block until the context is released by the other
thread.
MainLoop.run()
may be called recursively by the same thread (this is mainly
used for implementing modal dialogs in Gtk).
The issue: given a context, GLib provides no ways to know if there is an existing event loop running for that context. It implies the following divergences with PEP 3156:
.run_forever()
and .run_until_complete()
are not guaranteed to run
immediatly. If the context is owned by another thread, then they will
block until the context is released by the other thread.
.stop()
is relevant only when the currently running Glib.MainLoop
object
was created by this asyncio object (i.e. by calling .run_forever()
or
.run_until_complete()
). The event loop will quit only when it regains
control of the context. This can happen in two cases:
MainLoop
objects and calling .run()
recursively)It should be wiser not to use any recursion at all. GLibEventLoop
will
actually prevent you from doing that (in accordance with PEP 3156). However
you should keep in mind that enclosed loops may be started at any time by
third-party code calling directly GLib's primitives.