@@ -628,7 +628,7 @@ def __init__(self, tus_url):
628628 calls .append (("client" , tus_url ))
629629
630630 def uploader (self , ** kwargs ):
631- calls .append (("uploader" , kwargs ["metadata" ]))
631+ calls .append (("uploader" , kwargs ["metadata" ], kwargs [ "retries" ] ))
632632
633633 class _Uploader :
634634 def upload (self_inner ):
@@ -673,7 +673,7 @@ def upload(self_inner):
673673 self .assertEqual (post_mock .await_count , 2 )
674674 self .assertEqual (to_thread_mock .await_count , 1 )
675675 self .assertEqual (calls [0 ], ("client" , f"{ self .server .base_url } /uploads" ))
676- self .assertEqual (calls [1 ][ 0 ], "uploader" )
676+ self .assertEqual (calls [1 ], ( "uploader" , { "assembly_url" : f" { self . server . base_url } /assemblies/assembly-123" , "fieldname" : "file" , "filename" : "payload.bin" }, 2 ) )
677677
678678 async def test_async_assembly_resumable_rate_limit_skips_rewind_before_retrying (self ):
679679 calls = []
@@ -868,7 +868,7 @@ def uploader(self, **kwargs):
868868 async with AsyncTransloadit ("key" , "secret" , service = self .server .base_url ) as client :
869869 assembly = client .new_assembly ()
870870 upload = io .BytesIO (b"payload" )
871- upload .name = None
871+ upload .name = 123
872872 assembly .add_file (upload , "explicit_field" )
873873
874874 with mock .patch (
@@ -953,6 +953,46 @@ async def test_async_assembly_wait_retries_after_polling_rate_limit(self):
953953 )
954954 self .assertEqual (sleep_mock .await_args_list , [mock .call (0 ), mock .call (0 )])
955955
956+ async def test_async_assembly_wait_returns_last_poll_response_when_budget_exhausted (self ):
957+ async with AsyncTransloadit ("key" , "secret" , service = self .server .base_url ) as client :
958+ assembly = client .new_assembly ()
959+
960+ initial = Response (
961+ data = {
962+ "ok" : "ASSEMBLY_PROCESSING" ,
963+ "info" : {"retryIn" : 0 },
964+ "assembly_ssl_url" : f"{ self .server .base_url } /assemblies/assembly-123" ,
965+ },
966+ status_code = 200 ,
967+ headers = {"X-Async-Route" : "initial" },
968+ )
969+ rate_limited = Response (
970+ data = {
971+ "ok" : "ASSEMBLY_PROCESSING" ,
972+ "error" : "RATE_LIMIT_REACHED" ,
973+ "info" : {"retryIn" : 0 },
974+ "assembly_ssl_url" : f"{ self .server .base_url } /assemblies/assembly-123" ,
975+ },
976+ status_code = 200 ,
977+ headers = {"X-Async-Route" : "rate_limited" },
978+ )
979+
980+ with mock .patch .object (client .request , "post" , new = mock .AsyncMock (return_value = initial )) as post_mock :
981+ with mock .patch .object (
982+ client ,
983+ "get_assembly" ,
984+ new = mock .AsyncMock (return_value = rate_limited ),
985+ ) as get_mock :
986+ with mock .patch ("asyncio.sleep" , new_callable = mock .AsyncMock ) as sleep_mock :
987+ response = await assembly .create (wait = True , resumable = False , retries = 1 )
988+
989+ self .assertEqual (response .data ["error" ], "RATE_LIMIT_REACHED" )
990+ post_mock .assert_awaited_once ()
991+ get_mock .assert_awaited_once_with (
992+ assembly_url = f"{ self .server .base_url } /assemblies/assembly-123"
993+ )
994+ self .assertEqual (sleep_mock .await_args_list , [mock .call (0 )])
995+
956996 async def test_async_assembly_non_resumable_rate_limit_rewinds_files_for_retry (self ):
957997 reads = []
958998
@@ -1015,7 +1055,7 @@ async def test_async_request_uses_connect_and_read_timeouts_for_uploads(self):
10151055 session = _RecordingSession ({"ok" : "ASSEMBLY_COMPLETED" })
10161056 client = AsyncTransloadit ("key" , "secret" , service = self .server .base_url , session = session )
10171057 upload = io .BytesIO (b"payload" )
1018- upload .name = None
1058+ upload .name = "clip.jpg"
10191059
10201060 response = await client .request .post ("/assemblies" , data = {"foo" : "bar" }, files = {"file" : upload })
10211061
@@ -1024,6 +1064,18 @@ async def test_async_request_uses_connect_and_read_timeouts_for_uploads(self):
10241064 self .assertIsNone (timeout .total )
10251065 self .assertEqual (timeout .sock_connect , 60 )
10261066 self .assertIsNone (timeout .sock_read )
1067+ self .assertEqual (session .calls [0 ][1 ]["data" ]._fields [2 ][1 ]["Content-Type" ], "image/jpeg" )
1068+
1069+ async def test_async_request_uses_filename_fallback_for_trailing_slash_stream_name (self ):
1070+ session = _RecordingSession ({"ok" : "ASSEMBLY_COMPLETED" })
1071+ client = AsyncTransloadit ("key" , "secret" , service = self .server .base_url , session = session )
1072+ upload = io .BytesIO (b"payload" )
1073+ upload .name = "/tmp/"
1074+
1075+ response = await client .request .post ("/assemblies" , data = {"foo" : "bar" }, files = {"file" : upload })
1076+
1077+ self .assertEqual (response .data ["ok" ], "ASSEMBLY_COMPLETED" )
1078+ self .assertEqual (session .calls [0 ][1 ]["data" ]._fields [2 ][0 ]["filename" ], "file" )
10271079
10281080 async def test_async_resumable_upload_uses_to_thread (self ):
10291081 calls = []
0 commit comments