diff options
author | pukkandan <pukkandan.ytdlp@gmail.com> | 2021-06-08 20:11:00 +0530 |
---|---|---|
committer | pukkandan <pukkandan.ytdlp@gmail.com> | 2021-06-08 20:11:00 +0530 |
commit | 76a264ac9e7675bf67be844b9a9d0288ac7427a9 (patch) | |
tree | d6386564eb1c39ff250598ded0be83a16ee2a26c /yt_dlp | |
parent | 324ad82006748ebfe4b3fa8f67f160eb000ee6eb (diff) | |
download | hypervideo-pre-76a264ac9e7675bf67be844b9a9d0288ac7427a9.tar.lz hypervideo-pre-76a264ac9e7675bf67be844b9a9d0288ac7427a9.tar.xz hypervideo-pre-76a264ac9e7675bf67be844b9a9d0288ac7427a9.zip |
Make outtmpl more robust and catch errors early
Diffstat (limited to 'yt_dlp')
-rw-r--r-- | yt_dlp/YoutubeDL.py | 29 | ||||
-rw-r--r-- | yt_dlp/__init__.py | 11 |
2 files changed, 36 insertions, 4 deletions
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index 1643649fb..ad96cebcd 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -813,6 +813,19 @@ class YoutubeDL(object): 'Put from __future__ import unicode_literals at the top of your code file or consider switching to Python 3.x.') return outtmpl_dict + @staticmethod + def validate_outtmpl(tmpl): + ''' @return None or Exception object ''' + try: + re.sub( + STR_FORMAT_RE.format(''), + lambda mobj: ('%' if not mobj.group('has_key') else '') + mobj.group(0), + tmpl + ) % collections.defaultdict(int) + return None + except ValueError as err: + return err + def prepare_outtmpl(self, outtmpl, info_dict, sanitize=None): """ Make the template and info_dict suitable for substitution (outtmpl % info_dict)""" info_dict = dict(info_dict) @@ -852,10 +865,12 @@ class YoutubeDL(object): } tmpl_dict = {} + get_key = lambda k: traverse_obj( + info_dict, k.split('.'), is_user_input=True, traverse_string=True) + def get_value(mdict): # Object traversal - fields = mdict['fields'].split('.') - value = traverse_obj(info_dict, fields) + value = get_key(mdict['fields']) # Negative if mdict['negate']: value = float_or_none(value) @@ -872,7 +887,7 @@ class YoutubeDL(object): item, multiplier = (item[1:], -1) if item[0] == '-' else (item, 1) offset = float_or_none(item) if offset is None: - offset = float_or_none(traverse_obj(info_dict, item.split('.'))) + offset = float_or_none(get_key(item)) try: value = operator(value, multiplier * offset) except (TypeError, ZeroDivisionError): @@ -906,7 +921,13 @@ class YoutubeDL(object): value = default if value is None else value key += '\0%s' % fmt - if fmt[-1] not in 'crs': # numeric + if fmt == 'c': + value = compat_str(value) + if value is None: + value, fmt = default, 's' + else: + value = value[0] + elif fmt[-1] not in 'rs': # numeric value = float_or_none(value) if value is None: value, fmt = default, 's' diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py index 45a29d3c7..6d6b0dd66 100644 --- a/yt_dlp/__init__.py +++ b/yt_dlp/__init__.py @@ -24,6 +24,7 @@ from .utils import ( DateRange, decodeOption, DownloadError, + error_to_compat_str, ExistingVideoReached, expand_path, match_filter_func, @@ -307,6 +308,16 @@ def _real_main(argv=None): else: _unused_compat_opt('filename') + def validate_outtmpl(tmpl, msg): + err = YoutubeDL.validate_outtmpl(tmpl) + if err: + parser.error('invalid %s %r: %s' % (msg, tmpl, error_to_compat_str(err))) + + for k, tmpl in opts.outtmpl.items(): + validate_outtmpl(tmpl, '%s output template' % k) + for tmpl in opts.forceprint: + validate_outtmpl(tmpl, 'print template') + if opts.extractaudio and not opts.keepvideo and opts.format is None: opts.format = 'bestaudio/best' |