summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Finucane <sfinucan@redhat.com>2016-09-01 09:57:05 +0100
committerStephen Finucane <sfinucan@redhat.com>2016-11-22 14:42:59 +0000
commit2f8025b225e6211d18ab2074c08342905ba88fbc (patch)
treeb773289f1c51312c5c5bc087ba82eb08ecdab15e
parent2547c59d950065192aa19173d6946da480978035 (diff)
downloadoslo-config-2f8025b225e6211d18ab2074c08342905ba88fbc.tar.gz
Add 'summarize' option
Projects like Nova have been putting a lot of work into centralizing and improving documentation of configuration options. One unfortunate side effect of this change is the huge increase in the size of the 'nova.conf' configuration file, where, for every one line configuration option there will be many lines of documentation. Seeing as this documentation is already published using Sphinx, there may be little reason to pollute the configuration file with this level of detail. Add a configuration option that, when enabled, will ensure only the the first paragraph (a summary) of each opt or group will be output to the generated config file. The generated Sphinx documents remain unchanged. Change-Id: I5fed21a333b0ac75eef4ce17e5b377f956abde7b
-rw-r--r--oslo_config/generator.py62
-rw-r--r--oslo_config/tests/test_generator.py69
2 files changed, 112 insertions, 19 deletions
diff --git a/oslo_config/generator.py b/oslo_config/generator.py
index a133f04..8643631 100644
--- a/oslo_config/generator.py
+++ b/oslo_config/generator.py
@@ -39,17 +39,27 @@ import stevedore.named # noqa
LOG = logging.getLogger(__name__)
_generator_opts = [
- cfg.StrOpt('output-file',
- help='Path of the file to write to. Defaults to stdout.'),
- cfg.IntOpt('wrap-width',
- default=70,
- help='The maximum length of help lines.'),
- cfg.MultiStrOpt('namespace',
- required=True,
- help='Option namespace under "oslo.config.opts" in which '
- 'to query for options.'),
- cfg.BoolOpt('minimal', default=False,
- help='Generate a minimal required configuration.'),
+ cfg.StrOpt(
+ 'output-file',
+ help='Path of the file to write to. Defaults to stdout.'),
+ cfg.IntOpt(
+ 'wrap-width',
+ default=70,
+ help='The maximum length of help lines.'),
+ cfg.MultiStrOpt(
+ 'namespace',
+ required=True,
+ help='Option namespace under "oslo.config.opts" in which to query '
+ 'for options.'),
+ cfg.BoolOpt(
+ 'minimal',
+ default=False,
+ help='Generate a minimal required configuration.'),
+ cfg.BoolOpt(
+ 'summarize',
+ default=False,
+ help='Only output summaries of help text to config files. Retain '
+ 'longer help text for Sphinx documents.'),
]
@@ -173,6 +183,7 @@ class _OptFormatter(object):
"""Format the description of a group header to the output file
:param group_or_groupname: a cfg.OptGroup instance or a name of group
+ :returns: a formatted group description string
"""
if isinstance(group_or_groupname, cfg.OptGroup):
group = group_or_groupname
@@ -184,10 +195,14 @@ class _OptFormatter(object):
lines = ['[%s]\n' % groupname]
self.writelines(lines)
- def format(self, opt, group_name, minimal=False):
+ def format(self, opt, group_name, minimal=False, summarize=False):
"""Format a description of an option to the output file.
:param opt: a cfg.Opt instance
+ :param group_name: name of the group to which the opt is assigned
+ :param minimal: enable option by default, marking it as required
+ :param summarize: output a summarized description of the opt
+ :returns: a formatted opt description string
"""
if not opt.help:
LOG.warning(_LW('"%s" is missing a help string'), opt.dest)
@@ -199,8 +214,19 @@ class _OptFormatter(object):
opt_prefix = 'DEPRECATED: '
if opt.help:
+ # an empty line signifies a new paragraph. We only want the
+ # summary line
+ if summarize:
+ _split = opt.help.split('\n\n')
+ opt_help = _split[0].rstrip(':').rstrip('.')
+ if len(_split) > 1:
+ opt_help += '. For more information, refer to the '
+ opt_help += 'documentation.'
+ else:
+ opt_help = opt.help
+
help_text = u'%s%s (%s)' % (opt_prefix,
- opt.help,
+ opt_help,
opt_type)
else:
help_text = u'(%s)' % opt_type
@@ -392,7 +418,7 @@ def on_load_failure_callback(*args, **kwargs):
raise
-def _output_opts(f, group, group_data, minimal=False):
+def _output_opts(f, group, group_data, minimal=False, summarize=False):
f.format_group(group_data['object'] or group)
for (namespace, opts) in sorted(group_data['namespaces'],
key=operator.itemgetter(0)):
@@ -403,7 +429,7 @@ def _output_opts(f, group, group_data, minimal=False):
pass
else:
f.write('\n')
- f.format(opt, group, minimal)
+ f.format(opt, group, minimal, summarize)
except Exception as err:
f.write('# Warning: Failed to format sample for %s\n' %
(opt.dest,))
@@ -462,12 +488,14 @@ def generate(conf):
groups = _get_groups(_list_opts(conf.namespace))
# Output the "DEFAULT" section as the very first section
- _output_opts(formatter, 'DEFAULT', groups.pop('DEFAULT'), conf.minimal)
+ _output_opts(formatter, 'DEFAULT', groups.pop('DEFAULT'), conf.minimal,
+ conf.summarize)
# output all other config sections with groups in alphabetical order
for group, group_data in sorted(groups.items()):
formatter.write('\n\n')
- _output_opts(formatter, group, group_data, conf.minimal)
+ _output_opts(formatter, group, group_data, conf.minimal,
+ conf.summarize)
def main(args=None):
diff --git a/oslo_config/tests/test_generator.py b/oslo_config/tests/test_generator.py
index 1806dd1..4e8be5f 100644
--- a/oslo_config/tests/test_generator.py
+++ b/oslo_config/tests/test_generator.py
@@ -1200,8 +1200,10 @@ class RequiredOptionTestCase(base.BaseTestCase):
fd, tmp_file = tempfile.mkstemp()
with open(tmp_file, 'w+') as f:
formatter = generator._OptFormatter(output_file=f)
- generator._output_opts(formatter, 'alpha',
- groups.pop('alpha'), True)
+ generator._output_opts(formatter,
+ 'alpha',
+ groups.pop('alpha'),
+ minimal=True)
expected = '''[alpha]
#
@@ -1219,6 +1221,69 @@ bars = <None>
self.assertEqual(expected, actual)
+class SummarizedOptionsTestCase(base.BaseTestCase):
+ """Validate 'summarize' config option.
+
+ The 'summarize' switch ensures only summaries of each configuration
+ option are output.
+ """
+
+ opts = [
+ cfg.StrOpt(
+ 'foo',
+ default='fred',
+ help="""This is the summary line for a config option.
+
+I can provide a lot more detail here, but I may not want to bloat my
+config file. In this scenario, I can use the 'summarize' config option
+to ensure only a summary of the option is output to the config file.
+However, the Sphinx-generated documentation, hosted online, remains
+unchanged.
+
+Hopefully this works.
+"""),
+ cfg.StrOpt(
+ 'bar',
+ required=True,
+ help="""This is a less carefully formatted configuration
+option, where the author has not broken their description into a brief
+summary line and larger description. Watch this person's commit
+messages!""")]
+
+ def test_summarized_option_order_single_ns(self):
+
+ config = [('namespace1', [('alpha', self.opts)])]
+ groups = generator._get_groups(config)
+
+ fd, tmp_file = tempfile.mkstemp()
+ with open(tmp_file, 'w+') as f:
+ formatter = generator._OptFormatter(output_file=f)
+ generator._output_opts(formatter,
+ 'alpha',
+ groups.pop('alpha'),
+ summarize=True)
+ expected = '''[alpha]
+
+#
+# From namespace1
+#
+
+# This is the summary line for a config option. For more information,
+# refer to the documentation. (string value)
+#foo = fred
+
+# This is a less carefully formatted configuration
+# option, where the author has not broken their description into a
+# brief
+# summary line and larger description. Watch this person's commit
+# messages! (string value)
+#bar = <None>
+'''
+ with open(tmp_file, 'r') as f:
+ actual = f.read()
+ self.assertEqual(expected, actual)
+
+
class AdvancedOptionsTestCase(base.BaseTestCase):
opts = [cfg.StrOpt('foo', help='foo option', default='fred'),