swagger-api / swagger-api/swagger-codegen
[python] ApiClient.prepare_post_parameters should allow for FileStorage objects in addition to file paths
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
The python/flask-generate server code uses a FileStorage object to represent uploaded files.
My endpoint is supposed to call a subsequent API on another server and forward the same uploaded file, and do do this is uses an api_client as generated by the python client templates. I would like to be able to pass the FileStorage object to the api_client directly, without having to save it out to a file and then load it back in. (For one thing, if the file is small enough, the data resides in memory, but more importantly, if the file is large, then saving it off and loading it back in would result in multiple copies of the uploaded file).
However, the prepare_post_parameters expects the files parameter to be a list of objects that can be opened via an open() call. A FileStorage object is not such an object, as it's already open and ready for reading.
A simple fix would be to add a check to the file so that if it's a FileStorage object, don't bother opening it and instead just use the information available. The added benefit is that we wouldn't need to guess at the mimetype, as it would be available as a property of the object.
Swagger-codegen version
2.3.0
Swagger declaration file content or url
Command line used for generation
Steps to reproduce
Related issues/PRs
Suggest a fix/enhancement
The following would be a workable change, I think.
def prepare_post_parameters(self, post_params=None, files=None):
"""Builds form parameters.
:param post_params: Normal form parameters.
:param files: File parameters.
:return: Form parameters with files.
"""
params = []
if post_params:
params = post_params
if files:
for k, v in six.iteritems(files):
if not v:
continue
file_names = v if type(v) is list else [v]
for n in file_names:
if (type(n) is FileStorage):
filename = n.filename
filedata = n.read()
mimetype = n.mimetype
params.append(
tuple([k, tuple([filename, filedata, mimetype])]))
else:
with open(n, 'rb') as f:
filename = os.path.basename(f.name)
filedata = f.read()
mimetype = (mimetypes.guess_type(filename)[0] or
'application/octet-stream')
params.append(
tuple([k, tuple([filename, filedata, mimetype])]))
return params
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Python client template's ApiClient.prepare_post_parameters entry point and review how its files parameter currently handles file paths. Done means FileStorage objects can be forwarded using their filename, data, and mimetype while existing file-path handling continues to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- flask, python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100