@@ -247,9 +247,11 @@ def test_fetch__exception_if_youtube_request_fails(self):
247247 httpretty .GET , "https://www.youtube.com/watch" , status = 500
248248 )
249249
250- with self .assertRaises (YouTubeRequestFailed ):
250+ with self .assertRaises (YouTubeRequestFailed ) as cm :
251251 YouTubeTranscriptApi ().fetch ("abc" )
252252
253+ self .assertIn ("Request to YouTube failed: " , str (cm .exception ))
254+
253255 def test_fetch__exception_if_age_restricted (self ):
254256 httpretty .register_uri (
255257 httpretty .GET ,
@@ -277,21 +279,24 @@ def test_fetch__exception_request_blocked(self):
277279 body = load_asset ("youtube_request_blocked.html.static" ),
278280 )
279281
280- with self .assertRaises (RequestBlocked ):
282+ with self .assertRaises (RequestBlocked ) as cm :
281283 YouTubeTranscriptApi ().fetch ("Njp5uhTorCo" )
282284
285+ self .assertIn ("YouTube is blocking requests from your IP" , str (cm .exception ))
286+
283287 def test_fetch__exception_unplayable (self ):
284288 httpretty .register_uri (
285289 httpretty .GET ,
286290 "https://www.youtube.com/watch" ,
287291 body = load_asset ("youtube_unplayable.html.static" ),
288292 )
289293
290- with self .assertRaises (VideoUnplayable ) as error :
294+ with self .assertRaises (VideoUnplayable ) as cm :
291295 YouTubeTranscriptApi ().fetch ("Njp5uhTorCo" )
292- error = error .exception
293- self .assertEqual (error .reason , "Custom Reason" )
294- self .assertEqual (error .sub_reasons , ["Sub Reason 1" , "Sub Reason 2" ])
296+ exception = cm .exception
297+ self .assertEqual (exception .reason , "Custom Reason" )
298+ self .assertEqual (exception .sub_reasons , ["Sub Reason 1" , "Sub Reason 2" ])
299+ self .assertIn ("Custom Reason" , str (exception ))
295300
296301 def test_fetch__exception_if_transcripts_disabled (self ):
297302 httpretty .register_uri (
@@ -312,9 +317,11 @@ def test_fetch__exception_if_transcripts_disabled(self):
312317 YouTubeTranscriptApi ().fetch ("Fjg5lYqvzUs" )
313318
314319 def test_fetch__exception_if_language_unavailable (self ):
315- with self .assertRaises (NoTranscriptFound ):
320+ with self .assertRaises (NoTranscriptFound ) as cm :
316321 YouTubeTranscriptApi ().fetch ("GJLlxj_dtq8" , languages = ["cz" ])
317322
323+ self .assertIn ("No transcripts were found for" , str (cm .exception ))
324+
318325 @patch ("youtube_transcript_api.proxies.GenericProxyConfig.to_requests_dict" )
319326 def test_fetch__with_proxy (self , to_requests_dict ):
320327 proxy_config = GenericProxyConfig (
@@ -341,6 +348,64 @@ def test_fetch__with_proxy_prevent_alive_connections(self, to_requests_dict):
341348 request = httpretty .last_request ()
342349 self .assertEqual (request .headers .get ("Connection" ), "close" )
343350
351+ @patch ("youtube_transcript_api.proxies.GenericProxyConfig.to_requests_dict" )
352+ def test_fetch__with_proxy_retry_when_blocked (self , to_requests_dict ):
353+ for _ in range (3 ):
354+ httpretty .register_uri (
355+ httpretty .GET ,
356+ "https://www.youtube.com/watch" ,
357+ body = load_asset ("youtube_request_blocked.html.static" ),
358+ )
359+ proxy_config = WebshareProxyConfig (
360+ proxy_username = "username" ,
361+ proxy_password = "password" ,
362+ )
363+
364+ YouTubeTranscriptApi (proxy_config = proxy_config ).fetch ("Njp5uhTorCo" )
365+
366+ self .assertEqual (len (httpretty .latest_requests ()), 3 + 2 )
367+
368+ @patch ("youtube_transcript_api.proxies.GenericProxyConfig.to_requests_dict" )
369+ def test_fetch__with_webshare_proxy_reraise_when_blocked (self , to_requests_dict ):
370+ retries = 5
371+ for _ in range (retries ):
372+ httpretty .register_uri (
373+ httpretty .GET ,
374+ "https://www.youtube.com/watch" ,
375+ body = load_asset ("youtube_request_blocked.html.static" ),
376+ )
377+ proxy_config = WebshareProxyConfig (
378+ proxy_username = "username" ,
379+ proxy_password = "password" ,
380+ retries_when_blocked = retries ,
381+ )
382+
383+ with self .assertRaises (RequestBlocked ) as cm :
384+ YouTubeTranscriptApi (proxy_config = proxy_config ).fetch ("Njp5uhTorCo" )
385+
386+ self .assertEqual (len (httpretty .latest_requests ()), retries )
387+ self .assertEqual (cm .exception ._proxy_config , proxy_config )
388+ self .assertIn ("Webshare" , str (cm .exception ))
389+
390+ @patch ("youtube_transcript_api.proxies.GenericProxyConfig.to_requests_dict" )
391+ def test_fetch__with_generic_proxy_reraise_when_blocked (self , to_requests_dict ):
392+ httpretty .register_uri (
393+ httpretty .GET ,
394+ "https://www.youtube.com/watch" ,
395+ body = load_asset ("youtube_request_blocked.html.static" ),
396+ )
397+ proxy_config = GenericProxyConfig (
398+ http_url = "http://localhost:8080" ,
399+ https_url = "http://localhost:8080" ,
400+ )
401+
402+ with self .assertRaises (RequestBlocked ) as cm :
403+ YouTubeTranscriptApi (proxy_config = proxy_config ).fetch ("Njp5uhTorCo" )
404+
405+ self .assertEqual (len (httpretty .latest_requests ()), 1 )
406+ self .assertEqual (cm .exception ._proxy_config , proxy_config )
407+ self .assertIn ("YouTube is blocking your requests" , str (cm .exception ))
408+
344409 def test_fetch__with_cookies (self ):
345410 cookie_path = get_asset_path ("example_cookies.txt" )
346411 transcript = YouTubeTranscriptApi (cookie_path = cookie_path ).fetch ("GJLlxj_dtq8" )
0 commit comments