blob: b85d50d3efd9912ac02ff654a3380ccb3aff6961 [file] [log] [blame]
Alex Gaynor5951f462014-11-16 09:08:42 -08001# 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.
David Reiddcf62db2013-11-18 13:02:00 -08004
5from __future__ import absolute_import, division, print_function
6
Alex Gaynor15dde272014-10-21 11:41:53 -07007import abc
Paul Kehrer679e8f52015-08-08 09:59:48 -05008import binascii
Alex Gaynor4115d042014-10-21 10:55:30 -07009import inspect
Paul Kehrerbb81b342015-06-27 22:28:53 -050010import struct
Mohammed Attiacd2a1a82014-03-05 21:54:06 +020011import sys
Alex Gaynor307939e2015-01-01 17:02:35 -080012import warnings
Mohammed Attiacd2a1a82014-03-05 21:54:06 +020013
David Reiddcf62db2013-11-18 13:02:00 -080014
Paul Kehrerc6242dc2015-12-25 16:36:46 -060015# the functions deprecated in 1.0 are on an arbitrarily extended deprecation
16# cycle and should not be removed until we agree on when that cycle ends.
Paul Kehrer1e392ab2015-10-29 13:49:48 +090017DeprecatedIn10 = DeprecationWarning
Paul Kehrerc6242dc2015-12-25 16:36:46 -060018DeprecatedIn12 = PendingDeprecationWarning
Alex Stapletonf48f69d2015-01-18 15:57:28 +000019
Paul Kehrerdc378d12014-04-02 17:55:46 -050020
Alex Gaynor307939e2015-01-01 17:02:35 -080021def read_only_property(name):
22 return property(lambda self: getattr(self, name))
23
24
David Reiddcf62db2013-11-18 13:02:00 -080025def register_interface(iface):
26 def register_decorator(klass):
Alex Gaynord9185802014-10-22 10:12:07 -070027 verify_interface(iface, klass)
David Reiddcf62db2013-11-18 13:02:00 -080028 iface.register(klass)
29 return klass
30 return register_decorator
Mohammed Attiacd2a1a82014-03-05 21:54:06 +020031
32
Paul Kehrerbb81b342015-06-27 22:28:53 -050033if hasattr(int, "from_bytes"):
34 int_from_bytes = int.from_bytes
35else:
36 def int_from_bytes(data, byteorder, signed=False):
37 assert byteorder == 'big'
38 assert not signed
39
40 if len(data) % 4 != 0:
41 data = (b'\x00' * (4 - (len(data) % 4))) + data
42
43 result = 0
44
45 while len(data) > 0:
46 digit, = struct.unpack('>I', data[:4])
47 result = (result << 32) + digit
48 data = data[4:]
49
50 return result
51
52
Paul Kehrer467072f2015-10-25 15:44:29 -050053def int_to_bytes(integer, length=None):
Paul Kehrera39e3d12015-08-08 11:10:32 -050054 hex_string = '%x' % integer
Paul Kehrer467072f2015-10-25 15:44:29 -050055 if length is None:
56 n = len(hex_string)
57 else:
58 n = length * 2
Paul Kehrera39e3d12015-08-08 11:10:32 -050059 return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
Paul Kehrer679e8f52015-08-08 09:59:48 -050060
61
Alex Gaynor4115d042014-10-21 10:55:30 -070062class InterfaceNotImplemented(Exception):
63 pass
64
65
Alex Gaynor44878a52015-09-29 20:56:09 -040066if hasattr(inspect, "signature"):
67 signature = inspect.signature
68else:
69 signature = inspect.getargspec
70
Alex Gaynorc01a6c52015-09-29 21:31:00 -040071
Alex Gaynor4115d042014-10-21 10:55:30 -070072def verify_interface(iface, klass):
73 for method in iface.__abstractmethods__:
74 if not hasattr(klass, method):
75 raise InterfaceNotImplemented(
76 "{0} is missing a {1!r} method".format(klass, method)
77 )
Alex Gaynor15dde272014-10-21 11:41:53 -070078 if isinstance(getattr(iface, method), abc.abstractproperty):
79 # Can't properly verify these yet.
80 continue
Alex Gaynor44878a52015-09-29 20:56:09 -040081 sig = signature(getattr(iface, method))
82 actual = signature(getattr(klass, method))
83 if sig != actual:
Alex Gaynor4115d042014-10-21 10:55:30 -070084 raise InterfaceNotImplemented(
Alex Gaynor15dde272014-10-21 11:41:53 -070085 "{0}.{1}'s signature differs from the expected. Expected: "
86 "{2!r}. Received: {3!r}".format(
Alex Gaynor685a0112015-09-29 21:06:18 -040087 klass, method, sig, actual
Alex Gaynor4115d042014-10-21 10:55:30 -070088 )
89 )
90
91
Alex Gaynor993b85a2014-12-15 10:42:45 -080092if sys.version_info >= (2, 7):
93 def bit_length(x):
Mohammed Attiacd2a1a82014-03-05 21:54:06 +020094 return x.bit_length()
Alex Gaynor993b85a2014-12-15 10:42:45 -080095else:
96 def bit_length(x):
Mohammed Attiacd2a1a82014-03-05 21:54:06 +020097 return len(bin(x)) - (2 + (x <= 0))
Alex Gaynor307939e2015-01-01 17:02:35 -080098
99
100class _DeprecatedValue(object):
101 def __init__(self, value, message, warning_class):
102 self.value = value
103 self.message = message
104 self.warning_class = warning_class
105
106
107class _ModuleWithDeprecations(object):
108 def __init__(self, module):
109 self.__dict__["_module"] = module
110
111 def __getattr__(self, attr):
112 obj = getattr(self._module, attr)
113 if isinstance(obj, _DeprecatedValue):
114 warnings.warn(obj.message, obj.warning_class, stacklevel=2)
115 obj = obj.value
116 return obj
117
118 def __setattr__(self, attr, value):
119 setattr(self._module, attr, value)
120
121 def __dir__(self):
122 return ["_module"] + dir(self._module)
123
124
Alex Gaynor307939e2015-01-01 17:02:35 -0800125def deprecated(value, module_name, message, warning_class):
126 module = sys.modules[module_name]
127 if not isinstance(module, _ModuleWithDeprecations):
128 sys.modules[module_name] = module = _ModuleWithDeprecations(module)
129 return _DeprecatedValue(value, message, warning_class)