| # Copyright 2018 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| import functools |
| |
| import portage |
| portage.proxy.lazyimport.lazyimport(globals(), |
| 'portage.util.futures:asyncio', |
| ) |
| |
| |
| def _sync_decorator(func, loop=None): |
| """ |
| Decorate an asynchronous function (either a corouting function or a |
| function that returns a Future) with a wrapper that runs the function |
| synchronously. |
| """ |
| loop = asyncio._wrap_loop(loop) |
| @functools.wraps(func) |
| def wrapper(*args, **kwargs): |
| return loop.run_until_complete(func(*args, **kwargs)) |
| return wrapper |
| |
| |
| def _sync_methods(obj, loop=None): |
| """ |
| For use with synchronous code that needs to interact with an object |
| that has coroutine methods, this function generates a proxy which |
| conveniently converts coroutine methods into synchronous methods. |
| This allows coroutines to smoothly blend with synchronous |
| code, eliminating clutter that might otherwise discourage the |
| proliferation of coroutine usage for I/O bound tasks. |
| """ |
| loop = asyncio._wrap_loop(loop) |
| return _ObjectAttrWrapper(obj, |
| lambda attr: _sync_decorator(attr, loop=loop) |
| if asyncio.iscoroutinefunction(attr) else attr) |
| |
| |
| class _ObjectAttrWrapper(portage.proxy.objectproxy.ObjectProxy): |
| |
| __slots__ = ('_obj', '_attr_wrapper') |
| |
| def __init__(self, obj, attr_wrapper): |
| object.__setattr__(self, '_obj', obj) |
| object.__setattr__(self, '_attr_wrapper', attr_wrapper) |
| |
| def __getattribute__(self, attr): |
| obj = object.__getattribute__(self, '_obj') |
| attr_wrapper = object.__getattribute__(self, '_attr_wrapper') |
| return attr_wrapper(getattr(obj, attr)) |
| |
| def _get_target(self): |
| return object.__getattribute__(self, '_obj') |