1
0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2025-06-27 17:08:32 +00:00

* YoutubeDL:validate_destination_filename(): Bugfix of the previous commit when -o contains a directory.

* test_YoutubeDL:test_prepare_outtmpl_and_filename(): Prevents bogus test failure.
This commit is contained in:
Teika Kazura 2025-03-11 18:21:47 +09:00
parent 4f46e5a323
commit 52d0130a37
2 changed files with 31 additions and 17 deletions

View File

@ -742,6 +742,7 @@ def test(tmpl, expected, *, info=None, **params):
params['outtmpl'] = tmpl
ydl = FakeYDL(params)
ydl._num_downloads = 1
ydl.validate_destination_filename = lambda *args: None
self.assertEqual(ydl.validate_outtmpl(tmpl), None)
out = ydl.evaluate_outtmpl(tmpl, info or self.outtmpl_info)

View File

@ -12,6 +12,7 @@
import locale
import operator
import os
import pathlib
import random
import re
import shutil
@ -1481,27 +1482,39 @@ def validate_destination_filename(self, filename):
any error is simply raised, independent of the cause.
Without this, download would fail only after the entire file is downloaded."""
cwd = os.getcwd()
with tempfile.TemporaryDirectory() as d:
os.chdir(d)
try:
with open(filename, 'w') as f:
f.close()
except OSError as e:
if (os.name == 'nt' and e.errno == 206) or (e.errno == errno.ENAMETOOLONG):
# The first condition is for windows,
# and the second for unix-ish systems.
# An improvement idea:
# by default, retry (exec yt-dlp itself) by
# -o "%(id)s.%(ext)s" --write-info-json,
# but respect the directory from --output of the original call.
# An improvement idea:
# by default, retry (exec yt-dlp itself) by
# -o "%(id)s.%(ext)s" --write-info-json,
# but respect the directory from --output of the original call.
with tempfile.TemporaryDirectory() as d:
try:
# To make sure it's confined under tmpdir
tmpfn = '.' + os.sep + os.path.splitdrive(filename)[1]
parentDirStr = os.sep + '..' + os.sep
# This may contain '../' so remove them.
while parentDirStr in tmpfn:
tmpfn = tmpfn.replace(parentDirStr, os.sep)
tmpfn = os.path.join(d, tmpfn)
pathlib.Path(os.path.dirname(tmpfn)).mkdir(parents=True, exist_ok=True)
open(tmpfn, 'w').close()
except OSError as e:
if (os.name == 'nt' and e.errno == 206) or (os.name != 'nt' and e.errno == errno.ENAMETOOLONG):
# For Win, 206 means filename length exceeds MAX_PATH.
e.filename = filename
self.to_screen('''[Notice] The file name to be saved is too long, exceeding the OS limit.
[Notice] Consider options --trim-filenames or -o (--output).''')
raise
finally:
os.chdir(cwd)
elif os.name == 'nt' and e.errno == 22:
# Even when MAX_PATH is disabled, 255 chars is the limit, resulting in 22.
# https://github.com/python/cpython/issues/126929#issuecomment-2483684861
e.filename = filename
self.to_screen(f'''[Notice] Attempt to create file {filename} resulted in Errno 22.
This is often caused e.g. by too long filename or forbidden characters.''')
raise
def prepare_filename(self, info_dict, dir_type='', *, outtmpl=None, warn=False):
"""Generate the output filename"""