Skip to content

Commit ab463a4

Browse files
committed
<fix>[testlib]: fix multiple bugs in Python SDK template
1. Rewrite async poll URL to use client-configured hostname 2. Fix _error() using err.desc instead of err.description 3. Fix mutable default arg headers={} in _json_http 4. Fix re.findall regex missing escape for path param validation 5. Fix min_length validation using > instead of < 6. Fix path param check 'if u in params' should be 'if u not in params' 7. Fix bare except to except Exception 8. Remove duplicate import time 9. Decode rsp.data bytes to str for Python 3 readable error messages Resolves: ZSTAC-83925 Change-Id: I7a7062676b676a6f67646c7862706365666a6b6e
1 parent 3bcfed2 commit ab463a4

1 file changed

Lines changed: 31 additions & 9 deletions

File tree

testlib/src/main/resources/zssdk.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import hmac
1919
from hashlib import sha1
2020
import datetime
21-
import time
2221

2322
try:
2423
int_types = (int, long)
@@ -58,7 +57,7 @@ def _exception_safe(func):
5857
def wrap(*args, **kwargs):
5958
try:
6059
func(*args, **kwargs)
61-
except:
60+
except Exception:
6261
print(traceback.format_exc())
6362

6463
return wrap
@@ -80,7 +79,7 @@ def _http_error(status, body=None):
8079
def _error(code, desc, details):
8180
err = ErrorCode()
8281
err.code = code
83-
err.desc = desc
82+
err.description = desc
8483
err.details = details
8584
return {'error': err}
8685

@@ -181,7 +180,7 @@ def _check_params(self):
181180
if value is not None and isinstance(value, str) and annotation.max_length and len(value) > annotation.max_length:
182181
raise SdkError('invalid length[%s] of the parameter[%s], the max allowed length is %s' % (len(value), param_name, annotation.max_length))
183182

184-
if value is not None and isinstance(value, str) and annotation.min_length and len(value) > annotation.min_length:
183+
if value is not None and isinstance(value, str) and annotation.min_length and len(value) < annotation.min_length:
185184
raise SdkError('invalid length[%s] of the parameter[%s], the minimal allowed length is %s' % (len(value), param_name, annotation.min_length))
186185

187186
if value is not None and isinstance(value, list) and annotation.non_empty is True and len(value) == 0:
@@ -235,11 +234,11 @@ def _url(self):
235234
elements.append('/v1')
236235

237236
path = self.PATH.replace('{', '${')
238-
unresolved = re.findall('${(.+?)}', path)
237+
unresolved = re.findall(r'\$\{(.+?)\}', path)
239238
params = self._params()
240239
if unresolved:
241240
for u in unresolved:
242-
if u in params:
241+
if u not in params:
243242
raise SdkError('missing a mandatory parameter[%s]' % u)
244243

245244
path = string.Template(path).substitute(params)
@@ -364,6 +363,18 @@ def _poll_result(self, rsp, cb):
364363
if not location:
365364
raise SdkError("Internal Error] the api[%s] is an async API but the server doesn't return the polling location url")
366365

366+
# Rewrite poll URL to use client-configured hostname:port,
367+
# in case server returns an internal IP unreachable from client
368+
try:
369+
from urllib.parse import urlparse, urlunparse
370+
except ImportError:
371+
from urlparse import urlparse, urlunparse
372+
parsed = urlparse(location)
373+
configured_host = __config__[CONFIG_HOSTNAME]
374+
configured_port = str(__config__[CONFIG_PORT])
375+
location = urlunparse(parsed._replace(
376+
netloc='%s:%s' % (configured_host, configured_port)))
377+
367378
if cb:
368379
# async polling
369380
self._async_poll(location, cb)
@@ -480,11 +491,13 @@ def _uuid():
480491
def _json_http(
481492
uri,
482493
body=None,
483-
headers={},
494+
headers=None,
484495
method='POST',
485496
timeout=120.0
486497
):
487498
pool = urllib3.PoolManager(timeout=timeout, retries=urllib3.util.retry.Retry(15))
499+
if headers is None:
500+
headers = {}
488501
headers.update({'Content-Type': 'application/json', 'Connection': 'close'})
489502

490503
if body is not None and not isinstance(body, str):
@@ -497,6 +510,15 @@ def _json_http(
497510
else:
498511
rsp = pool.request(method, uri, headers=headers)
499512

500-
print('[Response to %s %s]: status: %s, body: %s' % (method, uri, rsp.status, rsp.data))
501-
return rsp
513+
data = rsp.data
514+
if isinstance(data, bytes):
515+
data = data.decode('utf-8')
516+
print('[Response to %s %s]: status: %s, body: %s' % (method, uri, rsp.status, data))
517+
518+
class _Rsp(object):
519+
pass
520+
r = _Rsp()
521+
r.status = rsp.status
522+
r.data = data
523+
return r
502524

0 commit comments

Comments
 (0)