Merge branch 'akamai_pv' of https://github.com/remitamine/youtube-dl into remitamine...
[youtube-dl] / test / test_YoutubeDL.py
1 #!/usr/bin/env python
2
3 from __future__ import unicode_literals
4
5 # Allow direct execution
6 import os
7 import sys
8 import unittest
9 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
11 import copy
12
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
20
21 TEST_URL = 'http://localhost/sample.mp4'
22
23
24 class YDL(FakeYDL):
25     def __init__(self, *args, **kwargs):
26         super(YDL, self).__init__(*args, **kwargs)
27         self.downloaded_info_dicts = []
28         self.msgs = []
29
30     def process_info(self, info_dict):
31         self.downloaded_info_dicts.append(info_dict)
32
33     def to_screen(self, msg):
34         self.msgs.append(msg)
35
36
37 def _make_result(formats, **kwargs):
38     res = {
39         'formats': formats,
40         'id': 'testid',
41         'title': 'testttitle',
42         'extractor': 'testex',
43     }
44     res.update(**kwargs)
45     return res
46
47
48 class TestFormatSelection(unittest.TestCase):
49     def test_prefer_free_formats(self):
50         # Same resolution => download webm
51         ydl = YDL()
52         ydl.params['prefer_free_formats'] = True
53         formats = [
54             {'ext': 'webm', 'height': 460, 'url': TEST_URL},
55             {'ext': 'mp4', 'height': 460, 'url': TEST_URL},
56         ]
57         info_dict = _make_result(formats)
58         yie = YoutubeIE(ydl)
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')
63
64         # Different resolution => download best quality (mp4)
65         ydl = YDL()
66         ydl.params['prefer_free_formats'] = True
67         formats = [
68             {'ext': 'webm', 'height': 720, 'url': TEST_URL},
69             {'ext': 'mp4', 'height': 1080, 'url': TEST_URL},
70         ]
71         info_dict['formats'] = formats
72         yie = YoutubeIE(ydl)
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')
77
78         # No prefer_free_formats => prefer mp4 and flv for greater compatibility
79         ydl = YDL()
80         ydl.params['prefer_free_formats'] = False
81         formats = [
82             {'ext': 'webm', 'height': 720, 'url': TEST_URL},
83             {'ext': 'mp4', 'height': 720, 'url': TEST_URL},
84             {'ext': 'flv', 'height': 720, 'url': TEST_URL},
85         ]
86         info_dict['formats'] = formats
87         yie = YoutubeIE(ydl)
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')
92
93         ydl = YDL()
94         ydl.params['prefer_free_formats'] = False
95         formats = [
96             {'ext': 'flv', 'height': 720, 'url': TEST_URL},
97             {'ext': 'webm', 'height': 720, 'url': TEST_URL},
98         ]
99         info_dict['formats'] = formats
100         yie = YoutubeIE(ydl)
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')
105
106     def test_format_selection(self):
107         formats = [
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},
113         ]
114         info_dict = _make_result(formats)
115
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')
120
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')
125
126         ydl = YDL()
127         ydl.process_ie_result(info_dict.copy())
128         downloaded = ydl.downloaded_info_dicts[0]
129         self.assertEqual(downloaded['format_id'], '2')
130
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')
135
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')
140
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')
145
146     def test_format_selection_audio(self):
147         formats = [
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},
152         ]
153         info_dict = _make_result(formats)
154
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')
159
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')
164
165         formats = [
166             {'format_id': 'vid-low', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
167             {'format_id': 'vid-high', 'ext': 'mp4', 'preference': 2, 'url': TEST_URL},
168         ]
169         info_dict = _make_result(formats)
170
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')
175
176     def test_format_selection_audio_exts(self):
177         formats = [
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'},
183         ]
184
185         info_dict = _make_result(formats)
186         ydl = YDL({'format': 'best'})
187         ie = YoutubeIE(ydl)
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')
192
193         ydl = YDL({'format': 'mp3'})
194         ie = YoutubeIE(ydl)
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')
199
200         ydl = YDL({'prefer_free_formats': True})
201         ie = YoutubeIE(ydl)
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')
206
207     def test_format_selection_video(self):
208         formats = [
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},
212         ]
213         info_dict = _make_result(formats)
214
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')
219
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')
224
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')
229
230         formats = [
231             {'format_id': 'vid-vcodec-dot', 'ext': 'mp4', 'preference': 1, 'vcodec': 'avc1.123456', 'acodec': 'none', 'url': TEST_URL},
232         ]
233         info_dict = _make_result(formats)
234
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')
239
240     def test_youtube_format_selection(self):
241         order = [
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',
245             # 3D
246             '85', '84', '102', '83', '101', '82', '100',
247             # Dash video
248             '137', '248', '136', '247', '135', '246',
249             '245', '244', '134', '243', '133', '242', '160',
250             # Dash audio
251             '141', '172', '140', '171', '139',
252         ]
253
254         def format_info(f_id):
255             info = YoutubeIE._formats[f_id].copy()
256
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
261             # this fix
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'
266
267             info['format_id'] = f_id
268             info['url'] = 'url:' + f_id
269             return info
270         formats_order = [format_info(f_id) for f_id in order]
271
272         info_dict = _make_result(list(formats_order), extractor='youtube')
273         ydl = YDL({'format': 'bestvideo+bestaudio'})
274         yie = YoutubeIE(ydl)
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')
280
281         info_dict = _make_result(list(formats_order), extractor='youtube')
282         ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
283         yie = YoutubeIE(ydl)
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')
288
289         info_dict = _make_result(list(formats_order), extractor='youtube')
290         ydl = YDL({'format': 'bestvideo/best,bestaudio'})
291         yie = YoutubeIE(ydl)
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'])
296
297         info_dict = _make_result(list(formats_order), extractor='youtube')
298         ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
299         yie = YoutubeIE(ydl)
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'])
304
305         info_dict = _make_result(list(formats_order), extractor='youtube')
306         ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])[height<=720]+bestaudio'})
307         yie = YoutubeIE(ydl)
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'])
312
313         info_dict = _make_result(list(formats_order), extractor='youtube')
314         ydl = YDL({'format': '(bestvideo[ext=none]/bestvideo[ext=webm])+bestaudio'})
315         yie = YoutubeIE(ydl)
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'])
320
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'})
324             yie = YoutubeIE(ydl)
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'])
329
330             info_dict = _make_result([f2, f1], extractor='youtube')
331             ydl = YDL({'format': 'best/bestvideo'})
332             yie = YoutubeIE(ydl)
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'])
337
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)
343
344         assert_syntax_error('bestvideo,,best')
345         assert_syntax_error('+bestaudio')
346         assert_syntax_error('bestvideo+')
347         assert_syntax_error('/')
348
349     def test_format_filtering(self):
350         formats = [
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},
356             {'format_id': 'F'},
357             {'format_id': 'G', 'filesize': 1000000},
358         ]
359         for f in formats:
360             f['url'] = 'http://_/'
361             f['ext'] = 'unknown'
362         info_dict = _make_result(formats)
363
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')
368
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')
373
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')
378
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')
383
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')
388
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')
393
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')
398
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')
403
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'])
408
409         ydl = YDL({'format': 'best[height<40]'})
410         try:
411             ydl.process_ie_result(info_dict)
412         except ExtractorError:
413             pass
414         self.assertEqual(ydl.downloaded_info_dicts, [])
415
416
417 class TestYoutubeDL(unittest.TestCase):
418     def test_subtitles(self):
419         def s_formats(lang, autocaption=False):
420             return [{
421                 'ext': ext,
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'])
427         info_dict = {
428             'id': 'test',
429             'title': 'Test',
430             'url': 'http://localhost/video.mp4',
431             'subtitles': subtitles,
432             'automatic_captions': auto_captions,
433             'extractor': 'TEST',
434         }
435
436         def get_info(params={}):
437             params.setdefault('simulate', True)
438             ydl = YDL(params)
439             ydl.report_warning = lambda *args, **kargs: None
440             return ydl.process_video_result(info_dict, download=False)
441
442         result = get_info()
443         self.assertFalse(result.get('requested_subtitles'))
444         self.assertEqual(result['subtitles'], subtitles)
445         self.assertEqual(result['automatic_captions'], auto_captions)
446
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')
453
454         result = get_info({'writesubtitles': True, 'subtitlesformat': 'foo/srt'})
455         subs = result['requested_subtitles']
456         self.assertEqual(subs['en']['ext'], 'srt')
457
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']))
462
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'])
469
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'])
476
477     def test_add_extra_info(self):
478         test_dict = {
479             'extractor': 'Foo',
480         }
481         extra_info = {
482             'extractor': 'Bar',
483             'playlist': 'funny videos',
484         }
485         YDL.add_extra_info(test_dict, extra_info)
486         self.assertEqual(test_dict['extractor'], 'Foo')
487         self.assertEqual(test_dict['playlist'], 'funny videos')
488
489     def test_prepare_filename(self):
490         info = {
491             'id': '1234',
492             'ext': 'mp4',
493             'width': None,
494         }
495
496         def fname(templ):
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')
503
504     def test_format_note(self):
505         ydl = YoutubeDL()
506         self.assertEqual(ydl._format_note({}), '')
507         assertRegexpMatches(self, ydl._format_note({
508             'vbr': 10,
509         }), '^\s*10k$')
510         assertRegexpMatches(self, ydl._format_note({
511             'fps': 30,
512         }), '^30fps$')
513
514     def test_postprocessors(self):
515         filename = 'post-processor-testfile.mp4'
516         audiofile = filename + '.mp3'
517
518         class SimplePP(PostProcessor):
519             def run(self, info):
520                 with open(audiofile, 'wt') as f:
521                     f.write('EXAMPLE')
522                 return [info['filepath']], info
523
524         def run_pp(params, PP):
525             with open(filename, 'wt') as f:
526                 f.write('EXAMPLE')
527             ydl = YoutubeDL(params)
528             ydl.add_post_processor(PP())
529             ydl.post_process(filename, {'filepath': filename})
530
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)
534         os.unlink(filename)
535         os.unlink(audiofile)
536
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)
540         os.unlink(audiofile)
541
542         class ModifierPP(PostProcessor):
543             def run(self, info):
544                 with open(info['filepath'], 'wt') as f:
545                     f.write('MODIFIED')
546                 return [], info
547
548         run_pp({'keepvideo': False}, ModifierPP)
549         self.assertTrue(os.path.exists(filename), '%s doesn\'t exist' % filename)
550         os.unlink(filename)
551
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
557
558             def process_info(self, info_dict):
559                 super(YDL, self).process_info(info_dict)
560
561             def _match_entry(self, info_dict, incomplete):
562                 res = super(FilterYDL, self)._match_entry(info_dict, incomplete)
563                 if res is None:
564                     self.downloaded_info_dicts.append(info_dict)
565                 return res
566
567         first = {
568             'id': '1',
569             'url': TEST_URL,
570             'title': 'one',
571             'extractor': 'TEST',
572             'duration': 30,
573             'filesize': 10 * 1024,
574         }
575         second = {
576             'id': '2',
577             'url': TEST_URL,
578             'title': 'two',
579             'extractor': 'TEST',
580             'duration': 10,
581             'description': 'foo',
582             'filesize': 5 * 1024,
583         }
584         videos = [first, second]
585
586         def get_videos(filter_=None):
587             ydl = FilterYDL({'match_filter': filter_})
588             for v in videos:
589                 ydl.process_ie_result(v, download=True)
590             return [v['id'] for v in ydl.downloaded_info_dicts]
591
592         res = get_videos()
593         self.assertEqual(res, ['1', '2'])
594
595         def f(v):
596             if v['id'] == '1':
597                 return None
598             else:
599                 return 'Video id is not 1'
600         res = get_videos(f)
601         self.assertEqual(res, ['1'])
602
603         f = match_filter_func('duration < 30')
604         res = get_videos(f)
605         self.assertEqual(res, ['2'])
606
607         f = match_filter_func('description = foo')
608         res = get_videos(f)
609         self.assertEqual(res, ['2'])
610
611         f = match_filter_func('description =? foo')
612         res = get_videos(f)
613         self.assertEqual(res, ['1', '2'])
614
615         f = match_filter_func('filesize > 5KiB')
616         res = get_videos(f)
617         self.assertEqual(res, ['1'])
618
619     def test_playlist_items_selection(self):
620         entries = [{
621             'id': compat_str(i),
622             'title': compat_str(i),
623             'url': TEST_URL,
624         } for i in range(1, 5)]
625         playlist = {
626             '_type': 'playlist',
627             'id': 'test',
628             'entries': entries,
629             'extractor': 'test:playlist',
630             'extractor_key': 'test:playlist',
631             'webpage_url': 'http://example.com',
632         }
633
634         def get_ids(params):
635             ydl = YDL(params)
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]
639
640         result = get_ids({})
641         self.assertEqual(result, [1, 2, 3, 4])
642
643         result = get_ids({'playlistend': 10})
644         self.assertEqual(result, [1, 2, 3, 4])
645
646         result = get_ids({'playlistend': 2})
647         self.assertEqual(result, [1, 2])
648
649         result = get_ids({'playliststart': 10})
650         self.assertEqual(result, [])
651
652         result = get_ids({'playliststart': 2})
653         self.assertEqual(result, [2, 3, 4])
654
655         result = get_ids({'playlist_items': '2-4'})
656         self.assertEqual(result, [2, 3, 4])
657
658         result = get_ids({'playlist_items': '2,4'})
659         self.assertEqual(result, [2, 4])
660
661         result = get_ids({'playlist_items': '10'})
662         self.assertEqual(result, [])
663
664     def test_urlopen_no_file_protocol(self):
665         # see https://github.com/rg3/youtube-dl/issues/8227
666         ydl = YDL()
667         self.assertRaises(compat_urllib_error.URLError, ydl.urlopen, 'file:///etc/passwd')
668
669     def test_do_not_override_ie_key_in_url_transparent(self):
670         ydl = YDL()
671
672         class Foo1IE(InfoExtractor):
673             _VALID_URL = r'foo1:'
674
675             def _real_extract(self, url):
676                 return {
677                     '_type': 'url_transparent',
678                     'url': 'foo2:',
679                     'ie_key': 'Foo2',
680                 }
681
682         class Foo2IE(InfoExtractor):
683             _VALID_URL = r'foo2:'
684
685             def _real_extract(self, url):
686                 return {
687                     '_type': 'url',
688                     'url': 'foo3:',
689                     'ie_key': 'Foo3',
690                 }
691
692         class Foo3IE(InfoExtractor):
693             _VALID_URL = r'foo3:'
694
695             def _real_extract(self, url):
696                 return _make_result([{'url': TEST_URL}])
697
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)
704
705
706 if __name__ == '__main__':
707     unittest.main()