base.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. """Various base classes."""
  2. from collections.abc import Awaitable
  3. from contextlib import AbstractAsyncContextManager
  4. from asyncio import get_running_loop
  5. class AsyncBase:
  6. def __init__(self, file, loop, executor):
  7. self._file = file
  8. self._executor = executor
  9. self._ref_loop = loop
  10. @property
  11. def _loop(self):
  12. return self._ref_loop or get_running_loop()
  13. def __aiter__(self):
  14. """We are our own iterator."""
  15. return self
  16. def __repr__(self):
  17. return super().__repr__() + " wrapping " + repr(self._file)
  18. async def __anext__(self):
  19. """Simulate normal file iteration."""
  20. line = await self.readline()
  21. if line:
  22. return line
  23. else:
  24. raise StopAsyncIteration
  25. class AsyncIndirectBase(AsyncBase):
  26. def __init__(self, name, loop, executor, indirect):
  27. self._indirect = indirect
  28. self._name = name
  29. super().__init__(None, loop, executor)
  30. @property
  31. def _file(self):
  32. return self._indirect()
  33. @_file.setter
  34. def _file(self, v):
  35. pass # discard writes
  36. class AiofilesContextManager(Awaitable, AbstractAsyncContextManager):
  37. """An adjusted async context manager for aiofiles."""
  38. __slots__ = ("_coro", "_obj")
  39. def __init__(self, coro):
  40. self._coro = coro
  41. self._obj = None
  42. def __await__(self):
  43. if self._obj is None:
  44. self._obj = yield from self._coro.__await__()
  45. return self._obj
  46. async def __aenter__(self):
  47. return await self
  48. async def __aexit__(self, exc_type, exc_val, exc_tb):
  49. await get_running_loop().run_in_executor(
  50. None, self._obj._file.__exit__, exc_type, exc_val, exc_tb
  51. )
  52. self._obj = None