Merge "Advanced Option"

This commit is contained in:
Jenkins 2016-08-05 10:47:18 +00:00 committed by Gerrit Code Review
commit 2449197425
5 changed files with 154 additions and 2 deletions

View File

@ -358,6 +358,43 @@ command line arguments using the SubCommandOpt class:
>>> conf.action.name, conf.action.id
('list', '10')
Advanced Option
---------------
Use if you need to label an option as advanced in sample files, indicating the
option is not normally used by the majority of users and might have a
significant effect on stability and/or performance::
from oslo_config import cfg
opts = [
cfg.StrOpt('option1', default='default_value',
advanced=True, help='This is help '
'text.'),
cfg.PortOpt('option2', default='default_value',
help='This is help text.'),
]
CONF = cfg.CONF
CONF.register_opts(opts)
This will result in the option being pushed to the bottom of the
namespace and labeled as advanced in the sample files, with a notation
about possible effects::
[DEFAULT]
...
# This is help text. (string value)
# option2 = default_value
...
<pushed to bottom of section>
...
# This is help text. (string value)
# Advanced Option: intended for advanced users and not used
# by the majority of users, and might have a significant
# effect on stability and/or performance.
# option1 = default_value
"""
import argparse
@ -666,6 +703,8 @@ class Opt(object):
strings are encouraged. Silently ignored if
deprecated_for_removal is False
:param mutable: True if this option may be reloaded
:param advanced: a bool True/False value if this option has advanced usage
and is not normally used by the majority of users
An Opt object has no public methods, but has a number of public properties:
@ -708,6 +747,10 @@ class Opt(object):
a string explaining how the option's value is used
.. py:attribute:: advanced
in sample files, a bool value indicating the option is advanced
.. versionchanged:: 1.2
Added *deprecated_opts* parameter.
@ -728,6 +771,9 @@ class Opt(object):
.. versionchanged:: 3.12
Added *deprecated_since* parameter.
.. versionchanged:: 3.15
Added *advanced* parameter and attribute.
"""
multi = False
@ -737,7 +783,7 @@ class Opt(object):
deprecated_name=None, deprecated_group=None,
deprecated_opts=None, sample_default=None,
deprecated_for_removal=False, deprecated_reason=None,
deprecated_since=None, mutable=False):
deprecated_since=None, mutable=False, advanced=False):
if name.startswith('_'):
raise ValueError('illegal name %s with prefix _' % (name,))
self.name = name
@ -775,6 +821,7 @@ class Opt(object):
self._check_default()
self.mutable = mutable
self.advanced = advanced
def _default_is_ref(self):
"""Check if default is a reference to another var."""

View File

@ -259,6 +259,13 @@ class _OptFormatter(object):
lines.extend(
self._format_help('Reason: ' + opt.deprecated_reason))
if opt.advanced:
lines.append(
'# Advanced Option: intended for advanced users and not used\n'
'# by the majority of users, and might have a significant\n'
'# effect on stability and/or performance.\n'
)
if hasattr(opt.type, 'format_defaults'):
defaults = opt.type.format_defaults(opt.default,
opt.sample_default)
@ -389,7 +396,7 @@ def _output_opts(f, group, group_data, minimal=False):
for (namespace, opts) in sorted(group_data['namespaces'],
key=operator.itemgetter(0)):
f.write('\n#\n# From %s\n#\n' % namespace)
for opt in opts:
for opt in sorted(opts, key=operator.attrgetter('advanced')):
try:
if minimal and not opt.required:
pass

View File

@ -140,6 +140,13 @@ def _format_group(app, namespace, group_name, group_obj, opt_list):
else:
warnings.warn('Failed to fully format sample for %s: %s' %
(opt.dest, err))
if opt.advanced:
yield _indent(
':Advanced Option: intended for advanced users and not used',)
yield _indent(
':by the majority of users, and might have a significant',)
yield _indent(
':effect on stability and/or performance.',)
yield ''
try:

View File

@ -1219,4 +1219,50 @@ bars = <None>
self.assertEqual(expected, actual)
class AdvancedOptionsTestCase(base.BaseTestCase):
opts = [cfg.StrOpt('foo', help='foo option', default='fred'),
cfg.StrOpt('bar', help='bar option', advanced=True),
cfg.StrOpt('foo_bar', help='foobar'),
cfg.BoolOpt('bars', help='bars foo', default=True, advanced=True)]
def test_advanced_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'))
expected = '''[alpha]
#
# From namespace1
#
# foo option (string value)
#foo = fred
# foobar (string value)
#foo_bar = <None>
# bar option (string value)
# Advanced Option: intended for advanced users and not used
# by the majority of users, and might have a significant
# effect on stability and/or performance.
#bar = <None>
# bars foo (boolean value)
# Advanced Option: intended for advanced users and not used
# by the majority of users, and might have a significant
# effect on stability and/or performance.
#bars = true
'''
with open(tmp_file, 'r') as f:
actual = f.read()
self.assertEqual(expected, actual)
GeneratorTestCase.generate_scenarios()

View File

@ -341,6 +341,51 @@ class FormatGroupTest(base.BaseTestCase):
''').lstrip(), results)
def test_advanced(self):
results = '\n'.join(list(sphinxext._format_group(
app=mock.Mock(),
namespace=None,
group_name=None,
group_obj=None,
opt_list=[
cfg.StrOpt('opt_name',
advanced=True),
],
)))
self.assertEqual(textwrap.dedent('''
.. oslo.config:group:: DEFAULT
.. oslo.config:option:: opt_name
:Type: string
:Default: ``<None>``
:Advanced Option: intended for advanced users and not used
:by the majority of users, and might have a significant
:effect on stability and/or performance.
''').lstrip(), results)
def test_not_advanced(self):
results = '\n'.join(list(sphinxext._format_group(
app=mock.Mock(),
namespace=None,
group_name=None,
group_obj=None,
opt_list=[
cfg.StrOpt('opt_name',
advanced=False),
],
)))
self.assertEqual(textwrap.dedent('''
.. oslo.config:group:: DEFAULT
.. oslo.config:option:: opt_name
:Type: string
:Default: ``<None>``
''').lstrip(), results)
class FormatOptionHelpTest(base.BaseTestCase):