Forum Discussion

delimitize's avatar
delimitize
Occasional Visitor
3 years ago

Python Swagger-Codegen Client File Upload Impossible?

Following the ApiClient object's call_api usage from the specification/implementation specific (swagger 2.0 spec), the file argument input set via kwarg 'files' or maybe even kwarg 'post_params' seems entirely inaccessible to the implementation of the specific API being called. 

 

In this example case, "upload_files" and by extension "upload_files_with_http_info".  The kwargs can't make it all the way to the API call and it fails at the kwarg check.  The call path is highlighed below...

 

So what is the de facto way to attach a file to a request if the keyword arguments do not pass all the way through a call chain from the user level back to the API call?? Is this a bug; a problem in a spec? PEBKAC also a possibility but struggling to see the expected path for attaching the file. Thanks in advance! 🙂

 

 

Take call_api, a method of the ApiClient objects (api_client.py) used as a base class by the consuming specific implementations':

 

# Take call_api, a method of the ApiClient objects (api_client.py) used as a base class by the consuming specific implementations':

    def call_api(self, resource_path, method,
        path_params=None, query_params=None, header_params=None,
        body=None, post_params=None, files=None,
        response_type=None, auth_settings=None, async_req=None,
        _return_http_data_only=None, collection_formats=None,
        _preload_content=True, _request_timeout=None):
        """Makes the HTTP request (synchronous) and returns deserialized data.
            :param files dict: key -> filename, value -> filepath, for `multipart/form-data`.
        ...
        ...
        """
        # ...
        return ... 

 


Now take the generated 'implementation' (./api/upload_file_api.py). The kwargs are passed directly to this and then down to the appropriate related function depending on '_return_http_data_only' flag...

 

 

def upload_file(self, file_name, some_param, **kwargs):  # noqa: E501
    """New - Create a new blob with attached file
    ...
    """
    kwargs['_return_http_data_only'] = True
    if kwargs.get('async_req'):
        return self.upload_file_with_http_info(file_name, some_param, **kwargs)  # noqa: E501
    else:
        (data) = self.upload_file_with_http_info(file_name, some_param, **kwargs)  # noqa: E501
        return data

 

 

# And then, in the async function called above - again, passed in - but if I were to have specified the 'files' or 'post_params' passed in pursuant to transmitting the file,  then the check on those args below that is generated prohibits this. 

 

 

def upload_file_with_http_info(self, file_name, some_param, **kwargs):
    """ upload the file """
    
    # ...

    all_params = ['file_name', 'some_param']  # noqa: E501
        all_params.append('async_req')
        all_params.append('_return_http_data_only')
        all_params.append('_preload_content')
        all_params.append('_request_timeout')

        params = locals()
        for key, val in six.iteritems(params['kwargs']):
            if key not in all_params:
                raise TypeError(
                    "Got an unexpected keyword argument '%s'"
                    " to method blobs_v1_upload_blob_async" % key
                )
            params[key] = val

 

 

For completeness, after the check there, the return is the original call to call_api:

 

    return self.api_client.call_api(
        '/blobs/uploadblob', 'POST',
        path_params,
        query_params,
        header_params,
        body=body_params,
        post_params=form_params,
        files=local_var_files,
        response_type='EntityV1Model',  # noqa: E501
        auth_settings=auth_settings,
        async_req=params.get('async_req'),
        _return_http_data_only=params.get('_return_http_data_only'),
        _preload_content=params.get('_preload_content', True),
        _request_timeout=params.get('_request_timeout'),
        collection_formats=collection_formats)

 

 

I have read access to the 2.0 openapi spec for this service but I cannot modify it. If I can get the API call to have the post_params or form_params or files, I can probably get by, but they look entirely inaccessible to me and I'm trying to figure out where I'm missing something. 

 

Any guidance or help is appreciated.

 

Thanks!

Mario

No RepliesBe the first to reply