diff options
author | Stephen Finucane <sfinucan@redhat.com> | 2016-09-01 09:57:05 +0100 |
---|---|---|
committer | Stephen Finucane <sfinucan@redhat.com> | 2016-11-22 14:42:59 +0000 |
commit | 2f8025b225e6211d18ab2074c08342905ba88fbc (patch) | |
tree | b773289f1c51312c5c5bc087ba82eb08ecdab15e | |
parent | 2547c59d950065192aa19173d6946da480978035 (diff) | |
download | oslo-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.py | 62 | ||||
-rw-r--r-- | oslo_config/tests/test_generator.py | 69 |
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'), |