Skip to content

Commit 70cf579

Browse files
committed
fix: support duplicate part names in 'files' parameter of prepare_request
1 parent 4fcaa66 commit 70cf579

File tree

2 files changed

+70
-19
lines changed

2 files changed

+70
-19
lines changed

ibm_cloud_sdk_core/base_service.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,26 @@ def prepare_request(self, method, url, headers=None,
197197
if self.authenticator:
198198
self.authenticator.authenticate(request)
199199

200-
files = remove_null_values(files)
200+
# Next, we need to process the 'files' argument to try to fill in
201+
# any missing filenames where possible.
202+
# 'files' can be a dictionary (i.e { '<part-name>': (<tuple>)} )
203+
# or a list of tuples [ (<part-name>, (<tuple>))... ]
204+
# If 'files' is a dictionary we'll convert it to a list of tuples.
205+
new_files = []
201206
if files is not None:
202-
for k, file_tuple in files.items():
203-
if file_tuple and len(
204-
file_tuple) == 3 and file_tuple[0] is None:
205-
file = file_tuple[1]
207+
# If 'files' is a dictionary, transform it into a list of tuples.
208+
if isinstance(files, dict):
209+
files = remove_null_values(files)
210+
files = files.items()
211+
# Next, fill in any missing filenames from file tuples.
212+
for part_name, tuple in files:
213+
if tuple and len(tuple) == 3 and tuple[0] is None:
214+
file = tuple[1]
206215
if file and hasattr(file, 'name'):
207216
filename = basename(file.name)
208-
files[k] = (filename, file_tuple[1], file_tuple[2])
209-
request['files'] = files
217+
tuple = (filename, tuple[1], tuple[2])
218+
new_files.append((part_name, tuple))
219+
request['files'] = new_files
210220
return request
211221

212222

test/test_base_service.py

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -391,26 +391,67 @@ def test_user_agent_header():
391391
assert response.get_result().request.headers.__getitem__(
392392
'user-agent') == user_agent_header['User-Agent']
393393

394-
@responses.activate
395-
def test_files():
394+
def test_files_dict():
396395
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
397396

398-
responses.add(
399-
responses.GET,
400-
'https://gateway.watsonplatform.net/test/api',
401-
status=200,
402-
body=json.dumps({
403-
'foo': 'bar'
404-
}),
405-
content_type='application/json')
406397
form_data = {}
407398
file = open(
408399
os.path.join(
409400
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r')
410401
form_data['file1'] = (None, file, 'application/octet-stream')
411-
form_data['string1'] = (None, 'hello', 'text.plain')
412-
service.prepare_request('GET', url='', headers={'X-opt-out': True}, files=form_data)
402+
form_data['string1'] = (None, 'hello', 'text/plain')
403+
request = service.prepare_request('GET', url='', headers={'X-opt-out': True}, files=form_data)
404+
files = request['files']
405+
assert isinstance(files, list)
406+
assert len(files) == 2
407+
filesDict = dict(files)
408+
file1 = filesDict['file1']
409+
assert file1[0] == 'ibm-credentials-iam.env'
410+
string1 = filesDict['string1']
411+
assert string1[0] is None
412+
413+
def test_files_list():
414+
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
415+
416+
form_data = []
417+
file = open(
418+
os.path.join(
419+
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r')
420+
form_data.append(('file1', (None, file, 'application/octet-stream')))
421+
form_data.append(('string1', (None, 'hello', 'text/plain')))
422+
request = service.prepare_request('GET', url='', headers={'X-opt-out': True}, files=form_data)
423+
files = request['files']
424+
assert isinstance(files, list)
425+
assert len(files) == 2
426+
filesDict = dict(files)
427+
file1 = filesDict['file1']
428+
assert file1[0] == 'ibm-credentials-iam.env'
429+
string1 = filesDict['string1']
430+
assert string1[0] is None
431+
432+
def test_files_duplicate_parts():
433+
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
413434

435+
form_data = []
436+
file = open(
437+
os.path.join(
438+
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r')
439+
form_data.append(('creds_file', (None, file, 'application/octet-stream')))
440+
file = open(
441+
os.path.join(
442+
os.path.dirname(__file__), '../resources/ibm-credentials-basic.env'), 'r')
443+
form_data.append(('creds_file', (None, file, 'application/octet-stream')))
444+
file = open(
445+
os.path.join(
446+
os.path.dirname(__file__), '../resources/ibm-credentials-bearer.env'), 'r')
447+
form_data.append(('creds_file', (None, file, 'application/octet-stream')))
448+
request = service.prepare_request('GET', url='', headers={'X-opt-out': True}, files=form_data)
449+
files = request['files']
450+
assert isinstance(files, list)
451+
assert len(files) == 3
452+
for part_name, tuple in files:
453+
assert part_name == 'creds_file'
454+
assert tuple[0] is not None
414455

415456
def test_json():
416457
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())

0 commit comments

Comments
 (0)