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_audio_only_extractor_format_selection(self):
339 # For extractors with incomplete formats (all formats are audio-only or
340 # video-only) best and worst should fallback to corresponding best/worst
341 # video-only or audio-only formats (as per
342 # https://github.com/rg3/youtube-dl/pull/5556)
344 {'format_id': 'low', 'ext': 'mp3', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
345 {'format_id': 'high', 'ext': 'mp3', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
347 info_dict = _make_result(formats)
349 ydl = YDL({'format': 'best'})
350 ydl.process_ie_result(info_dict.copy())
351 downloaded = ydl.downloaded_info_dicts[0]
352 self.assertEqual(downloaded['format_id'], 'high')
354 ydl = YDL({'format': 'worst'})
355 ydl.process_ie_result(info_dict.copy())
356 downloaded = ydl.downloaded_info_dicts[0]
357 self.assertEqual(downloaded['format_id'], 'low')
359 def test_format_not_available(self):
361 {'format_id': 'regular', 'ext': 'mp4', 'height': 360, 'url': TEST_URL},
362 {'format_id': 'video', 'ext': 'mp4', 'height': 720, 'acodec': 'none', 'url': TEST_URL},
364 info_dict = _make_result(formats)
366 # This must fail since complete video-audio format does not match filter
367 # and extractor does not provide incomplete only formats (i.e. only
368 # video-only or audio-only).
369 ydl = YDL({'format': 'best[height>360]'})
370 self.assertRaises(ExtractorError, ydl.process_ie_result, info_dict.copy())
372 def test_invalid_format_specs(self):
373 def assert_syntax_error(format_spec):
374 ydl = YDL({'format': format_spec})
375 info_dict = _make_result([{'format_id': 'foo', 'url': TEST_URL}])
376 self.assertRaises(SyntaxError, ydl.process_ie_result, info_dict)
378 assert_syntax_error('bestvideo,,best')
379 assert_syntax_error('+bestaudio')
380 assert_syntax_error('bestvideo+')
381 assert_syntax_error('/')
383 def test_format_filtering(self):
385 {'format_id': 'A', 'filesize': 500, 'width': 1000},
386 {'format_id': 'B', 'filesize': 1000, 'width': 500},
387 {'format_id': 'C', 'filesize': 1000, 'width': 400},
388 {'format_id': 'D', 'filesize': 2000, 'width': 600},
389 {'format_id': 'E', 'filesize': 3000},
391 {'format_id': 'G', 'filesize': 1000000},
394 f['url'] = 'http://_/'
396 info_dict = _make_result(formats)
398 ydl = YDL({'format': 'best[filesize<3000]'})
399 ydl.process_ie_result(info_dict)
400 downloaded = ydl.downloaded_info_dicts[0]
401 self.assertEqual(downloaded['format_id'], 'D')
403 ydl = YDL({'format': 'best[filesize<=3000]'})
404 ydl.process_ie_result(info_dict)
405 downloaded = ydl.downloaded_info_dicts[0]
406 self.assertEqual(downloaded['format_id'], 'E')
408 ydl = YDL({'format': 'best[filesize <= ? 3000]'})
409 ydl.process_ie_result(info_dict)
410 downloaded = ydl.downloaded_info_dicts[0]
411 self.assertEqual(downloaded['format_id'], 'F')
413 ydl = YDL({'format': 'best [filesize = 1000] [width>450]'})
414 ydl.process_ie_result(info_dict)
415 downloaded = ydl.downloaded_info_dicts[0]
416 self.assertEqual(downloaded['format_id'], 'B')
418 ydl = YDL({'format': 'best [filesize = 1000] [width!=450]'})
419 ydl.process_ie_result(info_dict)
420 downloaded = ydl.downloaded_info_dicts[0]
421 self.assertEqual(downloaded['format_id'], 'C')
423 ydl = YDL({'format': '[filesize>?1]'})
424 ydl.process_ie_result(info_dict)
425 downloaded = ydl.downloaded_info_dicts[0]
426 self.assertEqual(downloaded['format_id'], 'G')
428 ydl = YDL({'format': '[filesize<1M]'})
429 ydl.process_ie_result(info_dict)
430 downloaded = ydl.downloaded_info_dicts[0]
431 self.assertEqual(downloaded['format_id'], 'E')
433 ydl = YDL({'format': '[filesize<1MiB]'})
434 ydl.process_ie_result(info_dict)
435 downloaded = ydl.downloaded_info_dicts[0]
436 self.assertEqual(downloaded['format_id'], 'G')
438 ydl = YDL({'format': 'all[width>=400][width<=600]'})
439 ydl.process_ie_result(info_dict)
440 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
441 self.assertEqual(downloaded_ids, ['B', 'C', 'D'])
443 ydl = YDL({'format': 'best[height<40]'})
445 ydl.process_ie_result(info_dict)
446 except ExtractorError:
448 self.assertEqual(ydl.downloaded_info_dicts, [])
451 class TestYoutubeDL(unittest.TestCase):
452 def test_subtitles(self):
453 def s_formats(lang, autocaption=False):
456 'url': 'http://localhost/video.%s.%s' % (lang, ext),
457 '_auto': autocaption,
458 } for ext in ['vtt', 'srt', 'ass']]
459 subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es'])
460 auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es'])
464 'url': 'http://localhost/video.mp4',
465 'subtitles': subtitles,
466 'automatic_captions': auto_captions,
470 def get_info(params={}):
471 params.setdefault('simulate', True)
473 ydl.report_warning = lambda *args, **kargs: None
474 return ydl.process_video_result(info_dict, download=False)
477 self.assertFalse(result.get('requested_subtitles'))
478 self.assertEqual(result['subtitles'], subtitles)
479 self.assertEqual(result['automatic_captions'], auto_captions)
481 result = get_info({'writesubtitles': True})
482 subs = result['requested_subtitles']
483 self.assertTrue(subs)
484 self.assertEqual(set(subs.keys()), set(['en']))
485 self.assertTrue(subs['en'].get('data') is None)
486 self.assertEqual(subs['en']['ext'], 'ass')
488 result = get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
489 subs = result['requested_subtitles']
490 self.assertEqual(subs['en']['ext'], 'srt')
492 result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
493 subs = result['requested_subtitles']
494 self.assertTrue(subs)
495 self.assertEqual(set(subs.keys()), set(['es', 'fr']))
497 result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
498 subs = result['requested_subtitles']
499 self.assertTrue(subs)
500 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
501 self.assertFalse(subs['es']['_auto'])
502 self.assertTrue(subs['pt']['_auto'])
504 result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
505 subs = result['requested_subtitles']
506 self.assertTrue(subs)
507 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
508 self.assertTrue(subs['es']['_auto'])
509 self.assertTrue(subs['pt']['_auto'])
511 def test_add_extra_info(self):
517 'playlist': 'funny videos',
519 YDL.add_extra_info(test_dict, extra_info)
520 self.assertEqual(test_dict['extractor'], 'Foo')
521 self.assertEqual(test_dict['playlist'], 'funny videos')
523 def test_prepare_filename(self):
531 ydl = YoutubeDL({'outtmpl': templ})
532 return ydl.prepare_filename(info)
533 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
534 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
535 # Replace missing fields with 'NA'
536 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
538 def test_format_note(self):
540 self.assertEqual(ydl._format_note({}), '')
541 assertRegexpMatches(self, ydl._format_note({
544 assertRegexpMatches(self, ydl._format_note({
548 def test_postprocessors(self):
549 filename = 'post-processor-testfile.mp4'
550 audiofile = filename + '.mp3'
552 class SimplePP(PostProcessor):
554 with open(audiofile, 'wt') as f:
556 return [info['filepath']], info
558 def run_pp(params, PP):
559 with open(filename, 'wt') as f:
561 ydl = YoutubeDL(params)
562 ydl.add_post_processor(PP())
563 ydl.post_process(filename, {'filepath': filename})
565 run_pp({'keepvideo': True}, SimplePP)
566 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
567 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
571 run_pp({'keepvideo': False}, SimplePP)
572 self.assertFalse(os.path.exists(filename), '%s exists' % filename)
573 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
576 class ModifierPP(PostProcessor):
578 with open(info['filepath'], 'wt') as f:
582 run_pp({'keepvideo': False}, ModifierPP)
583 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
586 def test_match_filter(self):
587 class FilterYDL(YDL):
588 def __init__(self, *args, **kwargs):
589 super(FilterYDL, self).__init__(*args, **kwargs)
590 self.params['simulate'] = True
592 def process_info(self, info_dict):
593 super(YDL, self).process_info(info_dict)
595 def _match_entry(self, info_dict, incomplete):
596 res = super(FilterYDL, self)._match_entry(info_dict, incomplete)
598 self.downloaded_info_dicts.append(info_dict)
607 'filesize': 10 * 1024,
615 'description': 'foo',
616 'filesize': 5 * 1024,
618 videos = [first, second]
620 def get_videos(filter_=None):
621 ydl = FilterYDL({'match_filter': filter_})
623 ydl.process_ie_result(v, download=True)
624 return [v['id'] for v in ydl.downloaded_info_dicts]
627 self.assertEqual(res, ['1', '2'])
633 return 'Video id is not 1'
635 self.assertEqual(res, ['1'])
637 f = match_filter_func('duration < 30')
639 self.assertEqual(res, ['2'])
641 f = match_filter_func('description = foo')
643 self.assertEqual(res, ['2'])
645 f = match_filter_func('description =? foo')
647 self.assertEqual(res, ['1', '2'])
649 f = match_filter_func('filesize > 5KiB')
651 self.assertEqual(res, ['1'])
653 def test_playlist_items_selection(self):
656 'title': compat_str(i),
658 } for i in range(1, 5)]
663 'extractor': 'test:playlist',
664 'extractor_key': 'test:playlist',
665 'webpage_url': 'http://example.com',
670 # make a copy because the dictionary can be modified
671 ydl.process_ie_result(playlist.copy())
672 return [int(v['id']) for v in ydl.downloaded_info_dicts]
675 self.assertEqual(result, [1, 2, 3, 4])
677 result = get_ids({'playlistend': 10})
678 self.assertEqual(result, [1, 2, 3, 4])
680 result = get_ids({'playlistend': 2})
681 self.assertEqual(result, [1, 2])
683 result = get_ids({'playliststart': 10})
684 self.assertEqual(result, [])
686 result = get_ids({'playliststart': 2})
687 self.assertEqual(result, [2, 3, 4])
689 result = get_ids({'playlist_items': '2-4'})
690 self.assertEqual(result, [2, 3, 4])
692 result = get_ids({'playlist_items': '2,4'})
693 self.assertEqual(result, [2, 4])
695 result = get_ids({'playlist_items': '10'})
696 self.assertEqual(result, [])
698 def test_urlopen_no_file_protocol(self):
699 # see https://github.com/rg3/youtube-dl/issues/8227
701 self.assertRaises(compat_urllib_error.URLError, ydl.urlopen, 'file:///etc/passwd')
703 def test_do_not_override_ie_key_in_url_transparent(self):
706 class Foo1IE(InfoExtractor):
707 _VALID_URL = r'foo1:'
709 def _real_extract(self, url):
711 '_type': 'url_transparent',
716 class Foo2IE(InfoExtractor):
717 _VALID_URL = r'foo2:'
719 def _real_extract(self, url):
726 class Foo3IE(InfoExtractor):
727 _VALID_URL = r'foo3:'
729 def _real_extract(self, url):
730 return _make_result([{'url': TEST_URL}])
732 ydl.add_info_extractor(Foo1IE(ydl))
733 ydl.add_info_extractor(Foo2IE(ydl))
734 ydl.add_info_extractor(Foo3IE(ydl))
735 ydl.extract_info('foo1:')
736 downloaded = ydl.downloaded_info_dicts[0]
737 self.assertEqual(downloaded['url'], TEST_URL)
740 if __name__ == '__main__':