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.

162 lines
4.5 KiB

7 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. # Several APIs were deprecated with no specific end-of-life date because of the
  11. # ubiquity of their use. They should not be removed until we agree on when that
  12. # cycle ends.
  13. PersistentlyDeprecated = DeprecationWarning
  14. DeprecatedIn19 = DeprecationWarning
  15. DeprecatedIn21 = PendingDeprecationWarning
  16. def _check_bytes(name, value):
  17. if not isinstance(value, bytes):
  18. raise TypeError("{0} must be bytes".format(name))
  19. def read_only_property(name):
  20. return property(lambda self: getattr(self, name))
  21. def register_interface(iface):
  22. def register_decorator(klass):
  23. verify_interface(iface, klass)
  24. iface.register(klass)
  25. return klass
  26. return register_decorator
  27. def register_interface_if(predicate, iface):
  28. def register_decorator(klass):
  29. if predicate:
  30. verify_interface(iface, klass)
  31. iface.register(klass)
  32. return klass
  33. return register_decorator
  34. if hasattr(int, "from_bytes"):
  35. int_from_bytes = int.from_bytes
  36. else:
  37. def int_from_bytes(data, byteorder, signed=False):
  38. assert byteorder == 'big'
  39. assert not signed
  40. # call bytes() on data to allow the use of bytearrays
  41. return int(bytes(data).encode('hex'), 16)
  42. if hasattr(int, "to_bytes"):
  43. def int_to_bytes(integer, length=None):
  44. return integer.to_bytes(
  45. length or (integer.bit_length() + 7) // 8 or 1, 'big'
  46. )
  47. else:
  48. def int_to_bytes(integer, length=None):
  49. hex_string = '%x' % integer
  50. if length is None:
  51. n = len(hex_string)
  52. else:
  53. n = length * 2
  54. return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
  55. class InterfaceNotImplemented(Exception):
  56. pass
  57. if hasattr(inspect, "signature"):
  58. signature = inspect.signature
  59. else:
  60. signature = inspect.getargspec
  61. def verify_interface(iface, klass):
  62. for method in iface.__abstractmethods__:
  63. if not hasattr(klass, method):
  64. raise InterfaceNotImplemented(
  65. "{0} is missing a {1!r} method".format(klass, method)
  66. )
  67. if isinstance(getattr(iface, method), abc.abstractproperty):
  68. # Can't properly verify these yet.
  69. continue
  70. sig = signature(getattr(iface, method))
  71. actual = signature(getattr(klass, method))
  72. if sig != actual:
  73. raise InterfaceNotImplemented(
  74. "{0}.{1}'s signature differs from the expected. Expected: "
  75. "{2!r}. Received: {3!r}".format(
  76. klass, method, sig, actual
  77. )
  78. )
  79. if sys.version_info >= (2, 7):
  80. def bit_length(x):
  81. return x.bit_length()
  82. else:
  83. def bit_length(x):
  84. return len(bin(x)) - (2 + (x <= 0))
  85. class _DeprecatedValue(object):
  86. def __init__(self, value, message, warning_class):
  87. self.value = value
  88. self.message = message
  89. self.warning_class = warning_class
  90. class _ModuleWithDeprecations(object):
  91. def __init__(self, module):
  92. self.__dict__["_module"] = module
  93. def __getattr__(self, attr):
  94. obj = getattr(self._module, attr)
  95. if isinstance(obj, _DeprecatedValue):
  96. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  97. obj = obj.value
  98. return obj
  99. def __setattr__(self, attr, value):
  100. setattr(self._module, attr, value)
  101. def __delattr__(self, attr):
  102. obj = getattr(self._module, attr)
  103. if isinstance(obj, _DeprecatedValue):
  104. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  105. delattr(self._module, attr)
  106. def __dir__(self):
  107. return ["_module"] + dir(self._module)
  108. def deprecated(value, module_name, message, warning_class):
  109. module = sys.modules[module_name]
  110. if not isinstance(module, _ModuleWithDeprecations):
  111. sys.modules[module_name] = _ModuleWithDeprecations(module)
  112. return _DeprecatedValue(value, message, warning_class)
  113. def cached_property(func):
  114. cached_name = "_cached_{0}".format(func)
  115. sentinel = object()
  116. def inner(instance):
  117. cache = getattr(instance, cached_name, sentinel)
  118. if cache is not sentinel:
  119. return cache
  120. result = func(instance)
  121. setattr(instance, cached_name, result)
  122. return result
  123. return property(inner)

Powered by TurnKey Linux.