Skip to content

Commit 110dc4a

Browse files
committed
fix: ensure hook added if client is re-set
1 parent 72970cd commit 110dc4a

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

ibmcloudant/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from ibm_cloud_sdk_core import IAMTokenManager, DetailedResponse, BaseService, ApiException, get_authenticator
2020
from .couchdb_session_authenticator import CouchDbSessionAuthenticator
2121
from .couchdb_session_get_authenticator_patch import new_construct_authenticator
22-
from .cloudant_base_service import new_init, new_prepare_request, new_set_service_url, new_set_default_headers
22+
from .cloudant_base_service import new_init, new_prepare_request, new_set_default_headers, new_set_http_client, new_set_service_url
2323
from .couchdb_session_token_manager import CouchDbSessionTokenManager
2424
from .cloudant_v1 import CloudantV1
2525
from .features.changes_follower import ChangesFollower
@@ -34,3 +34,5 @@
3434
CloudantV1.set_default_headers = new_set_default_headers
3535

3636
CloudantV1.prepare_request = new_prepare_request
37+
38+
CloudantV1.set_http_client = new_set_http_client

ibmcloudant/cloudant_base_service.py

+26-21
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from io import BytesIO
2626

2727
from ibm_cloud_sdk_core.authenticators import Authenticator
28-
from requests import Response
28+
from requests import Response, Session
2929
from requests.cookies import RequestsCookieJar
3030

3131
from .common import get_sdk_headers
@@ -72,12 +72,10 @@ def __hash__(self):
7272
# Since Py3.6 dict is ordered so use a key only dict for our set
7373
rules_by_operation.setdefault(operation_id, dict()).setdefault(rule)
7474

75-
76-
old_init = CloudantV1.__init__
77-
75+
_old_init = CloudantV1.__init__
7876

7977
def new_init(self, authenticator: Authenticator = None):
80-
old_init(self, authenticator)
78+
_old_init(self, authenticator)
8179
# Overwrite default read timeout to 2.5 minutes
8280
if not ('timeout' in self.http_config):
8381
new_http_config = self.http_config.copy()
@@ -88,27 +86,22 @@ def new_init(self, authenticator: Authenticator = None):
8886
# Replacing BaseService's http.cookiejar.CookieJar as RequestsCookieJar supports update(CookieJar)
8987
self.jar = RequestsCookieJar(self.jar)
9088
self.authenticator.set_jar(self.jar) # Authenticators don't have access to cookie jars by default
91-
response_hooks = self.get_http_client().hooks['response']
92-
if _error_response_hook not in response_hooks:
93-
response_hooks.append(_error_response_hook)
94-
95-
old_set_service_url = CloudantV1.set_service_url
89+
add_hooks(self)
9690

91+
_old_set_service_url = CloudantV1.set_service_url
9792

9893
def new_set_service_url(self, service_url: str):
99-
old_set_service_url(self, service_url)
94+
_old_set_service_url(self, service_url)
10095
try:
10196
if isinstance(self.authenticator, CouchDbSessionAuthenticator):
10297
self.authenticator.token_manager.set_service_url(service_url)
10398
except AttributeError:
10499
pass # in case no authenticator is configured yet, pass
105100

106-
107-
old_set_default_headers = CloudantV1.set_default_headers
108-
101+
_old_set_default_headers = CloudantV1.set_default_headers
109102

110103
def new_set_default_headers(self, headers: Dict[str, str]):
111-
old_set_default_headers(self, headers)
104+
_old_set_default_headers(self, headers)
112105
if isinstance(self.authenticator, CouchDbSessionAuthenticator):
113106
combined_headers = {}
114107
combined_headers.update(headers)
@@ -119,12 +112,13 @@ def new_set_default_headers(self, headers: Dict[str, str]):
119112
)
120113
self.authenticator.token_manager.set_default_headers(combined_headers)
121114

115+
_old_set_disable_ssl_verification = CloudantV1.set_disable_ssl_verification
122116

123-
old_set_disable_ssl_verification = CloudantV1.set_disable_ssl_verification
124-
125-
117+
# Note this is currently unused, but probably should be enabled.
118+
# To enable it we need to resolve whether CouchDbSessionAuthenticator
119+
# should ever be allowed to have a different value from the service client.
126120
def new_set_disable_ssl_verification(self, status: bool = False) -> None:
127-
old_set_disable_ssl_verification(self, status)
121+
_old_set_disable_ssl_verification(self, status)
128122
if isinstance(self.authenticator, CouchDbSessionAuthenticator):
129123
self.authenticator.token_manager.set_disable_ssl_verification(status)
130124

@@ -193,7 +187,7 @@ def _error_response_hook(response:Response, *args, **kwargs) -> Optional[Respons
193187
pass
194188
return response
195189

196-
old_prepare_request = CloudantV1.prepare_request
190+
_old_prepare_request = CloudantV1.prepare_request
197191

198192
def new_prepare_request(self,
199193
method: str,
@@ -229,4 +223,15 @@ def new_prepare_request(self,
229223
if segment_to_validate.startswith('_'):
230224
raise ValueError('{0} {1} starts with the invalid _ character.'.format(rule.error_parameter_name,
231225
unquote(segment_to_validate)))
232-
return old_prepare_request(self, method, url, *args, headers=headers, params=params, data=data, files=files, **kwargs)
226+
return _old_prepare_request(self, method, url, *args, headers=headers, params=params, data=data, files=files, **kwargs)
227+
228+
def add_hooks(self):
229+
response_hooks = self.get_http_client().hooks['response']
230+
if _error_response_hook not in response_hooks:
231+
response_hooks.append(_error_response_hook)
232+
233+
_old_set_http_client = CloudantV1.set_http_client
234+
235+
def new_set_http_client(self, http_client: Session) -> None:
236+
_old_set_http_client(self, http_client)
237+
add_hooks(self)

test/unit/test_cloudant_base_error_augment.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,22 @@ def _response_callback(cls, resp):
167167
return _error_response_hook(resp)
168168

169169
def test_response_hook_added(self):
170-
self.assertEqual(_error_response_hook, self._service.get_http_client().hooks['response'][0])
170+
self.assertEqual(_error_response_hook, self._service.get_http_client().hooks['response'][0])
171+
172+
def test_response_hook_not_double_added_via_set_http_client(self):
173+
client = self._service.get_http_client()
174+
self._service.set_http_client(client)
175+
response_hooks = self._service.get_http_client().hooks['response']
176+
self.assertEqual(1, len(response_hooks))
177+
self.assertEqual(_error_response_hook, response_hooks[0])
178+
179+
def test_response_hook_added_via_set_http_client(self):
180+
client = self._service.get_http_client()
181+
client.hooks['response'].clear()
182+
self._service.set_http_client(client)
183+
response_hooks = self._service.get_http_client().hooks['response']
184+
self.assertEqual(1, len(response_hooks))
185+
self.assertEqual(_error_response_hook, response_hooks[0])
171186

172187
def test_augment_error(self):
173188
self._run_test(

0 commit comments

Comments
 (0)