PageRenderTime 59ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/venv/Lib/site-packages/async_timeout/__init__.py

https://bitbucket.org/echarles5wits/kioskcommutility
Python | 104 lines | 93 code | 5 blank | 6 comment | 0 complexity | a64bd9c82f7ec52eda11090d72fba383 MD5 | raw file
  1. import asyncio
  2. import sys
  3. __version__ = '2.0.1'
  4. PY_37 = sys.version_info >= (3, 7)
  5. class timeout:
  6. """timeout context manager.
  7. Useful in cases when you want to apply timeout logic around block
  8. of code or in cases when asyncio.wait_for is not suitable. For example:
  9. >>> with timeout(0.001):
  10. ... async with aiohttp.get('https://github.com') as r:
  11. ... await r.text()
  12. timeout - value in seconds or None to disable timeout logic
  13. loop - asyncio compatible event loop
  14. """
  15. def __init__(self, timeout, *, loop=None):
  16. self._timeout = timeout
  17. if loop is None:
  18. loop = asyncio.get_event_loop()
  19. self._loop = loop
  20. self._task = None
  21. self._cancelled = False
  22. self._cancel_handler = None
  23. self._cancel_at = None
  24. def __enter__(self):
  25. return self._do_enter()
  26. def __exit__(self, exc_type, exc_val, exc_tb):
  27. self._do_exit(exc_type)
  28. @asyncio.coroutine
  29. def __aenter__(self):
  30. return self._do_enter()
  31. @asyncio.coroutine
  32. def __aexit__(self, exc_type, exc_val, exc_tb):
  33. self._do_exit(exc_type)
  34. @property
  35. def expired(self):
  36. return self._cancelled
  37. @property
  38. def remaining(self):
  39. if self._cancel_at is not None:
  40. return max(self._cancel_at - self._loop.time(), 0.0)
  41. else:
  42. return None
  43. def _do_enter(self):
  44. # Support Tornado 5- without timeout
  45. # Details: https://github.com/python/asyncio/issues/392
  46. if self._timeout is None:
  47. return self
  48. self._task = current_task(self._loop)
  49. if self._task is None:
  50. raise RuntimeError('Timeout context manager should be used '
  51. 'inside a task')
  52. if self._timeout <= 0:
  53. self._loop.call_soon(self._cancel_task)
  54. return self
  55. self._cancel_at = self._loop.time() + self._timeout
  56. self._cancel_handler = self._loop.call_at(
  57. self._cancel_at, self._cancel_task)
  58. return self
  59. def _do_exit(self, exc_type):
  60. if exc_type is asyncio.CancelledError and self._cancelled:
  61. self._cancel_handler = None
  62. self._task = None
  63. raise asyncio.TimeoutError
  64. if self._timeout is not None and self._cancel_handler is not None:
  65. self._cancel_handler.cancel()
  66. self._cancel_handler = None
  67. self._task = None
  68. def _cancel_task(self):
  69. self._task.cancel()
  70. self._cancelled = True
  71. def current_task(loop):
  72. if PY_37:
  73. task = asyncio.current_task(loop=loop)
  74. else:
  75. task = asyncio.Task.current_task(loop=loop)
  76. if task is None:
  77. # this should be removed, tokio must use register_task and family API
  78. if hasattr(loop, 'current_task'):
  79. task = loop.current_task()
  80. return task