Repository: streamlink/streamlink
Pull request #2333 (2019-03-01 18:53:31)

cli.argparser: Fix single hyphen params at the beginning of --player-args

use workaround solution from

https://bugs.python.org/issue9334

don't know if there is any downside,
but seems like it could work

it can be reversed, if there are some issue

closes https://github.com/streamlink/streamlink/issues/971


Patch:
diff --git a/src/streamlink_cli/argparser.py b/src/streamlink_cli/argparser.py
index 3958a085..6351fa00 100644
--- a/src/streamlink_cli/argparser.py
+++ b/src/streamlink_cli/argparser.py
@@ -1,4 +1,5 @@
 import argparse
+import numbers
 import re
 from string import printable
 from textwrap import dedent
@@ -44,6 +45,37 @@ class ArgumentParser(argparse.ArgumentParser):
         elif name:
             yield u"--{0}".format(name)
 
+    def _match_argument(self, action, arg_strings_pattern):
+        # - https://github.com/streamlink/streamlink/issues/971
+        # - https://bugs.python.org/issue9334
+
+        # match the pattern for this action to the arg strings
+        nargs_pattern = self._get_nargs_pattern(action)
+        match = argparse._re.match(nargs_pattern, arg_strings_pattern)
+
+        # if no match, see if we can emulate optparse and return the
+        # required number of arguments regardless of their values
+        if match is None:
+            nargs = action.nargs if action.nargs is not None else 1
+            if isinstance(nargs, numbers.Number) and len(arg_strings_pattern) >= nargs:
+                return nargs
+
+        # raise an exception if we weren't able to find a match
+        if match is None:
+            nargs_errors = {
+                None: argparse._('expected one argument'),
+                argparse.OPTIONAL: argparse._('expected at most one argument'),
+                argparse.ONE_OR_MORE: argparse._('expected at least one argument'),
+            }
+            default = argparse.ngettext('expected %s argument',
+                                        'expected %s arguments',
+                                        action.nargs) % action.nargs
+            msg = nargs_errors.get(action.nargs, default)
+            raise argparse.ArgumentError(action, msg)
+
+        # return the number of arguments matched
+        return len(match.group(1))
+
 
 class HelpFormatter(argparse.RawDescriptionHelpFormatter):
     """A nicer help formatter.


Test patch:
diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py
index 8f829e59..cb8ce253 100644
--- a/tests/test_cmdline.py
+++ b/tests/test_cmdline.py
@@ -1,4 +1,3 @@
-import sys
 import os.path
 import unittest
 
@@ -83,6 +82,13 @@ class TestCommandLinePOSIX(CommandLineTestCase):
                         ["/usr/bin/player", "--input-title-format", 'Poker "Stars"', "rtmp://test.se"],
                         passthrough=True)
 
+    def test_single_hyphen_extra_player_args_971(self):
+        """single hyphen params at the beginning of --player-args
+           - https://github.com/streamlink/streamlink/issues/971 """
+        self._test_args(["streamlink", "-p", "/usr/bin/player", "-a", "-v {filename}",
+                         "http://test.se", "test"],
+                        ["/usr/bin/player", "-v", "-"])
+
 
 @unittest.skipIf(not is_win32, "test only applicable on Windows")
 class TestCommandLineWindows(CommandLineTestCase):
@@ -117,6 +123,9 @@ class TestCommandLineWindows(CommandLineTestCase):
                         '''c:\\Program Files\\Player\\player.exe --input-title-format "Poker \\"Stars\\"" \"rtmp://test.se\"''',
                         passthrough=True)
 
-
-if __name__ == "__main__":
-    unittest.main()
+    def test_single_hyphen_extra_player_args_971(self):
+        """single hyphen params at the beginning of --player-args
+           - https://github.com/streamlink/streamlink/issues/971 """
+        self._test_args(["streamlink", "-p", "c:\\Program Files\\Player\\player.exe",
+                         "-a", "-v {filename}", "http://test.se", "test"],
+                        "c:\\Program Files\\Player\\player.exe -v -")