From ca6d9a7d998d480ecbc8e2168266400b507be7c5 Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Mon, 25 Oct 2021 20:37:15 +0200 Subject: [PATCH 01/11] Fix errors when uploading File and FileSet data --- neptune/internal/storage/datastream.py | 9 ++++---- .../backends/hosted_file_operations.py | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/neptune/internal/storage/datastream.py b/neptune/internal/storage/datastream.py index 45c430cf8..e3047a303 100644 --- a/neptune/internal/storage/datastream.py +++ b/neptune/internal/storage/datastream.py @@ -18,6 +18,7 @@ import os import stat import tarfile +from typing import AnyStr from future.builtins import object @@ -25,13 +26,13 @@ class FileChunk(object): - def __init__(self, data, start, end): + def __init__(self, data: AnyStr, start, end): self.data = data self.start = start self.end = end - def get_data(self): - return io.BytesIO(self.data) + def get_data(self) -> AnyStr: + return self.data def __eq__(self, other): return self.__dict__ == other.__dict__ @@ -84,7 +85,7 @@ def close(self): self.fobj.close() -def compress_to_tar_gz_in_memory(upload_entries): +def compress_to_tar_gz_in_memory(upload_entries) -> bytes: f = io.BytesIO(b'') with tarfile.TarFile.open(fileobj=f, mode='w|gz', dereference=True) as archive: diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index 33e0881c6..f5b782a88 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -17,7 +17,7 @@ import os import time from io import BytesIO -from typing import List, Optional, Dict, Iterable, Callable, Set, Union +from typing import List, Optional, Dict, Iterable, Callable, Set, Union, AnyStr from urllib.parse import urlencode from bravado.client import SwaggerClient @@ -57,7 +57,7 @@ def upload_file_attribute(swagger_client: SwaggerClient, response_handler=_attribute_upload_response_handler, http_client=swagger_client.swagger_spec.http_client, url=url, - query_params={ + query_params_gen=lambda _: { "experimentId": run_id, "attribute": attribute, "ext": ext @@ -91,7 +91,7 @@ def upload_file_set_attribute(swagger_client: SwaggerClient, ) result = upload_raw_data(http_client=swagger_client.swagger_spec.http_client, url=url, - data=BytesIO(data), + data=data, headers={"Content-Type": "application/octet-stream"}, query_params={ "experimentId": run_id, @@ -109,10 +109,10 @@ def upload_file_set_attribute(swagger_client: SwaggerClient, response_handler=_attribute_upload_response_handler, http_client=swagger_client.swagger_spec.http_client, url=url, - query_params={ + query_params_gen=lambda iteration: { "experimentId": str(run_id), "attribute": attribute, - "reset": str(reset), + "reset": str(iteration == 0 and reset), "path": file_chunk_stream.filename }) @@ -152,9 +152,14 @@ def _attribute_upload_response_handler(result: bytes) -> None: raise InternalClientError("Unexpected response from server: {}".format(result)) -def _upload_loop(file_chunk_stream: FileChunkStream, response_handler: Callable[[bytes], None], **kwargs): +def _upload_loop(file_chunk_stream: FileChunkStream, + response_handler: Callable[[bytes], None], + query_params_gen: Callable[[int], any], + **kwargs): + iteration = 0 for chunk in file_chunk_stream.generate(): - result = _upload_loop_chunk(chunk, file_chunk_stream, **kwargs) + result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params_gen(iteration), **kwargs) + iteration += 1 response_handler(result) file_chunk_stream.close() @@ -178,7 +183,7 @@ def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, **k @with_api_exceptions_handler def upload_raw_data(http_client: RequestsClient, url: str, - data, + data: AnyStr, path_params: Optional[Dict[str, str]] = None, query_params: Optional[Dict[str, str]] = None, headers: Optional[Dict[str, str]] = None): From e21cb077ad44ce6df840284d09040d60036d3903 Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Tue, 26 Oct 2021 08:22:22 +0200 Subject: [PATCH 02/11] fix --- .../backends/hosted_file_operations.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index f5b782a88..96422759c 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -105,16 +105,20 @@ def upload_file_set_attribute(swagger_client: SwaggerClient, swagger_client.api.uploadFileSetAttributeChunk.operation.path_name ) file_chunk_stream = FileChunkStream(package.items[0]) + + def query_params_gen(stream): + return lambda iteration: { + "experimentId": str(run_id), + "attribute": attribute, + "reset": str(reset), + "path": stream.filename + } + _upload_loop(file_chunk_stream=file_chunk_stream, response_handler=_attribute_upload_response_handler, http_client=swagger_client.swagger_spec.http_client, url=url, - query_params_gen=lambda iteration: { - "experimentId": str(run_id), - "attribute": attribute, - "reset": str(iteration == 0 and reset), - "path": file_chunk_stream.filename - }) + query_params_gen=query_params_gen(file_chunk_stream)) reset = False except MetadataInconsistency as e: @@ -188,6 +192,8 @@ def upload_raw_data(http_client: RequestsClient, query_params: Optional[Dict[str, str]] = None, headers: Optional[Dict[str, str]] = None): url = _generate_url(url=url, path_params=path_params, query_params=query_params) + print(url) + print(headers) session = http_client.session request = http_client.authenticator.apply(Request(method='POST', url=url, data=data, headers=headers)) From c54be70670fce8be417af3939f625409ff72714a Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Tue, 26 Oct 2021 08:33:15 +0200 Subject: [PATCH 03/11] fix --- .../backends/test_hosted_file_operations.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/tests/neptune/new/internal/backends/test_hosted_file_operations.py b/tests/neptune/new/internal/backends/test_hosted_file_operations.py index 90bb9e318..2b75e7813 100644 --- a/tests/neptune/new/internal/backends/test_hosted_file_operations.py +++ b/tests/neptune/new/internal/backends/test_hosted_file_operations.py @@ -53,11 +53,7 @@ def test_upload_file_attribute(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/attributes/upload", - query_params={ - "experimentId": str(exp_uuid), - "attribute": "target/path.txt", - "ext": "txt" - }) + query_params_gen=mock.ANY) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop') @@ -81,11 +77,7 @@ def test_upload_file_attribute_from_stream(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/attributes/upload", - query_params={ - "experimentId": str(exp_uuid), - "attribute": "target/path.txt", - "ext": "txt" - }) + query_params_gen=mock.ANY) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop') @@ -111,12 +103,7 @@ def test_upload_single_file_in_file_set_attribute(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/uploadFileSetChunk", - query_params={ - "experimentId": str(exp_uuid), - "attribute": "some/attribute", - "reset": "True", - "path": os.path.basename(temp_file.name) - }) + query_params=mock.ANY) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations.upload_raw_data') From 46cf15fb3ae560728fc90aea637e8447df09a72b Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Tue, 26 Oct 2021 08:45:50 +0200 Subject: [PATCH 04/11] fix --- .../new/internal/backends/test_hosted_file_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/neptune/new/internal/backends/test_hosted_file_operations.py b/tests/neptune/new/internal/backends/test_hosted_file_operations.py index 2b75e7813..715a8671e 100644 --- a/tests/neptune/new/internal/backends/test_hosted_file_operations.py +++ b/tests/neptune/new/internal/backends/test_hosted_file_operations.py @@ -103,7 +103,7 @@ def test_upload_single_file_in_file_set_attribute(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/uploadFileSetChunk", - query_params=mock.ANY) + query_params_gen=mock.ANY) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations.upload_raw_data') From e862622dd97306a6d67cbd462336c3dcc0447c08 Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Tue, 26 Oct 2021 13:35:23 +0200 Subject: [PATCH 05/11] Review changes --- CHANGELOG.md | 5 +++++ neptune/new/internal/backends/hosted_file_operations.py | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cd296e0d..d259ee83c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## neptune-client 0.13.1 [UNRELEASED] + +### Fixes +- Fix issue with file upload retry buffer causing 400 bad requests ([#743](https://github.com/neptune-ai/neptune-client/pull/743)) + ## neptune-client 0.13.0 ### Features diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index 96422759c..b75b0f41b 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -192,8 +192,6 @@ def upload_raw_data(http_client: RequestsClient, query_params: Optional[Dict[str, str]] = None, headers: Optional[Dict[str, str]] = None): url = _generate_url(url=url, path_params=path_params, query_params=query_params) - print(url) - print(headers) session = http_client.session request = http_client.authenticator.apply(Request(method='POST', url=url, data=data, headers=headers)) From 20af586351f555a23d952027512edd9f189a2bbb Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Wed, 27 Oct 2021 13:28:39 +0200 Subject: [PATCH 06/11] Review changes --- .../backends/hosted_file_operations.py | 26 +++++++++---------- .../backends/test_hosted_file_operations.py | 19 +++++++++++--- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index b75b0f41b..e9f6ef06e 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -57,7 +57,7 @@ def upload_file_attribute(swagger_client: SwaggerClient, response_handler=_attribute_upload_response_handler, http_client=swagger_client.swagger_spec.http_client, url=url, - query_params_gen=lambda _: { + query_params={ "experimentId": run_id, "attribute": attribute, "ext": ext @@ -105,20 +105,16 @@ def upload_file_set_attribute(swagger_client: SwaggerClient, swagger_client.api.uploadFileSetAttributeChunk.operation.path_name ) file_chunk_stream = FileChunkStream(package.items[0]) - - def query_params_gen(stream): - return lambda iteration: { - "experimentId": str(run_id), - "attribute": attribute, - "reset": str(reset), - "path": stream.filename - } - _upload_loop(file_chunk_stream=file_chunk_stream, response_handler=_attribute_upload_response_handler, http_client=swagger_client.swagger_spec.http_client, url=url, - query_params_gen=query_params_gen(file_chunk_stream)) + query_params={ + "experimentId": str(run_id), + "attribute": attribute, + "reset": str(reset), + "path": file_chunk_stream.filename + }) reset = False except MetadataInconsistency as e: @@ -158,18 +154,20 @@ def _attribute_upload_response_handler(result: bytes) -> None: def _upload_loop(file_chunk_stream: FileChunkStream, response_handler: Callable[[bytes], None], - query_params_gen: Callable[[int], any], + query_params: dict, **kwargs): iteration = 0 for chunk in file_chunk_stream.generate(): - result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params_gen(iteration), **kwargs) + if 'reset' in query_params and iteration != 0: + query_params['reset'] = str(False) + result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params, **kwargs) iteration += 1 response_handler(result) file_chunk_stream.close() -def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, **kwargs): +def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, query_params, **kwargs): if file_chunk_stream.length is not None: binary_range = "bytes=%d-%d/%d" % (chunk.start, chunk.end - 1, file_chunk_stream.length) else: diff --git a/tests/neptune/new/internal/backends/test_hosted_file_operations.py b/tests/neptune/new/internal/backends/test_hosted_file_operations.py index 715a8671e..90bb9e318 100644 --- a/tests/neptune/new/internal/backends/test_hosted_file_operations.py +++ b/tests/neptune/new/internal/backends/test_hosted_file_operations.py @@ -53,7 +53,11 @@ def test_upload_file_attribute(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/attributes/upload", - query_params_gen=mock.ANY) + query_params={ + "experimentId": str(exp_uuid), + "attribute": "target/path.txt", + "ext": "txt" + }) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop') @@ -77,7 +81,11 @@ def test_upload_file_attribute_from_stream(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/attributes/upload", - query_params_gen=mock.ANY) + query_params={ + "experimentId": str(exp_uuid), + "attribute": "target/path.txt", + "ext": "txt" + }) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop') @@ -103,7 +111,12 @@ def test_upload_single_file_in_file_set_attribute(self, upload_loop_mock): response_handler=_attribute_upload_response_handler, http_client=swagger_mock.swagger_spec.http_client, url="https://ui.neptune.ai/uploadFileSetChunk", - query_params_gen=mock.ANY) + query_params={ + "experimentId": str(exp_uuid), + "attribute": "some/attribute", + "reset": "True", + "path": os.path.basename(temp_file.name) + }) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations.upload_raw_data') From db33026768e446943a1492d4a5293e5ff377a505 Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Wed, 27 Oct 2021 13:43:16 +0200 Subject: [PATCH 07/11] fix --- neptune/new/internal/backends/hosted_file_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index e9f6ef06e..ea9945570 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -179,7 +179,7 @@ def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, que } if file_chunk_stream.permissions is not None: headers["X-File-Permissions"] = file_chunk_stream.permissions - return upload_raw_data(data=chunk.get_data(), headers=headers, **kwargs) + return upload_raw_data(data=chunk.get_data(), headers=headers, query_params=query_params, **kwargs) @with_api_exceptions_handler From 527acd7f820aabc5b8f07075dfa975ecfda13b2d Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Wed, 27 Oct 2021 14:01:42 +0200 Subject: [PATCH 08/11] review change --- neptune/new/internal/backends/hosted_file_operations.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index ea9945570..4d476fa33 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -156,8 +156,7 @@ def _upload_loop(file_chunk_stream: FileChunkStream, response_handler: Callable[[bytes], None], query_params: dict, **kwargs): - iteration = 0 - for chunk in file_chunk_stream.generate(): + for iteration, chunk in enumerate(file_chunk_stream.generate()): if 'reset' in query_params and iteration != 0: query_params['reset'] = str(False) result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params, **kwargs) From ca8e332683f86a0e37925198ff241a1ef68fe257 Mon Sep 17 00:00:00 2001 From: Hubert Jaworski Date: Wed, 27 Oct 2021 14:02:09 +0200 Subject: [PATCH 09/11] fix --- neptune/new/internal/backends/hosted_file_operations.py | 1 - 1 file changed, 1 deletion(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index 4d476fa33..309650e23 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -160,7 +160,6 @@ def _upload_loop(file_chunk_stream: FileChunkStream, if 'reset' in query_params and iteration != 0: query_params['reset'] = str(False) result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params, **kwargs) - iteration += 1 response_handler(result) file_chunk_stream.close() From f26207969abcf35eaafd59d44d6f4a90a83b82ce Mon Sep 17 00:00:00 2001 From: Rafal Jankowski Date: Wed, 27 Oct 2021 15:03:52 +0200 Subject: [PATCH 10/11] Tests added --- .../backends/hosted_file_operations.py | 2 +- .../backends/test_hosted_file_operations.py | 52 +++++++++++++------ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index 309650e23..7ef9398a2 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -159,7 +159,7 @@ def _upload_loop(file_chunk_stream: FileChunkStream, for iteration, chunk in enumerate(file_chunk_stream.generate()): if 'reset' in query_params and iteration != 0: query_params['reset'] = str(False) - result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params, **kwargs) + result = _upload_loop_chunk(chunk, file_chunk_stream, query_params=query_params.copy(), **kwargs) response_handler(result) file_chunk_stream.close() diff --git a/tests/neptune/new/internal/backends/test_hosted_file_operations.py b/tests/neptune/new/internal/backends/test_hosted_file_operations.py index 90bb9e318..5b3ff7927 100644 --- a/tests/neptune/new/internal/backends/test_hosted_file_operations.py +++ b/tests/neptune/new/internal/backends/test_hosted_file_operations.py @@ -19,7 +19,7 @@ from tempfile import NamedTemporaryFile, TemporaryDirectory import mock -from mock import MagicMock, patch +from mock import MagicMock, patch, call from neptune.new.internal.backends.hosted_file_operations import upload_file_attribute, upload_file_set_attribute, \ download_file_attribute, _get_content_disposition_filename, _attribute_upload_response_handler, \ @@ -88,35 +88,55 @@ def test_upload_file_attribute_from_stream(self, upload_loop_mock): }) @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") - @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop') + @patch('neptune.new.internal.backends.hosted_file_operations._upload_loop_chunk') @patch('neptune.new.internal.utils.glob', new=lambda path, recursive=False: [path.replace('*', 'file.txt')]) - def test_upload_single_file_in_file_set_attribute(self, upload_loop_mock): + def test_upload_single_file_in_file_set_attribute(self, upload_loop_chunk_mock): # given exp_uuid = uuid.uuid4() swagger_mock = self._get_swagger_mock() - upload_loop_mock.return_value = b'null' + upload_loop_chunk_mock.return_value = b'null' + chunk_size = 1024 * 1024 # when with NamedTemporaryFile("w") as temp_file: + with open(temp_file.name, 'wb') as handler: + handler.write(os.urandom(2 * chunk_size)) + upload_file_set_attribute( swagger_client=swagger_mock, - run_id=exp_uuid, + run_id=str(exp_uuid), attribute="some/attribute", file_globs=[temp_file.name], reset=True) # then - upload_loop_mock.assert_called_once_with( - file_chunk_stream=mock.ANY, - response_handler=_attribute_upload_response_handler, - http_client=swagger_mock.swagger_spec.http_client, - url="https://ui.neptune.ai/uploadFileSetChunk", - query_params={ - "experimentId": str(exp_uuid), - "attribute": "some/attribute", - "reset": "True", - "path": os.path.basename(temp_file.name) - }) + upload_loop_chunk_mock.assert_has_calls([ + call( + mock.ANY, + mock.ANY, + http_client=swagger_mock.swagger_spec.http_client, + query_params={ + "experimentId": str(exp_uuid), + "attribute": "some/attribute", + "reset": "True", + "path": os.path.basename(temp_file.name) + }, + url='https://ui.neptune.ai/uploadFileSetChunk' + ), + call( + mock.ANY, + mock.ANY, + http_client=swagger_mock.swagger_spec.http_client, + query_params={ + "experimentId": str(exp_uuid), + "attribute": "some/attribute", + "reset": "False", + "path": os.path.basename(temp_file.name) + }, + url='https://ui.neptune.ai/uploadFileSetChunk' + ) + ]) + @unittest.skipIf(IS_WINDOWS, "Windows behaves strangely") @patch('neptune.new.internal.backends.hosted_file_operations.upload_raw_data') From 7b86a5a9ea409a66d2e2fc595c0ce82055f877ac Mon Sep 17 00:00:00 2001 From: Rafal Jankowski Date: Wed, 27 Oct 2021 15:18:54 +0200 Subject: [PATCH 11/11] typing --- neptune/new/internal/backends/hosted_file_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neptune/new/internal/backends/hosted_file_operations.py b/neptune/new/internal/backends/hosted_file_operations.py index 7ef9398a2..c8e4341bf 100644 --- a/neptune/new/internal/backends/hosted_file_operations.py +++ b/neptune/new/internal/backends/hosted_file_operations.py @@ -165,7 +165,7 @@ def _upload_loop(file_chunk_stream: FileChunkStream, file_chunk_stream.close() -def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, query_params, **kwargs): +def _upload_loop_chunk(chunk: FileChunk, file_chunk_stream: FileChunkStream, query_params: dict, **kwargs): if file_chunk_stream.length is not None: binary_range = "bytes=%d-%d/%d" % (chunk.start, chunk.end - 1, file_chunk_stream.length) else: