Hello community,
here is the log from the commit of package python-oslo.config for
openSUSE:Factory checked in at 2015-07-12 22:52:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-oslo.config (Old)
and /work/SRC/openSUSE:Factory/.python-oslo.config.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-oslo.config"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-oslo.config/python-oslo.config.changes
2015-05-02 21:35:13.000000000 +0200
+++
/work/SRC/openSUSE:Factory/.python-oslo.config.new/python-oslo.config.changes
2015-07-12 22:52:29.000000000 +0200
@@ -1,0 +2,36 @@
+Mon Mar 30 05:59:51 UTC 2015 - [email protected]
+
+- update to 1.9.3:
+ * Switch to non-namespaced module imports
+
+-------------------------------------------------------------------
+Tue Mar 10 10:09:49 UTC 2015 - [email protected]
+
+- update to 1.9.2:
+ * print better message when choices has an empty string
+ * None in config choices breaks oslo-config-generator
+ * Generate help text indicating possible values
+ * fix bug link in readme
+ * Add ability to deprecate opts for removal
+ * Typo in StrOpt docstring: Integer to String
+ * Add exception handling for entry points
+
+-------------------------------------------------------------------
+Tue Feb 24 08:29:05 UTC 2015 - [email protected]
+
+- update to 1.7.0:
+ * Updated from global requirements
+ * Log a warning when deprecated opts are used
+ * Do not import our namespace package
+ * Fixes deprecation warning for oslo.config in cfg.py
+ * Clear up MultiStrOpt and related documentation
+ * Add a list_all_sections method to ConfigOpts
+ * Better check for integer range to account for 0
+ * Reword DeprecatedOpt docstring
+ * Support i18n messages in config generator
+ * Fix of wrong cli opts unregistration
+- Cleanup BuildRequires. SLES 11 is no longer a build target
+- Add python-oslo.i18n as BuildRequires for tests
+- Disable testrun for now
+
+-------------------------------------------------------------------
Old:
----
oslo.config-1.6.0.tar.gz
New:
----
oslo.config-1.9.3.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-oslo.config.spec ++++++
--- /var/tmp/diff_new_pack.z2HKgP/_old 2015-07-12 22:52:29.000000000 +0200
+++ /var/tmp/diff_new_pack.z2HKgP/_new 2015-07-12 22:52:29.000000000 +0200
@@ -17,7 +17,7 @@
Name: python-oslo.config
-Version: 1.6.0
+Version: 1.9.3
Release: 0
Url: https://launchpad.net/oslo/
Summary: OpenStack configuration API
@@ -31,14 +31,10 @@
BuildRequires: python-oslosphinx
BuildRequires: python-pbr
# Test requirements:
-#BuildRequires: python-coverage >= 3.6
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-BuildRequires: python-argparse
-BuildRequires: python-discover
-%endif
BuildRequires: python-fixtures >= 0.3.14
BuildRequires: python-mock >= 1.0
BuildRequires: python-netaddr
+BuildRequires: python-oslo.i18n >= 1.3.0
BuildRequires: python-oslotest >= 1.2.0
BuildRequires: python-python-subunit >= 0.0.18
BuildRequires: python-six
@@ -48,16 +44,11 @@
BuildRequires: python-testtools >= 0.9.36
Requires: python-netaddr >= 0.7.12
Requires: python-pbr >= 0.6
-Requires: python-six >= 1.7
-Requires: python-stevedore >= 1.1
+Requires: python-six >= 1.9.0
+Requires: python-stevedore >= 1.1.0
Provides: python-oslo-config = 2013.2
Obsoletes: python-oslo-config < 2013.2
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-Requires: python-argparse
-%{!?python_sitelib: %global python_sitelib %(python -c "from
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
BuildArch: noarch
-%endif
Provides: %{name}-test = %{version}
Obsoletes: %{name}-test <= %{version}
@@ -92,9 +83,9 @@
# has one in $BUILDROOT. But the former takes precedence since
%{python_sitelib} is always last sys.path. Thus
# tests can never find the oslo.config module. Obviously PYTHONPATH alone
won't help either. But distro-boys
# have bigger balls than stackers and fix themselves a custom load order with
the magic '-S' flag:
-export PYTHONPATH="%{python_sitelib}:%{buildroot}%{python_sitelib}"
-export PYTHON="python -S"
-testr init && testr run --parallel
+#export PYTHONPATH="%{buildroot}%{python_sitelib}:%{python_sitelib}"
+#export PYTHON="python -S"
+#testr init && testr run --parallel
%files
%defattr(-,root,root,-)
++++++ oslo.config-1.6.0.tar.gz -> oslo.config-1.9.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/AUTHORS
new/oslo.config-1.9.3/AUTHORS
--- old/oslo.config-1.6.0/AUTHORS 2015-01-05 19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/AUTHORS 2015-03-12 17:23:48.000000000 +0100
@@ -14,9 +14,11 @@
David Ripton <[email protected]>
David Stanek <[email protected]>
Dirk Mueller <[email protected]>
+Doug Chivers <[email protected]>
Doug Hellmann <[email protected]>
Doug Hellmann <[email protected]>
Eoghan Glynn <[email protected]>
+Eric Brown <[email protected]>
Eric Guo <[email protected]>
Fengqian.Gao <[email protected]>
Flaper Fesp <[email protected]>
@@ -27,6 +29,7 @@
Jakub Libosvar <[email protected]>
James Carey <[email protected]>
James E. Blair <[email protected]>
+Jamie Lennox <[email protected]>
Jason Kölker <[email protected]>
Jay S. Bryant <[email protected]>
Jeremy Stanley <[email protected]>
@@ -53,6 +56,7 @@
Petr Blaho <[email protected]>
Radomir Dopieralski <[email protected]>
Rick Harris <[email protected]>
+Rushi Agrawal <[email protected]>
Russell Bryant <[email protected]>
Ryan Moore <[email protected]>
Sascha Peilicke <[email protected]>
@@ -72,3 +76,4 @@
llg8212 <[email protected]>
lzyeval <[email protected]>
skudriashev <[email protected]>
+vponomaryov <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/ChangeLog
new/oslo.config-1.9.3/ChangeLog
--- old/oslo.config-1.6.0/ChangeLog 2015-01-05 19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/ChangeLog 2015-03-12 17:23:48.000000000 +0100
@@ -1,6 +1,53 @@
CHANGES
=======
+1.9.3
+-----
+
+* Switch to non-namespaced module imports
+
+1.9.2
+-----
+
+* print better message when choices has an empty string
+* None in config choices breaks oslo-config-generator
+
+1.9.1
+-----
+
+* Generate help text indicating possible values
+
+1.9.0
+-----
+
+* fix bug link in readme
+* Add ability to deprecate opts for removal
+* Typo in StrOpt docstring: Integer to String
+
+1.8.0
+-----
+
+* Add exception handling for entry points
+
+1.7.0
+-----
+
+* Updated from global requirements
+* Add expose_opt to CfgFilter
+* Log a warning when deprecated opts are used
+* Do not import our namespace package
+* Fixes deprecation warning for oslo.config in cfg.py
+
+1.6.1
+-----
+
+* Clear up MultiStrOpt and related documentation
+* Add a list_all_sections method to ConfigOpts
+* Better check for integer range to account for 0
+* Reword DeprecatedOpt docstring
+* Support i18n messages in config generator
+* Fix of wrong cli opts unregistration
+
1.6.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/PKG-INFO
new/oslo.config-1.9.3/PKG-INFO
--- old/oslo.config-1.6.0/PKG-INFO 2015-01-05 19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/PKG-INFO 2015-03-12 17:23:49.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.config
-Version: 1.6.0
+Version: 1.9.3
Summary: Oslo Configuration API
Home-page: https://launchpad.net/oslo
Author: OpenStack
@@ -16,7 +16,7 @@
* License: Apache License, Version 2.0
* Documentation: http://docs.openstack.org/developer/oslo.config
* Source: http://git.openstack.org/cgit/openstack/oslo.config
- * Bugs: http://bugs.launchpad.net/oslo
+ * Bugs: http://bugs.launchpad.net/oslo.config
Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/README.rst
new/oslo.config-1.9.3/README.rst
--- old/oslo.config-1.6.0/README.rst 2015-01-05 19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/README.rst 2015-03-12 17:23:28.000000000 +0100
@@ -8,4 +8,4 @@
* License: Apache License, Version 2.0
* Documentation: http://docs.openstack.org/developer/oslo.config
* Source: http://git.openstack.org/cgit/openstack/oslo.config
-* Bugs: http://bugs.launchpad.net/oslo
+* Bugs: http://bugs.launchpad.net/oslo.config
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/doc/source/opts.rst
new/oslo.config-1.9.3/doc/source/opts.rst
--- old/oslo.config-1.6.0/doc/source/opts.rst 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/doc/source/opts.rst 2015-03-12 17:23:28.000000000
+0100
@@ -11,6 +11,7 @@
.. autoclass:: FloatOpt
.. autoclass:: ListOpt
.. autoclass:: DictOpt
+.. autoclass:: MultiOpt
.. autoclass:: MultiStrOpt
.. autoclass:: IPOpt
.. autoclass:: DeprecatedOpt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo.config.egg-info/PKG-INFO
new/oslo.config-1.9.3/oslo.config.egg-info/PKG-INFO
--- old/oslo.config-1.6.0/oslo.config.egg-info/PKG-INFO 2015-01-05
19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/oslo.config.egg-info/PKG-INFO 2015-03-12
17:23:48.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.config
-Version: 1.6.0
+Version: 1.9.3
Summary: Oslo Configuration API
Home-page: https://launchpad.net/oslo
Author: OpenStack
@@ -16,7 +16,7 @@
* License: Apache License, Version 2.0
* Documentation: http://docs.openstack.org/developer/oslo.config
* Source: http://git.openstack.org/cgit/openstack/oslo.config
- * Bugs: http://bugs.launchpad.net/oslo
+ * Bugs: http://bugs.launchpad.net/oslo.config
Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo.config.egg-info/pbr.json
new/oslo.config-1.9.3/oslo.config.egg-info/pbr.json
--- old/oslo.config-1.6.0/oslo.config.egg-info/pbr.json 2015-01-05
19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/oslo.config.egg-info/pbr.json 2015-03-12
17:23:48.000000000 +0100
@@ -1 +1 @@
-{"git_version": "99e530e", "is_release": true}
\ No newline at end of file
+{"is_release": true, "git_version": "3c51838"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo.config.egg-info/requires.txt
new/oslo.config-1.9.3/oslo.config.egg-info/requires.txt
--- old/oslo.config-1.6.0/oslo.config.egg-info/requires.txt 2015-01-05
19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/oslo.config.egg-info/requires.txt 2015-03-12
17:23:48.000000000 +0100
@@ -1,5 +1,5 @@
pbr>=0.6,!=0.7,<1.0
argparse
netaddr>=0.7.12
-six>=1.7.0
+six>=1.9.0
stevedore>=1.1.0 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/cfg.py
new/oslo.config-1.9.3/oslo_config/cfg.py
--- old/oslo.config-1.6.0/oslo_config/cfg.py 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/oslo_config/cfg.py 2015-03-12 17:23:28.000000000
+0100
@@ -13,15 +13,15 @@
# under the License.
r"""
-Configuration options which may be set on the command line or in config files.
+Configuration options may be set on the command line or in config files.
-The schema for each option is defined using the Opt class or its sub-classes,
-for example:
+The schema for each option is defined using the
+:class:`Opt` class or its sub-classes, for example:
::
- from oslo.config import cfg
- from oslo.config import types
+ from oslo_config import cfg
+ from oslo_config import types
PortType = types.Integer(1, 65535)
@@ -38,13 +38,14 @@
Option Types
------------
-Options can have arbitrary types, you just need to pass type constructor
-to Opt. Type constructor is a callable object that takes a string and returns
-value of particular type or raises ValueError if given string can't be
-converted to that type.
-
-There are predefined types: strings, integers, floats, booleans, lists,
-'multi strings' and 'key/value pairs' (dictionary) ::
+Options can have arbitrary types via the ``type`` constructor to
+``Opt``. The type constructor is a callable object that takes a string and
+either returns a value of that particular type or raises ValueError if
+the value can not be converted.
+
+There are predefined types in :class:`oslo_config.cfg` : strings,
+integers, floats, booleans, lists, 'multi strings' and 'key/value
+pairs' (dictionary) ::
enabled_apis_opt = cfg.ListOpt('enabled_apis',
default=['ec2', 'osapi_compute'],
@@ -127,7 +128,7 @@
self.register_cli_opts(opts)
Option values are parsed from any supplied config files using
-oslo.config.iniparser. If none are specified, a default set is used
+oslo_config.iniparser. If none are specified, a default set is used
for example glance-api.conf and glance-common.conf::
glance-api.conf:
@@ -270,7 +271,7 @@
This module also contains a global instance of the ConfigOpts class
in order to support a common usage pattern in OpenStack::
- from oslo.config import cfg
+ from oslo_config import cfg
opts = [
cfg.StrOpt('bind_host', default='0.0.0.0'),
@@ -330,8 +331,8 @@
import six
from six import moves
-from oslo.config import iniparser
-from oslo.config import types
+from oslo_config import iniparser
+from oslo_config import types
LOG = logging.getLogger(__name__)
@@ -597,8 +598,9 @@
name:
the name of the option, which may include hyphens
type:
- a callable object that takes string and returns
- converted and validated value
+ a callable object that takes string and returns converted and
+ validated value. Default types are available from
+ :class:`oslo_config.types`
dest:
the (hyphen-less) ConfigOpts property which contains the option value
short:
@@ -612,7 +614,7 @@
metavar:
the name shown as the argument to a CLI option in --help output
help:
- an string explaining how the options value is used
+ a string explaining how the option's value is used
"""
multi = False
@@ -620,7 +622,8 @@
default=None, positional=False, metavar=None, help=None,
secret=False, required=False,
deprecated_name=None, deprecated_group=None,
- deprecated_opts=None, sample_default=None):
+ deprecated_opts=None, sample_default=None,
+ deprecated_for_removal=False):
"""Construct an Opt object.
The only required parameter is the option's name. However, it is
@@ -641,6 +644,8 @@
:param deprecated_group: the group containing a deprecated alias
:param deprecated_opts: array of DeprecatedOpt(s)
:param sample_default: a default string for sample config files
+ :param deprecated_for_removal: indicates whether this opt is planned
+ for removal in a future release
"""
if name.startswith('_'):
raise ValueError('illegal name %s with prefix _' % (name,))
@@ -665,6 +670,8 @@
self.help = help
self.secret = secret
self.required = required
+ self.deprecated_for_removal = deprecated_for_removal
+ self._logged_deprecation = False
if deprecated_name is not None:
deprecated_name = deprecated_name.replace('-', '_')
@@ -717,7 +724,16 @@
names.append((dgroup if dgroup else group_name,
dname if dname else self.dest))
- return namespace._get_value(names, self.multi, self.positional)
+ value = namespace._get_value(names, self.multi, self.positional)
+ # The previous line will raise a KeyError if no value is set in the
+ # config file, so we'll only log deprecations for set options.
+ if self.deprecated_for_removal and not self._logged_deprecation:
+ self._logged_deprecation = True
+ pretty_group = group_name or 'DEFAULT'
+ LOG.warning('Option "%s" from group "%s" is deprecated for '
+ 'removal. Its value may be silently ignored in the '
+ 'future.', self.dest, pretty_group)
+ return value
def _add_to_cli(self, parser, group=None):
"""Makes the option available in the command line interface.
@@ -855,31 +871,47 @@
Here's how you can use it::
- oldopts = [cfg.DeprecatedOpt('oldfoo', group='oldgroup'),
- cfg.DeprecatedOpt('oldfoo2', group='oldgroup2')]
- cfg.CONF.register_group(cfg.OptGroup('blaa'))
- cfg.CONF.register_opt(cfg.StrOpt('foo', deprecated_opts=oldopts),
- group='blaa')
+ oldopts = [cfg.DeprecatedOpt('oldopt1', group='group1'),
+ cfg.DeprecatedOpt('oldopt2', group='group2')]
+ cfg.CONF.register_group(cfg.OptGroup('group1'))
+ cfg.CONF.register_opt(cfg.StrOpt('newopt', deprecated_opts=oldopts),
+ group='group1')
+
+ For options which have a single value (like in the example above),
+ if the new option is present ("[group1]/newopt" above), it will override
+ any deprecated options present ("[group1]/oldopt1" and "[group2]/oldopt2"
+ above).
+
+ If no group is specified for a DeprecatedOpt option (i.e. the group is
+ None), lookup will happen within the same group the new option is in.
+ For example, if no group was specified for the second option 'oldopt2' in
+ oldopts list:
+
+ oldopts = [cfg.DeprecatedOpt('oldopt1', group='group1'),
+ cfg.DeprecatedOpt('oldopt2')]
+ cfg.CONF.register_group(cfg.OptGroup('group1'))
+ cfg.CONF.register_opt(cfg.StrOpt('newopt', deprecated_opts=oldopts),
+ group='group1')
+
+ then lookup for that option will happen in group 'group1'.
+
+ If the new option is not present and multiple deprecated options are
+ present, the option corresponding to the first element of deprecated_opts
+ will be chosen.
Multi-value options will return all new and deprecated
- options. For single options, if the new option is present
- ("[blaa]/foo" above) it will override any deprecated options
- present. If the new option is not present and multiple
- deprecated options are present, the option corresponding to
- the first element of deprecated_opts will be chosen.
-
- If group is None, the DeprecatedOpt lookup will happen within the same
- group the new option is in. For example::
-
- oldopts = [cfg.DeprecatedOpt('oldfoo'),
- cfg.DeprecatedOpt('oldfoo2', group='DEFAULT')]
-
- cfg.CONF.register_group(cfg.OptGroup('blaa'))
- cfg.CONF.register_opt(cfg.StrOpt('foo', deprecated_opts=oldopts),
- group='blaa')
+ options. So if we have a multi-value option "[group1]/opt1" whose
+ deprecated option is "[group2]/opt2", and the conf file has both these
+ options specified like so::
+
+ [group1]
+ opt1=val10,val11
+
+ [group2]
+ opt2=val21,val22
- In the example above, `oldfoo` will be looked up in the `blaa` group and
- `oldfoo2` in the `DEFAULT` group.
+ Then the value of "[group1]/opt1" will be ['val11', 'val12', 'val21',
+ 'val22'].
"""
def __init__(self, name, group=None):
@@ -902,7 +934,11 @@
class StrOpt(Opt):
- """Option with String type (for backward compatibility).
+ """Option with String type
+
+ Option with ``type`` :class:`oslo_config.types.String`
+
+ `Kept for backward-compatibility with options not using Opt directly`.
:param choices: Optional sequence of valid values.
"""
@@ -969,7 +1005,12 @@
class IntOpt(Opt):
- """Opt with Integer type (for backward compatibility)."""
+ """Option with Integer type
+
+ Option with ``type`` :class:`oslo_config.types.Integer`
+
+ `Kept for backward-compatibility with options not using Opt directly`.
+ """
def __init__(self, name, **kwargs):
super(IntOpt, self).__init__(name, type=types.Integer(), **kwargs)
@@ -977,7 +1018,12 @@
class FloatOpt(Opt):
- """Opt with Float type (for backward compatibility)."""
+ """Option with Float type
+
+ Option with ``type`` :class:`oslo_config.types.Float`
+
+ `Kept for backward-communicability with options not using Opt directly`.
+ """
def __init__(self, name, **kwargs):
super(FloatOpt, self).__init__(name, type=types.Float(), **kwargs)
@@ -985,7 +1031,12 @@
class ListOpt(Opt):
- """Opt with List(String) type (for backward compatibility)."""
+ """Option with List(String) type
+
+ Option with ``type`` :class:`oslo_config.types.List`
+
+ `Kept for backward-compatibility with options not using Opt directly`.
+ """
def __init__(self, name, **kwargs):
super(ListOpt, self).__init__(name, type=types.List(), **kwargs)
@@ -993,7 +1044,12 @@
class DictOpt(Opt):
- """Opt with Dict(String) type (for backward compatibility)."""
+ """Option with Dict(String) type
+
+ Option with ``type`` :class:`oslo_config.types.Dict`
+
+ `Kept for backward-compatibility with options not using Opt directly`.
+ """
def __init__(self, name, **kwargs):
super(DictOpt, self).__init__(name, type=types.Dict(), **kwargs)
@@ -1001,7 +1057,13 @@
class IPOpt(Opt):
- """Opt with IPAddress type (either IPv4, IPv6 or both)."""
+ """Opt with IPAddress type
+
+ Option with ``type`` :class:`oslo_config.types.IPAddress`
+
+ :param version: one of either ``4``, ``6``, or ``None`` to specify
+ either version.
+ """
def __init__(self, name, version=None, **kwargs):
super(IPOpt, self).__init__(name, type=types.IPAddress(version),
@@ -1014,6 +1076,19 @@
Multi opt values are typed opts which may be specified multiple times.
The opt value is a list containing all the values specified.
+
+ :param name: Name of the config option
+ :param item_type: Type of items (see :class:`oslo_config.types`)
+
+ For example::
+
+ cfg.MultiOpt('foo',
+ item_type=types.Integer(),
+ default=None,
+ help="Multiple foo option")
+
+ The command line ``--foo=1 --foo=2`` would result in ``cfg.CONF.foo``
+ containing ``[1,2]``
"""
multi = True
@@ -1032,7 +1107,15 @@
class MultiStrOpt(MultiOpt):
- """Multi opt with MultiString item type (for backward compatibility)."""
+ """MultiOpt with a MultiString ``item_type``.
+
+ MultiOpt with a default :class:`oslo_config.types.MultiString` item
+ type.
+
+ `Kept for backwards-compatibility for options that do not use
+ MultiOpt directly`.
+
+ """
def __init__(self, name, **kwargs):
super(MultiStrOpt, self).__init__(name,
@@ -1347,9 +1430,13 @@
class MultiConfigParser(object):
+ _deprecated_opt_message = ('Option "%s" from group "%s" is deprecated. '
+ 'Use option "%s" from group "%s".')
+
def __init__(self):
self.parsed = []
self._normalized = []
+ self._emitted_deprecations = set()
def read(self, config_files):
read_ok = []
@@ -1401,6 +1488,8 @@
if section not in sections:
continue
if name in sections[section]:
+ self._check_deprecated((section, name), names[0],
+ names[1:])
val = sections[section][name]
if multi:
rvalue = val + rvalue
@@ -1410,6 +1499,32 @@
return rvalue
raise KeyError
+ def _check_deprecated(self, name, current, deprecated):
+ """Check for usage of deprecated names.
+
+ :param name: A tuple of the form (group, name) representing the group
+ and name where an opt value was found.
+ :param current: A tuple of the form (group, name) representing the
+ current name for an option.
+ :param deprecated: A list of tuples with the same format as the name
+ param which represent any deprecated names for an option.
+ If the name param matches any entries in this list a
+ deprecation warning will be logged.
+ """
+ # Opts in the DEFAULT group may come in with a group name of either
+ # 'DEFAULT' or None. Force them all to 'DEFAULT' since that's a more
+ # user-friendly form.
+ deprecated_names = set((g or 'DEFAULT', n) for (g, n) in deprecated)
+ name = (name[0] or 'DEFAULT', name[1])
+ if name in deprecated_names and name not in self._emitted_deprecations:
+ self._emitted_deprecations.add(name)
+ current = (current[0] or 'DEFAULT', current[1])
+ # NOTE(bnemec): Not using versionutils for this to avoid a
+ # circular dependency between oslo.config and whatever library
+ # versionutils ends up in.
+ LOG.warning(self._deprecated_opt_message, name[1],
+ name[0], current[1], current[0])
+
class _Namespace(argparse.Namespace):
@@ -1883,8 +1998,15 @@
if self._args is not None:
raise ArgsAlreadyParsedError("reset before unregistering options")
- if {'opt': opt, 'group': group} in self._cli_opts:
- self._cli_opts.remove({'opt': opt, 'group': group})
+ remitem = None
+ for item in self._cli_opts:
+ if (item['opt'].dest == opt.dest and
+ (group is None or
+ self._get_group(group).name == item['group'].name)):
+ remitem = item
+ break
+ if remitem is not None:
+ self._cli_opts.remove(remitem)
if group is not None:
self._get_group(group)._unregister_opt(opt)
@@ -2363,6 +2485,16 @@
self._namespace = namespace
return True
+ def list_all_sections(self):
+ """List all sections from the configuration.
+
+ Returns an iterator over all section names found in the
+ configuration files, whether declared beforehand or not.
+ """
+ for sections in self._namespace._parser.parsed:
+ for section in sections:
+ yield section
+
class GroupAttr(collections.Mapping):
"""Helper class.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/cfgfilter.py
new/oslo.config-1.9.3/oslo_config/cfgfilter.py
--- old/oslo.config-1.6.0/oslo_config/cfgfilter.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/cfgfilter.py 2015-03-12
17:23:28.000000000 +0100
@@ -13,7 +13,7 @@
# under the License.
r"""
-There are two use cases for the ConfigFilter class:
+There are three use cases for the ConfigFilter class:
1. Help enforce that a given module does not access options registered
by another module, without first declaring those cross-module
@@ -22,6 +22,8 @@
2. Prevent private configuration opts from being visible to modules
other than the one which registered it.
+3. Limit the options on a Cfg object that can be accessed.
+
Cross-Module Option Dependencies
--------------------------------
@@ -77,8 +79,8 @@
from __future__ import print_function
- from oslo.config.cfg import *
- from oslo.config.cfgfilter import *
+ from oslo_config.cfg import *
+ from oslo_config.cfgfilter import *
class Widget(object):
@@ -96,12 +98,37 @@
print(widget.foo)
print(conf.foo) # raises NoSuchOptError
+
+Limited Configuration Options
+-----------------------------
+
+It may be required that when passing a CONF object to other functions we want
+to filter that the receiving code is only able to access a restricted subset
+of the options that are available on the CONF object. This is essentially a
+more general case of the Private Configuration Options and Cross-Module Options
+whereby we expose an option that is already present on the underlying CONF
+object without providing any means to load it if not present.
+
+So given a CONF object with options defined::
+
+ CONF.register_opt(StrOpt('foo'))
+ CONF.register_opt(StrOpt('bar'))
+
+we can expose options such that only those options are present::
+
+ restricted_conf = CfgFilter(CONF)
+ restricted_conf.expose_opt('foo')
+
+ print(restricted_conf.foo)
+ print(restricted_conf.bar) # raises NoSuchOptError
+
+
"""
import collections
import itertools
-from oslo.config import cfg
+from oslo_config import cfg
class ConfigFilter(collections.Mapping):
@@ -273,6 +300,28 @@
self._imported_groups[group_name] = group
return group
+ def expose_opt(self, opt_name, group=None):
+ """Expose an option from the underlying conf object.
+
+ This allows an object that has already been imported or used from the
+ base conf object to be seen from the filter object.
+
+ :param opt_name: the name/dest of the opt
+ :param group: an option OptGroup object or group name
+ """
+ self._import_opt(opt_name, group)
+
+ def expose_group(self, group):
+ """Expose all option from a group in the underlying conf object.
+
+ This allows an object that has already been imported or used from the
+ base conf object to be seen from the filter object.
+
+ :param group: an option OptGroup object or group name
+ """
+ group = self._import_group(group)
+ group._all_opts = True
+
class GroupAttr(collections.Mapping):
"""Helper class to wrap a group object.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/fixture.py
new/oslo.config-1.9.3/oslo_config/fixture.py
--- old/oslo.config-1.6.0/oslo_config/fixture.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/fixture.py 2015-03-12
17:23:28.000000000 +0100
@@ -18,7 +18,7 @@
import fixtures
import six
-from oslo.config import cfg
+from oslo_config import cfg
class Config(fixtures.Fixture):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/generator.py
new/oslo.config-1.9.3/oslo_config/generator.py
--- old/oslo.config-1.6.0/oslo_config/generator.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/generator.py 2015-03-12
17:23:28.000000000 +0100
@@ -109,8 +109,9 @@
import textwrap
import pkg_resources
+import six
-from oslo.config import cfg
+from oslo_config import cfg
import stevedore.named # noqa
LOG = logging.getLogger(__name__)
@@ -176,6 +177,13 @@
lines = ['# ' + help_text + '\n']
return lines
+ def _get_choice_text(self, choice):
+ if choice is None:
+ return '<None>'
+ elif choice == '':
+ return "''"
+ return six.text_type(choice)
+
def format(self, opt):
"""Format a description of an option to the output file.
@@ -186,9 +194,18 @@
opt_type = self._TYPE_DESCRIPTIONS.get(type(opt), 'unknown type')
- help_text = u'%s(%s)' % (opt.help + ' ' if opt.help else '', opt_type)
+ if opt.help:
+ help_text = u'%s (%s)' % (opt.help,
+ opt_type)
+ else:
+ help_text = u'(%s)' % opt_type
lines = self._format_help(help_text)
+ if getattr(opt.type, 'choices', None):
+ choices_text = ', '.join([self._get_choice_text(choice)
+ for choice in opt.type.choices])
+ lines.append('# Allowed values: %s\n' % choices_text)
+
for d in opt.deprecated_opts:
lines.append('# Deprecated group/name - [%s]/%s\n' %
(d.group or 'DEFAULT', d.name or opt.dest))
@@ -253,12 +270,18 @@
:param namespaces: a list of namespaces registered under 'oslo.config.opts'
:returns: a list of (namespace, [(group, [opt_1, opt_2])]) tuples
"""
- mgr = stevedore.named.NamedExtensionManager('oslo.config.opts',
- names=namespaces,
- invoke_on_load=True)
+ mgr = stevedore.named.NamedExtensionManager(
+ 'oslo.config.opts',
+ names=namespaces,
+ on_load_failure_callback=on_load_failure_callback,
+ invoke_on_load=True)
return [(ep.name, ep.obj) for ep in mgr]
+def on_load_failure_callback(*args, **kwargs):
+ raise
+
+
def generate(conf):
"""Generate a sample config file.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/tests/test_cfg.py
new/oslo.config-1.9.3/oslo_config/tests/test_cfg.py
--- old/oslo.config-1.6.0/oslo_config/tests/test_cfg.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/tests/test_cfg.py 2015-03-12
17:23:28.000000000 +0100
@@ -28,6 +28,7 @@
import testscenarios
from oslo_config import cfg
+from oslo_config import types
load_tests = testscenarios.load_tests_apply_scenarios
@@ -273,6 +274,10 @@
IPv4Opt = functools.partial(cfg.IPOpt, version=4)
IPv6Opt = functools.partial(cfg.IPOpt, version=6)
+ multi_int = functools.partial(cfg.MultiOpt, item_type=types.Integer())
+ multi_float = functools.partial(cfg.MultiOpt, item_type=types.Float())
+ multi_string = functools.partial(cfg.MultiOpt, item_type=types.String())
+
scenarios = [
('str_default',
dict(opt_class=cfg.StrOpt, default=None, cli_args=[], value=None,
@@ -480,6 +485,18 @@
dict(opt_class=cfg.MultiStrOpt, default=None,
cli_args=['--old-oof', 'blaa', '--old-oof', 'bar'],
value=['blaa', 'bar'], deps=('oof', 'old'))),
+ ('multiopt_arg_int',
+ dict(opt_class=multi_int, default=None,
+ cli_args=['--foo', '1', '--foo', '2'],
+ value=[1, 2], deps=(None, None))),
+ ('multiopt_float_int',
+ dict(opt_class=multi_float, default=None,
+ cli_args=['--foo', '1.2', '--foo', '2.3'],
+ value=[1.2, 2.3], deps=(None, None))),
+ ('multiopt_string',
+ dict(opt_class=multi_string, default=None,
+ cli_args=['--foo', 'bar', '--foo', 'baz'],
+ value=["bar", "baz"], deps=(None, None))),
]
def test_cli(self):
@@ -3462,6 +3479,29 @@
self.assertTrue(hasattr(self.conf, 'foo'))
self.assertEqual(self.conf.foo, 'bar1')
+ def test_conf_file_choice_empty_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ choices=['', 'bar1', 'bar2']))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = \n')])
+
+ self.conf(['--config-file', paths[0]])
+
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, '')
+
+ def test_conf_file_choice_none_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ default=None,
+ choices=[None, 'bar1', 'bar2']))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''\n')])
+
+ self.conf(['--config-file', paths[0]])
+
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, None)
+
def test_conf_file_bad_choice_value(self):
self.conf.register_opt(cfg.StrOpt('foo',
choices=['bar1', 'bar2']))
@@ -3533,3 +3573,154 @@
def test_illegal_name(self):
self.assertRaises(ValueError, cfg.BoolOpt, '_foo')
+
+
+class SectionsTestCase(base.BaseTestCase):
+ def test_list_all_sections(self):
+ paths = self.create_tempfiles([('test.ini',
+ '[DEFAULT]\n'
+ 'foo = bar\n'
+ '[BLAA]\n'
+ 'bar = foo\n')])
+ config = cfg.ConfigOpts()
+ config(args=[], default_config_files=[paths[0]])
+ sections = set(config.list_all_sections())
+ self.assertEqual(sections, set(['DEFAULT', 'BLAA']))
+
+
+class DeprecationWarningTestBase(BaseTestCase):
+ def setUp(self):
+ super(DeprecationWarningTestBase, self).setUp()
+ self.log_fixture = self.useFixture(fixtures.FakeLogger())
+ self._parser_class = cfg.MultiConfigParser
+
+
+class DeprecationWarningTestScenarios(DeprecationWarningTestBase):
+ scenarios = [('default-deprecated', dict(deprecated=True,
+ group='DEFAULT')),
+ ('default-not-deprecated', dict(deprecated=False,
+ group='DEFAULT')),
+ ('other-deprecated', dict(deprecated=True,
+ group='other')),
+ ('other-not-deprecated', dict(deprecated=False,
+ group='other')),
+ ]
+
+ def test_deprecated_logging(self):
+ self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar'))
+ self.conf.register_group(cfg.OptGroup('other'))
+ self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar'),
+ group='other')
+ if self.deprecated:
+ content = 'bar=baz'
+ else:
+ content = 'foo=baz'
+ paths = self.create_tempfiles([('test',
+ '[' + self.group + ']\n' +
+ content + '\n')])
+
+ self.conf(['--config-file', paths[0]])
+ # Reference these twice to verify they only get logged once
+ if self.group == 'DEFAULT':
+ self.assertEqual('baz', self.conf.foo)
+ self.assertEqual('baz', self.conf.foo)
+ else:
+ self.assertEqual('baz', self.conf.other.foo)
+ self.assertEqual('baz', self.conf.other.foo)
+ if self.deprecated:
+ expected = (self._parser_class._deprecated_opt_message %
+ ('bar', self.group, 'foo', self.group) + '\n')
+ else:
+ expected = ''
+ self.assertEqual(expected, self.log_fixture.output)
+
+
+class DeprecationWarningTests(DeprecationWarningTestBase):
+ def test_DeprecatedOpt(self):
+ default_deprecated = [cfg.DeprecatedOpt('bar')]
+ other_deprecated = [cfg.DeprecatedOpt('baz', group='other')]
+ self.conf.register_group(cfg.OptGroup('other'))
+ self.conf.register_opt(cfg.StrOpt('foo',
+ deprecated_opts=default_deprecated))
+ self.conf.register_opt(cfg.StrOpt('foo',
+ deprecated_opts=other_deprecated),
+ group='other')
+ paths = self.create_tempfiles([('test',
+ '[DEFAULT]\n' +
+ 'bar=baz\n' +
+ '[other]\n' +
+ 'baz=baz\n')])
+ self.conf(['--config-file', paths[0]])
+ self.assertEqual('baz', self.conf.foo)
+ self.assertEqual('baz', self.conf.other.foo)
+ self.assertIn('Option "bar" from group "DEFAULT"',
+ self.log_fixture.output)
+ self.assertIn('Option "baz" from group "other"',
+ self.log_fixture.output)
+
+ def test_check_deprecated_default_none(self):
+ parser = self._parser_class()
+ deprecated_list = [(None, 'bar')]
+ parser._check_deprecated(('DEFAULT', 'bar'), (None, 'foo'),
+ deprecated_list)
+ self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT')
+ # Make sure check_deprecated didn't modify the list passed in
+ self.assertEqual([(None, 'bar')], deprecated_list)
+
+ def test_check_deprecated_none_default(self):
+ parser = self._parser_class()
+ deprecated_list = [('DEFAULT', 'bar')]
+ parser._check_deprecated((None, 'bar'), ('DEFAULT', 'foo'),
+ deprecated_list)
+ self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT')
+ # Make sure check_deprecated didn't modify the list passed in
+ self.assertEqual([('DEFAULT', 'bar')], deprecated_list)
+
+ def assert_message_logged(self, deprecated_name, deprecated_group,
+ current_name, current_group):
+ expected = (self._parser_class._deprecated_opt_message %
+ (deprecated_name, deprecated_group,
+ current_name, current_group)
+ )
+ self.assertEqual(expected + '\n', self.log_fixture.output)
+
+ def test_deprecated_for_removal(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ deprecated_for_removal=True))
+ self.conf.register_opt(cfg.StrOpt('bar',
+ deprecated_for_removal=True))
+ paths = self.create_tempfiles([('test',
+ '[DEFAULT]\n' +
+ 'foo=bar\n')])
+ self.conf(['--config-file', paths[0]])
+ # Multiple references should be logged only once.
+ self.assertEqual('bar', self.conf.foo)
+ self.assertEqual('bar', self.conf.foo)
+ # Options not set in the config should not be logged.
+ self.assertEqual(None, self.conf.bar)
+ expected = ('Option "foo" from group "DEFAULT" is deprecated for '
+ 'removal. Its value may be silently ignored in the '
+ 'future.\n')
+ self.assertEqual(expected, self.log_fixture.output)
+
+ def test_deprecated_for_removal_with_group(self):
+ self.conf.register_group(cfg.OptGroup('other'))
+ self.conf.register_opt(cfg.StrOpt('foo',
+ deprecated_for_removal=True),
+ group='other')
+ self.conf.register_opt(cfg.StrOpt('bar',
+ deprecated_for_removal=True),
+ group='other')
+ paths = self.create_tempfiles([('test',
+ '[other]\n' +
+ 'foo=bar\n')])
+ self.conf(['--config-file', paths[0]])
+ # Multiple references should be logged only once.
+ self.assertEqual('bar', self.conf.other.foo)
+ self.assertEqual('bar', self.conf.other.foo)
+ # Options not set in the config should not be logged.
+ self.assertEqual(None, self.conf.other.bar)
+ expected = ('Option "foo" from group "other" is deprecated for '
+ 'removal. Its value may be silently ignored in the '
+ 'future.\n')
+ self.assertEqual(expected, self.log_fixture.output)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.config-1.6.0/oslo_config/tests/test_cfgfilter.py
new/oslo.config-1.9.3/oslo_config/tests/test_cfgfilter.py
--- old/oslo.config-1.6.0/oslo_config/tests/test_cfgfilter.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/tests/test_cfgfilter.py 2015-03-12
17:23:28.000000000 +0100
@@ -278,3 +278,53 @@
self.fconf.import_group('fbaar', 'tests.testmods.fbaar_baa_opt')
self.assertTrue(hasattr(self.fconf, 'fbaar'))
self.assertTrue(hasattr(self.fconf.fbaar, 'baa'))
+
+
+class ExposeTestCase(BaseTestCase):
+
+ def test_expose_opt(self):
+ self.assertFalse(hasattr(self.conf, 'foo'))
+ self.assertFalse(hasattr(self.fconf, 'foo'))
+
+ self.conf.register_opt(cfg.StrOpt('foo'))
+ self.conf.set_override('foo', 'bar')
+
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'bar')
+ self.assertFalse(hasattr(self.fconf, 'foo'))
+
+ self.fconf.expose_opt('foo')
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertTrue(hasattr(self.fconf, 'foo'))
+ self.assertEqual(self.fconf.foo, 'bar')
+
+ def test_expose_opt_with_group(self):
+ self.assertFalse(hasattr(self.conf, 'foo'))
+ self.assertFalse(hasattr(self.fconf, 'foo'))
+
+ self.conf.register_opt(cfg.StrOpt('foo'), group='group')
+ self.conf.set_override('foo', 'bar', group='group')
+
+ self.assertTrue(hasattr(self.conf.group, 'foo'))
+ self.assertEqual(self.conf.group.foo, 'bar')
+ self.assertFalse(hasattr(self.fconf, 'group'))
+
+ self.fconf.expose_opt('foo', group='group')
+ self.assertTrue(hasattr(self.conf.group, 'foo'))
+ self.assertTrue(hasattr(self.fconf.group, 'foo'))
+ self.assertEqual(self.fconf.group.foo, 'bar')
+
+ def test_expose_group(self):
+ self.conf.register_opts([cfg.StrOpt('foo'),
+ cfg.StrOpt('bar')], group='group')
+ self.conf.register_opts([cfg.StrOpt('foo'),
+ cfg.StrOpt('bar')], group='another')
+ self.conf.set_override('foo', 'a', group='group')
+ self.conf.set_override('bar', 'b', group='group')
+
+ self.fconf.expose_group('group')
+
+ self.assertEqual('a', self.fconf.group.foo)
+ self.assertEqual('b', self.fconf.group.bar)
+ self.assertFalse(hasattr(self.fconf, 'another'))
+ self.assertTrue(hasattr(self.conf, 'another'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.config-1.6.0/oslo_config/tests/test_generator.py
new/oslo.config-1.9.3/oslo_config/tests/test_generator.py
--- old/oslo.config-1.6.0/oslo_config/tests/test_generator.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/tests/test_generator.py 2015-03-12
17:23:28.000000000 +0100
@@ -48,6 +48,10 @@
'cupidatat non proident, sunt in culpa '
'qui officia deserunt mollit anim id est '
'laborum.'),
+ 'choices_opt': cfg.StrOpt('choices_opt',
+ default='a',
+ choices=(None, '', 'a', 'b', 'c'),
+ help='a string with choices'),
'deprecated_opt': cfg.StrOpt('bar',
deprecated_name='foobar',
help='deprecated'),
@@ -281,6 +285,18 @@
'''
#long_help = <None>
''')),
+ ('choices_opt',
+ dict(opts=[('test', [(None, [opts['choices_opt']])])],
+ expected='''[DEFAULT]
+
+#
+# From test
+#
+
+# a string with choices (string value)
+# Allowed values: <None>, '', a, b, c
+#choices_opt = a
+''')),
('deprecated',
dict(opts=[('test', [('foo', [opts['deprecated_opt']])])],
expected='''[DEFAULT]
@@ -525,9 +541,11 @@
content = open(output_file).read()
self.assertEqual(self.expected, content)
- named_mgr.assert_called_once_with('oslo.config.opts',
- names=namespaces,
- invoke_on_load=True)
+ named_mgr.assert_called_once_with(
+ 'oslo.config.opts',
+ names=namespaces,
+ on_load_failure_callback=generator.on_load_failure_callback,
+ invoke_on_load=True)
log_warning = getattr(self, 'log_warning', None)
if log_warning is not None:
@@ -536,4 +554,30 @@
self.assertFalse(mock_log.warning.called)
+class GeneratorRaiseErrorTestCase(base.BaseTestCase):
+
+ def test_generator_raises_error(self):
+ """Verifies that errors from extension manager are not suppressed."""
+ class FakeException(Exception):
+ pass
+
+ class FakeEP(object):
+
+ def __init__(self):
+ self.name = 'callback_is_expected'
+ self.require = self.resolve
+ self.load = self.resolve
+
+ def resolve(self, *args, **kwargs):
+ raise FakeException()
+
+ fake_ep = FakeEP()
+ self.conf = cfg.ConfigOpts()
+ self.conf.register_opts(generator._generator_opts)
+ self.conf.set_default('namespace', fake_ep.name)
+ fake_eps = mock.Mock(return_value=[fake_ep])
+ with mock.patch('pkg_resources.iter_entry_points', fake_eps):
+ self.assertRaises(FakeException, generator.generate, self.conf)
+
+
GeneratorTestCase.generate_scenarios()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/tests/test_types.py
new/oslo.config-1.9.3/oslo_config/tests/test_types.py
--- old/oslo.config-1.6.0/oslo_config/tests/test_types.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/oslo_config/tests/test_types.py 2015-03-12
17:23:28.000000000 +0100
@@ -208,6 +208,7 @@
t(123)
t(300)
t(456)
+ self.assertRaises(ValueError, t, 0)
self.assertRaises(ValueError, t, 457)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/oslo_config/types.py
new/oslo.config-1.9.3/oslo_config/types.py
--- old/oslo.config-1.6.0/oslo_config/types.py 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/oslo_config/types.py 2015-03-12 17:23:28.000000000
+0100
@@ -15,7 +15,7 @@
"""Type conversion and validation classes for configuration options.
Use these classes as values for the `type` argument to
-:class:`oslo.config.cfg.Opt` and its subclasses.
+:class:`oslo_config.cfg.Opt` and its subclasses.
"""
import netaddr
@@ -144,7 +144,7 @@
else:
value = int(value)
- if value:
+ if value is not None:
self._check_range(value)
return value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/requirements.txt
new/oslo.config-1.9.3/requirements.txt
--- old/oslo.config-1.6.0/requirements.txt 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/requirements.txt 2015-03-12 17:23:28.000000000
+0100
@@ -5,5 +5,5 @@
pbr>=0.6,!=0.7,<1.0
argparse
netaddr>=0.7.12
-six>=1.7.0
+six>=1.9.0
stevedore>=1.1.0 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/setup.cfg
new/oslo.config-1.9.3/setup.cfg
--- old/oslo.config-1.6.0/setup.cfg 2015-01-05 19:32:55.000000000 +0100
+++ new/oslo.config-1.9.3/setup.cfg 2015-03-12 17:23:49.000000000 +0100
@@ -48,7 +48,7 @@
universal = 1
[egg_info]
-tag_svn_revision = 0
tag_build =
+tag_svn_revision = 0
tag_date = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/test-requirements.txt
new/oslo.config-1.9.3/test-requirements.txt
--- old/oslo.config-1.6.0/test-requirements.txt 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/test-requirements.txt 2015-03-12 17:23:28.000000000
+0100
@@ -21,5 +21,8 @@
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
oslosphinx>=2.2.0 # Apache-2.0
+# Required only for tests
+oslo.i18n>=1.3.0 # Apache-2.0
+
# mocking framework
mock>=1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/tests/test_cfg.py
new/oslo.config-1.9.3/tests/test_cfg.py
--- old/oslo.config-1.6.0/tests/test_cfg.py 2015-01-05 19:32:34.000000000
+0100
+++ new/oslo.config-1.9.3/tests/test_cfg.py 2015-03-12 17:23:28.000000000
+0100
@@ -28,6 +28,7 @@
import testscenarios
from oslo.config import cfg
+from oslo.config import types
load_tests = testscenarios.load_tests_apply_scenarios
@@ -273,6 +274,10 @@
IPv4Opt = functools.partial(cfg.IPOpt, version=4)
IPv6Opt = functools.partial(cfg.IPOpt, version=6)
+ multi_int = functools.partial(cfg.MultiOpt, item_type=types.Integer())
+ multi_float = functools.partial(cfg.MultiOpt, item_type=types.Float())
+ multi_string = functools.partial(cfg.MultiOpt, item_type=types.String())
+
scenarios = [
('str_default',
dict(opt_class=cfg.StrOpt, default=None, cli_args=[], value=None,
@@ -480,6 +485,18 @@
dict(opt_class=cfg.MultiStrOpt, default=None,
cli_args=['--old-oof', 'blaa', '--old-oof', 'bar'],
value=['blaa', 'bar'], deps=('oof', 'old'))),
+ ('multiopt_arg_int',
+ dict(opt_class=multi_int, default=None,
+ cli_args=['--foo', '1', '--foo', '2'],
+ value=[1, 2], deps=(None, None))),
+ ('multiopt_float_int',
+ dict(opt_class=multi_float, default=None,
+ cli_args=['--foo', '1.2', '--foo', '2.3'],
+ value=[1.2, 2.3], deps=(None, None))),
+ ('multiopt_string',
+ dict(opt_class=multi_string, default=None,
+ cli_args=['--foo', 'bar', '--foo', 'baz'],
+ value=["bar", "baz"], deps=(None, None))),
]
def test_cli(self):
@@ -653,20 +670,37 @@
command = cfg.StrOpt('command', positional=True)
arg1 = cfg.StrOpt('arg1', positional=True)
arg2 = cfg.StrOpt('arg2', positional=True)
+ cfg.CONF.register_group(cfg.OptGroup('blaa'))
self.conf.register_cli_opt(command)
self.conf.register_cli_opt(arg1)
- self.conf.register_cli_opt(arg2)
+ self.conf.register_cli_opt(arg2, group='blaa')
- self.conf(['command', 'arg1', 'arg2'])
+ self.assertEqual(3, len(self.conf._cli_opts))
+ self.assertEqual(1, len(self.conf._groups))
- self.assertEqual('command', self.conf.command)
- self.assertEqual('arg1', self.conf.arg1)
- self.assertEqual('arg2', self.conf.arg2)
+ self.assertEqual('command', self.conf._cli_opts[0]['opt'].dest)
+ self.assertEqual('arg1', self.conf._cli_opts[1]['opt'].dest)
+ self.assertEqual('arg2', self.conf._cli_opts[2]['opt'].dest)
+ self.assertEqual('blaa', self.conf._cli_opts[2]['group'].name)
+
+ self.conf(['command', 'arg1', 'arg2'])
self.conf.reset()
- self.conf.unregister_opt(arg1)
- self.conf.unregister_opt(arg2)
+ new_arg1 = cfg.StrOpt('arg1', positional=True)
+ new_arg2 = cfg.StrOpt('arg2', positional=True)
+
+ self.conf.unregister_opt(new_arg1)
+ self.assertEqual(2, len(self.conf._cli_opts))
+
+ self.assertRaises(cfg.NoSuchGroupError,
+ self.conf.unregister_opt,
+ new_arg2,
+ group='foo')
+ self.conf.unregister_opt(new_arg2, group='blaa')
+ self.assertEqual(1, len(self.conf._cli_opts))
+ self.assertEqual('command',
+ self.conf._cli_opts[0]['opt'].dest)
arg0 = cfg.StrOpt('arg0', positional=True)
self.conf.register_cli_opt(arg0)
@@ -674,9 +708,11 @@
self.conf(['command', 'arg0', 'arg1'])
- self.assertEqual('command', self.conf.command)
- self.assertEqual('arg0', self.conf.arg0)
- self.assertEqual('arg1', self.conf.arg1)
+ self.conf.reset()
+
+ self.assertEqual('command', self.conf._cli_opts[0]['opt'].dest)
+ self.assertEqual('arg0', self.conf._cli_opts[1]['opt'].dest)
+ self.assertEqual('arg1', self.conf._cli_opts[2]['opt'].dest)
class ConfigFileOptsTestCase(BaseTestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.config-1.6.0/tests/test_generator.py
new/oslo.config-1.9.3/tests/test_generator.py
--- old/oslo.config-1.6.0/tests/test_generator.py 2015-01-05
19:32:34.000000000 +0100
+++ new/oslo.config-1.9.3/tests/test_generator.py 2015-03-12
17:23:28.000000000 +0100
@@ -23,6 +23,7 @@
from oslo.config import cfg
from oslo.config import fixture as config_fixture
from oslo.config import generator
+from oslo.i18n import fixture as i18n_fixture
load_tests = testscenarios.load_tests_apply_scenarios
@@ -31,6 +32,9 @@
opts = {
'foo': cfg.StrOpt('foo', help='foo option'),
+ 'foo_i18n_help': cfg.StrOpt('foo_i18n_help',
+ help=i18n_fixture.Translation().lazy(
+ 'this is a lazy message')),
'bar': cfg.StrOpt('bar', help='bar option'),
'foo-bar': cfg.StrOpt('foo-bar', help='foobar'),
'no_help': cfg.StrOpt('no_help'),
@@ -48,6 +52,10 @@
'cupidatat non proident, sunt in culpa '
'qui officia deserunt mollit anim id est '
'laborum.'),
+ 'choices_opt': cfg.StrOpt('choices_opt',
+ default='a',
+ choices=(None, '', 'a', 'b', 'c'),
+ help='a string with choices'),
'deprecated_opt': cfg.StrOpt('bar',
deprecated_name='foobar',
help='deprecated'),
@@ -207,6 +215,17 @@
# foobar (string value)
#foo_bar = <None>
''')),
+ ('i18n_help',
+ dict(opts=[('test', [(None, [opts['foo_i18n_help']])])],
+ expected='''[DEFAULT]
+
+#
+# From test
+#
+
+# this is a lazy message (string value)
+#foo_i18n_help = <None>
+''')),
('no_help',
dict(opts=[('test', [(None, [opts['no_help']])])],
log_warning=('"%s" is missing a help string', 'no_help'),
@@ -281,6 +300,18 @@
'''
#long_help = <None>
''')),
+ ('choices_opt',
+ dict(opts=[('test', [(None, [opts['choices_opt']])])],
+ expected='''[DEFAULT]
+
+#
+# From test
+#
+
+# a string with choices (string value)
+# Allowed values: <None>, '', a, b, c
+#choices_opt = a
+''')),
('deprecated',
dict(opts=[('test', [('foo', [opts['deprecated_opt']])])],
expected='''[DEFAULT]
@@ -525,9 +556,11 @@
content = open(output_file).read()
self.assertEqual(self.expected, content)
- named_mgr.assert_called_once_with('oslo.config.opts',
- names=namespaces,
- invoke_on_load=True)
+ named_mgr.assert_called_once_with(
+ 'oslo.config.opts',
+ names=namespaces,
+ on_load_failure_callback=generator.on_load_failure_callback,
+ invoke_on_load=True)
log_warning = getattr(self, 'log_warning', None)
if log_warning is not None: