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 5from __future__ import absolute_import, division, print_function 6 7import abc 8import binascii 9import inspect 10import sys 11import warnings 12 13 14# We use a UserWarning subclass, instead of DeprecationWarning, because CPython 15# decided deprecation warnings should be invisble by default. 16class CryptographyDeprecationWarning(UserWarning): 17 pass 18 19 20# Several APIs were deprecated with no specific end-of-life date because of the 21# ubiquity of their use. They should not be removed until we agree on when that 22# cycle ends. 23PersistentlyDeprecated = CryptographyDeprecationWarning 24DeprecatedIn21 = CryptographyDeprecationWarning 25DeprecatedIn23 = CryptographyDeprecationWarning 26DeprecatedIn25 = CryptographyDeprecationWarning 27 28 29def _check_bytes(name, value): 30 if not isinstance(value, bytes): 31 raise TypeError("{0} must be bytes".format(name)) 32 33 34def _check_byteslike(name, value): 35 try: 36 memoryview(value) 37 except TypeError: 38 raise TypeError("{0} must be bytes-like".format(name)) 39 40 41def read_only_property(name): 42 return property(lambda self: getattr(self, name)) 43 44 45def register_interface(iface): 46 def register_decorator(klass): 47 verify_interface(iface, klass) 48 iface.register(klass) 49 return klass 50 return register_decorator 51 52 53def register_interface_if(predicate, iface): 54 def register_decorator(klass): 55 if predicate: 56 verify_interface(iface, klass) 57 iface.register(klass) 58 return klass 59 return register_decorator 60 61 62if hasattr(int, "from_bytes"): 63 int_from_bytes = int.from_bytes 64else: 65 def int_from_bytes(data, byteorder, signed=False): 66 assert byteorder == 'big' 67 assert not signed 68 69 return int(binascii.hexlify(data), 16) 70 71 72if hasattr(int, "to_bytes"): 73 def int_to_bytes(integer, length=None): 74 return integer.to_bytes( 75 length or (integer.bit_length() + 7) // 8 or 1, 'big' 76 ) 77else: 78 def int_to_bytes(integer, length=None): 79 hex_string = '%x' % integer 80 if length is None: 81 n = len(hex_string) 82 else: 83 n = length * 2 84 return binascii.unhexlify(hex_string.zfill(n + (n & 1))) 85 86 87class InterfaceNotImplemented(Exception): 88 pass 89 90 91if hasattr(inspect, "signature"): 92 signature = inspect.signature 93else: 94 signature = inspect.getargspec 95 96 97def verify_interface(iface, klass): 98 for method in iface.__abstractmethods__: 99 if not hasattr(klass, method): 100 raise InterfaceNotImplemented( 101 "{0} is missing a {1!r} method".format(klass, method) 102 ) 103 if isinstance(getattr(iface, method), abc.abstractproperty): 104 # Can't properly verify these yet. 105 continue 106 sig = signature(getattr(iface, method)) 107 actual = signature(getattr(klass, method)) 108 if sig != actual: 109 raise InterfaceNotImplemented( 110 "{0}.{1}'s signature differs from the expected. Expected: " 111 "{2!r}. Received: {3!r}".format( 112 klass, method, sig, actual 113 ) 114 ) 115 116 117# No longer needed as of 2.2, but retained because we have external consumers 118# who use it. 119def bit_length(x): 120 return x.bit_length() 121 122 123class _DeprecatedValue(object): 124 def __init__(self, value, message, warning_class): 125 self.value = value 126 self.message = message 127 self.warning_class = warning_class 128 129 130class _ModuleWithDeprecations(object): 131 def __init__(self, module): 132 self.__dict__["_module"] = module 133 134 def __getattr__(self, attr): 135 obj = getattr(self._module, attr) 136 if isinstance(obj, _DeprecatedValue): 137 warnings.warn(obj.message, obj.warning_class, stacklevel=2) 138 obj = obj.value 139 return obj 140 141 def __setattr__(self, attr, value): 142 setattr(self._module, attr, value) 143 144 def __delattr__(self, attr): 145 obj = getattr(self._module, attr) 146 if isinstance(obj, _DeprecatedValue): 147 warnings.warn(obj.message, obj.warning_class, stacklevel=2) 148 149 delattr(self._module, attr) 150 151 def __dir__(self): 152 return ["_module"] + dir(self._module) 153 154 155def deprecated(value, module_name, message, warning_class): 156 module = sys.modules[module_name] 157 if not isinstance(module, _ModuleWithDeprecations): 158 sys.modules[module_name] = _ModuleWithDeprecations(module) 159 return _DeprecatedValue(value, message, warning_class) 160 161 162def cached_property(func): 163 cached_name = "_cached_{0}".format(func) 164 sentinel = object() 165 166 def inner(instance): 167 cache = getattr(instance, cached_name, sentinel) 168 if cache is not sentinel: 169 return cache 170 result = func(instance) 171 setattr(instance, cached_name, result) 172 return result 173 return property(inner) 174