aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey M․ <dstftw@gmail.com>2016-03-06 03:52:42 +0600
committerSergey M <dstftw@gmail.com>2017-02-23 22:57:53 +0800
commitd0d9ade4860fd44a07f5513d13b66233fdca0e89 (patch)
treecfff31416171320f6b1973ce3da05a9d2b778011
parent28572a1a0b27ba3ccedac5d8d093f925dfb7485f (diff)
[YoutubeDL] Add support for string formatting operations in output template
-rw-r--r--test/test_YoutubeDL.py14
-rwxr-xr-xyoutube_dl/YoutubeDL.py36
2 files changed, 49 insertions, 1 deletions
diff --git a/test/test_YoutubeDL.py b/test/test_YoutubeDL.py
index 2cfcf743a..8491a88bd 100644
--- a/test/test_YoutubeDL.py
+++ b/test/test_YoutubeDL.py
@@ -526,6 +526,7 @@ class TestYoutubeDL(unittest.TestCase):
'id': '1234',
'ext': 'mp4',
'width': None,
+ 'height': 1080,
}
def fname(templ):
@@ -535,6 +536,19 @@ class TestYoutubeDL(unittest.TestCase):
self.assertEqual(fname('%(id)s-%(width)s.%(ext)s'), '1234-NA.mp4')
# Replace missing fields with 'NA'
self.assertEqual(fname('%(uploader_date)s-%(id)s.%(ext)s'), 'NA-1234.mp4')
+ self.assertEqual(fname('%(height)d.%(ext)s'), '1080.mp4')
+ self.assertEqual(fname('%(height)6d.%(ext)s'), ' 1080.mp4')
+ self.assertEqual(fname('%(height)-6d.%(ext)s'), '1080 .mp4')
+ self.assertEqual(fname('%(height)06d.%(ext)s'), '001080.mp4')
+ self.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
+ self.assertEqual(fname('%(height) 06d.%(ext)s'), ' 01080.mp4')
+ self.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
+ self.assertEqual(fname('%(height)0 6d.%(ext)s'), ' 01080.mp4')
+ self.assertEqual(fname('%(height) 0 6d.%(ext)s'), ' 01080.mp4')
+ self.assertEqual(fname('%%(height)06d.%(ext)s'), '%(height)06d.mp4')
+ self.assertEqual(fname('%(width)06d.%(ext)s'), 'NA.mp4')
+ self.assertEqual(fname('%(width)06d.%%(ext)s'), 'NA.%(ext)s')
+ self.assertEqual(fname('%%(width)06d.%(ext)s'), '%(width)06d.mp4')
def test_format_note(self):
ydl = YoutubeDL()
diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py
index 68000dea2..bdaf06e62 100755
--- a/youtube_dl/YoutubeDL.py
+++ b/youtube_dl/YoutubeDL.py
@@ -33,6 +33,7 @@ from .compat import (
compat_get_terminal_size,
compat_http_client,
compat_kwargs,
+ compat_numeric_types,
compat_os_name,
compat_str,
compat_tokenize_tokenize,
@@ -609,12 +610,45 @@ class YoutubeDL(object):
compat_str(v),
restricted=self.params.get('restrictfilenames'),
is_id=(k == 'id'))
- template_dict = dict((k, sanitize(k, v))
+ template_dict = dict((k, v if isinstance(v, compat_numeric_types) else sanitize(k, v))
for k, v in template_dict.items()
if v is not None and not isinstance(v, (list, tuple, dict)))
template_dict = collections.defaultdict(lambda: 'NA', template_dict)
outtmpl = self.params.get('outtmpl', DEFAULT_OUTTMPL)
+
+ NUMERIC_FIELDS = set((
+ 'width', 'height', 'tbr', 'abr', 'asr', 'vbr', 'fps', 'filesize', 'filesize_approx',
+ 'upload_year', 'upload_month', 'upload_day',
+ 'duration', 'view_count', 'like_count', 'dislike_count', 'repost_count',
+ 'average_rating', 'comment_count', 'age_limit',
+ 'start_time', 'end_time',
+ 'chapter_number', 'season_number', 'episode_number',
+ ))
+
+ # Missing numeric fields used together with integer presentation types
+ # in format specification will break the argument substitution since
+ # string 'NA' is returned for missing fields. We will patch output
+ # template for missing fields to meet string presentation type.
+ for numeric_field in NUMERIC_FIELDS:
+ if numeric_field not in template_dict:
+ # As of [1] format syntax is:
+ # %[mapping_key][conversion_flags][minimum_width][.precision][length_modifier]type
+ # 1. https://docs.python.org/2/library/stdtypes.html#string-formatting
+ FORMAT_RE = r'''(?x)
+ (?<!%)
+ %
+ \({0}\) # mapping key
+ (?:[#0\-+ ]+)? # conversion flags (optional)
+ (?:\d+)? # minimum field width (optional)
+ (?:\.\d+)? # precision (optional)
+ [hlL]? # length modifier (optional)
+ [diouxXeEfFgGcrs%] # conversion type
+ '''
+ outtmpl = re.sub(
+ FORMAT_RE.format(numeric_field),
+ r'%({0})s'.format(numeric_field), outtmpl)
+
tmpl = compat_expanduser(outtmpl)
filename = tmpl % template_dict
# Temporary fix for #4787