compat.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. """
  2. The `compat` module provides support for backwards compatibility with older
  3. versions of python, and compatibility wrappers around optional packages.
  4. """
  5. # flake8: noqa
  6. import hmac
  7. import struct
  8. import sys
  9. PY3 = sys.version_info[0] == 3
  10. if PY3:
  11. text_type = str
  12. binary_type = bytes
  13. else:
  14. text_type = unicode
  15. binary_type = str
  16. string_types = (text_type, binary_type)
  17. try:
  18. # Importing ABCs from collections will be removed in PY3.8
  19. from collections.abc import Iterable, Mapping
  20. except ImportError:
  21. from collections import Iterable, Mapping
  22. try:
  23. constant_time_compare = hmac.compare_digest
  24. except AttributeError:
  25. # Fallback for Python < 2.7
  26. def constant_time_compare(val1, val2):
  27. """
  28. Returns True if the two strings are equal, False otherwise.
  29. The time taken is independent of the number of characters that match.
  30. """
  31. if len(val1) != len(val2):
  32. return False
  33. result = 0
  34. for x, y in zip(val1, val2):
  35. result |= ord(x) ^ ord(y)
  36. return result == 0
  37. # Use int.to_bytes if it exists (Python 3)
  38. if getattr(int, 'to_bytes', None):
  39. def bytes_from_int(val):
  40. remaining = val
  41. byte_length = 0
  42. while remaining != 0:
  43. remaining = remaining >> 8
  44. byte_length += 1
  45. return val.to_bytes(byte_length, 'big', signed=False)
  46. else:
  47. def bytes_from_int(val):
  48. buf = []
  49. while val:
  50. val, remainder = divmod(val, 256)
  51. buf.append(remainder)
  52. buf.reverse()
  53. return struct.pack('%sB' % len(buf), *buf)