4 from __future__ import unicode_literals
6 # Allow direct execution
10 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
14 from test.helper import FakeYDL, assertRegexpMatches
15 from youtube_dl import YoutubeDL
16 from youtube_dl.compat import compat_str, compat_urllib_error
17 from youtube_dl.extractor import YoutubeIE
18 from youtube_dl.extractor.common import InfoExtractor
19 from youtube_dl.postprocessor.common import PostProcessor
20 from youtube_dl.utils import ExtractorError, match_filter_func
22 TEST_URL = 'http://localhost/sample.mp4'
26 def __init__(self, *args, **kwargs):
27 super(YDL, self).__init__(*args, **kwargs)
28 self.downloaded_info_dicts = []
31 def process_info(self, info_dict):
32 self.downloaded_info_dicts.append(info_dict)
34 def to_screen(self, msg):
38 def _make_result(formats, **kwargs):
42 'title': 'testttitle',
43 'extractor': 'testex',
49 class TestFormatSelection(unittest.TestCase):
50 def test_prefer_free_formats(self):
51 # Same resolution => download webm
53 ydl.params['prefer_free_formats'] = True
55 {'ext': 'webm', 'height': 460, 'url': TEST_URL},
56 {'ext': 'mp4', 'height': 460, 'url': TEST_URL},
58 info_dict = _make_result(formats)
60 yie._sort_formats(info_dict['formats'])
61 ydl.process_ie_result(info_dict)
62 downloaded = ydl.downloaded_info_dicts[0]
63 self.assertEqual(downloaded['ext'], 'webm')
65 # Different resolution => download best quality (mp4)
67 ydl.params['prefer_free_formats'] = True
69 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
70 {'ext': 'mp4', 'height': 1080, 'url': TEST_URL},
72 info_dict['formats'] = formats
74 yie._sort_formats(info_dict['formats'])
75 ydl.process_ie_result(info_dict)
76 downloaded = ydl.downloaded_info_dicts[0]
77 self.assertEqual(downloaded['ext'], 'mp4')
79 # No prefer_free_formats => prefer mp4 and flv for greater compatibility
81 ydl.params['prefer_free_formats'] = False
83 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
84 {'ext': 'mp4', 'height': 720, 'url': TEST_URL},
85 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
87 info_dict['formats'] = formats
89 yie._sort_formats(info_dict['formats'])
90 ydl.process_ie_result(info_dict)
91 downloaded = ydl.downloaded_info_dicts[0]
92 self.assertEqual(downloaded['ext'], 'mp4')
95 ydl.params['prefer_free_formats'] = False
97 {'ext': 'flv', 'height': 720, 'url': TEST_URL},
98 {'ext': 'webm', 'height': 720, 'url': TEST_URL},
100 info_dict['formats'] = formats
102 yie._sort_formats(info_dict['formats'])
103 ydl.process_ie_result(info_dict)
104 downloaded = ydl.downloaded_info_dicts[0]
105 self.assertEqual(downloaded['ext'], 'flv')
107 def test_format_selection(self):
109 {'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
110 {'format_id': 'example-with-dashes', 'ext': 'webm', 'preference': 1, 'url': TEST_URL},
111 {'format_id': '45', 'ext': 'webm', 'preference': 2, 'url': TEST_URL},
112 {'format_id': '47', 'ext': 'webm', 'preference': 3, 'url': TEST_URL},
113 {'format_id': '2', 'ext': 'flv', 'preference': 4, 'url': TEST_URL},
115 info_dict = _make_result(formats)
117 ydl = YDL({'format': '20/47'})
118 ydl.process_ie_result(info_dict.copy())
119 downloaded = ydl.downloaded_info_dicts[0]
120 self.assertEqual(downloaded['format_id'], '47')
122 ydl = YDL({'format': '20/71/worst'})
123 ydl.process_ie_result(info_dict.copy())
124 downloaded = ydl.downloaded_info_dicts[0]
125 self.assertEqual(downloaded['format_id'], '35')
128 ydl.process_ie_result(info_dict.copy())
129 downloaded = ydl.downloaded_info_dicts[0]
130 self.assertEqual(downloaded['format_id'], '2')
132 ydl = YDL({'format': 'webm/mp4'})
133 ydl.process_ie_result(info_dict.copy())
134 downloaded = ydl.downloaded_info_dicts[0]
135 self.assertEqual(downloaded['format_id'], '47')
137 ydl = YDL({'format': '3gp/40/mp4'})
138 ydl.process_ie_result(info_dict.copy())
139 downloaded = ydl.downloaded_info_dicts[0]
140 self.assertEqual(downloaded['format_id'], '35')
142 ydl = YDL({'format': 'example-with-dashes'})
143 ydl.process_ie_result(info_dict.copy())
144 downloaded = ydl.downloaded_info_dicts[0]
145 self.assertEqual(downloaded['format_id'], 'example-with-dashes')
147 def test_format_selection_audio(self):
149 {'format_id': 'audio-low', 'ext': 'webm', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
150 {'format_id': 'audio-mid', 'ext': 'webm', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
151 {'format_id': 'audio-high', 'ext': 'flv', 'preference': 3, 'vcodec': 'none', 'url': TEST_URL},
152 {'format_id': 'vid', 'ext': 'mp4', 'preference': 4, 'url': TEST_URL},
154 info_dict = _make_result(formats)
156 ydl = YDL({'format': 'bestaudio'})
157 ydl.process_ie_result(info_dict.copy())
158 downloaded = ydl.downloaded_info_dicts[0]
159 self.assertEqual(downloaded['format_id'], 'audio-high')
161 ydl = YDL({'format': 'worstaudio'})
162 ydl.process_ie_result(info_dict.copy())
163 downloaded = ydl.downloaded_info_dicts[0]
164 self.assertEqual(downloaded['format_id'], 'audio-low')
167 {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
168 {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL},
170 info_dict = _make_result(formats)
172 ydl = YDL({'format': 'bestaudio/worstaudio/best'})
173 ydl.process_ie_result(info_dict.copy())
174 downloaded = ydl.downloaded_info_dicts[0]
175 self.assertEqual(downloaded['format_id'], 'vid-high')
177 def test_format_selection_audio_exts(self):
179 {'format_id': 'mp3-64', 'ext': 'mp3', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
180 {'format_id': 'ogg-64', 'ext': 'ogg', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
181 {'format_id': 'aac-64', 'ext': 'aac', 'abr': 64, 'url': 'http://_', 'vcodec': 'none'},
182 {'format_id': 'mp3-32', 'ext': 'mp3', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
183 {'format_id': 'aac-32', 'ext': 'aac', 'abr': 32, 'url': 'http://_', 'vcodec': 'none'},
186 info_dict = _make_result(formats)
187 ydl = YDL({'format': 'best'})
189 ie._sort_formats(info_dict['formats'])
190 ydl.process_ie_result(copy.deepcopy(info_dict))
191 downloaded = ydl.downloaded_info_dicts[0]
192 self.assertEqual(downloaded['format_id'], 'aac-64')
194 ydl = YDL({'format': 'mp3'})
196 ie._sort_formats(info_dict['formats'])
197 ydl.process_ie_result(copy.deepcopy(info_dict))
198 downloaded = ydl.downloaded_info_dicts[0]
199 self.assertEqual(downloaded['format_id'], 'mp3-64')
201 ydl = YDL({'prefer_free_formats': True})
203 ie._sort_formats(info_dict['formats'])
204 ydl.process_ie_result(copy.deepcopy(info_dict))
205 downloaded = ydl.downloaded_info_dicts[0]
206 self.assertEqual(downloaded['format_id'], 'ogg-64')
208 def test_format_selection_video(self):
210 {'format_id': 'dash-video-low', 'ext': 'mp4', 'preference': 1, 'acodec': 'none', 'url': TEST_URL},
211 {'format_id': 'dash-video-high', 'ext': 'mp4', 'preference': 2, 'acodec': 'none', 'url': TEST_URL},
212 {'format_id': 'vid', 'ext': 'mp4', 'preference': 3, 'url': TEST_URL},
214 info_dict = _make_result(formats)
216 ydl = YDL({'format': 'bestvideo'})
217 ydl.process_ie_result(info_dict.copy())
218 downloaded = ydl.downloaded_info_dicts[0]
219 self.assertEqual(downloaded['format_id'], 'dash-video-high')
221 ydl = YDL({'format': 'worstvideo'})
222 ydl.process_ie_result(info_dict.copy())
223 downloaded = ydl.downloaded_info_dicts[0]
224 self.assertEqual(downloaded['format_id'], 'dash-video-low')
226 ydl = YDL({'format': 'bestvideo[format_id^=dash][format_id$=low]'})
227 ydl.process_ie_result(info_dict.copy())
228 downloaded = ydl.downloaded_info_dicts[0]
229 self.assertEqual(downloaded['format_id'], 'dash-video-low')
232 {'format_id': 'vid-vcodec-dot', 'ext': 'mp4', 'preference': 1, 'vcodec': 'avc1.123456', 'acodec': 'none', 'url': TEST_URL},
234 info_dict = _make_result(formats)
236 ydl = YDL({'format': 'bestvideo[vcodec=avc1.123456]'})
237 ydl.process_ie_result(info_dict.copy())
238 downloaded = ydl.downloaded_info_dicts[0]
239 self.assertEqual(downloaded['format_id'], 'vid-vcodec-dot')
241 def test_youtube_format_selection(self):
243 '38', '37', '46', '22', '45', '35', '44', '18', '34', '43', '6', '5', '17', '36', '13',
244 # Apple HTTP Live Streaming
245 '96', '95', '94', '93', '92', '132', '151',
247 '85', '84', '102', '83', '101', '82', '100',
249 '137', '248', '136', '247', '135', '246',
250 '245', '244', '134', '243', '133', '242', '160',
252 '141', '172', '140', '171', '139',
255 def format_info(f_id):
256 info = YoutubeIE._formats[f_id].copy()
258 # XXX: In real cases InfoExtractor._parse_mpd_formats() fills up 'acodec'
259 # and 'vcodec', while in tests such information is incomplete since
260 # commit a6c2c24479e5f4827ceb06f64d855329c0a6f593
261 # test_YoutubeDL.test_youtube_format_selection is broken without
263 if 'acodec' in info and 'vcodec' not in info:
264 info['vcodec'] = 'none'
265 elif 'vcodec' in info and 'acodec' not in info:
266 info['acodec'] = 'none'
268 info['format_id'] = f_id
269 info['url'] = 'url:' + f_id
271 formats_order = [format_info(f_id) for f_id in order]
273 info_dict = _make_result(list(formats_order), extractor='youtube')
274 ydl = YDL({'format': 'bestvideo+bestaudio'})
276 yie._sort_formats(info_dict['formats'])
277 ydl.process_ie_result(info_dict)
278 downloaded = ydl.downloaded_info_dicts[0]
279 self.assertEqual(downloaded['format_id'], '137+141')
280 self.assertEqual(downloaded['ext'], 'mp4')
282 info_dict = _make_result(list(formats_order), extractor='youtube')
283 ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
285 yie._sort_formats(info_dict['formats'])
286 ydl.process_ie_result(info_dict)
287 downloaded = ydl.downloaded_info_dicts[0]
288 self.assertEqual(downloaded['format_id'], '38')
290 info_dict = _make_result(list(formats_order), extractor='youtube')
291 ydl = YDL({'format': 'bestvideo/best,bestaudio'})
293 yie._sort_formats(info_dict['formats'])
294 ydl.process_ie_result(info_dict)
295 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
296 self.assertEqual(downloaded_ids, ['137', '141'])
298 info_dict = _make_result(list(formats_order), extractor='youtube')
299 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
301 yie._sort_formats(info_dict['formats'])
302 ydl.process_ie_result(info_dict)
303 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
304 self.assertEqual(downloaded_ids, ['137+141', '248+141'])
306 info_dict = _make_result(list(formats_order), extractor='youtube')
307 ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])[height<=720]+bestaudio'})
309 yie._sort_formats(info_dict['formats'])
310 ydl.process_ie_result(info_dict)
311 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
312 self.assertEqual(downloaded_ids, ['136+141', '247+141'])
314 info_dict = _make_result(list(formats_order), extractor='youtube')
315 ydl = YDL({'format': '(bestvideo[ext=none]/bestvideo[ext=webm])+bestaudio'})
317 yie._sort_formats(info_dict['formats'])
318 ydl.process_ie_result(info_dict)
319 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
320 self.assertEqual(downloaded_ids, ['248+141'])
322 for f1, f2 in zip(formats_order, formats_order[1:]):
323 info_dict = _make_result([f1, f2], extractor='youtube')
324 ydl = YDL({'format': 'best/bestvideo'})
326 yie._sort_formats(info_dict['formats'])
327 ydl.process_ie_result(info_dict)
328 downloaded = ydl.downloaded_info_dicts[0]
329 self.assertEqual(downloaded['format_id'], f1['format_id'])
331 info_dict = _make_result([f2, f1], extractor='youtube')
332 ydl = YDL({'format': 'best/bestvideo'})
334 yie._sort_formats(info_dict['formats'])
335 ydl.process_ie_result(info_dict)
336 downloaded = ydl.downloaded_info_dicts[0]
337 self.assertEqual(downloaded['format_id'], f1['format_id'])
339 def test_audio_only_extractor_format_selection(self):
340 # For extractors with incomplete formats (all formats are audio-only or
341 # video-only) best and worst should fallback to corresponding best/worst
342 # video-only or audio-only formats (as per
343 # https://github.com/rg3/youtube-dl/pull/5556)
345 {'format_id': 'low', 'ext': 'mp3', 'preference': 1, 'vcodec': 'none', 'url': TEST_URL},
346 {'format_id': 'high', 'ext': 'mp3', 'preference': 2, 'vcodec': 'none', 'url': TEST_URL},
348 info_dict = _make_result(formats)
350 ydl = YDL({'format': 'best'})
351 ydl.process_ie_result(info_dict.copy())
352 downloaded = ydl.downloaded_info_dicts[0]
353 self.assertEqual(downloaded['format_id'], 'high')
355 ydl = YDL({'format': 'worst'})
356 ydl.process_ie_result(info_dict.copy())
357 downloaded = ydl.downloaded_info_dicts[0]
358 self.assertEqual(downloaded['format_id'], 'low')
360 def test_format_not_available(self):
362 {'format_id': 'regular', 'ext': 'mp4', 'height': 360, 'url': TEST_URL},
363 {'format_id': 'video', 'ext': 'mp4', 'height': 720, 'acodec': 'none', 'url': TEST_URL},
365 info_dict = _make_result(formats)
367 # This must fail since complete video-audio format does not match filter
368 # and extractor does not provide incomplete only formats (i.e. only
369 # video-only or audio-only).
370 ydl = YDL({'format': 'best[height>360]'})
371 self.assertRaises(ExtractorError, ydl.process_ie_result, info_dict.copy())
373 def test_invalid_format_specs(self):
374 def assert_syntax_error(format_spec):
375 ydl = YDL({'format': format_spec})
376 info_dict = _make_result([{'format_id': 'foo', 'url': TEST_URL}])
377 self.assertRaises(SyntaxError, ydl.process_ie_result, info_dict)
379 assert_syntax_error('bestvideo,,best')
380 assert_syntax_error('+bestaudio')
381 assert_syntax_error('bestvideo+')
382 assert_syntax_error('/')
384 def test_format_filtering(self):
386 {'format_id': 'A', 'filesize': 500, 'width': 1000},
387 {'format_id': 'B', 'filesize': 1000, 'width': 500},
388 {'format_id': 'C', 'filesize': 1000, 'width': 400},
389 {'format_id': 'D', 'filesize': 2000, 'width': 600},
390 {'format_id': 'E', 'filesize': 3000},
392 {'format_id': 'G', 'filesize': 1000000},
395 f['url'] = 'http://_/'
397 info_dict = _make_result(formats)
399 ydl = YDL({'format': 'best[filesize<3000]'})
400 ydl.process_ie_result(info_dict)
401 downloaded = ydl.downloaded_info_dicts[0]
402 self.assertEqual(downloaded['format_id'], 'D')
404 ydl = YDL({'format': 'best[filesize<=3000]'})
405 ydl.process_ie_result(info_dict)
406 downloaded = ydl.downloaded_info_dicts[0]
407 self.assertEqual(downloaded['format_id'], 'E')
409 ydl = YDL({'format': 'best[filesize <= ? 3000]'})
410 ydl.process_ie_result(info_dict)
411 downloaded = ydl.downloaded_info_dicts[0]
412 self.assertEqual(downloaded['format_id'], 'F')
414 ydl = YDL({'format': 'best [filesize = 1000] [width>450]'})
415 ydl.process_ie_result(info_dict)
416 downloaded = ydl.downloaded_info_dicts[0]
417 self.assertEqual(downloaded['format_id'], 'B')
419 ydl = YDL({'format': 'best [filesize = 1000] [width!=450]'})
420 ydl.process_ie_result(info_dict)
421 downloaded = ydl.downloaded_info_dicts[0]
422 self.assertEqual(downloaded['format_id'], 'C')
424 ydl = YDL({'format': '[filesize>?1]'})
425 ydl.process_ie_result(info_dict)
426 downloaded = ydl.downloaded_info_dicts[0]
427 self.assertEqual(downloaded['format_id'], 'G')
429 ydl = YDL({'format': '[filesize<1M]'})
430 ydl.process_ie_result(info_dict)
431 downloaded = ydl.downloaded_info_dicts[0]
432 self.assertEqual(downloaded['format_id'], 'E')
434 ydl = YDL({'format': '[filesize<1MiB]'})
435 ydl.process_ie_result(info_dict)
436 downloaded = ydl.downloaded_info_dicts[0]
437 self.assertEqual(downloaded['format_id'], 'G')
439 ydl = YDL({'format': 'all[width>=400][width<=600]'})
440 ydl.process_ie_result(info_dict)
441 downloaded_ids = [info['format_id'] for info in ydl.downloaded_info_dicts]
442 self.assertEqual(downloaded_ids, ['B', 'C', 'D'])
444 ydl = YDL({'format': 'best[height<40]'})
446 ydl.process_ie_result(info_dict)
447 except ExtractorError:
449 self.assertEqual(ydl.downloaded_info_dicts, [])
452 class TestYoutubeDL(unittest.TestCase):
453 def test_subtitles(self):
454 def s_formats(lang, autocaption=False):
457 'url': 'http://localhost/video.%s.%s' % (lang, ext),
458 '_auto': autocaption,
459 } for ext in ['vtt', 'srt', 'ass']]
460 subtitles = dict((l, s_formats(l)) for l in ['en', 'fr', 'es'])
461 auto_captions = dict((l, s_formats(l, True)) for l in ['it', 'pt', 'es'])
465 'url': 'http://localhost/video.mp4',
466 'subtitles': subtitles,
467 'automatic_captions': auto_captions,
471 def get_info(params={}):
472 params.setdefault('simulate', True)
474 ydl.report_warning = lambda *args, **kargs: None
475 return ydl.process_video_result(info_dict, download=False)
478 self.assertFalse(result.get('requested_subtitles'))
479 self.assertEqual(result['subtitles'], subtitles)
480 self.assertEqual(result['automatic_captions'], auto_captions)
482 result = get_info({'writesubtitles': True})
483 subs = result['requested_subtitles']
484 self.assertTrue(subs)
485 self.assertEqual(set(subs.keys()), set(['en']))
486 self.assertTrue(subs['en'].get('data') is None)
487 self.assertEqual(subs['en']['ext'], 'ass')
489 result = get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
490 subs = result['requested_subtitles']
491 self.assertEqual(subs['en']['ext'], 'srt')
493 result = get_info({'writesubtitles': True, 'subtitleslangs': ['es', 'fr', 'it']})
494 subs = result['requested_subtitles']
495 self.assertTrue(subs)
496 self.assertEqual(set(subs.keys()), set(['es', 'fr']))
498 result = get_info({'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
499 subs = result['requested_subtitles']
500 self.assertTrue(subs)
501 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
502 self.assertFalse(subs['es']['_auto'])
503 self.assertTrue(subs['pt']['_auto'])
505 result = get_info({'writeautomaticsub': True, 'subtitleslangs': ['es', 'pt']})
506 subs = result['requested_subtitles']
507 self.assertTrue(subs)
508 self.assertEqual(set(subs.keys()), set(['es', 'pt']))
509 self.assertTrue(subs['es']['_auto'])
510 self.assertTrue(subs['pt']['_auto'])
512 def test_add_extra_info(self):
518 'playlist': 'funny videos',
520 YDL.add_extra_info(test_dict, extra_info)
521 self.assertEqual(test_dict['extractor'], 'Foo')
522 self.assertEqual(test_dict['playlist'], 'funny videos')
524 def test_prepare_filename(self):
532 ydl = YoutubeDL({'outtmpl': templ})
533 return ydl.prepare_filename(info)
534 self.assertEqual(fname('%(id)s.%(ext)s'), '1234.mp4')
535 self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
536 # Replace missing fields with 'NA'
537 self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
539 def test_format_note(self):
541 self.assertEqual(ydl._format_note({}), '')
542 assertRegexpMatches(self, ydl._format_note({
545 assertRegexpMatches(self, ydl._format_note({
549 def test_postprocessors(self):
550 filename = 'post-processor-testfile.mp4'
551 audiofile = filename + '.mp3'
553 class SimplePP(PostProcessor):
555 with open(audiofile, 'wt') as f:
557 return [info['filepath']], info
559 def run_pp(params, PP):
560 with open(filename, 'wt') as f:
562 ydl = YoutubeDL(params)
563 ydl.add_post_processor(PP())
564 ydl.post_process(filename, {'filepath': filename})
566 run_pp({'keepvideo': True}, SimplePP)
567 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
568 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
572 run_pp({'keepvideo': False}, SimplePP)
573 self.assertFalse(os.path.exists(filename), '%s exists' % filename)
574 self.assertTrue(os.path.exists(audiofile), '%s doesn\'t exist' % audiofile)
577 class ModifierPP(PostProcessor):
579 with open(info['filepath'], 'wt') as f:
583 run_pp({'keepvideo': False}, ModifierPP)
584 self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
587 def test_match_filter(self):
588 class FilterYDL(YDL):
589 def __init__(self, *args, **kwargs):
590 super(FilterYDL, self).__init__(*args, **kwargs)
591 self.params['simulate'] = True
593 def process_info(self, info_dict):
594 super(YDL, self).process_info(info_dict)
596 def _match_entry(self, info_dict, incomplete):
597 res = super(FilterYDL, self)._match_entry(info_dict, incomplete)
599 self.downloaded_info_dicts.append(info_dict)
608 'filesize': 10 * 1024,
610 'uploader': "變態妍字幕版 太妍 тест",
611 'creator': "тест ' 123 ' тест--",
619 'description': 'foo',
620 'filesize': 5 * 1024,
622 'uploader': "тест 123",
624 videos = [first, second]
626 def get_videos(filter_=None):
627 ydl = FilterYDL({'match_filter': filter_})
629 ydl.process_ie_result(v, download=True)
630 return [v['id'] for v in ydl.downloaded_info_dicts]
633 self.assertEqual(res, ['1', '2'])
639 return 'Video id is not 1'
641 self.assertEqual(res, ['1'])
643 f = match_filter_func('duration < 30')
645 self.assertEqual(res, ['2'])
647 f = match_filter_func('description = foo')
649 self.assertEqual(res, ['2'])
651 f = match_filter_func('description =? foo')
653 self.assertEqual(res, ['1', '2'])
655 f = match_filter_func('filesize > 5KiB')
657 self.assertEqual(res, ['1'])
659 f = match_filter_func('playlist_id = 42')
661 self.assertEqual(res, ['1'])
663 f = match_filter_func('uploader = "變態妍字幕版 太妍 тест"')
665 self.assertEqual(res, ['1'])
667 f = match_filter_func('uploader != "變態妍字幕版 太妍 тест"')
669 self.assertEqual(res, ['2'])
671 f = match_filter_func('creator = "тест \' 123 \' тест--"')
673 self.assertEqual(res, ['1'])
675 f = match_filter_func("creator = 'тест \\' 123 \\' тест--'")
677 self.assertEqual(res, ['1'])
679 f = match_filter_func(r"creator = 'тест \' 123 \' тест--' & duration > 30")
681 self.assertEqual(res, [])
683 def test_playlist_items_selection(self):
686 'title': compat_str(i),
688 } for i in range(1, 5)]
693 'extractor': 'test:playlist',
694 'extractor_key': 'test:playlist',
695 'webpage_url': 'http://example.com',
700 # make a copy because the dictionary can be modified
701 ydl.process_ie_result(playlist.copy())
702 return [int(v['id']) for v in ydl.downloaded_info_dicts]
705 self.assertEqual(result, [1, 2, 3, 4])
707 result = get_ids({'playlistend': 10})
708 self.assertEqual(result, [1, 2, 3, 4])
710 result = get_ids({'playlistend': 2})
711 self.assertEqual(result, [1, 2])
713 result = get_ids({'playliststart': 10})
714 self.assertEqual(result, [])
716 result = get_ids({'playliststart': 2})
717 self.assertEqual(result, [2, 3, 4])
719 result = get_ids({'playlist_items': '2-4'})
720 self.assertEqual(result, [2, 3, 4])
722 result = get_ids({'playlist_items': '2,4'})
723 self.assertEqual(result, [2, 4])
725 result = get_ids({'playlist_items': '10'})
726 self.assertEqual(result, [])
728 def test_urlopen_no_file_protocol(self):
729 # see https://github.com/rg3/youtube-dl/issues/8227
731 self.assertRaises(compat_urllib_error.URLError, ydl.urlopen, 'file:///etc/passwd')
733 def test_do_not_override_ie_key_in_url_transparent(self):
736 class Foo1IE(InfoExtractor):
737 _VALID_URL = r'foo1:'
739 def _real_extract(self, url):
741 '_type': 'url_transparent',
746 class Foo2IE(InfoExtractor):
747 _VALID_URL = r'foo2:'
749 def _real_extract(self, url):
756 class Foo3IE(InfoExtractor):
757 _VALID_URL = r'foo3:'
759 def _real_extract(self, url):
760 return _make_result([{'url': TEST_URL}])
762 ydl.add_info_extractor(Foo1IE(ydl))
763 ydl.add_info_extractor(Foo2IE(ydl))
764 ydl.add_info_extractor(Foo3IE(ydl))
765 ydl.extract_info('foo1:')
766 downloaded = ydl.downloaded_info_dicts[0]
767 self.assertEqual(downloaded['url'], TEST_URL)
770 if __name__ == '__main__':