-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapiWrapper.py
More file actions
118 lines (98 loc) · 3.67 KB
/
apiWrapper.py
File metadata and controls
118 lines (98 loc) · 3.67 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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# -*- coding: utf-8 -*-
import traceback
from functionsex import *
from errors import CapybaraMailError, ERROR_MSG
class ApiWrapperBase(type):
"""
This Meta-Class wraps each public method of Api and do some protocol-specific magic or add authentication support.
:note:
Auth can be disabled for whole class by attr `_noAuth`.
:note:
Call-wrapping can be disabled for whole class by attr `_noCall`.
"""
def __new__(cls, className, bases, classDict):
_noAuth=classDict.get('_noAuth', False)
_noCall=classDict.get('_noCall', False)
for k, v in classDict.items():
if not k.startswith('_') and callable(v):
classDict[k]=cls.wrap(
classDict, v,
disableAuth=getattr(v, '_noAuth', _noAuth),
disableCall=getattr(v, '_noCall', _noCall),
)
return type.__new__(cls, className, bases, classDict)
@classmethod
def wrap(cls, classDict, f, disableAuth=False, disableCall=False):
disableAuth, disableCall=cls._wrapping_before(classDict, f, disableAuth=False, disableCall=False)
@functools.wraps(f)
def fNew(self, *args, **kwargs):
scope=cls._wrapped_pre({}, f, self, args, kwargs)
if not disableAuth:
cls._wrapped_auth(scope, f, self, args, kwargs)
if not disableCall:
return cls._wrapped_call(scope, f, self, args, kwargs)
else:
return f(self, *args, **kwargs)
fNew._original=f
fNew=cls._wrapping_after(classDict, fNew, f)
return fNew
@classmethod
def _wrapping_before(cls, classDict, fOld, disableAuth, disableCall):
return disableAuth, disableCall
@classmethod
def _wrapping_after(cls, classDict, fNew, fOld):
return fNew
@classmethod
def _wrapped_pre(cls, scope, f, self, args, kwargs):
return scope
@classmethod
def _wrapped_auth(cls, scope, f, self, args, kwargs):
pass
@classmethod
def _wrapped_call(cls, scope, f, self, args, kwargs):
return f(self, *args, **kwargs)
class ApiWrapperJSONRPC(ApiWrapperBase):
@classmethod
def _wrapping_before(cls, classDict, fOld, disableAuth, disableCall):
if 'login' not in inspect.getargs(fOld.__code__)[0]:
disableAuth=False
return disableAuth, disableCall
# @classmethod
# def _wrapping_after(cls, classDict, fNew, fOld):
# if '_dispatcherMap' not in classDict:
# classDict['_dispatcherMap']={}
# classDict['_dispatcherMap'][fOld.__name__]=fNew
# return fNew
@classmethod
def _prepBadResp(cls, e):
if isinstance(e, AssertionError):
return {'code':-6, 'data':'%s\n%s'%(ERROR_MSG[-6], traceback.format_exc())}
elif isinstance(e, NotImplementedError):
return {'code':-1, 'data':'%s\n%s'%(ERROR_MSG[-1], traceback.format_exc())}
if isinstance(e, CapybaraMailError):
return {'code':e.code, 'data':e.msg}
else:
return {'code':False, 'data':getErrorInfo(fallback=False)}
@classmethod
def _prepResp(cls, data):
if isinstance(data, Exception):
return cls._prepBadResp(data)
else:
return {'code':True, 'data':data}
@classmethod
def _wrapped_pre(cls, scope, f, self, args, kwargs):
scope['conn']=kwargs.get('_conn', {})
return scope
@classmethod
def _wrapped_auth(cls, scope, f, self, args, kwargs):
pass
@classmethod
def _wrapped_call(cls, scope, f, self, args, kwargs):
if scope['conn'].get('__getRawResponse', False):
r=f(self, *args, **kwargs)
else:
try:
r=cls._prepResp(f(self, *args, **kwargs))
except Exception, e:
r=cls._prepBadResp(e)
return r