diff options
Diffstat (limited to 'youtube_dl/YoutubeDL.py')
| -rwxr-xr-x | youtube_dl/YoutubeDL.py | 39 | 
1 files changed, 37 insertions, 2 deletions
| diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 258e612af..e5b46f87e 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -920,6 +920,7 @@ class YoutubeDL(object):          PICKFIRST = 'PICKFIRST'          MERGE = 'MERGE'          SINGLE = 'SINGLE' +        GROUP = 'GROUP'          FormatSelector = collections.namedtuple('FormatSelector', ['type', 'selector', 'filters'])          def _parse_filter(tokens): @@ -942,6 +943,10 @@ class YoutubeDL(object):                  elif type == tokenize.OP:                      if string in endwith:                          break +                    elif string == ')': +                        # ')' will be handled by the parentheses group +                        tokens.restore_last_token() +                        break                      if string == ',':                          selectors.append(current_selector)                          current_selector = None @@ -955,6 +960,10 @@ class YoutubeDL(object):                              current_selector = FormatSelector(SINGLE, 'best', [])                          format_filter = _parse_filter(tokens)                          current_selector.filters.append(format_filter) +                    elif string == '(': +                        if current_selector: +                            raise syntax_error('Unexpected "("', start) +                        current_selector = FormatSelector(GROUP, _parse_format_selection(tokens, [')']), [])                      elif string == '+':                          video_selector = current_selector                          audio_selector = _parse_format_selection(tokens, [',']) @@ -977,6 +986,8 @@ class YoutubeDL(object):                          for format in f(formats):                              yield format                  return selector_function +            elif selector.type == GROUP: +                selector_function = _build_selector_function(selector.selector)              elif selector.type == PICKFIRST:                  fs = [_build_selector_function(s) for s in selector.selector] @@ -1084,8 +1095,32 @@ class YoutubeDL(object):              return final_selector          stream = io.BytesIO(format_spec.encode('utf-8')) -        tokens = compat_tokenize_tokenize(stream.readline) -        parsed_selector = _parse_format_selection(tokens) +        try: +            tokens = list(compat_tokenize_tokenize(stream.readline)) +        except tokenize.TokenError: +            raise syntax_error('Missing closing/opening brackets or parenthesis', (0, len(format_spec))) + +        class TokenIterator(object): +            def __init__(self, tokens): +                self.tokens = tokens +                self.counter = 0 + +            def __iter__(self): +                return self + +            def __next__(self): +                if self.counter >= len(self.tokens): +                    raise StopIteration() +                value = self.tokens[self.counter] +                self.counter += 1 +                return value + +            next = __next__ + +            def restore_last_token(self): +                self.counter -= 1 + +        parsed_selector = _parse_format_selection(iter(TokenIterator(tokens)))          return _build_selector_function(parsed_selector)      def _calc_headers(self, info_dict): | 
