def _safe_loop(): """ Return an event loop that's safe to use within the current context. For portage internal callers or external API consumers calling from the main thread, this returns a globally shared event loop instance. For external API consumers calling from a non-main thread, an asyncio loop must be registered for the current thread, or else the asyncio.get_event_loop() function will raise an error like this: RuntimeError: There is no current event loop in thread 'Thread-1'. In order to avoid this RuntimeError, a loop will be automatically created like this: asyncio.set_event_loop(asyncio.new_event_loop()) In order to avoid a ResourceWarning, automatically created loops are added to a WeakValueDictionary, and closed via an atexit hook if they still exist during exit for the current pid. @rtype: asyncio.AbstractEventLoop (or compatible) @return: event loop instance """ loop = _get_running_loop() if loop is not None: return loop thread_key = threading.get_ident() with _thread_weakrefs.lock: if _thread_weakrefs.pid != portage.getpid(): _thread_weakrefs.pid = portage.getpid() _thread_weakrefs.mainloop = None _thread_weakrefs.loops = weakref.WeakValueDictionary() try: loop = _thread_weakrefs.loops[thread_key] except KeyError: try: try: _loop = _real_asyncio.get_running_loop() except AttributeError: _loop = _real_asyncio.get_event_loop() except RuntimeError: _loop = _real_asyncio.new_event_loop() _real_asyncio.set_event_loop(_loop) loop = _thread_weakrefs.loops[thread_key] = _AsyncioEventLoop(loop=_loop) if ( _thread_weakrefs.mainloop is None and threading.current_thread() is threading.main_thread() ): _thread_weakrefs.mainloop = loop return loop
def _wrap_loop(loop=None): """ In order to deal with asyncio event loop compatibility issues, use this function to wrap the loop parameter for functions that support it. For example, since python3.4 does not have the AbstractEventLoop.create_future() method, this helper function can be used to add a wrapper that implements the create_future method for python3.4. @type loop: asyncio.AbstractEventLoop (or compatible) @param loop: event loop @rtype: asyncio.AbstractEventLoop (or compatible) @return: event loop """ # The default loop returned by _wrap_loop should be consistent # with global_event_loop, in order to avoid accidental registration # of callbacks with a loop that is not intended to run. loop = loop or _safe_loop() return loop if hasattr(loop, "_asyncio_wrapper") else _AsyncioEventLoop(loop=loop)
def _wrap_loop(loop=None): loop = loop or _global_event_loop() return (loop if hasattr(loop, '_asyncio_wrapper') else _AsyncioEventLoop(loop=loop))