-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathinterface.py
More file actions
83 lines (62 loc) · 3.31 KB
/
interface.py
File metadata and controls
83 lines (62 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Credit: Pedro Matiello, https://github.com/pmatiello/python-interface
from inspect import getargspec #@UnresolvedImport
class interface(object):
pass
class method(object):
def __init__(self, args=None, varargs=None, keywords=None, defaults=0):
self.args = args or []
self.varargs = varargs
self.keywords = keywords
self.defaults = defaults
def __str__(self):
return "(%s,%s,%s)" % (self.args, self.varargs, self.keywords)
class implements(object):
def __init__(self, interface):
self.interface = interface
def __call__(self, clazz):
methods = [each for each in dir(self.interface) if self._is_method(each)]
for each in methods:
self._assert_implements(clazz, each)
return clazz
def _is_method(self, name):
try:
return type(self._attribute(self.interface, name)) == method
except:
False
def _assert_implements(self, clazz, method_name):
contract = self._attribute(self.interface, method_name)
self._assert_method_presence(clazz, method_name, contract)
method_impl = getargspec(self._attribute(clazz, method_name))
self._assert_method_arguments(clazz, method_name, method_impl, contract)
self._assert_method_varargs(clazz, method_name, method_impl, contract)
self._assert_method_keyword_args(clazz, method_name, method_impl, contract)
self._assert_method_default_args(clazz, method_name, method_impl, contract)
def _assert_method_presence(self, clazz, method_name, contract):
if (method_name not in dir(clazz)):
raise InterfaceNotImplemented(self.interface, clazz, method_name, contract)
def _assert_method_arguments(self, clazz, method_name, method_impl, contract):
if (not contract.args == method_impl.args):
raise InterfaceNotImplemented(self.interface, clazz, method_name, contract)
def _assert_method_varargs(self, clazz, method_name, method_impl, contract):
if (not contract.varargs == method_impl.varargs):
raise InterfaceNotImplemented(self.interface, clazz, method_name, contract)
def _assert_method_keyword_args(self, clazz, method_name, method_impl, contract):
if (not contract.keywords == method_impl.keywords):
raise InterfaceNotImplemented(self.interface, clazz, method_name, contract)
def _assert_method_default_args(self, clazz, method_name, method_impl, contract):
if (method_impl.defaults is None):
defaults = 0
else:
defaults = len(method_impl.defaults)
if (not contract.defaults == defaults):
raise InterfaceNotImplemented(self.interface, clazz, method_name, contract)
def _attribute(self, clazz, attribute):
return object.__getattribute__(clazz, attribute)
class InterfaceNotImplemented(Exception):
def __init__(self, interface, clazz, method_name, method_signature):
self.interface = interface
self.clazz = clazz
self.method_name = method_name
self.method_signature = method_signature
def __str__(self):
return "Class %s must implement method %s with arguments %s as defined in interface %s" % (self.clazz.__name__, self.method_name, self.method_signature, self.interface.__name__)