You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.7 KiB

4 years ago
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. from __future__ import absolute_import, division, print_function
  5. import abc
  6. import binascii
  7. import inspect
  8. import sys
  9. import warnings
  10. # We use a UserWarning subclass, instead of DeprecationWarning, because CPython
  11. # decided deprecation warnings should be invisble by default.
  12. class CryptographyDeprecationWarning(UserWarning):
  13. pass
  14. # Several APIs were deprecated with no specific end-of-life date because of the
  15. # ubiquity of their use. They should not be removed until we agree on when that
  16. # cycle ends.
  17. PersistentlyDeprecated = CryptographyDeprecationWarning
  18. DeprecatedIn21 = CryptographyDeprecationWarning
  19. DeprecatedIn23 = CryptographyDeprecationWarning
  20. def _check_bytes(name, value):
  21. if not isinstance(value, bytes):
  22. raise TypeError("{0} must be bytes".format(name))
  23. def read_only_property(name):
  24. return property(lambda self: getattr(self, name))
  25. def register_interface(iface):
  26. def register_decorator(klass):
  27. verify_interface(iface, klass)
  28. iface.register(klass)
  29. return klass
  30. return register_decorator
  31. def register_interface_if(predicate, iface):
  32. def register_decorator(klass):
  33. if predicate:
  34. verify_interface(iface, klass)
  35. iface.register(klass)
  36. return klass
  37. return register_decorator
  38. if hasattr(int, "from_bytes"):
  39. int_from_bytes = int.from_bytes
  40. else:
  41. def int_from_bytes(data, byteorder, signed=False):
  42. assert byteorder == 'big'
  43. assert not signed
  44. return int(binascii.hexlify(data), 16)
  45. if hasattr(int, "to_bytes"):
  46. def int_to_bytes(integer, length=None):
  47. return integer.to_bytes(
  48. length or (integer.bit_length() + 7) // 8 or 1, 'big'
  49. )
  50. else:
  51. def int_to_bytes(integer, length=None):
  52. hex_string = '%x' % integer
  53. if length is None:
  54. n = len(hex_string)
  55. else:
  56. n = length * 2
  57. return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
  58. class InterfaceNotImplemented(Exception):
  59. pass
  60. if hasattr(inspect, "signature"):
  61. signature = inspect.signature
  62. else:
  63. signature = inspect.getargspec
  64. def verify_interface(iface, klass):
  65. for method in iface.__abstractmethods__:
  66. if not hasattr(klass, method):
  67. raise InterfaceNotImplemented(
  68. "{0} is missing a {1!r} method".format(klass, method)
  69. )
  70. if isinstance(getattr(iface, method), abc.abstractproperty):
  71. # Can't properly verify these yet.
  72. continue
  73. sig = signature(getattr(iface, method))
  74. actual = signature(getattr(klass, method))
  75. if sig != actual:
  76. raise InterfaceNotImplemented(
  77. "{0}.{1}'s signature differs from the expected. Expected: "
  78. "{2!r}. Received: {3!r}".format(
  79. klass, method, sig, actual
  80. )
  81. )
  82. # No longer needed as of 2.2, but retained because we have external consumers
  83. # who use it.
  84. def bit_length(x):
  85. return x.bit_length()
  86. class _DeprecatedValue(object):
  87. def __init__(self, value, message, warning_class):
  88. self.value = value
  89. self.message = message
  90. self.warning_class = warning_class
  91. class _ModuleWithDeprecations(object):
  92. def __init__(self, module):
  93. self.__dict__["_module"] = module
  94. def __getattr__(self, attr):
  95. obj = getattr(self._module, attr)
  96. if isinstance(obj, _DeprecatedValue):
  97. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  98. obj = obj.value
  99. return obj
  100. def __setattr__(self, attr, value):
  101. setattr(self._module, attr, value)
  102. def __delattr__(self, attr):
  103. obj = getattr(self._module, attr)
  104. if isinstance(obj, _DeprecatedValue):
  105. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  106. delattr(self._module, attr)
  107. def __dir__(self):
  108. return ["_module"] + dir(self._module)
  109. def deprecated(value, module_name, message, warning_class):
  110. module = sys.modules[module_name]
  111. if not isinstance(module, _ModuleWithDeprecations):
  112. sys.modules[module_name] = _ModuleWithDeprecations(module)
  113. return _DeprecatedValue(value, message, warning_class)
  114. def cached_property(func):
  115. cached_name = "_cached_{0}".format(func)
  116. sentinel = object()
  117. def inner(instance):
  118. cache = getattr(instance, cached_name, sentinel)
  119. if cache is not sentinel:
  120. return cache
  121. result = func(instance)
  122. setattr(instance, cached_name, result)
  123. return result
  124. return property(inner)