configglue team mailing list archive
-
configglue team
-
Mailing list archive
-
Message #00199
[Merge] lp:~ricardokirkner/configglue/short-options into lp:configglue
Ricardo Kirkner has proposed merging lp:~ricardokirkner/configglue/short-options into lp:configglue.
Requested reviews:
Canonical ISD hackers (canonical-isd-hackers)
Configglue developers (configglue)
For more details, see:
https://code.launchpad.net/~ricardokirkner/configglue/short-options/+merge/66411
Overview
========
This branch adds support for specifying short names for options so that they
can be used from the command line.
Details
=======
The Option class and any derived classes now have an extra short_name
attribute that is used to indicate the preferred short name for that option
when specified via the command line.
For example,
class MySchema(Schema):
foo = IntOption(short_name='f')
will allow that option to be overridden via command line both using
--foo <value>
or
-f <value>
--
https://code.launchpad.net/~ricardokirkner/configglue/short-options/+merge/66411
Your team Configglue developers is requested to review the proposed merge of lp:~ricardokirkner/configglue/short-options into lp:configglue.
=== modified file 'configglue/app/tests/test_base.py'
--- configglue/app/tests/test_base.py 2011-06-23 18:55:16 +0000
+++ configglue/app/tests/test_base.py 2011-06-30 04:09:28 +0000
@@ -24,10 +24,12 @@
def make_app(name=None, schema=None, plugin_manager=None):
# patch sys.argv so that nose can be run with extra options
# without conflicting with the schema validation
+ # patch sys.stderr to prevent spurious output
mock_sys = Mock()
mock_sys.argv = ['foo.py']
with patch('configglue.pyschema.glue.sys', mock_sys):
- app = App(name=name, schema=schema, plugin_manager=plugin_manager)
+ with patch('configglue.app.base.sys.stderr'):
+ app = App(name=name, schema=schema, plugin_manager=plugin_manager)
return app
=== modified file 'configglue/pyschema/glue.py'
--- configglue/pyschema/glue.py 2011-06-19 21:24:56 +0000
+++ configglue/pyschema/glue.py 2011-06-30 04:09:28 +0000
@@ -70,7 +70,11 @@
if not option.fatal:
kwargs['default'] = parser.get(section.name, option.name)
kwargs['action'] = option.action
- og.add_option('--' + long_name(option), **kwargs)
+ args = ['--' + long_name(option)]
+ if option.short_name:
+ # prepend the option's short name
+ args.insert(0, '-' + option.short_name)
+ og.add_option(*args, **kwargs)
options, args = op.parse_args(argv)
def set_value(section, option, value):
=== modified file 'configglue/pyschema/schema.py'
--- configglue/pyschema/schema.py 2011-06-22 23:00:16 +0000
+++ configglue/pyschema/schema.py 2011-06-30 04:09:28 +0000
@@ -288,8 +288,9 @@
require_parser = False
def __init__(self, name='', raw=False, default=NO_DEFAULT, fatal=False,
- help='', section=None, action='store'):
+ help='', section=None, action='store', short_name=''):
self.name = name
+ self.short_name = short_name
self.raw = raw
self.fatal = fatal
if default is NO_DEFAULT:
@@ -413,9 +414,13 @@
"""
def __init__(self, name='', item=None, raw=False, default=NO_DEFAULT,
- fatal=False, help='', action='store', remove_duplicates=False):
+ fatal=False, help='', action='store', remove_duplicates=False,
+ short_name=''):
super(ListOption, self).__init__(name=name, raw=raw,
- default=default, fatal=fatal, help=help, action=action)
+ default=default, fatal=fatal, help=help, action=action,
+ short_name=short_name)
+ if item is None:
+ item = StringOption()
self.item = item
self.require_parser = item.require_parser
self.raw = item.raw
@@ -459,10 +464,11 @@
"""
def __init__(self, name='', raw=False, default=NO_DEFAULT, fatal=False,
- null=False, help='', action='store'):
+ null=False, help='', action='store', short_name=''):
self.null = null
super(StringOption, self).__init__(name=name, raw=raw,
- default=default, fatal=fatal, help=help, action=action)
+ default=default, fatal=fatal, help=help, action=action,
+ short_name=short_name)
def _get_default(self):
return '' if not self.null else None
@@ -501,9 +507,10 @@
"""
def __init__(self, name='', length=0, raw=False, default=NO_DEFAULT,
- fatal=False, help='', action='store'):
+ fatal=False, help='', action='store', short_name=''):
super(TupleOption, self).__init__(name=name, raw=raw,
- default=default, fatal=fatal, help=help, action=action)
+ default=default, fatal=fatal, help=help, action=action,
+ short_name=short_name)
self.length = length
def _get_default(self):
@@ -551,7 +558,7 @@
def __init__(self, name='', spec=None, strict=False, raw=False,
default=NO_DEFAULT, fatal=False, help='', action='store',
- item=None):
+ item=None, short_name=''):
if spec is None:
spec = {}
if item is None:
@@ -560,7 +567,8 @@
self.strict = strict
self.item = item
super(DictOption, self).__init__(name=name, raw=raw,
- default=default, fatal=fatal, help=help, action=action)
+ default=default, fatal=fatal, help=help, action=action,
+ short_name=short_name)
def _get_default(self):
default = {}
=== modified file 'configglue/tests/pyschema/test_schema.py'
--- configglue/tests/pyschema/test_schema.py 2011-06-23 17:31:13 +0000
+++ configglue/tests/pyschema/test_schema.py 2011-06-30 04:09:28 +0000
@@ -201,9 +201,15 @@
self.assertNotEqual(opt1, opt2)
def test_validate(self):
+ """Test Option default validate behaviour."""
opt = self.cls()
self.assertRaises(NotImplementedError, opt.validate, 0)
+ def test_short_name(self):
+ """Test Option short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestConfigOption(TestOption):
cls = ConfigOption
@@ -370,6 +376,11 @@
self.assertEqual(self.opt.to_string(''), '')
self.assertEqual(self.opt.to_string('foo'), 'foo')
+ def test_short_name(self):
+ """Test StringOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestStringConfigOption(TestStringOption):
cls = StringConfigOption
@@ -415,6 +426,11 @@
opt = self.cls()
self.assertEqual(opt.validate(''), False)
+ def test_short_name(self):
+ """Test IntOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestIntConfigOption(TestIntOption):
cls = IntConfigOption
@@ -465,6 +481,11 @@
opt = self.cls()
self.assertEqual(opt.validate(''), False)
+ def test_short_name(self):
+ """Test BoolOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestBoolConfigOption(TestBoolOption):
cls = BoolConfigOption
@@ -564,6 +585,16 @@
opt = self.cls(item=IntOption())
self.assertEqual(opt.validate(''), False)
+ def test_default_item(self):
+ """Test ListOption default item."""
+ opt = self.cls()
+ self.assertEqual(opt.item, StringOption())
+
+ def test_short_name(self):
+ """Test ListOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestLinesConfigOption(TestListOption):
cls = LinesConfigOption
@@ -631,6 +662,11 @@
opt = self.cls(length=2)
self.assertEqual(opt.validate(0), False)
+ def test_short_name(self):
+ """Test TupleOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestTupleConfigOption(TupleOption):
cls = TupleConfigOption
@@ -833,6 +869,11 @@
opt = self.cls()
self.assertEqual(opt.validate(0), False)
+ def test_short_name(self):
+ """Test DictOption short name."""
+ opt = self.cls(short_name='f')
+ self.assertEqual(opt.short_name, 'f')
+
class TestDictConfigOption(TestDictOption):
cls = DictConfigOption
=== modified file 'configglue/tests/pyschema/test_schemaconfig.py'
--- configglue/tests/pyschema/test_schemaconfig.py 2011-06-19 20:14:50 +0000
+++ configglue/tests/pyschema/test_schemaconfig.py 2011-06-30 04:09:28 +0000
@@ -20,6 +20,7 @@
import os
import sys
from StringIO import StringIO
+from optparse import OptionConflictError
from mock import (
Mock,
@@ -297,6 +298,39 @@
'fóobâr')
self.assertEqual(parser.get('__main__', 'foo'), 'fóobâr')
+ def test_option_short_name(self):
+ """Test schemaconfigglue support for short option names."""
+ class MySchema(Schema):
+ foo = IntOption(short_name='f')
+
+ parser = SchemaConfigParser(MySchema())
+ op, options, args = schemaconfigglue(
+ parser, argv=['-f', '42'])
+ self.assertEqual(parser.get('__main__', 'foo'), 42)
+
+ def test_option_conflicting_short_name(self):
+ """Test schemaconfigglue with conflicting short option names."""
+ class MySchema(Schema):
+ foo = IntOption(short_name='f')
+ flup = StringOption(short_name='f')
+
+ parser = SchemaConfigParser(MySchema())
+ self.assertRaises(OptionConflictError, schemaconfigglue, parser,
+ argv=['-f', '42'])
+
+ def test_option_specified_twice(self):
+ """Test schemaconfigglue with option name specified twice."""
+ class MySchema(Schema):
+ foo = IntOption(short_name='f')
+
+ parser = SchemaConfigParser(MySchema())
+ op, options, args = schemaconfigglue(
+ parser, argv=['-f', '42', '--foo', '24'])
+ self.assertEqual(parser.get('__main__', 'foo'), 24)
+ op, options, args = schemaconfigglue(
+ parser, argv=['-f', '24', '--foo', '42'])
+ self.assertEqual(parser.get('__main__', 'foo'), 42)
+
class ConfigglueTestCase(unittest.TestCase):
@patch('configglue.pyschema.glue.SchemaConfigParser')
Follow ups