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 - tbecht...@suse.com
+
+- update to 1.9.3:
+  * Switch to non-namespaced module imports
+
+-------------------------------------------------------------------
+Tue Mar 10 10:09:49 UTC 2015 - tbecht...@suse.com
+
+- 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 - tbecht...@suse.com
+
+- 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 <drip...@redhat.com>
 David Stanek <dsta...@dstanek.com>
 Dirk Mueller <d...@dmllr.de>
+Doug Chivers <doug.chiv...@hp.com>
 Doug Hellmann <doug.hellm...@dreamhost.com>
 Doug Hellmann <d...@doughellmann.com>
 Eoghan Glynn <egl...@redhat.com>
+Eric Brown <bro...@vmware.com>
 Eric Guo <eric....@easystack.cn>
 Fengqian.Gao <fengqian....@intel.com>
 Flaper Fesp <flape...@gmail.com>
@@ -27,6 +29,7 @@
 Jakub Libosvar <libos...@redhat.com>
 James Carey <jeca...@us.ibm.com>
 James E. Blair <jebl...@openstack.org>
+Jamie Lennox <jamielen...@redhat.com>
 Jason Kölker <ja...@koelker.net>
 Jay S. Bryant <jsbry...@us.ibm.com>
 Jeremy Stanley <fu...@yuggoth.org>
@@ -53,6 +56,7 @@
 Petr Blaho <petrbl...@gmail.com>
 Radomir Dopieralski <openst...@sheep.art.pl>
 Rick Harris <rconradhar...@gmail.com>
+Rushi Agrawal <rushi....@gmail.com>
 Russell Bryant <rbry...@redhat.com>
 Ryan Moore <ryan.mo...@hp.com>
 Sascha Peilicke <sasc...@gmx.de>
@@ -72,3 +76,4 @@
 llg8212 <lilin...@huawei.com>
 lzyeval <lzye...@gmail.com>
 skudriashev <skudrias...@griddynamics.com>
+vponomaryov <vponomar...@mirantis.com>
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:



Reply via email to