mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-07-09 06:48:30 +00:00
Complete implementation
This commit is contained in:
parent
9eb3124219
commit
8c01f4a92d
@ -70,6 +70,7 @@
|
|||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
DEFAULT_OUTTMPL,
|
DEFAULT_OUTTMPL,
|
||||||
|
DEFAULT_MAX_FILE_NAME,
|
||||||
IDENTITY,
|
IDENTITY,
|
||||||
LINK_TEMPLATES,
|
LINK_TEMPLATES,
|
||||||
MEDIA_EXTENSIONS,
|
MEDIA_EXTENSIONS,
|
||||||
@ -266,6 +267,8 @@ class YoutubeDL:
|
|||||||
outtmpl_na_placeholder: Placeholder for unavailable meta fields.
|
outtmpl_na_placeholder: Placeholder for unavailable meta fields.
|
||||||
restrictfilenames: Do not allow "&" and spaces in file names
|
restrictfilenames: Do not allow "&" and spaces in file names
|
||||||
trim_file_name: Limit length of filename (extension excluded)
|
trim_file_name: Limit length of filename (extension excluded)
|
||||||
|
max_file_name: Limit length of filename (extension included)
|
||||||
|
filesystem_encoding: Encoding to use when calculating filename length in bytes
|
||||||
windowsfilenames: True: Force filenames to be Windows compatible
|
windowsfilenames: True: Force filenames to be Windows compatible
|
||||||
False: Sanitize filenames only minimally
|
False: Sanitize filenames only minimally
|
||||||
This option has no effect when running on Windows
|
This option has no effect when running on Windows
|
||||||
@ -1424,7 +1427,10 @@ def create_key(outer_mobj):
|
|||||||
return EXTERNAL_FORMAT_RE.sub(create_key, outtmpl), TMPL_DICT
|
return EXTERNAL_FORMAT_RE.sub(create_key, outtmpl), TMPL_DICT
|
||||||
|
|
||||||
def evaluate_outtmpl(self, outtmpl, info_dict, *args, **kwargs):
|
def evaluate_outtmpl(self, outtmpl, info_dict, *args, **kwargs):
|
||||||
print(outtmpl)
|
outtmpl, info_dict = self.prepare_outtmpl(outtmpl, info_dict, *args, **kwargs)
|
||||||
|
return self.escape_outtmpl(outtmpl) % info_dict
|
||||||
|
|
||||||
|
def evaluate_outtmpl_for_filename(self, outtmpl, info_dict, *args, **kwargs):
|
||||||
outtmpl, info_dict = self.prepare_outtmpl(outtmpl, info_dict, *args, **kwargs)
|
outtmpl, info_dict = self.prepare_outtmpl(outtmpl, info_dict, *args, **kwargs)
|
||||||
ext_suffix = '.%(ext\x00s)s' # not sure why this has null char
|
ext_suffix = '.%(ext\x00s)s' # not sure why this has null char
|
||||||
suffix = ''
|
suffix = ''
|
||||||
@ -1433,10 +1439,44 @@ def evaluate_outtmpl(self, outtmpl, info_dict, *args, **kwargs):
|
|||||||
suffix = ext_suffix % info_dict
|
suffix = ext_suffix % info_dict
|
||||||
outtmpl = self.escape_outtmpl(outtmpl)
|
outtmpl = self.escape_outtmpl(outtmpl)
|
||||||
filename = outtmpl % info_dict
|
filename = outtmpl % info_dict
|
||||||
encoding = sys.getfilesystemencoding() # make option to override
|
|
||||||
filename = filename.encode(encoding)
|
def parse_max_file_name(max_file_name: str):
|
||||||
filename = filename[:255 - len('.flac.part')] # make option to override
|
try:
|
||||||
filename = filename.decode(encoding, 'ignore')
|
max_length = int(max_file_name[:-1])
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError('Invalid --max-filename-length specified')
|
||||||
|
|
||||||
|
if max_file_name[-1].lower() == 'c':
|
||||||
|
return 'c', max_length
|
||||||
|
elif max_file_name[-1].lower() == 'b':
|
||||||
|
return 'b', max_length
|
||||||
|
else:
|
||||||
|
raise ValueError("--max-filename-length must end with 'b' or 'c'")
|
||||||
|
|
||||||
|
max_file_name = self.params.get('max_file_name', DEFAULT_MAX_FILE_NAME)
|
||||||
|
mode, max_file_name = parse_max_file_name(max_file_name)
|
||||||
|
encoding = self.params.get('filesystem_encoding', sys.getfilesystemencoding())
|
||||||
|
|
||||||
|
# extension may be replaced later
|
||||||
|
if mode == 'b':
|
||||||
|
max_suffix_len = len('.annotations.xml'.encode(encoding))
|
||||||
|
else:
|
||||||
|
max_suffix_len = len('.annotations.xml')
|
||||||
|
|
||||||
|
def trim_filename(name: str, length: int):
|
||||||
|
if length < 1:
|
||||||
|
raise ValueError('Cannot trim filename to such short length')
|
||||||
|
if mode == 'b':
|
||||||
|
name = name.encode(encoding)
|
||||||
|
name = name[:length]
|
||||||
|
return name.decode(encoding, 'ignore')
|
||||||
|
else:
|
||||||
|
return name[:length]
|
||||||
|
|
||||||
|
# only trim last component of path - assume the directories are valid names
|
||||||
|
head, tail = os.path.split(filename)
|
||||||
|
tail = trim_filename(tail, max_file_name - max_suffix_len)
|
||||||
|
filename = os.path.join(head, tail)
|
||||||
return filename + suffix
|
return filename + suffix
|
||||||
|
|
||||||
@_catch_unsafe_extension_error
|
@_catch_unsafe_extension_error
|
||||||
@ -1446,8 +1486,7 @@ def _prepare_filename(self, info_dict, *, outtmpl=None, tmpl_type=None):
|
|||||||
outtmpl = self.params['outtmpl'].get(tmpl_type or 'default', self.params['outtmpl']['default'])
|
outtmpl = self.params['outtmpl'].get(tmpl_type or 'default', self.params['outtmpl']['default'])
|
||||||
try:
|
try:
|
||||||
outtmpl = self._outtmpl_expandpath(outtmpl)
|
outtmpl = self._outtmpl_expandpath(outtmpl)
|
||||||
filename = self.evaluate_outtmpl(outtmpl, info_dict, True)
|
filename = self.evaluate_outtmpl_for_filename(outtmpl, info_dict, True)
|
||||||
print(filename)
|
|
||||||
if not filename:
|
if not filename:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -886,6 +886,8 @@ def parse_options(argv=None):
|
|||||||
'max_downloads': opts.max_downloads,
|
'max_downloads': opts.max_downloads,
|
||||||
'prefer_free_formats': opts.prefer_free_formats,
|
'prefer_free_formats': opts.prefer_free_formats,
|
||||||
'trim_file_name': opts.trim_file_name,
|
'trim_file_name': opts.trim_file_name,
|
||||||
|
'max_file_name': opts.max_file_name,
|
||||||
|
'filesystem_encoding': opts.filesystem_encoding,
|
||||||
'verbose': opts.verbose,
|
'verbose': opts.verbose,
|
||||||
'dump_intermediate_pages': opts.dump_intermediate_pages,
|
'dump_intermediate_pages': opts.dump_intermediate_pages,
|
||||||
'write_pages': opts.write_pages,
|
'write_pages': opts.write_pages,
|
||||||
|
@ -1380,6 +1380,14 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs):
|
|||||||
'--trim-filenames', '--trim-file-names', metavar='LENGTH',
|
'--trim-filenames', '--trim-file-names', metavar='LENGTH',
|
||||||
dest='trim_file_name', default=0, type=int,
|
dest='trim_file_name', default=0, type=int,
|
||||||
help='Limit the filename length (excluding extension) to the specified number of characters')
|
help='Limit the filename length (excluding extension) to the specified number of characters')
|
||||||
|
filesystem.add_option(
|
||||||
|
'--max-filename-length', metavar='LENGTH',
|
||||||
|
dest='max_file_name',
|
||||||
|
help='Limit the filename length (including extension) to the specified number of characters or bytes')
|
||||||
|
filesystem.add_option(
|
||||||
|
'--filesystem-encoding', metavar='ENCODING',
|
||||||
|
dest='filesystem_encoding',
|
||||||
|
help='Override filesystem encoding used when calculating filename length in bytes')
|
||||||
filesystem.add_option(
|
filesystem.add_option(
|
||||||
'-w', '--no-overwrites',
|
'-w', '--no-overwrites',
|
||||||
action='store_false', dest='overwrites', default=None,
|
action='store_false', dest='overwrites', default=None,
|
||||||
|
@ -2852,6 +2852,12 @@ def q(qid):
|
|||||||
'pl_infojson': 'info.json',
|
'pl_infojson': 'info.json',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# https://en.m.wikipedia.org/wiki/Comparison_of_file_systems#Limits
|
||||||
|
if platform.system() in ('Darwin', 'Windows'):
|
||||||
|
DEFAULT_MAX_FILE_NAME = '255c'
|
||||||
|
else:
|
||||||
|
DEFAULT_MAX_FILE_NAME = '255b'
|
||||||
|
|
||||||
# As of [1] format syntax is:
|
# As of [1] format syntax is:
|
||||||
# %[mapping_key][conversion_flags][minimum_width][.precision][length_modifier]type
|
# %[mapping_key][conversion_flags][minimum_width][.precision][length_modifier]type
|
||||||
# 1. https://docs.python.org/2/library/stdtypes.html#string-formatting
|
# 1. https://docs.python.org/2/library/stdtypes.html#string-formatting
|
||||||
|
Loading…
Reference in New Issue
Block a user