Deepcopy optparse defaults to avoid re-appending multistrings (#890489)

This is actually a bug in optparse itself, but luckily we can work
around it. I'll file it upstream when bugs.python.org's account
registration isn't broken.

Change-Id: I87c3271562caa4336c11fe445475650a9f16950c
This commit is contained in:
Mark McLoughlin
2011-11-14 23:36:48 +00:00
parent d089fb642a
commit 5b10461388
2 changed files with 22 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ stepping stone.
"""
import copy
import optparse
import os
import socket
@@ -93,6 +94,12 @@ class FlagValues(object):
values = extra = None
#
# This horrendous hack is needed because optparse only
# shallow copies its defaults dict before parsing
#
defaults = copy.deepcopy(self._parser.defaults)
#
# This horrendous hack allows us to stop optparse
# exiting when it encounters an unknown option
@@ -110,8 +117,11 @@ class FlagValues(object):
break
args.remove(unknown)
self._parser.defaults = defaults
defaults = copy.deepcopy(defaults)
finally:
self._parser.error = error_catcher.orig_error
self._parser.defaults = defaults
values = self._apply_multistring_defaults(values)

View File

@@ -85,6 +85,10 @@ class FlagsTestCase(test.TestCase):
self.assertEqual(self.FLAGS.multi, ['foo', 'bar'])
# Re-parse to test multistring isn't append multiple times
self.FLAGS(argv + ['--unknown1', '--unknown2'])
self.assertEqual(self.FLAGS.multi, ['foo', 'bar'])
def test_define_list(self):
flags.DEFINE_list('list', ['foo'], 'desc', flag_values=self.FLAGS)
@@ -180,11 +184,14 @@ class FlagsTestCase(test.TestCase):
flags.DEFINE_integer('int', 1, 'desc', flag_values=self.FLAGS)
flags.DEFINE_bool('false', False, 'desc', flag_values=self.FLAGS)
flags.DEFINE_bool('true', True, 'desc', flag_values=self.FLAGS)
flags.DEFINE_multistring('multi', ['blaa'], 'desc',
flag_values=self.FLAGS)
(fd, path) = tempfile.mkstemp(prefix='nova', suffix='.flags')
try:
os.write(fd, '--string=foo\n--int=2\n--false\n--notrue\n')
os.write(fd, '--multi=foo\n--multi=bar\n')
os.close(fd)
self.FLAGS(['flags_test', '--flagfile=' + path])
@@ -193,6 +200,11 @@ class FlagsTestCase(test.TestCase):
self.assertEqual(self.FLAGS.int, 2)
self.assertEqual(self.FLAGS.false, True)
self.assertEqual(self.FLAGS.true, False)
self.assertEqual(self.FLAGS.multi, ['foo', 'bar'])
# Re-parse to test multistring isn't append multiple times
self.FLAGS(['flags_test', '--flagfile=' + path])
self.assertEqual(self.FLAGS.multi, ['foo', 'bar'])
finally:
os.remove(path)