[YoutubeDL] format spec: Fix handling of '+' with '/'

'bestvideo+bestaudio/best' was incorrectly interpreted as 'bestvideo+(bestaudio/best)', so it would fail if 'bestaudio' doesn't exist instead of falling back to 'best'.
This commit is contained in:
Jaime Marquínez Ferrándiz 2015-06-30 19:45:42 +02:00
parent 0130afb76e
commit cf2ac6df68
2 changed files with 23 additions and 10 deletions

View File

@ -245,6 +245,14 @@ def format_info(f_id):
self.assertEqual(downloaded['format_id'], '137+141') self.assertEqual(downloaded['format_id'], '137+141')
self.assertEqual(downloaded['ext'], 'mp4') self.assertEqual(downloaded['ext'], 'mp4')
info_dict = _make_result(list(formats_order), extractor='youtube')
ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
yie = YoutubeIE(ydl)
yie._sort_formats(info_dict['formats'])
ydl.process_ie_result(info_dict)
downloaded = ydl.downloaded_info_dicts[0]
self.assertEqual(downloaded['format_id'], '38')
info_dict = _make_result(list(formats_order), extractor='youtube') info_dict = _make_result(list(formats_order), extractor='youtube')
ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'}) ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
yie = YoutubeIE(ydl) yie = YoutubeIE(ydl)

View File

@ -931,7 +931,7 @@ def _parse_filter(tokens):
else: else:
filter_parts.append(string) filter_parts.append(string)
def _parse_format_selection(tokens, endwith=[]): def _parse_format_selection(tokens, inside_merge=False, inside_choice=False, inside_group=False):
selectors = [] selectors = []
current_selector = None current_selector = None
for type, string, start, _, _ in tokens: for type, string, start, _, _ in tokens:
@ -941,18 +941,23 @@ def _parse_format_selection(tokens, endwith=[]):
elif type in [tokenize.NAME, tokenize.NUMBER]: elif type in [tokenize.NAME, tokenize.NUMBER]:
current_selector = FormatSelector(SINGLE, string, []) current_selector = FormatSelector(SINGLE, string, [])
elif type == tokenize.OP: elif type == tokenize.OP:
if string in endwith: if string == ')':
break if not inside_group:
elif string == ')':
# ')' will be handled by the parentheses group # ')' will be handled by the parentheses group
tokens.restore_last_token() tokens.restore_last_token()
break break
if string == ',': elif inside_merge and string in ['/', ',']:
tokens.restore_last_token()
break
elif inside_choice and string == ',':
tokens.restore_last_token()
break
elif string == ',':
selectors.append(current_selector) selectors.append(current_selector)
current_selector = None current_selector = None
elif string == '/': elif string == '/':
first_choice = current_selector first_choice = current_selector
second_choice = _parse_format_selection(tokens, [',']) second_choice = _parse_format_selection(tokens, inside_choice=True)
current_selector = None current_selector = None
selectors.append(FormatSelector(PICKFIRST, (first_choice, second_choice), [])) selectors.append(FormatSelector(PICKFIRST, (first_choice, second_choice), []))
elif string == '[': elif string == '[':
@ -963,12 +968,12 @@ def _parse_format_selection(tokens, endwith=[]):
elif string == '(': elif string == '(':
if current_selector: if current_selector:
raise syntax_error('Unexpected "("', start) raise syntax_error('Unexpected "("', start)
current_selector = FormatSelector(GROUP, _parse_format_selection(tokens, [')']), []) group = _parse_format_selection(tokens, inside_group=True)
current_selector = FormatSelector(GROUP, group, [])
elif string == '+': elif string == '+':
video_selector = current_selector video_selector = current_selector
audio_selector = _parse_format_selection(tokens, [',']) audio_selector = _parse_format_selection(tokens, inside_merge=True)
current_selector = None current_selector = FormatSelector(MERGE, (video_selector, audio_selector), [])
selectors.append(FormatSelector(MERGE, (video_selector, audio_selector), []))
else: else:
raise syntax_error('Operator not recognized: "{0}"'.format(string), start) raise syntax_error('Operator not recognized: "{0}"'.format(string), start)
elif type == tokenize.ENDMARKER: elif type == tokenize.ENDMARKER: