StubResponseError on add_client_error with Stubber
Describe the bug Using the stubber, addind a client error it generate a "StubResponseError".
Versions:
- boto3: 1.19.3
- botocore: 1.22.3
Steps to reproduce With this code you can reproduce:
import boto3
from botocore.exceptions import ClientError
from botocore.stub import Stubber`
client = boto3.client('s3')
stubber = Stubber(client)
stubber.add_client_error('download_file')
with stubber:
try:
r = client.download_file('xxx', 'xxx', 'xxx')
except ClientError as c:
print(c)
Expected behavior I expect that the code go into the exception handle
Debug logs Full stack trace:
Traceback (most recent call last):
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/src/boto_error.py", line 11, in <module>
r = client.download_file('xxx', 'xxx', 'xxx')
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/boto3/s3/inject.py", line 171, in download_file
return transfer.download_file(
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/boto3/s3/transfer.py", line 307, in download_file
future.result()
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/s3transfer/futures.py", line 106, in result
return self._coordinator.result()
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/s3transfer/futures.py", line 265, in result
raise self._exception
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/s3transfer/tasks.py", line 255, in _main
self._submit(transfer_future=transfer_future, **kwargs)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/s3transfer/download.py", line 340, in _submit
response = client.head_object(
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/client.py", line 388, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/client.py", line 680, in _make_api_call
request_dict = self._convert_to_request_dict(
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/client.py", line 726, in _convert_to_request_dict
api_params = self._emit_api_params(
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/client.py", line 755, in _emit_api_params
self.meta.events.emit(
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/hooks.py", line 357, in emit
return self._emitter.emit(aliased_event_name, **kwargs)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/hooks.py", line 228, in emit
return self._emit(event_name, kwargs)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/hooks.py", line 211, in _emit
response = handler(**kwargs)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/stub.py", line 350, in _assert_expected_params
self._assert_expected_call_order(model, params)
File "/media/mint/Barracuda/Digitiamo/aiknowyou-ai-clusterizer/venv/lib/python3.8/site-packages/botocore/stub.py", line 338, in _assert_expected_call_order
raise StubResponseError(
botocore.exceptions.StubResponseError: Error getting response stub for operation HeadObject: Operation mismatch: found response for None.
Process finished with exit code 1
Hi @nicolalandro,
Sorry to hear you're having issues. Because download_file is not a native s3 operation (it's part of s3Transfer), I'm not sure if there's any way around the operation mismatch because it uses several native S3 operations to calculate the object size, download the file, etc. I'll check with the team to see if there's a way to accomplish this.
Thank you, I will wait the fix, for now I fix with manual mock that raise exception, to have official version will simplify the code and make it more real.
# download do not return error
s3mock_cli.download_file = lambda x, y, z: True
error = mock.Mock()
error.get = lambda x, y: 200 if x == 'Code' else 'text'
response = mock.Mock()
response.get = lambda x, y: error
response.__contains__ = lambda x, y: False
# upload return error
s3mock_cli.upload_file = lambda x, y, z: (_ for _ in ()).throw(ClientError(response, 'name'))
I'm waiting news.
Hi @nicolalandro,
I was able to review this with the team earlier today and it's currently not possible to work around this using the botocore stubber due to the reasons I mentioned before— We will have to write a customization for the S3Transfer methods (upload_file, download_file, etc.), as they are customizations over s3 APIs themselves. This could be documented better as well. Thanks for pointing this out!