| """Various base classes.""" |
| from types import coroutine |
| from collections.abc import Coroutine |
| from asyncio import get_running_loop |
|
|
|
|
| class AsyncBase: |
| def __init__(self, file, loop, executor): |
| self._file = file |
| self._executor = executor |
| self._ref_loop = loop |
|
|
| @property |
| def _loop(self): |
| return self._ref_loop or get_running_loop() |
|
|
| def __aiter__(self): |
| """We are our own iterator.""" |
| return self |
|
|
| def __repr__(self): |
| return super().__repr__() + " wrapping " + repr(self._file) |
|
|
| async def __anext__(self): |
| """Simulate normal file iteration.""" |
| line = await self.readline() |
| if line: |
| return line |
| else: |
| raise StopAsyncIteration |
|
|
|
|
| class AsyncIndirectBase(AsyncBase): |
| def __init__(self, name, loop, executor, indirect): |
| self._indirect = indirect |
| self._name = name |
| super().__init__(None, loop, executor) |
|
|
| @property |
| def _file(self): |
| return self._indirect() |
|
|
| @_file.setter |
| def _file(self, v): |
| pass |
|
|
|
|
| class _ContextManager(Coroutine): |
| __slots__ = ("_coro", "_obj") |
|
|
| def __init__(self, coro): |
| self._coro = coro |
| self._obj = None |
|
|
| def send(self, value): |
| return self._coro.send(value) |
|
|
| def throw(self, typ, val=None, tb=None): |
| if val is None: |
| return self._coro.throw(typ) |
| elif tb is None: |
| return self._coro.throw(typ, val) |
| else: |
| return self._coro.throw(typ, val, tb) |
|
|
| def close(self): |
| return self._coro.close() |
|
|
| @property |
| def gi_frame(self): |
| return self._coro.gi_frame |
|
|
| @property |
| def gi_running(self): |
| return self._coro.gi_running |
|
|
| @property |
| def gi_code(self): |
| return self._coro.gi_code |
|
|
| def __next__(self): |
| return self.send(None) |
|
|
| @coroutine |
| def __iter__(self): |
| resp = yield from self._coro |
| return resp |
|
|
| def __await__(self): |
| resp = yield from self._coro |
| return resp |
|
|
| async def __anext__(self): |
| resp = await self._coro |
| return resp |
|
|
| async def __aenter__(self): |
| self._obj = await self._coro |
| return self._obj |
|
|
| async def __aexit__(self, exc_type, exc, tb): |
| self._obj.close() |
| self._obj = None |
|
|
|
|
| class AiofilesContextManager(_ContextManager): |
| """An adjusted async context manager for aiofiles.""" |
|
|
| async def __aexit__(self, exc_type, exc_val, exc_tb): |
| await get_running_loop().run_in_executor( |
| None, self._obj._file.__exit__, exc_type, exc_val, exc_tb |
| ) |
| self._obj = None |
|
|