From ed9663237ccf8bd04b0cc1bfd856a94b11a24855 Mon Sep 17 00:00:00 2001 From: Dean Troyer Date: Wed, 3 Aug 2016 16:51:15 -0500 Subject: [PATCH] Decode argv to Unicode on py2 Decode default argv into Unicode on Python 2 (Python 3 does this under the covers). Backport of OSC change https://review.openstack.org/#/c/343035/ Co-Authored-By: John Dennis Related-Bug: 1603494 Change-Id: I192f17962bb5e21c20c3743b8f3e88c2450432c7 --- osc_lib/shell.py | 13 ++++++- osc_lib/tests/test_shell.py | 34 +++++++++++++++++++ .../shell-argv-decode-cdc13dc0c4ec07af.yaml | 5 +++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/shell-argv-decode-cdc13dc0c4ec07af.yaml diff --git a/osc_lib/shell.py b/osc_lib/shell.py index 6d8639a..a0f932b 100644 --- a/osc_lib/shell.py +++ b/osc_lib/shell.py @@ -18,6 +18,7 @@ import argparse import getpass +import locale import logging import sys import traceback @@ -28,6 +29,7 @@ from cliff import complete from cliff import help from oslo_utils import importutils from oslo_utils import strutils +import six from osc_lib.cli import client_config as cloud_config from osc_lib import clientmanager @@ -458,8 +460,17 @@ class OpenStackShell(app.App): tcmd.run(targs) -def main(argv=sys.argv[1:]): +def main(argv=None): + if argv is None: + argv = sys.argv[1:] + if six.PY2: + # Emulate Py3, decode argv into Unicode based on locale so that + # commands always see arguments as text instead of binary data + encoding = locale.getpreferredencoding() + if encoding: + argv = map(lambda arg: arg.decode(encoding), argv) return OpenStackShell().run(argv) + if __name__ == "__main__": sys.exit(main(sys.argv[1:])) diff --git a/osc_lib/tests/test_shell.py b/osc_lib/tests/test_shell.py index e4e1e00..dc215bf 100644 --- a/osc_lib/tests/test_shell.py +++ b/osc_lib/tests/test_shell.py @@ -16,8 +16,10 @@ import copy import mock import os +import sys import testtools +from osc_lib import shell from osc_lib.tests import utils @@ -115,6 +117,38 @@ global_options = { } +class TestShellArgV(utils.TestShell): + """Test the deferred help flag""" + + def setUp(self): + super(TestShellArgV, self).setUp() + + def test_shell_argv(self): + """Test argv decoding + + Python 2 does nothing with argv while Python 3 decodes it into + Unicode before we ever see it. We manually decode when running + under Python 2 so verify that we get the right argv types. + + Use the argv supplied by the test runner so we get actual Python + runtime behaviour; we only need to check the type of argv[0] + which will alwyas be present. + """ + + with mock.patch( + "osc_lib.shell.OpenStackShell.run", + self.app, + ): + # Ensure type gets through unmolested through shell.main() + argv = sys.argv + shell.main(sys.argv) + self.assertEqual(type(argv[0]), type(self.app.call_args[0][0][0])) + + # When shell.main() gets sys.argv itself it should be decoded + shell.main() + self.assertEqual(type(u'x'), type(self.app.call_args[0][0][0])) + + class TestShellHelp(utils.TestShell): """Test the deferred help flag""" diff --git a/releasenotes/notes/shell-argv-decode-cdc13dc0c4ec07af.yaml b/releasenotes/notes/shell-argv-decode-cdc13dc0c4ec07af.yaml new file mode 100644 index 0000000..7d5dbc4 --- /dev/null +++ b/releasenotes/notes/shell-argv-decode-cdc13dc0c4ec07af.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Decode argv into Unicode on Python 2 in ``OpenStackShell.main()`` + [OSC Bug `1603494 `_]