[utils] Add orderedSet_from_options
This commit is contained in:
parent
13db4e7b9e
commit
5314b52192
3 changed files with 47 additions and 45 deletions
|
@ -115,6 +115,7 @@ from .utils import (
|
||||||
network_exceptions,
|
network_exceptions,
|
||||||
number_of_digits,
|
number_of_digits,
|
||||||
orderedSet,
|
orderedSet,
|
||||||
|
orderedSet_from_options,
|
||||||
parse_filesize,
|
parse_filesize,
|
||||||
preferredencoding,
|
preferredencoding,
|
||||||
prepend_extension,
|
prepend_extension,
|
||||||
|
@ -2737,27 +2738,11 @@ class YoutubeDL:
|
||||||
if self.params.get('allsubtitles', False):
|
if self.params.get('allsubtitles', False):
|
||||||
requested_langs = all_sub_langs
|
requested_langs = all_sub_langs
|
||||||
elif self.params.get('subtitleslangs', False):
|
elif self.params.get('subtitleslangs', False):
|
||||||
# A list is used so that the order of languages will be the same as
|
try:
|
||||||
# given in subtitleslangs. See https://github.com/yt-dlp/yt-dlp/issues/1041
|
requested_langs = orderedSet_from_options(
|
||||||
requested_langs = []
|
self.params.get('subtitleslangs'), {'all': all_sub_langs}, use_regex=True)
|
||||||
for lang_re in self.params.get('subtitleslangs'):
|
except re.error as e:
|
||||||
discard = lang_re[0] == '-'
|
raise ValueError(f'Wrong regex for subtitlelangs: {e.pattern}')
|
||||||
if discard:
|
|
||||||
lang_re = lang_re[1:]
|
|
||||||
if lang_re == 'all':
|
|
||||||
if discard:
|
|
||||||
requested_langs = []
|
|
||||||
else:
|
|
||||||
requested_langs.extend(all_sub_langs)
|
|
||||||
continue
|
|
||||||
current_langs = filter(re.compile(lang_re + '$').match, all_sub_langs)
|
|
||||||
if discard:
|
|
||||||
for lang in current_langs:
|
|
||||||
while lang in requested_langs:
|
|
||||||
requested_langs.remove(lang)
|
|
||||||
else:
|
|
||||||
requested_langs.extend(current_langs)
|
|
||||||
requested_langs = orderedSet(requested_langs)
|
|
||||||
elif normal_sub_langs:
|
elif normal_sub_langs:
|
||||||
requested_langs = ['en'] if 'en' in normal_sub_langs else normal_sub_langs[:1]
|
requested_langs = ['en'] if 'en' in normal_sub_langs else normal_sub_langs[:1]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -29,6 +29,7 @@ from .utils import (
|
||||||
format_field,
|
format_field,
|
||||||
get_executable_path,
|
get_executable_path,
|
||||||
join_nonempty,
|
join_nonempty,
|
||||||
|
orderedSet_from_options,
|
||||||
remove_end,
|
remove_end,
|
||||||
write_string,
|
write_string,
|
||||||
)
|
)
|
||||||
|
@ -232,30 +233,16 @@ def create_parser():
|
||||||
current + value if append is True else value + current)
|
current + value if append is True else value + current)
|
||||||
|
|
||||||
def _set_from_options_callback(
|
def _set_from_options_callback(
|
||||||
option, opt_str, value, parser, delim=',', allowed_values=None, aliases={},
|
option, opt_str, value, parser, allowed_values, delim=',', aliases={},
|
||||||
process=lambda x: x.lower().strip()):
|
process=lambda x: x.lower().strip()):
|
||||||
current = set(getattr(parser.values, option.dest))
|
values = [process(value)] if delim is None else map(process, value.split(delim))
|
||||||
values = [process(value)] if delim is None else list(map(process, value.split(delim)[::-1]))
|
try:
|
||||||
while values:
|
requested = orderedSet_from_options(values, collections.ChainMap(aliases, {'all': allowed_values}),
|
||||||
actual_val = val = values.pop()
|
start=getattr(parser.values, option.dest))
|
||||||
if not val:
|
except ValueError as e:
|
||||||
raise optparse.OptionValueError(f'Invalid {option.metavar} for {opt_str}: {value}')
|
raise optparse.OptionValueError(f'wrong {option.metavar} for {opt_str}: {e.args[0]}')
|
||||||
if val == 'all':
|
|
||||||
current.update(allowed_values)
|
|
||||||
elif val == '-all':
|
|
||||||
current = set()
|
|
||||||
elif val in aliases:
|
|
||||||
values.extend(aliases[val])
|
|
||||||
else:
|
|
||||||
if val[0] == '-':
|
|
||||||
val = val[1:]
|
|
||||||
current.discard(val)
|
|
||||||
else:
|
|
||||||
current.update([val])
|
|
||||||
if allowed_values is not None and val not in allowed_values:
|
|
||||||
raise optparse.OptionValueError(f'wrong {option.metavar} for {opt_str}: {actual_val}')
|
|
||||||
|
|
||||||
setattr(parser.values, option.dest, current)
|
setattr(parser.values, option.dest, set(requested))
|
||||||
|
|
||||||
def _dict_from_options_callback(
|
def _dict_from_options_callback(
|
||||||
option, opt_str, value, parser,
|
option, opt_str, value, parser,
|
||||||
|
@ -447,8 +434,8 @@ def create_parser():
|
||||||
'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-attach-info-json', 'embed-metadata',
|
'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-attach-info-json', 'embed-metadata',
|
||||||
'embed-thumbnail-atomicparsley', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', 'no-certifi',
|
'embed-thumbnail-atomicparsley', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', 'no-certifi',
|
||||||
}, 'aliases': {
|
}, 'aliases': {
|
||||||
'youtube-dl': ['-multistreams', 'all'],
|
'youtube-dl': ['all', '-multistreams'],
|
||||||
'youtube-dlc': ['-no-youtube-channel-redirect', '-no-live-chat', 'all'],
|
'youtube-dlc': ['all', '-no-youtube-channel-redirect', '-no-live-chat'],
|
||||||
}
|
}
|
||||||
}, help=(
|
}, help=(
|
||||||
'Options that can help keep compatibility with youtube-dl or youtube-dlc '
|
'Options that can help keep compatibility with youtube-dl or youtube-dlc '
|
||||||
|
|
|
@ -5785,6 +5785,36 @@ def truncate_string(s, left, right=0):
|
||||||
return f'{s[:left-3]}...{s[-right:]}'
|
return f'{s[:left-3]}...{s[-right:]}'
|
||||||
|
|
||||||
|
|
||||||
|
def orderedSet_from_options(options, alias_dict, *, use_regex=False, start=None):
|
||||||
|
assert 'all' in alias_dict, '"all" alias is required'
|
||||||
|
requested = list(start or [])
|
||||||
|
for val in options:
|
||||||
|
discard = val.startswith('-')
|
||||||
|
if discard:
|
||||||
|
val = val[1:]
|
||||||
|
|
||||||
|
if val in alias_dict:
|
||||||
|
val = alias_dict[val] if not discard else [
|
||||||
|
i[1:] if i.startswith('-') else f'-{i}' for i in alias_dict[val]]
|
||||||
|
# NB: Do not allow regex in aliases for performance
|
||||||
|
requested = orderedSet_from_options(val, alias_dict, start=requested)
|
||||||
|
continue
|
||||||
|
|
||||||
|
current = (filter(re.compile(val, re.I).fullmatch, alias_dict['all']) if use_regex
|
||||||
|
else [val] if val in alias_dict['all'] else None)
|
||||||
|
if current is None:
|
||||||
|
raise ValueError(val)
|
||||||
|
|
||||||
|
if discard:
|
||||||
|
for item in current:
|
||||||
|
while item in requested:
|
||||||
|
requested.remove(item)
|
||||||
|
else:
|
||||||
|
requested.extend(current)
|
||||||
|
|
||||||
|
return orderedSet(requested)
|
||||||
|
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
has_certifi = bool(certifi)
|
has_certifi = bool(certifi)
|
||||||
has_websockets = bool(websockets)
|
has_websockets = bool(websockets)
|
||||||
|
|
Loading…
Reference in a new issue