Support backwards compat for _ args

Instead of putting tons of hidden options to allow for variations of
argparse options with _ in them, just manipulate the argv when it's
passed in to translate to - instead. (why the heck does argparse not
already do this?)

Change-Id: I5f0bd9d9a333781ad13d531b3667fff5fdac9eac
This commit is contained in:
Monty Taylor 2015-12-12 13:03:07 -05:00 committed by Morgan Fainberg
parent 22d740b700
commit 3a34378f71
2 changed files with 63 additions and 0 deletions

View File

@ -15,6 +15,7 @@
# alias because we already had an option named argparse
import argparse as argparse_mod
import collections
import copy
import json
import os
@ -136,6 +137,34 @@ def _auth_update(old_dict, new_dict_source):
return old_dict
def _fix_argv(argv):
# Transform any _ characters in arg names to - so that we don't
# have to throw billions of compat argparse arguments around all
# over the place.
processed = collections.defaultdict(list)
for index in range(0, len(argv)):
if argv[index].startswith('--'):
split_args = argv[index].split('=')
orig = split_args[0]
new = orig.replace('_', '-')
if orig != new:
split_args[0] = new
argv[index] = "=".join(split_args)
# Save both for later so we can throw an error about dupes
processed[new].append(orig)
overlap = []
for new, old in processed.items():
if len(old) > 1:
overlap.extend(old)
if overlap:
raise exceptions.OpenStackConfigException(
"The following options were given: '{options}' which contain"
" duplicates except that one has _ and one has -. There is"
" no sane way for us to know what you're doing. Remove the"
" duplicate option and try again".format(
options=','.join(overlap)))
class OpenStackConfig(object):
def __init__(self, config_files=None, vendor_files=None,
@ -521,6 +550,9 @@ class OpenStackConfig(object):
is requested
"""
# Fix argv in place - mapping any keys with embedded _ in them to -
_fix_argv(argv)
local_parser = argparse_mod.ArgumentParser(add_help=False)
for p in (parser, local_parser):

View File

@ -431,6 +431,37 @@ class TestConfigArgparse(base.TestCase):
self.assertEqual(cc.config['auth_type'], 'token')
self.assertEqual(cc.config['auth']['token'], 'very-bad-things')
def test_argparse_underscores(self):
c = config.OpenStackConfig(config_files=[self.no_yaml],
vendor_files=[self.no_yaml],
secure_files=[self.no_yaml])
parser = argparse.ArgumentParser()
parser.add_argument('--os_username')
argv = [
'--os_username', 'user', '--os_password', 'pass',
'--os-auth-url', 'auth-url', '--os-project-name', 'project']
c.register_argparse_arguments(parser, argv=argv)
opts, _remain = parser.parse_known_args(argv)
cc = c.get_one_cloud(argparse=opts)
self.assertEqual(cc.config['auth']['username'], 'user')
self.assertEqual(cc.config['auth']['password'], 'pass')
self.assertEqual(cc.config['auth']['auth_url'], 'auth-url')
def test_argparse_underscores_duplicate(self):
c = config.OpenStackConfig(config_files=[self.no_yaml],
vendor_files=[self.no_yaml],
secure_files=[self.no_yaml])
parser = argparse.ArgumentParser()
parser.add_argument('--os_username')
argv = [
'--os_username', 'user', '--os_password', 'pass',
'--os-username', 'user1', '--os-password', 'pass1',
'--os-auth-url', 'auth-url', '--os-project-name', 'project']
self.assertRaises(
exceptions.OpenStackConfigException,
c.register_argparse_arguments,
parser=parser, argv=argv)
def test_register_argparse_bad_plugin(self):
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
vendor_files=[self.vendor_yaml])