Provide guidance when called with a YouTube ID starting with a dash.
authorPhilipp Hagemeister <phihag@phihag.de>
Sun, 23 Nov 2014 09:49:19 +0000 (10:49 +0100)
committerPhilipp Hagemeister <phihag@phihag.de>
Sun, 23 Nov 2014 09:51:09 +0000 (10:51 +0100)
Reported at https://news.ycombinator.com/item?id=8648121

test/test_utils.py
youtube_dl/YoutubeDL.py
youtube_dl/__init__.py
youtube_dl/compat.py
youtube_dl/utils.py

index 0fa8731473317577f6ef7534d9ad5ead2064e32b..9a62322f019b9a05ec0ff38ee4d31815eb921eef 100644 (file)
@@ -47,6 +47,7 @@ from youtube_dl.utils import (
     js_to_json,
     get_filesystem_encoding,
     intlist_to_bytes,
+    args_to_str,
 )
 
 
@@ -361,5 +362,11 @@ class TestUtil(unittest.TestCase):
             intlist_to_bytes([0, 1, 127, 128, 255]),
             b'\x00\x01\x7f\x80\xff')
 
+    def test_args_to_str(self):
+        self.assertEqual(
+            args_to_str(['foo', 'ba/r', '-baz', '2 be', '']),
+            'foo ba/r -baz \'2 be\' \'\''
+        )
+
 if __name__ == '__main__':
     unittest.main()
index fde026fbf695781ac22d936c87c0216e4c12cfd9..bfa0c6d431e2c14f5d89d5f5d0681639fc663fb0 100755 (executable)
@@ -29,6 +29,7 @@ from .compat import (
     compat_str,
     compat_urllib_error,
     compat_urllib_request,
+    shlex_quote,
 )
 from .utils import (
     escape_url,
@@ -60,6 +61,7 @@ from .utils import (
     write_string,
     YoutubeDLHandler,
     prepend_extension,
+    args_to_str,
 )
 from .cache import Cache
 from .extractor import get_info_extractor, gen_extractors
@@ -253,6 +255,22 @@ class YoutubeDL(object):
             self.print_debug_header()
             self.add_default_info_extractors()
 
+    def warn_if_short_id(self, argv):
+        # short YouTube ID starting with dash?
+        idxs = [
+            i for i, a in enumerate(argv)
+            if re.match(r'^-[0-9A-Za-z_-]{10}$', a)]
+        if idxs:
+            correct_argv = (
+                ['youtube-dl'] +
+                [a for i, a in enumerate(argv) if i not in idxs] +
+                ['--'] + [argv[i] for i in idxs]
+            )
+            self.report_warning(
+                'Long argument string detected. '
+                'Use -- to separate parameters and URLs, like this:\n%s\n' %
+                args_to_str(correct_argv))
+
     def add_info_extractor(self, ie):
         """Add an InfoExtractor object to the end of the list."""
         self._ies.append(ie)
@@ -1410,3 +1428,4 @@ class YoutubeDL(object):
         if encoding is None:
             encoding = preferredencoding()
         return encoding
+
index c1323b4f35e532851cecad6931fb9f58aba0d85e..f519fae3e4311f4871130c899300d24033fd9119 100644 (file)
@@ -334,11 +334,12 @@ def _real_main(argv=None):
 
         # Maybe do nothing
         if (len(all_urls) < 1) and (opts.load_info_filename is None):
-            if not (opts.update_self or opts.rm_cachedir):
-                parser.error('you must provide at least one URL')
-            else:
+            if opts.update_self or opts.rm_cachedir:
                 sys.exit()
 
+            ydl.warn_if_short_id(sys.argv[1:] if argv is None else argv)
+            parser.error('you must provide at least one URL')
+
         try:
             if opts.load_info_filename is not None:
                 retcode = ydl.download_with_info_file(opts.load_info_filename)
index 9d33a8ec5fbd80a75a5d382e8621f6dc616c7aa0..54920653412b77e1fdd440a6ddf331b7a86c41d3 100644 (file)
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
 import getpass
 import optparse
 import os
+import re
 import subprocess
 import sys
 
@@ -174,7 +175,10 @@ try:
     from shlex import quote as shlex_quote
 except ImportError:  # Python < 3.3
     def shlex_quote(s):
-        return "'" + s.replace("'", "'\"'\"'") + "'"
+        if re.match(r'^[-_\w./]+$', s):
+            return s
+        else:
+            return "'" + s.replace("'", "'\"'\"'") + "'"
 
 
 def compat_ord(c):
index 5be7cf99200c57639af17b1dc89f9a861658f331..c3d8bf8e9d8260438b6edd655d299843548a8415 100644 (file)
@@ -41,6 +41,7 @@ from .compat import (
     compat_urllib_parse_urlparse,
     compat_urllib_request,
     compat_urlparse,
+    shlex_quote,
 )
 
 
@@ -1433,3 +1434,8 @@ def ytdl_is_updateable():
     from zipimport import zipimporter
 
     return isinstance(globals().get('__loader__'), zipimporter) or hasattr(sys, 'frozen')
+
+
+def args_to_str(args):
+    # Get a short string representation for a subprocess command
+    return ' '.join(shlex_quote(a) for a in args)