Skip to content

Commit fb1bcfd

Browse files
committed
Gate async TUS upload on successful create
1 parent 37e4cc5 commit fb1bcfd

2 files changed

Lines changed: 90 additions & 6 deletions

File tree

tests/test_async_client.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,84 @@ def uploader(self, **kwargs):
668668
sleep_mock.assert_not_awaited()
669669
self.assertEqual(calls, [])
670670

671+
async def test_async_assembly_resumable_error_response_skips_tus_upload(self):
672+
calls = []
673+
674+
class _TusClient:
675+
def __init__(self, tus_url):
676+
calls.append(("client", tus_url))
677+
678+
def uploader(self, **kwargs):
679+
raise AssertionError("TUS upload should not start for error responses")
680+
681+
async with AsyncTransloadit("key", "secret", service=self.server.base_url) as client:
682+
assembly = client.new_assembly()
683+
assembly.add_file(io.BytesIO(b"payload"))
684+
685+
error_response = Response(
686+
data={
687+
"error": "ASSEMBLY_NOT_AUTHORIZED",
688+
},
689+
status_code=401,
690+
headers={},
691+
)
692+
693+
with mock.patch.object(client.request, "post", new=mock.AsyncMock(return_value=error_response)) as post_mock:
694+
with mock.patch("transloadit.async_assembly.tus.TusClient", new=_TusClient):
695+
response = await assembly.create(resumable=True)
696+
697+
self.assertIs(response, error_response)
698+
post_mock.assert_awaited_once()
699+
self.assertEqual(calls, [])
700+
701+
async def test_async_assembly_resumable_response_without_upload_urls_skips_tus_upload(self):
702+
calls = []
703+
704+
class _TusClient:
705+
def __init__(self, tus_url):
706+
calls.append(("client", tus_url))
707+
708+
def uploader(self, **kwargs):
709+
raise AssertionError("TUS upload should not start when upload URLs are missing")
710+
711+
async with AsyncTransloadit("key", "secret", service=self.server.base_url) as client:
712+
assembly = client.new_assembly()
713+
assembly.add_file(io.BytesIO(b"payload"))
714+
715+
incomplete_response = Response(
716+
data={"ok": "ASSEMBLY_PROCESSING"},
717+
status_code=200,
718+
headers={},
719+
)
720+
721+
with mock.patch.object(client.request, "post", new=mock.AsyncMock(return_value=incomplete_response)) as post_mock:
722+
with mock.patch("transloadit.async_assembly.tus.TusClient", new=_TusClient):
723+
response = await assembly.create(resumable=True)
724+
725+
self.assertIs(response, incomplete_response)
726+
post_mock.assert_awaited_once()
727+
self.assertEqual(calls, [])
728+
729+
async def test_async_assembly_wait_returns_response_without_assembly_url(self):
730+
incomplete_response = Response(
731+
data={"ok": "ASSEMBLY_PROCESSING"},
732+
status_code=200,
733+
headers={},
734+
)
735+
736+
async with AsyncTransloadit("key", "secret", service=self.server.base_url) as client:
737+
assembly = client.new_assembly()
738+
739+
with mock.patch.object(client.request, "post", new=mock.AsyncMock(return_value=incomplete_response)) as post_mock:
740+
with mock.patch.object(client, "get_assembly", new=mock.AsyncMock()) as get_mock:
741+
with mock.patch("asyncio.sleep", new_callable=mock.AsyncMock) as sleep_mock:
742+
response = await assembly.create(wait=True, resumable=False)
743+
744+
self.assertIs(response, incomplete_response)
745+
post_mock.assert_awaited_once()
746+
get_mock.assert_not_awaited()
747+
sleep_mock.assert_not_awaited()
748+
671749
async def test_async_resumable_upload_posts_extra_data_and_uses_tus_metadata(self):
672750
calls = []
673751

transloadit/async_assembly.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,21 @@ async def create(self, wait=False, resumable=True, retries=3):
106106
return await self.create(wait, resumable, retries - 1)
107107
return response
108108

109+
error = response_data.get("error")
110+
assembly_url = response_data.get("assembly_ssl_url")
111+
tus_url = response_data.get("tus_url")
112+
113+
if error is not None:
114+
return response
115+
109116
if resumable:
110-
await self._do_tus_upload_async(
111-
response_data.get("assembly_ssl_url"),
112-
response_data.get("tus_url"),
113-
retries,
114-
)
117+
if not assembly_url or not tus_url:
118+
return response
119+
await self._do_tus_upload_async(assembly_url, tus_url, retries)
115120

116121
if wait:
117-
assembly_url = response_data.get("assembly_ssl_url")
122+
if not assembly_url:
123+
return response
118124
while not self._assembly_finished(response_data):
119125
sleep_time = response_data.get("info", {}).get("retryIn", 1)
120126
await asyncio.sleep(sleep_time)

0 commit comments

Comments
 (0)