Merge "Advanced Option"
This commit is contained in:
commit
2449197425
@ -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."""
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user