3 from __future__ import unicode_literals
5 # Allow direct execution
9 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13 from test.helper import FakeYDL, assertRegexpMatches
14 from youtube_dl import YoutubeDL
15 from youtube_dl.compat import compat_str, compat_urllib_error
16 from youtube_dl.extractor import YoutubeIE
17 from youtube_dl.extractor.common import InfoExtractor
18 from youtube_dl.postprocessor.common import PostProcessor
19 from youtube_dl.utils import ExtractorError, match_filter_func
21 TEST_URL = 'http://localhost/sample.mp4'
25 def __init__(self, *args, **kwargs):
26 super(YDL, self).__init__(*args, **kwargs)
27 self.downloaded_info_dicts = []
30 def process_info(self, info_dict):
31 self.downloaded_info_dicts.append(info_dict)
33 def to_screen(self, msg):
37 def _make_result(formats, **kwargs):
41 'title': 'testttitle',
42 'extractor': 'testex',
48 class TestFormatSelection(unittest.TestCase):
49 def test_prefer_free_formats(self):
50 # Same resolution => download webm
52 ydl.params['prefer_free_formats'] = True
54 {'ext': 'webm', 'height': 460, 'url': TEST_URL},
55 {'ext': 'mp4', 'height': 460, 'url': TEST_URL},
57 info_dict = _make_result(formats)
59 yie._sort_formats(info_dict['formats'])
60 ydl.process_ie_result(info_dict)
61 downloaded = ydl.downloaded_info_dicts[0]
62 self.assertEqual(downloaded['ext'], 'webm')
64 # Different resolution => download best quality (mp4)
66 ydl.params['prefer_free_formats'] = True
68 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
69 {'ext': 'mp4', 'height': 1080, 'url': TEST_URL},
71 info_dict['formats'] = formats
73 yie._sort_formats(info_dict['formats'])
74 ydl.process_ie_result(info_dict)
75 downloaded = ydl.downloaded_info_dicts[0]
76 self.assertEqual(downloaded['ext'], 'mp4')
78 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
80 ydl.params['prefer_free_formats'] = False
82 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
83 {'ext': 'mp4', 'height': 720, 'url': TEST_URL},
84 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
86 info_dict['formats'] = formats
88 yie._sort_formats(info_dict['formats'])
89 ydl.process_ie_result(info_dict)
90 downloaded = ydl.downloaded_info_dicts[0]
91 self.assertEqual(downloaded['ext'], 'mp4')
94 ydl.params['prefer_free_formats'] = False
96 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
97 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
99 info_dict['formats'] = formats
101 yie._sort_formats(info_dict['formats'])
102 ydl.process_ie_result(info_dict)
103 downloaded = ydl.downloaded_info_dicts[0]
104 self.assertEqual(downloaded['ext'], 'flv')
106 def test_format_selection(self):
108 {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
109 {'format_id': 'example-with-dashes', 'ext': 'webm', 'preference': 1, 'url': TEST_URL},
110 {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': TEST_URL},
111 {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': TEST_URL},
112 {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': TEST_URL},
114 info_dict = _make_result(formats)
116 ydl = YDL({'format': '20/47'})
117 ydl.process_ie_result(info_dict.copy())
118 downloaded = ydl.downloaded_info_dicts[0]
119 self.assertEqual(downloaded['format_id'], '47')
121 ydl = YDL({'format': '20/71/worst'})
122 ydl.process_ie_result(info_dict.copy())
123 downloaded = ydl.downloaded_info_dicts[0]
124 self.assertEqual(downloaded['format_id'], '35')
127 ydl.process_ie_result(info_dict.copy())
128 downloaded = ydl.downloaded_info_dicts[0]
129 self.assertEqual(downloaded['format_id'], '2')
131 ydl = YDL({'format': 'webm/mp4'})
132 ydl.process_ie_result(info_dict.copy())
133 downloaded = ydl.downloaded_info_dicts[0]
134 self.assertEqual(downloaded['format_id'], '47')
136 ydl = YDL({'format': '3gp/40/mp4'})
137 ydl.process_ie_result(info_dict.copy())
138 downloaded = ydl.downloaded_info_dicts[0]
139 self.assertEqual(downloaded['format_id'], '35')
141 ydl = YDL({'format': 'example-with-dashes'})
142 ydl.process_ie_result(info_dict.copy())
143 downloaded = ydl.downloaded_info_dicts[0]
144 self.assertEqual(downloaded['format_id'], 'example-with-dashes')
146 def test_format_selection_audio(self):
148 {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
149 {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
150 {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': TEST_URL},
151 {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': TEST_URL},
153 info_dict = _make_result(formats)
155 ydl = YDL({'format': 'bestaudio'})
156 ydl.process_ie_result(info_dict.copy())
157 downloaded = ydl.downloaded_info_dicts[0]
158 self.assertEqual(downloaded['format_id'], 'audio-high')
160 ydl = YDL({'format': 'worstaudio'})
161 ydl.process_ie_result(info_dict.copy())
162 downloaded = ydl.downloaded_info_dicts[0]
163 self.assertEqual(downloaded['format_id'], 'audio-low')
166 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
167 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL},
169 info_dict = _make_result(formats)
171 ydl = YDL({'format': 'bestaudio/worstaudio/best'})
172 ydl.process_ie_result(info_dict.copy())
173 downloaded = ydl.downloaded_info_dicts[0]
174 self.assertEqual(downloaded['format_id'], 'vid-high')
176 def test_format_selection_audio_exts(self):
178 {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
179 {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
180 {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
181 {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
182 {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
185 info_dict = _make_result(formats)
186 ydl = YDL({'format': 'best'})
188 ie._sort_formats(info_dict['formats'])
189 ydl.process_ie_result(copy.deepcopy(info_dict))
190 downloaded = ydl.downloaded_info_dicts[0]
191 self.assertEqual(downloaded['format_id'], 'aac-64')
193 ydl = YDL({'format': 'mp3'})
195 ie._sort_formats(info_dict['formats'])
196 ydl.process_ie_result(copy.deepcopy(info_dict))
197 downloaded = ydl.downloaded_info_dicts[0]
198 self.assertEqual(downloaded['format_id'], 'mp3-64')
200 ydl = YDL({'prefer_free_formats': True})
202 ie._sort_formats(info_dict['formats'])
203 ydl.process_ie_result(copy.deepcopy(info_dict))
204 downloaded = ydl.downloaded_info_dicts[0]
205 self.assertEqual(downloaded['format_id'], 'ogg-64')
207 def test_format_selection_video(self):
209 {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': TEST_URL},
210 {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': TEST_URL},
211 {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': TEST_URL},
213 info_dict = _make_result(formats)
215 ydl = YDL({'format': 'bestvideo'})
216 ydl.process_ie_result(info_dict.copy())
217 downloaded = ydl.downloaded_info_dicts[0]
218 self.assertEqual(downloaded['format_id'], 'dash-video-high')
220 ydl = YDL({'format': 'worstvideo'})
221 ydl.process_ie_result(info_dict.copy())
222 downloaded = ydl.downloaded_info_dicts[0]
223 self.assertEqual(downloaded['format_id'], 'dash-video-low')
225 ydl = YDL({'format': 'bestvideo[format_id^=dash][format_id$=low]'})
226 ydl.process_ie_result(info_dict.copy())
227 downloaded = ydl.downloaded_info_dicts[0]
228 self.assertEqual(downloaded['format_id'], 'dash-video-low')
231 {'format_id': 'vid-vcodec-dot', 'ext': 'mp4', 'preference': 1, 'vcodec': 'avc1.123456', 'acodec': 'none', 'url': TEST_URL},
233 info_dict = _make_result(formats)
235 ydl = YDL({'format': 'bestvideo[vcodec=avc1.123456]'})
236 ydl.process_ie_result(info_dict.copy())
237 downloaded = ydl.downloaded_info_dicts[0]
238 self.assertEqual(downloaded['format_id'], 'vid-vcodec-dot')
240 def test_youtube_format_selection(self):
242 '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '17', '36', '13',
243 # Apple HTTP Live Streaming
244 '96', '95', '94', '93', '92', '132', '151',
246 '85', '84', '102', '83', '101', '82', '100',
248 '137', '248', '136', '247', '135', '246',
249 '245', '244', '134', '243', '133', '242', '160',
251 '141', '172', '140', '171', '139',
254 def format_info(f_id):
255 info = YoutubeIE._formats[f_id].copy()
257 # XXX: In real cases InfoExtractor._parse_mpd_formats() fills up 'acodec'
258 # and 'vcodec', while in tests such information is incomplete since
259 # commit a6c2c24479e5f4827ceb06f64d855329c0a6f593
260 # test_YoutubeDL.test_youtube_format_selection is broken without
262 if 'acodec' in info and 'vcodec' not in info:
263 info['vcodec'] = 'none'
264 elif 'vcodec' in info and 'acodec' not in info:
265 info['acodec'] = 'none'
267 info['format_id'] = f_id
268 info['url'] = 'url:' + f_id
270 formats_order = [format_info(f_id) for f_id in order]
272 info_dict = _make_result(list(formats_order), extractor='youtube')
273 ydl = YDL({'format': 'bestvideo+bestaudio'})
275 yie._sort_formats(info_dict['formats'])
276 ydl.process_ie_result(info_dict)
277 downloaded = ydl.downloaded_info_dicts[0]
278 self.assertEqual(downloaded['format_id'], '137+141')
279 self.assertEqual(downloaded['ext'], 'mp4')
281 info_dict = _make_result(list(formats_order), extractor='youtube')
282 ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
284 yie._sort_formats(info_dict['formats'])
285 ydl.process_ie_result(info_dict)
286 downloaded = ydl.downloaded_info_dicts[0]
287 self.assertEqual(downloaded['format_id'], '38')
289 info_dict = _make_result(list(formats_order), extractor='youtube')
290 ydl = YDL({'format': 'bestvideo/best,bestaudio'})
292 yie._sort_formats(info_dict['formats'])
293 ydl.process_ie_result(info_dict)
294 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
295 self.assertEqual(downloaded_ids, ['137', '141'])
297 info_dict = _make_result(list(formats_order), extractor='youtube')
298 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
300 yie._sort_formats(info_dict['formats'])
301 ydl.process_ie_result(info_dict)
302 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
303 self.assertEqual(downloaded_ids, ['137+141', '248+141'])
305 info_dict = _make_result(list(formats_order), extractor='youtube')
306 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])[height<=720]+bestaudio'})
308 yie._sort_formats(info_dict['formats'])
309 ydl.process_ie_result(info_dict)
310 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
311 self.assertEqual(downloaded_ids, ['136+141', '247+141'])
313 info_dict = _make_result(list(formats_order), extractor='youtube')
314 ydl = YDL({'format': '(bestvideo[ext=none]/bestvideo[ext=webm])+bestaudio'})
316 yie._sort_formats(info_dict['formats'])
317 ydl.process_ie_result(info_dict)
318 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
319 self.assertEqual(downloaded_ids, ['248+141'])
321 for f1, f2 in zip(formats_order, formats_order[1:]):
322 info_dict = _make_result([f1, f2], extractor='youtube')
323 ydl = YDL({'format': 'best/bestvideo'})
325 yie._sort_formats(info_dict['formats'])
326 ydl.process_ie_result(info_dict)
327 downloaded = ydl.downloaded_info_dicts[0]
328 self.assertEqual(downloaded['format_id'], f1['format_id'])
330 info_dict = _make_result([f2, f1], extractor='youtube')
331 ydl = YDL({'format': 'best/bestvideo'})
333 yie._sort_formats(info_dict['formats'])
334 ydl.process_ie_result(info_dict)
335 downloaded = ydl.downloaded_info_dicts[0]
336 self.assertEqual(downloaded['format_id'], f1['format_id'])
338 def test_invalid_format_specs(self):
339 def assert_syntax_error(format_spec):
340 ydl = YDL({'format': format_spec})
341 info_dict = _make_result([{'format_id': 'foo', 'url': TEST_URL}])
342 self.assertRaises(SyntaxError, ydl.process_ie_result, info_dict)
344 assert_syntax_error('bestvideo,,best')
345 assert_syntax_error('+bestaudio')
346 assert_syntax_error('bestvideo+')
347 assert_syntax_error('/')
349 def test_format_filtering(self):
351 {'format_id': 'A', 'filesize': 500, 'width': 1000},
352 {'format_id': 'B', 'filesize': 1000, 'width': 500},
353 {'format_id': 'C', 'filesize': 1000, 'width': 400},
354 {'format_id': 'D', 'filesize': 2000, 'width': 600},
355 {'format_id': 'E', 'filesize': 3000},
357 {'format_id': 'G', 'filesize': 1000000},
360 f['url'] = 'http://_/'
362 info_dict = _make_result(formats)
364 ydl = YDL({'format': 'best[filesize<3000]'})
365 ydl.process_ie_result(info_dict)
366 downloaded = ydl.downloaded_info_dicts[0]
367 self.assertEqual(downloaded['format_id'], 'D')
369 ydl = YDL({'format': 'best[filesize<=3000]'})
370 ydl.process_ie_result(info_dict)
371 downloaded = ydl.downloaded_info_dicts[0]
372 self.assertEqual(downloaded['format_id'], 'E')
374 ydl = YDL({'format': 'best[filesize <= ? 3000]'})
375 ydl.process_ie_result(info_dict)
376 downloaded = ydl.downloaded_info_dicts[0]
377 self.assertEqual(downloaded['format_id'], 'F')
379 ydl = YDL({'format': 'best [filesize = 1000] [width>450]'})
380 ydl.process_ie_result(info_dict)
381 downloaded = ydl.downloaded_info_dicts[0]
382 self.assertEqual(downloaded['format_id'], 'B')
384 ydl = YDL({'format': 'best [filesize = 1000] [width!=450]'})
385 ydl.process_ie_result(info_dict)
386 downloaded = ydl.downloaded_info_dicts[0]
387 self.assertEqual(downloaded['format_id'], 'C')
389 ydl = YDL({'format': '[filesize>?1]'})
390 ydl.process_ie_result(info_dict)
391 downloaded = ydl.downloaded_info_dicts[0]
392 self.assertEqual(downloaded['format_id'], 'G')
394 ydl = YDL({'format': '[filesize<1M]'})
395 ydl.process_ie_result(info_dict)
396 downloaded = ydl.downloaded_info_dicts[0]
397 self.assertEqual(downloaded['format_id'], 'E')
399 ydl = YDL({'format': '[filesize<1MiB]'})
400 ydl.process_ie_result(info_dict)
401 downloaded = ydl.downloaded_info_dicts[0]
402 self.assertEqual(downloaded['format_id'], 'G')
404 ydl = YDL({'format': 'all[width>=400][width<=600]'})
405 ydl.process_ie_result(info_dict)
406 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
407 self.assertEqual(downloaded_ids, ['B', 'C', 'D'])
409 ydl = YDL({'format': 'best[height<40]'})
411 ydl.process_ie_result(info_dict)
412 except ExtractorError:
414 self.assertEqual(ydl.downloaded_info_dicts, [])
417 class TestYoutubeDL(unittest.TestCase):
418 def test_subtitles(self):
419 def s_formats(lang, autocaption=False):
422 'url': 'http://localhost/video.%s.%s' % (lang, ext),
423 '_auto': autocaption,
424 } for ext in ['vtt', 'srt', 'ass']]
425 subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es'])
426 auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es'])
430 'url': 'http://localhost/video.mp4',
431 'subtitles': subtitles,
432 'automatic_captions': auto_captions,
436 def get_info(params={}):
437 params.setdefault('simulate', True)
439 ydl.report_warning = lambda *args, **kargs: None
440 return ydl.process_video_result(info_dict, download=False)
443 self.assertFalse(result.get('requested_subtitles'))
444 self.assertEqual(result['subtitles'], subtitles)
445 self.assertEqual(result['automatic_captions'], auto_captions)
447 result = get_info({'writesubtitles': True})
448 subs = result['requested_subtitles']
449 self.assertTrue(subs)
450 self.assertEqual(set(subs.keys()), set(['en']))
451 self.assertTrue(subs['en'].get('data') is None)
452 self.assertEqual(subs['en']['ext'], 'ass')
454 result = get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
455 subs = result['requested_subtitles']
456 self.assertEqual(subs['en']['ext'], 'srt')
458 result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
459 subs = result['requested_subtitles']
460 self.assertTrue(subs)
461 self.assertEqual(set(subs.keys()), set(['es', 'fr']))
463 result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
464 subs = result['requested_subtitles']
465 self.assertTrue(subs)
466 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
467 self.assertFalse(subs['es']['_auto'])
468 self.assertTrue(subs['pt']['_auto'])
470 result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
471 subs = result['requested_subtitles']
472 self.assertTrue(subs)
473 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
474 self.assertTrue(subs['es']['_auto'])
475 self.assertTrue(subs['pt']['_auto'])
477 def test_add_extra_info(self):
483 'playlist': 'funny videos',
485 YDL.add_extra_info(test_dict, extra_info)
486 self.assertEqual(test_dict['extractor'], 'Foo')
487 self.assertEqual(test_dict['playlist'], 'funny videos')
489 def test_prepare_filename(self):
497 ydl = YoutubeDL({'outtmpl': templ})
498 return ydl.prepare_filename(info)
499 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
500 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
501 # Replace missing fields with 'NA'
502 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
504 def test_format_note(self):
506 self.assertEqual(ydl._format_note({}), '')
507 assertRegexpMatches(self, ydl._format_note({
510 assertRegexpMatches(self, ydl._format_note({
514 def test_postprocessors(self):
515 filename = 'post-processor-testfile.mp4'
516 audiofile = filename + '.mp3'
518 class SimplePP(PostProcessor):
520 with open(audiofile, 'wt') as f:
522 return [info['filepath']], info
524 def run_pp(params, PP):
525 with open(filename, 'wt') as f:
527 ydl = YoutubeDL(params)
528 ydl.add_post_processor(PP())
529 ydl.post_process(filename, {'filepath': filename})
531 run_pp({'keepvideo': True}, SimplePP)
532 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
533 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
537 run_pp({'keepvideo': False}, SimplePP)
538 self.assertFalse(os.path.exists(filename), '%s exists' % filename)
539 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
542 class ModifierPP(PostProcessor):
544 with open(info['filepath'], 'wt') as f:
548 run_pp({'keepvideo': False}, ModifierPP)
549 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
552 def test_match_filter(self):
553 class FilterYDL(YDL):
554 def __init__(self, *args, **kwargs):
555 super(FilterYDL, self).__init__(*args, **kwargs)
556 self.params['simulate'] = True
558 def process_info(self, info_dict):
559 super(YDL, self).process_info(info_dict)
561 def _match_entry(self, info_dict, incomplete):
562 res = super(FilterYDL, self)._match_entry(info_dict, incomplete)
564 self.downloaded_info_dicts.append(info_dict)
573 'filesize': 10 * 1024,
581 'description': 'foo',
582 'filesize': 5 * 1024,
584 videos = [first, second]
586 def get_videos(filter_=None):
587 ydl = FilterYDL({'match_filter': filter_})
589 ydl.process_ie_result(v, download=True)
590 return [v['id'] for v in ydl.downloaded_info_dicts]
593 self.assertEqual(res, ['1', '2'])
599 return 'Video id is not 1'
601 self.assertEqual(res, ['1'])
603 f = match_filter_func('duration < 30')
605 self.assertEqual(res, ['2'])
607 f = match_filter_func('description = foo')
609 self.assertEqual(res, ['2'])
611 f = match_filter_func('description =? foo')
613 self.assertEqual(res, ['1', '2'])
615 f = match_filter_func('filesize > 5KiB')
617 self.assertEqual(res, ['1'])
619 def test_playlist_items_selection(self):
622 'title': compat_str(i),
624 } for i in range(1, 5)]
629 'extractor': 'test:playlist',
630 'extractor_key': 'test:playlist',
631 'webpage_url': 'http://example.com',
636 # make a copy because the dictionary can be modified
637 ydl.process_ie_result(playlist.copy())
638 return [int(v['id']) for v in ydl.downloaded_info_dicts]
641 self.assertEqual(result, [1, 2, 3, 4])
643 result = get_ids({'playlistend': 10})
644 self.assertEqual(result, [1, 2, 3, 4])
646 result = get_ids({'playlistend': 2})
647 self.assertEqual(result, [1, 2])
649 result = get_ids({'playliststart': 10})
650 self.assertEqual(result, [])
652 result = get_ids({'playliststart': 2})
653 self.assertEqual(result, [2, 3, 4])
655 result = get_ids({'playlist_items': '2-4'})
656 self.assertEqual(result, [2, 3, 4])
658 result = get_ids({'playlist_items': '2,4'})
659 self.assertEqual(result, [2, 4])
661 result = get_ids({'playlist_items': '10'})
662 self.assertEqual(result, [])
664 def test_urlopen_no_file_protocol(self):
665 # see https://github.com/rg3/youtube-dl/issues/8227
667 self.assertRaises(compat_urllib_error.URLError, ydl.urlopen, 'file:///etc/passwd')
669 def test_do_not_override_ie_key_in_url_transparent(self):
672 class Foo1IE(InfoExtractor):
673 _VALID_URL = r'foo1:'
675 def _real_extract(self, url):
677 '_type': 'url_transparent',
682 class Foo2IE(InfoExtractor):
683 _VALID_URL = r'foo2:'
685 def _real_extract(self, url):
692 class Foo3IE(InfoExtractor):
693 _VALID_URL = r'foo3:'
695 def _real_extract(self, url):
696 return _make_result([{'url': TEST_URL}])
698 ydl.add_info_extractor(Foo1IE(ydl))
699 ydl.add_info_extractor(Foo2IE(ydl))
700 ydl.add_info_extractor(Foo3IE(ydl))
701 ydl.extract_info('foo1:')
702 downloaded = ydl.downloaded_info_dicts[0]
703 self.assertEqual(downloaded['url'], TEST_URL)
706 if __name__ == '__main__':