Skip to content

Commit 995a449

Browse files
Merge pull request #7 from Ledej/enable-resttool-customization
Enable the `RestTool` class to be customized
2 parents 472e30b + 553ec82 commit 995a449

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

mangopaysdk/configuration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ class Configuration:
2222

2323
#AuthenticationType = enums.AuthenticationType.Strong
2424

25+
# RestTool class
26+
# NB: you can swap this class for one of ours that implement some custom logic
27+
RestToolClass = None
28+
29+
2530
# we use DEBUG level for internal debugging
2631
if (Configuration.DebugMode):
2732
logging.basicConfig(level=logging.DEBUG)

mangopaysdk/tools/resttool.py

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66

77

8-
class RestTool:
8+
class BaseRestTool(object):
99
"""Class to prepare HTTP request, call the request and decode the response."""
1010

1111
# Root/parent MangoPayApi instance that holds the OAuthToken and Configuration instance
@@ -53,12 +53,10 @@ def Request(self, urlMethod, requestType, requestData = None, pagination = None,
5353

5454
return response
5555

56-
def _runRequest(self, urlMethod, pagination, additionalUrlParams):
57-
"""Execute request and check response.
58-
return object Respons data
59-
throws Exception If cURL has error
56+
def _generateRequest(self, urlMethod, pagination, additionalUrlParams):
57+
"""Generate the request object
58+
that will be used in the `_runRequest`
6059
"""
61-
6260
urlToolObj = UrlTool(self._root.Config)
6361
restUrl = urlToolObj.GetRestUrl(urlMethod, self._authRequired, pagination, additionalUrlParams)
6462
fullUrl = urlToolObj.GetFullUrl(restUrl)
@@ -71,14 +69,31 @@ def _runRequest(self, urlMethod, pagination, additionalUrlParams):
7169
if (self._debugMode): logging.getLogger(__name__).debug('REQUEST: {0} {1}\n DATA: {2}'.format(self._requestType, fullUrl, self._requestData))
7270

7371
if self._requestType == "POST":
74-
response = requests.post(fullUrl, json.dumps(self._requestData), auth = authObj, verify=False, headers=headersJson)
72+
request = requests.Request('POST', fullUrl, data=json.dumps(self._requestData), auth=authObj, headers=headersJson)
7573
elif self._requestType == "GET":
76-
response = requests.get(fullUrl, auth = authObj, verify=False)
74+
request = requests.Request('GET', fullUrl, auth=authObj)
7775
elif self._requestType == "PUT":
78-
response = requests.put(fullUrl, json.dumps(self._requestData), auth = authObj, verify=False, headers=headersJson)
76+
request = requests.Request('PUT', fullUrl, data=json.dumps(self._requestData), auth=authObj, headers=headersJson)
7977
elif self._requestType == "DELETE":
80-
response = requests.delete(fullUrl, auth = authObj, verify=False, headers=headers)
81-
78+
request = requests.Request('DELETE', fullUrl, auth=authObj, headers=headers)
79+
80+
return request
81+
82+
def _sendRequest(self, request):
83+
"""Prepare and send the request"""
84+
prepared_request = request.prepare()
85+
session = requests.Session()
86+
response = session.send(prepared_request, verify=False)
87+
return response
88+
89+
def _runRequest(self, urlMethod, pagination, additionalUrlParams):
90+
"""Execute request and check response.
91+
return object Respons data
92+
throws Exception If cURL has error
93+
"""
94+
request = self._generateRequest(urlMethod, pagination, additionalUrlParams)
95+
response = self._sendRequest(request)
96+
8297
if (self._debugMode): logging.getLogger(__name__).debug('RESPONSE: {0}\n {1}\n {2}'.format(response.status_code, response.headers, response.text))
8398

8499
decodedResp = json.loads(response.text) if (response.text != '' and 'application/json' in response.headers['content-type']) else None
@@ -125,3 +140,37 @@ def _checkResponseCode(self, response, decodedResp):
125140
elif decodedResp != None and decodedResp.get('error') != None:
126141
message = decodedResp.get('error')
127142
raise ResponseException(response.request.url, response.status_code, message)
143+
144+
145+
def _getRestTool(root, *args, **kwargs):
146+
RestToolClass = root.Config.RestToolClass
147+
if RestToolClass is None:
148+
RestToolClass = BaseRestTool
149+
150+
# in the case the user swap for his own class, check it's good enough
151+
if not issubclass(RestToolClass, BaseRestTool):
152+
raise ValueError("You've swapped the `Configuration.RestToolClass` "
153+
"for you own but you need `%s` to subclass "
154+
"the original class `%s`" % (RestToolClass,
155+
BaseRestTool))
156+
157+
return RestToolClass(root, *args, **kwargs)
158+
159+
160+
class RestToolProxy(object):
161+
"""
162+
Wrapper around the `BaseRestTool` class
163+
It decides which class should be used based on the `root.Config.RestToolClass`
164+
And then proxies the calls to the wrapped class instance
165+
"""
166+
167+
def __init__(self, root, *args, **kwargs):
168+
resttool = _getRestTool(root, *args, **kwargs)
169+
self._resttool = resttool
170+
171+
def __getattribute__(self, attr):
172+
return getattr(object.__getattribute__(self, '_resttool'), attr)
173+
174+
175+
# for easy backward compatibility we use the proxy as the main class
176+
RestTool = RestToolProxy

0 commit comments

Comments
 (0)