Alex Gaynor | 5951f46 | 2014-11-16 09:08:42 -0800 | [diff] [blame] | 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. |
David Reid | dcf62db | 2013-11-18 13:02:00 -0800 | [diff] [blame] | 4 | |
| 5 | from __future__ import absolute_import, division, print_function |
| 6 | |
Alex Gaynor | 15dde27 | 2014-10-21 11:41:53 -0700 | [diff] [blame] | 7 | import abc |
Paul Kehrer | 679e8f5 | 2015-08-08 09:59:48 -0500 | [diff] [blame] | 8 | import binascii |
Alex Gaynor | 4115d04 | 2014-10-21 10:55:30 -0700 | [diff] [blame] | 9 | import inspect |
Paul Kehrer | bb81b34 | 2015-06-27 22:28:53 -0500 | [diff] [blame] | 10 | import struct |
Mohammed Attia | cd2a1a8 | 2014-03-05 21:54:06 +0200 | [diff] [blame] | 11 | import sys |
Alex Gaynor | 307939e | 2015-01-01 17:02:35 -0800 | [diff] [blame] | 12 | import warnings |
Mohammed Attia | cd2a1a8 | 2014-03-05 21:54:06 +0200 | [diff] [blame] | 13 | |
David Reid | dcf62db | 2013-11-18 13:02:00 -0800 | [diff] [blame] | 14 | |
Paul Kehrer | c6242dc | 2015-12-25 16:36:46 -0600 | [diff] [blame] | 15 | # 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 Kehrer | 1e392ab | 2015-10-29 13:49:48 +0900 | [diff] [blame] | 17 | DeprecatedIn10 = DeprecationWarning |
Paul Kehrer | c6242dc | 2015-12-25 16:36:46 -0600 | [diff] [blame] | 18 | DeprecatedIn12 = PendingDeprecationWarning |
Alex Stapleton | f48f69d | 2015-01-18 15:57:28 +0000 | [diff] [blame] | 19 | |
Paul Kehrer | dc378d1 | 2014-04-02 17:55:46 -0500 | [diff] [blame] | 20 | |
Alex Gaynor | 307939e | 2015-01-01 17:02:35 -0800 | [diff] [blame] | 21 | def read_only_property(name): |
| 22 | return property(lambda self: getattr(self, name)) |
| 23 | |
| 24 | |
David Reid | dcf62db | 2013-11-18 13:02:00 -0800 | [diff] [blame] | 25 | def register_interface(iface): |
| 26 | def register_decorator(klass): |
Alex Gaynor | d918580 | 2014-10-22 10:12:07 -0700 | [diff] [blame] | 27 | verify_interface(iface, klass) |
David Reid | dcf62db | 2013-11-18 13:02:00 -0800 | [diff] [blame] | 28 | iface.register(klass) |
| 29 | return klass |
| 30 | return register_decorator |
Mohammed Attia | cd2a1a8 | 2014-03-05 21:54:06 +0200 | [diff] [blame] | 31 | |
| 32 | |
Paul Kehrer | bb81b34 | 2015-06-27 22:28:53 -0500 | [diff] [blame] | 33 | if hasattr(int, "from_bytes"): |
| 34 | int_from_bytes = int.from_bytes |
| 35 | else: |
| 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 Kehrer | 467072f | 2015-10-25 15:44:29 -0500 | [diff] [blame] | 53 | def int_to_bytes(integer, length=None): |
Paul Kehrer | a39e3d1 | 2015-08-08 11:10:32 -0500 | [diff] [blame] | 54 | hex_string = '%x' % integer |
Paul Kehrer | 467072f | 2015-10-25 15:44:29 -0500 | [diff] [blame] | 55 | if length is None: |
| 56 | n = len(hex_string) |
| 57 | else: |
| 58 | n = length * 2 |
Paul Kehrer | a39e3d1 | 2015-08-08 11:10:32 -0500 | [diff] [blame] | 59 | return binascii.unhexlify(hex_string.zfill(n + (n & 1))) |
Paul Kehrer | 679e8f5 | 2015-08-08 09:59:48 -0500 | [diff] [blame] | 60 | |
| 61 | |
Alex Gaynor | 4115d04 | 2014-10-21 10:55:30 -0700 | [diff] [blame] | 62 | class InterfaceNotImplemented(Exception): |
| 63 | pass |
| 64 | |
| 65 | |
Alex Gaynor | 44878a5 | 2015-09-29 20:56:09 -0400 | [diff] [blame] | 66 | if hasattr(inspect, "signature"): |
| 67 | signature = inspect.signature |
| 68 | else: |
| 69 | signature = inspect.getargspec |
| 70 | |
Alex Gaynor | c01a6c5 | 2015-09-29 21:31:00 -0400 | [diff] [blame] | 71 | |
Alex Gaynor | 4115d04 | 2014-10-21 10:55:30 -0700 | [diff] [blame] | 72 | def 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 Gaynor | 15dde27 | 2014-10-21 11:41:53 -0700 | [diff] [blame] | 78 | if isinstance(getattr(iface, method), abc.abstractproperty): |
| 79 | # Can't properly verify these yet. |
| 80 | continue |
Alex Gaynor | 44878a5 | 2015-09-29 20:56:09 -0400 | [diff] [blame] | 81 | sig = signature(getattr(iface, method)) |
| 82 | actual = signature(getattr(klass, method)) |
| 83 | if sig != actual: |
Alex Gaynor | 4115d04 | 2014-10-21 10:55:30 -0700 | [diff] [blame] | 84 | raise InterfaceNotImplemented( |
Alex Gaynor | 15dde27 | 2014-10-21 11:41:53 -0700 | [diff] [blame] | 85 | "{0}.{1}'s signature differs from the expected. Expected: " |
| 86 | "{2!r}. Received: {3!r}".format( |
Alex Gaynor | 685a011 | 2015-09-29 21:06:18 -0400 | [diff] [blame] | 87 | klass, method, sig, actual |
Alex Gaynor | 4115d04 | 2014-10-21 10:55:30 -0700 | [diff] [blame] | 88 | ) |
| 89 | ) |
| 90 | |
| 91 | |
Alex Gaynor | 993b85a | 2014-12-15 10:42:45 -0800 | [diff] [blame] | 92 | if sys.version_info >= (2, 7): |
| 93 | def bit_length(x): |
Mohammed Attia | cd2a1a8 | 2014-03-05 21:54:06 +0200 | [diff] [blame] | 94 | return x.bit_length() |
Alex Gaynor | 993b85a | 2014-12-15 10:42:45 -0800 | [diff] [blame] | 95 | else: |
| 96 | def bit_length(x): |
Mohammed Attia | cd2a1a8 | 2014-03-05 21:54:06 +0200 | [diff] [blame] | 97 | return len(bin(x)) - (2 + (x <= 0)) |
Alex Gaynor | 307939e | 2015-01-01 17:02:35 -0800 | [diff] [blame] | 98 | |
| 99 | |
| 100 | class _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 | |
| 107 | class _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 Gaynor | 307939e | 2015-01-01 17:02:35 -0800 | [diff] [blame] | 125 | def 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) |