mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-06-27 17:08:32 +00:00
Merge 134f604982
into 73bf102116
This commit is contained in:
commit
b5b397f110
@ -2,6 +2,7 @@
|
||||
|
||||
# Allow direct execution
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
@ -724,6 +725,7 @@ def test_add_extra_info(self):
|
||||
'title3': 'foo/bar\\test',
|
||||
'title4': 'foo "bar" test',
|
||||
'title5': 'áéí 𝐀',
|
||||
'title6': 'あ' * 10,
|
||||
'timestamp': 1618488000,
|
||||
'duration': 100000,
|
||||
'playlist_index': 1,
|
||||
@ -739,12 +741,14 @@ def test_add_extra_info(self):
|
||||
|
||||
def test_prepare_outtmpl_and_filename(self):
|
||||
def test(tmpl, expected, *, info=None, **params):
|
||||
if 'trim_file_name' not in params:
|
||||
params['trim_file_name'] = 'none' # disable trimming
|
||||
params['outtmpl'] = tmpl
|
||||
ydl = FakeYDL(params)
|
||||
ydl._num_downloads = 1
|
||||
self.assertEqual(ydl.validate_outtmpl(tmpl), None)
|
||||
|
||||
out = ydl.evaluate_outtmpl(tmpl, info or self.outtmpl_info)
|
||||
out = ydl.evaluate_outtmpl(tmpl, info or self.outtmpl_info, trim_filename=True)
|
||||
fname = ydl.prepare_filename(info or self.outtmpl_info)
|
||||
|
||||
if not isinstance(expected, (list, tuple)):
|
||||
@ -951,6 +955,20 @@ def gen():
|
||||
test('%(title3)s', ('foo/bar\\test', 'foo⧸bar⧹test'))
|
||||
test('folder/%(title3)s', ('folder/foo/bar\\test', f'folder{os.path.sep}foo⧸bar⧹test'))
|
||||
|
||||
# --trim-filenames
|
||||
test('%(title6)s.%(ext)s', 'あ' * 10 + '.mp4')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 3 + '.mp4', trim_file_name='3c')
|
||||
if sys.getfilesystemencoding() == 'utf-8' and platform.system() != 'Windows':
|
||||
test('%(title6)s.%(ext)s', 'あ' * 3 + '.mp4', trim_file_name='9b')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 3 + '.mp4', trim_file_name='10b')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 3 + '.mp4', trim_file_name='11b')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 4 + '.mp4', trim_file_name='12b')
|
||||
elif platform.system() == 'Windows':
|
||||
test('%(title6)s.%(ext)s', 'あ' * 4 + '.mp4', trim_file_name='8b')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 4 + '.mp4', trim_file_name='9b')
|
||||
test('%(title6)s.%(ext)s', 'あ' * 5 + '.mp4', trim_file_name='10b')
|
||||
test('folder/%(title6)s.%(ext)s', f'fol{os.path.sep}あああ.mp4', trim_file_name='3c')
|
||||
|
||||
def test_format_note(self):
|
||||
ydl = YoutubeDL()
|
||||
self.assertEqual(ydl._format_note({}), '')
|
||||
|
@ -12,6 +12,8 @@
|
||||
import locale
|
||||
import operator
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
@ -1451,9 +1453,42 @@ def create_key(outer_mobj):
|
||||
|
||||
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, trim_filename=False, **kwargs):
|
||||
outtmpl, info_dict = self.prepare_outtmpl(outtmpl, info_dict, *args, **kwargs)
|
||||
return self.escape_outtmpl(outtmpl) % info_dict
|
||||
if not trim_filename:
|
||||
return self.escape_outtmpl(outtmpl) % info_dict
|
||||
|
||||
ext_suffix = '.%(ext\0s)s'
|
||||
suffix = ''
|
||||
if outtmpl.endswith(ext_suffix):
|
||||
outtmpl = outtmpl[:-len(ext_suffix)]
|
||||
suffix = ext_suffix % info_dict
|
||||
outtmpl = self.escape_outtmpl(outtmpl)
|
||||
filename = outtmpl % info_dict
|
||||
|
||||
def parse_trim_file_name(trim_file_name):
|
||||
if trim_file_name is None or trim_file_name == 'none':
|
||||
return 0, None
|
||||
mobj = re.match(r'(?:(?P<length>\d+)(?P<mode>b|c)?|none)', trim_file_name)
|
||||
return int(mobj.group('length')), mobj.group('mode') or 'c'
|
||||
|
||||
max_file_name, mode = parse_trim_file_name(self.params.get('trim_file_name'))
|
||||
if max_file_name == 0:
|
||||
# no maximum
|
||||
return filename + suffix
|
||||
|
||||
encoding = sys.getfilesystemencoding() if platform.system() != 'Windows' else 'utf-16-le'
|
||||
|
||||
def trim_filename(name: str):
|
||||
if mode == 'b':
|
||||
name = name.encode(encoding)
|
||||
name = name[:max_file_name]
|
||||
return name.decode(encoding, 'ignore')
|
||||
else:
|
||||
return name[:max_file_name]
|
||||
|
||||
filename = os.path.join(*map(trim_filename, Path(filename).parts or '.'))
|
||||
return filename + suffix
|
||||
|
||||
@_catch_unsafe_extension_error
|
||||
def _prepare_filename(self, info_dict, *, outtmpl=None, tmpl_type=None):
|
||||
@ -1462,7 +1497,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'])
|
||||
try:
|
||||
outtmpl = self._outtmpl_expandpath(outtmpl)
|
||||
filename = self.evaluate_outtmpl(outtmpl, info_dict, True)
|
||||
filename = self.evaluate_outtmpl(outtmpl, info_dict, True, trim_filename=True)
|
||||
if not filename:
|
||||
return None
|
||||
|
||||
@ -1474,13 +1509,6 @@ def _prepare_filename(self, info_dict, *, outtmpl=None, tmpl_type=None):
|
||||
force_ext = OUTTMPL_TYPES[tmpl_type]
|
||||
if force_ext:
|
||||
filename = replace_extension(filename, force_ext, info_dict.get('ext'))
|
||||
|
||||
# https://github.com/blackjack4494/youtube-dlc/issues/85
|
||||
trim_file_name = self.params.get('trim_file_name', False)
|
||||
if trim_file_name:
|
||||
no_ext, *ext = filename.rsplit('.', 2)
|
||||
filename = join_nonempty(no_ext[:trim_file_name], *ext, delim='.')
|
||||
|
||||
return filename
|
||||
except ValueError as err:
|
||||
self.report_error('Error in output template: ' + str(err) + ' (encoding: ' + repr(preferredencoding()) + ')')
|
||||
|
@ -436,6 +436,8 @@ def metadataparser_actions(f):
|
||||
if opts.plugin_dirs is None:
|
||||
opts.plugin_dirs = ['default']
|
||||
|
||||
validate_regex('trim filenames', opts.trim_file_name, r'(?:\d+[bc]?|none)')
|
||||
|
||||
if opts.playlist_items is not None:
|
||||
try:
|
||||
tuple(PlaylistEntries.parse_playlist_items(opts.playlist_items))
|
||||
|
@ -1432,8 +1432,8 @@ def _preset_alias_callback(option, opt_str, value, parser):
|
||||
help='Sanitize filenames only minimally')
|
||||
filesystem.add_option(
|
||||
'--trim-filenames', '--trim-file-names', metavar='LENGTH',
|
||||
dest='trim_file_name', default=0, type=int,
|
||||
help='Limit the filename length (excluding extension) to the specified number of characters')
|
||||
dest='trim_file_name', default='none',
|
||||
help='Limit the filename length (excluding extension) to the specified number of characters or bytes')
|
||||
filesystem.add_option(
|
||||
'-w', '--no-overwrites',
|
||||
action='store_false', dest='overwrites', default=None,
|
||||
|
Loading…
Reference in New Issue
Block a user