_shared.py 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. from __future__ import annotations
  2. from email.utils import parsedate_to_datetime
  3. from http import HTTPStatus
  4. def parse_retry_after(header: str | None) -> float | None:
  5. if header is None:
  6. return None
  7. # of seconds, e.g., Retry-After: 120
  8. try:
  9. ret = int(header)
  10. if ret < 0:
  11. return None
  12. return float(ret)
  13. except ValueError:
  14. pass
  15. # Date, e.g., Retry-After: Wed, 21 Oct 2015 07:28:00 GMT
  16. try:
  17. dt = parsedate_to_datetime(header)
  18. except Exception:
  19. return None
  20. delta = (dt - dt.now(dt.tzinfo)).total_seconds()
  21. if delta < 0:
  22. return None
  23. return delta
  24. def default_should_retry_request(_method: str) -> bool:
  25. # By default, allow retries for any methods for connection errors.
  26. # The default response hook checks idempotency for other errors.
  27. return True
  28. _IDEMPOTENT_METHODS = ("GET", "HEAD", "PUT", "DELETE")
  29. def default_should_retry_response(method: str, status: int | Exception) -> bool:
  30. if isinstance(status, ConnectionError):
  31. return True
  32. if method not in _IDEMPOTENT_METHODS:
  33. return False
  34. if isinstance(status, Exception):
  35. return True
  36. if status == HTTPStatus.TOO_MANY_REQUESTS:
  37. return True
  38. return status >= 500 and status != HTTPStatus.NOT_IMPLEMENTED