Skip to content

Commit 94b1440

Browse files
authored
[Python] Add Support for Content-Disposition Header without filename (#11055)
* [Python] Add Support for CD header w/o filename * updated documentation per PR instructions * fixed formatting and updated samples and docs * revert docs changes * regenerate python samples * updated sample python test
1 parent b1c6513 commit 94b1440

7 files changed

Lines changed: 83 additions & 37 deletions

File tree

modules/openapi-generator/src/main/resources/python/model_utils.mustache

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import os
88
import pprint
99
import re
1010
import tempfile
11+
import uuid
1112

1213
from dateutil.parser import parse
1314

@@ -1082,7 +1083,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
10821083

10831084
if content_disposition:
10841085
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1085-
content_disposition).group(1)
1086+
content_disposition,
1087+
flags=re.I)
1088+
if filename is not None:
1089+
filename = filename.group(1)
1090+
else:
1091+
filename = "default_" + str(uuid.uuid4())
1092+
10861093
path = os.path.join(os.path.dirname(path), filename)
10871094

10881095
with open(path, "wb") as f:

samples/client/petstore/python/petstore_api/model_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pprint
1717
import re
1818
import tempfile
19+
import uuid
1920

2021
from dateutil.parser import parse
2122

@@ -1399,7 +1400,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
13991400

14001401
if content_disposition:
14011402
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1402-
content_disposition).group(1)
1403+
content_disposition,
1404+
flags=re.I)
1405+
if filename is not None:
1406+
filename = filename.group(1)
1407+
else:
1408+
filename = "default_" + str(uuid.uuid4())
1409+
14031410
path = os.path.join(os.path.dirname(path), filename)
14041411

14051412
with open(path, "wb") as f:

samples/client/petstore/python_disallowAdditionalPropertiesIfNotPresent/petstore_api/model_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pprint
1717
import re
1818
import tempfile
19+
import uuid
1920

2021
from dateutil.parser import parse
2122

@@ -1399,7 +1400,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
13991400

14001401
if content_disposition:
14011402
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1402-
content_disposition).group(1)
1403+
content_disposition,
1404+
flags=re.I)
1405+
if filename is not None:
1406+
filename = filename.group(1)
1407+
else:
1408+
filename = "default_" + str(uuid.uuid4())
1409+
14031410
path = os.path.join(os.path.dirname(path), filename)
14041411

14051412
with open(path, "wb") as f:

samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pprint
1717
import re
1818
import tempfile
19+
import uuid
1920

2021
from dateutil.parser import parse
2122

@@ -1399,7 +1400,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
13991400

14001401
if content_disposition:
14011402
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1402-
content_disposition).group(1)
1403+
content_disposition,
1404+
flags=re.I)
1405+
if filename is not None:
1406+
filename = filename.group(1)
1407+
else:
1408+
filename = "default_" + str(uuid.uuid4())
1409+
14031410
path = os.path.join(os.path.dirname(path), filename)
14041411

14051412
with open(path, "wb") as f:

samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pprint
1717
import re
1818
import tempfile
19+
import uuid
1920

2021
from dateutil.parser import parse
2122

@@ -1399,7 +1400,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
13991400

14001401
if content_disposition:
14011402
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1402-
content_disposition).group(1)
1403+
content_disposition,
1404+
flags=re.I)
1405+
if filename is not None:
1406+
filename = filename.group(1)
1407+
else:
1408+
filename = "default_" + str(uuid.uuid4())
1409+
14031410
path = os.path.join(os.path.dirname(path), filename)
14041411

14051412
with open(path, "wb") as f:

samples/openapi3/client/petstore/python/petstore_api/model_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pprint
1717
import re
1818
import tempfile
19+
import uuid
1920

2021
from dateutil.parser import parse
2122

@@ -1399,7 +1400,13 @@ def deserialize_file(response_data, configuration, content_disposition=None):
13991400

14001401
if content_disposition:
14011402
filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
1402-
content_disposition).group(1)
1403+
content_disposition,
1404+
flags=re.I)
1405+
if filename is not None:
1406+
filename = filename.group(1)
1407+
else:
1408+
filename = "default_" + str(uuid.uuid4())
1409+
14031410
path = os.path.join(os.path.dirname(path), filename)
14041411

14051412
with open(path, "wb") as f:

samples/openapi3/client/petstore/python/tests_manual/test_fake_api.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -495,42 +495,46 @@ def test_download_attachment(self):
495495

496496
# sample from http://www.jtricks.com/download-text
497497
file_name = 'content.txt'
498-
headers = {'Content-Disposition': 'attachment; filename={}'.format(file_name), 'Content-Type': 'text/plain'}
499-
def get_headers():
500-
return headers
501-
def get_header(name, default=None):
502-
return headers.get(name, default)
498+
headers_dict = {
499+
'with_filename': {'Content-Disposition': 'attachment; filename={}'.format(file_name), 'Content-Type': 'text/plain'},
500+
'no_filename': {'Content-Disposition': 'attachment;', 'Content-Type': 'text/plain'}
501+
}
502+
def get_headers(*args):
503+
return args
503504
file_data = (
504505
"You are reading text file that was supposed to be downloaded\r\n"
505506
"to your hard disk. If your browser offered to save you the file,"
506507
"\r\nthen it handled the Content-Disposition header correctly."
507508
)
508-
http_response = HTTPResponse(
509-
status=200,
510-
reason='OK',
511-
data=file_data,
512-
getheaders=get_headers,
513-
getheader=get_header
514-
)
515-
# deserialize response to a file
516-
mock_response = RESTResponse(http_response)
517-
with patch.object(RESTClientObject, 'request') as mock_method:
518-
mock_method.return_value = mock_response
519-
try:
520-
file_object = self.api.download_attachment(file_name='download-text')
521-
self.assert_request_called_with(
522-
mock_method,
523-
'http://www.jtricks.com/download-text',
524-
http_method='GET',
525-
accept='text/plain',
526-
content_type=None,
527-
)
528-
self.assertTrue(isinstance(file_object, file_type))
529-
self.assertFalse(file_object.closed)
530-
self.assertEqual(file_object.read(), file_data.encode('utf-8'))
531-
finally:
532-
file_object.close()
533-
os.unlink(file_object.name)
509+
for key, headers in headers_dict.items():
510+
def get_header(name, default=None):
511+
return headers_dict[key].get(name, default)
512+
http_response = HTTPResponse(
513+
status=200,
514+
reason='OK',
515+
data=file_data,
516+
getheaders=get_headers(headers),
517+
getheader=get_header
518+
)
519+
# deserialize response to a file
520+
mock_response = RESTResponse(http_response)
521+
with patch.object(RESTClientObject, 'request') as mock_method:
522+
mock_method.return_value = mock_response
523+
try:
524+
file_object = self.api.download_attachment(file_name='download-text')
525+
self.assert_request_called_with(
526+
mock_method,
527+
'http://www.jtricks.com/download-text',
528+
http_method='GET',
529+
accept='text/plain',
530+
content_type=None,
531+
)
532+
self.assertTrue(isinstance(file_object, file_type))
533+
self.assertFalse(file_object.closed)
534+
self.assertEqual(file_object.read(), file_data.encode('utf-8'))
535+
finally:
536+
file_object.close()
537+
os.unlink(file_object.name)
534538

535539
def test_upload_download_file(self):
536540
test_file_dir = os.path.realpath(

0 commit comments

Comments
 (0)