@@ -247,9 +247,11 @@ def test_fetch__exception_if_youtube_request_fails(self):
247
247
httpretty .GET , "https://www.youtube.com/watch" , status = 500
248
248
)
249
249
250
- with self .assertRaises (YouTubeRequestFailed ):
250
+ with self .assertRaises (YouTubeRequestFailed ) as cm :
251
251
YouTubeTranscriptApi ().fetch ("abc" )
252
252
253
+ self .assertIn ("Request to YouTube failed: " , str (cm .exception ))
254
+
253
255
def test_fetch__exception_if_age_restricted (self ):
254
256
httpretty .register_uri (
255
257
httpretty .GET ,
@@ -277,21 +279,24 @@ def test_fetch__exception_request_blocked(self):
277
279
body = load_asset ("youtube_request_blocked.html.static" ),
278
280
)
279
281
280
- with self .assertRaises (RequestBlocked ):
282
+ with self .assertRaises (RequestBlocked ) as cm :
281
283
YouTubeTranscriptApi ().fetch ("Njp5uhTorCo" )
282
284
285
+ self .assertIn ("YouTube is blocking requests from your IP" , str (cm .exception ))
286
+
283
287
def test_fetch__exception_unplayable (self ):
284
288
httpretty .register_uri (
285
289
httpretty .GET ,
286
290
"https://www.youtube.com/watch" ,
287
291
body = load_asset ("youtube_unplayable.html.static" ),
288
292
)
289
293
290
- with self .assertRaises (VideoUnplayable ) as error :
294
+ with self .assertRaises (VideoUnplayable ) as cm :
291
295
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 ))
295
300
296
301
def test_fetch__exception_if_transcripts_disabled (self ):
297
302
httpretty .register_uri (
@@ -312,9 +317,11 @@ def test_fetch__exception_if_transcripts_disabled(self):
312
317
YouTubeTranscriptApi ().fetch ("Fjg5lYqvzUs" )
313
318
314
319
def test_fetch__exception_if_language_unavailable (self ):
315
- with self .assertRaises (NoTranscriptFound ):
320
+ with self .assertRaises (NoTranscriptFound ) as cm :
316
321
YouTubeTranscriptApi ().fetch ("GJLlxj_dtq8" , languages = ["cz" ])
317
322
323
+ self .assertIn ("No transcripts were found for" , str (cm .exception ))
324
+
318
325
@patch ("youtube_transcript_api.proxies.GenericProxyConfig.to_requests_dict" )
319
326
def test_fetch__with_proxy (self , to_requests_dict ):
320
327
proxy_config = GenericProxyConfig (
@@ -341,6 +348,64 @@ def test_fetch__with_proxy_prevent_alive_connections(self, to_requests_dict):
341
348
request = httpretty .last_request ()
342
349
self .assertEqual (request .headers .get ("Connection" ), "close" )
343
350
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
+
344
409
def test_fetch__with_cookies (self ):
345
410
cookie_path = get_asset_path ("example_cookies.txt" )
346
411
transcript = YouTubeTranscriptApi (cookie_path = cookie_path ).fetch ("GJLlxj_dtq8" )
0 commit comments