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 <jdennis@redhat.com>
Related-Bug: 1603494
Change-Id: I192f17962bb5e21c20c3743b8f3e88c2450432c7
This commit is contained in:
Dean Troyer 2016-08-03 16:51:15 -05:00
parent c64b13b63d
commit ed9663237c
3 changed files with 51 additions and 1 deletions

View File

@ -18,6 +18,7 @@
import argparse import argparse
import getpass import getpass
import locale
import logging import logging
import sys import sys
import traceback import traceback
@ -28,6 +29,7 @@ from cliff import complete
from cliff import help from cliff import help
from oslo_utils import importutils from oslo_utils import importutils
from oslo_utils import strutils from oslo_utils import strutils
import six
from osc_lib.cli import client_config as cloud_config from osc_lib.cli import client_config as cloud_config
from osc_lib import clientmanager from osc_lib import clientmanager
@ -458,8 +460,17 @@ class OpenStackShell(app.App):
tcmd.run(targs) 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) return OpenStackShell().run(argv)
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(main(sys.argv[1:])) sys.exit(main(sys.argv[1:]))

View File

@ -16,8 +16,10 @@
import copy import copy
import mock import mock
import os import os
import sys
import testtools import testtools
from osc_lib import shell
from osc_lib.tests import utils 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): class TestShellHelp(utils.TestShell):
"""Test the deferred help flag""" """Test the deferred help flag"""

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Decode argv into Unicode on Python 2 in ``OpenStackShell.main()``
[OSC Bug `1603494 <https://bugs.launchpad.net/bugs/1603494>`_]