Hello community,
here is the log from the commit of package python-oslo.config for openSUSE:Factory checked in at 2015-12-21 12:04:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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-09-02 07:53:57.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-oslo.config.new/python-oslo.config.changes 2015-12-21 12:04:19.000000000 +0100
@@ -1,0 +2,26 @@
+Fri Nov 20 07:03:21 UTC 2015 - bwiedemann@suse.com
+
+- update to 2.7.0:
+ * Add max length check to StrOpt
+ * Fix StrOpt to allow setting quotes and regex
+ * Improve default type checking
+ * Use versionadded and versionchanged in doc
+ * update doc to use new type PortOpt
+ * Fix versionchanged
+ * Raise exception when wrong type is used as default
+ * Add PortOpt for integer with range 1 to 65535
+ * Fix typos in cfg.py
+ * Case insensitiveness when comparing choices values
+ * Add missing tests and generator code for IPOpt
+ * Fix coverage configuration and execution
+ * Add item_type and bounds to ListOpt
+ * Fix bad exception for StrOpt with invalid choice value
+ * fix literal rendering in dictionary options docs
+ * Fix home-page value in setup.cfg with Oslo wiki
+ * docs - Set pbr 'warnerrors' option for doc build
+ * Include changelog/history in docs
+ * Correct the comment of __call__ method
+ * Demonstrate that MultiStr values from multiple sources are merged
+ * Make Integer type class honor zero for min/max
+
+-------------------------------------------------------------------
Old:
----
oslo.config-2.3.0.tar.gz
New:
----
oslo.config-2.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-oslo.config.spec ++++++
--- /var/tmp/diff_new_pack.MG2X3C/_old 2015-12-21 12:04:20.000000000 +0100
+++ /var/tmp/diff_new_pack.MG2X3C/_new 2015-12-21 12:04:20.000000000 +0100
@@ -17,7 +17,7 @@
Name: python-oslo.config
-Version: 2.3.0
+Version: 2.7.0
Release: 0
Summary: OpenStack configuration API
License: Apache-2.0
++++++ oslo.config-2.3.0.tar.gz -> oslo.config-2.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/.coveragerc new/oslo.config-2.7.0/.coveragerc
--- old/oslo.config-2.3.0/.coveragerc 1970-01-01 01:00:00.000000000 +0100
+++ new/oslo.config-2.7.0/.coveragerc 2015-11-16 21:22:43.000000000 +0100
@@ -0,0 +1,8 @@
+[run]
+branch = True
+source = oslo_config
+omit = oslo_config/tests/*
+
+[report]
+ignore_errors = True
+precision = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/AUTHORS new/oslo.config-2.7.0/AUTHORS
--- old/oslo.config-2.3.0/AUTHORS 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/AUTHORS 2015-11-16 21:23:02.000000000 +0100
@@ -1,6 +1,8 @@
+Akihiro Motoki
Alex Gaynor
Andreas Jaeger
Anthony Young
+BaoLiang Cui
Ben Nemec
Brant Knudson
Brian Waldon
@@ -10,7 +12,9 @@
Chris St. Pierre
Christian Berendt
Chuck Short
+Chung Chih, Hung
Cyril Roelandt
+Daisuke Fujita
Dan Prince
Davanum Srinivas
Davanum Srinivas
@@ -41,6 +45,7 @@
Joe Gordon
Joe Heck
Johannes Erdfelt
+John L. Villalovos
Jonathan LaCour
Joshua Harlow
Joshua Harlow
@@ -50,10 +55,12 @@
Laurence Miao
Lianhao Lu
LingxianKong
+Lucas Alvares Gomes
Luis A. Garcia
Mark McLoughlin
Mark Vanderwiel
Markus Zoeller
+Masaki Matsushita
Matt Riedemann
Matthew Treinish
Maxim Kulkin
@@ -69,6 +76,7 @@
Petr Blaho
Radomir Dopieralski
Rick Harris
+Ronald Bradford
Roxana Gherle
Rushi Agrawal
Russell Bryant
@@ -82,10 +90,12 @@
Tim Miller
Tom Cammann
Tong Damon Da
+Victor Stinner
Vincent Untz
Vishvananda Ishaya
YAMAMOTO Takashi
Yuriy Taraday
+ZhiQiang Fan
Zhongyue Luo
Zhongyue Luo
liu-sheng
@@ -93,4 +103,5 @@
llg8212
lzyeval
skudriashev
+venkatamahesh
vponomaryov
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/ChangeLog new/oslo.config-2.7.0/ChangeLog
--- old/oslo.config-2.3.0/ChangeLog 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/ChangeLog 2015-11-16 21:23:02.000000000 +0100
@@ -1,6 +1,47 @@
CHANGES
=======
+2.7.0
+-----
+
+* Add max length check to StrOpt
+* Remove "Kept for backward-compatibility" comment
+* Fix StrOpt to allow setting quotes and regex
+* Improve default type checking
+* Use versionadded and versionchanged in doc
+* update doc to use new type PortOpt
+* Fix versionchanged
+* Raise exception when wrong type is used as default
+
+2.6.0
+-----
+
+* Add PortOpt for integer with range 1 to 65535
+
+2.5.0
+-----
+
+* Fix typos in cfg.py
+* Case insensitiveness when comparing choices values
+* Add missing tests and generator code for IPOpt
+* Fix coverage configuration and execution
+* Add item_type and bounds to ListOpt
+* Fix bad exception for StrOpt with invalid choice value
+* fix literal rendering in dictionary options docs
+* Fix home-page value in setup.cfg with Oslo wiki
+* docs - Set pbr 'warnerrors' option for doc build
+* Include changelog/history in docs
+* Document DictOpt class
+* Correct the comment of __call__ method
+* Updated from global requirements
+* Demonstrate that MultiStr values from multiple sources are merged
+
+2.4.0
+-----
+
+* Updated from global requirements
+* Make Integer type class honor zero for min/max
+
2.3.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/PKG-INFO new/oslo.config-2.7.0/PKG-INFO
--- old/oslo.config-2.3.0/PKG-INFO 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/PKG-INFO 2015-11-16 21:23:02.000000000 +0100
@@ -1,8 +1,8 @@
Metadata-Version: 1.1
Name: oslo.config
-Version: 2.3.0
+Version: 2.7.0
Summary: Oslo Configuration API
-Home-page: https://launchpad.net/oslo
+Home-page: https://wiki.openstack.org/wiki/Oslo#oslo.config
Author: OpenStack
Author-email: openstack-dev@lists.openstack.org
License: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/doc/source/generator.rst new/oslo.config-2.7.0/doc/source/generator.rst
--- old/oslo.config-2.3.0/doc/source/generator.rst 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/doc/source/generator.rst 2015-11-16 21:22:43.000000000 +0100
@@ -16,6 +16,8 @@
$> oslo-config-generator --namespace myapp --namespace oslo.messaging > myapp.conf
+.. versionadded:: 1.4
+
Defining Option Discovery Entry Points
--------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/doc/source/history.rst new/oslo.config-2.7.0/doc/source/history.rst
--- old/oslo.config-2.3.0/doc/source/history.rst 1970-01-01 01:00:00.000000000 +0100
+++ new/oslo.config-2.7.0/doc/source/history.rst 2015-11-16 21:22:43.000000000 +0100
@@ -0,0 +1,2 @@
+.. include:: ../../ChangeLog
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/doc/source/index.rst new/oslo.config-2.7.0/doc/source/index.rst
--- old/oslo.config-2.3.0/doc/source/index.rst 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/doc/source/index.rst 2015-11-16 21:22:43.000000000 +0100
@@ -26,6 +26,14 @@
contributing
sphinxconfiggen
+Release Notes
+=============
+
+.. toctree::
+ :maxdepth: 1
+
+ history
+
Indices and tables
==================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/doc/source/opts.rst new/oslo.config-2.7.0/doc/source/opts.rst
--- old/oslo.config-2.3.0/doc/source/opts.rst 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/doc/source/opts.rst 2015-11-16 21:22:43.000000000 +0100
@@ -14,6 +14,7 @@
.. autoclass:: MultiOpt
.. autoclass:: MultiStrOpt
.. autoclass:: IPOpt
+.. autoclass:: PortOpt
.. autoclass:: DeprecatedOpt
.. autoclass:: SubCommandOpt
.. autoclass:: OptGroup
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/doc/source/styleguide.rst new/oslo.config-2.7.0/doc/source/styleguide.rst
--- old/oslo.config-2.3.0/doc/source/styleguide.rst 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/doc/source/styleguide.rst 2015-11-16 21:22:43.000000000 +0100
@@ -16,9 +16,9 @@
cfg.StrOpt('bind_host',
default='0.0.0.0',
help='IP address to listen on.'),
- cfg.IntOpt('bind_port',
- default=9292,
- help='Port number to listen on.')
+ cfg.PortOpt('bind_port',
+ default=9292,
+ help='Port number to listen on.')
Style Guide
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo.config.egg-info/PKG-INFO new/oslo.config-2.7.0/oslo.config.egg-info/PKG-INFO
--- old/oslo.config-2.3.0/oslo.config.egg-info/PKG-INFO 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/oslo.config.egg-info/PKG-INFO 2015-11-16 21:23:02.000000000 +0100
@@ -1,8 +1,8 @@
Metadata-Version: 1.1
Name: oslo.config
-Version: 2.3.0
+Version: 2.7.0
Summary: Oslo Configuration API
-Home-page: https://launchpad.net/oslo
+Home-page: https://wiki.openstack.org/wiki/Oslo#oslo.config
Author: OpenStack
Author-email: openstack-dev@lists.openstack.org
License: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo.config.egg-info/SOURCES.txt new/oslo.config-2.7.0/oslo.config.egg-info/SOURCES.txt
--- old/oslo.config-2.3.0/oslo.config.egg-info/SOURCES.txt 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/oslo.config.egg-info/SOURCES.txt 2015-11-16 21:23:02.000000000 +0100
@@ -1,3 +1,4 @@
+.coveragerc
.testr.conf
AUTHORS
CONTRIBUTING.rst
@@ -21,6 +22,7 @@
doc/source/fixture.rst
doc/source/generator.rst
doc/source/helpers.rst
+doc/source/history.rst
doc/source/index.rst
doc/source/namespaces.rst
doc/source/opts.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo.config.egg-info/pbr.json new/oslo.config-2.7.0/oslo.config.egg-info/pbr.json
--- old/oslo.config-2.3.0/oslo.config.egg-info/pbr.json 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/oslo.config.egg-info/pbr.json 2015-11-16 21:23:02.000000000 +0100
@@ -1 +1 @@
-{"is_release": true, "git_version": "bc13758"}
\ No newline at end of file
+{"git_version": "260891b", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo.config.egg-info/requires.txt new/oslo.config-2.7.0/oslo.config.egg-info/requires.txt
--- old/oslo.config-2.3.0/oslo.config.egg-info/requires.txt 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/oslo.config.egg-info/requires.txt 2015-11-16 21:23:02.000000000 +0100
@@ -1,4 +1,4 @@
argparse
-netaddr>=0.7.12
+netaddr!=0.7.16,>=0.7.12
six>=1.9.0
-stevedore>=1.5.0 # Apache-2.0
+stevedore>=1.5.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/cfg.py new/oslo.config-2.7.0/oslo_config/cfg.py
--- old/oslo.config-2.3.0/oslo_config/cfg.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/cfg.py 2015-11-16 21:22:43.000000000 +0100
@@ -166,9 +166,9 @@
rabbit_host_opt = cfg.StrOpt('host',
default='localhost',
help='IP/hostname to listen on.'),
- rabbit_port_opt = cfg.IntOpt('port',
- default=5672,
- help='Port number to listen on.')
+ rabbit_port_opt = cfg.PortOpt('port',
+ default=5672,
+ help='Port number to listen on.')
def register_rabbit_opts(conf):
conf.register_group(rabbit_group)
@@ -266,6 +266,26 @@
...
]
+Dictionary Options
+------------------
+
+If you need end users to specify a dictionary of key/value pairs, then you can
+use the DictOpt::
+
+ opts = [
+ cfg.DictOpt('foo',
+ default={})
+ ]
+
+The end users can then specify the option foo in their configuration file
+as shown below:
+
+.. code-block:: ini
+
+ [DEFAULT]
+ foo = k1:v1,k2:v2
+
+
Global ConfigOpts
-----------------
@@ -276,7 +296,7 @@
opts = [
cfg.StrOpt('bind_host', default='0.0.0.0'),
- cfg.IntOpt('bind_port', default=9292),
+ cfg.PortOpt('bind_port', default=9292),
]
CONF = cfg.CONF
@@ -465,11 +485,15 @@
return 'Failed to parse %s: %s' % (self.config_file, self.msg)
-class ConfigFileValueError(Error):
+class ConfigFileValueError(Error, ValueError):
"""Raised if a config file value does not match its opt type."""
pass
+class DefaultValueError(Error, ValueError):
+ """Raised if a default config type does not fit the opt type."""
+
+
def _fixpath(p):
"""Apply tilde expansion and absolutization to a path."""
return os.path.abspath(os.path.expanduser(p))
@@ -653,6 +677,19 @@
.. py:attribute:: help
a string explaining how the option's value is used
+
+ .. versionchanged:: 1.2
+ Added *deprecated_opts* parameter.
+
+ .. versionchanged:: 1.4
+ Added *sample_default* parameter.
+
+ .. versionchanged:: 1.9
+ Added *deprecated_for_removal* parameter.
+
+ .. versionchanged:: 2.7
+
+ An exception is now raised if the default value has the wrong type.
"""
multi = False
@@ -694,7 +731,7 @@
if deprecated_name is not None or deprecated_group is not None:
self.deprecated_opts.append(DeprecatedOpt(deprecated_name,
group=deprecated_group))
- self._assert_default_is_of_opt_type()
+ self._check_default()
def _default_is_ref(self):
"""Check if default is a reference to another var."""
@@ -703,19 +740,16 @@
return '$' in tmpl
return False
- def _assert_default_is_of_opt_type(self):
+ def _check_default(self):
if (self.default is not None
- and not self._default_is_ref()
- and hasattr(self.type, 'is_base_type')
- and not self.type.is_base_type(self.default)):
- # NOTE(tcammann) Change this to raise error after K relase
- expected_types = ", ".join(
- [t.__name__ for t in self.type.BASE_TYPES])
- LOG.debug(('Expected default value of type(s) %(extypes)s but got '
- '%(default)r of type %(deftypes)s'),
- {'extypes': expected_types,
- 'default': self.default,
- 'deftypes': type(self.default).__name__})
+ and not self._default_is_ref()):
+ try:
+ self.type(self.default)
+ except Exception:
+ raise DefaultValueError("Error processing default value "
+ "%(default)s for Opt type of %(opt)s."
+ % {'default': self.default,
+ 'opt': self.type})
def __ne__(self, another):
return vars(self) != vars(another)
@@ -929,6 +963,8 @@
Then the value of "[group1]/opt1" will be ['val11', 'val12', 'val21',
'val22'].
+
+ .. versionadded:: 1.2
"""
def __init__(self, name, group=None):
@@ -955,14 +991,39 @@
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.
+ :param quotes: If True and string is enclosed with single or double
+ quotes, will strip those quotes.
+ :param regex: Optional regular expression (string or compiled
+ regex) that the value must match on an unanchored
+ search.
+ :param ignore_case: If True case differences (uppercase vs. lowercase)
+ between 'choices' or 'regex' will be ignored.
+ :param max_length: If positive integer, the value must be less than or
+ equal to this parameter.
+
+ .. versionchanged:: 2.7
+ Added *quotes* parameter
+
+ .. versionchanged:: 2.7
+ Added *regex* parameter
+
+ .. versionchanged:: 2.7
+ Added *ignore_case* parameter
+
+ .. versionchanged:: 2.7
+ Added *max_length* parameter
"""
- def __init__(self, name, choices=None, **kwargs):
+ def __init__(self, name, choices=None, quotes=None,
+ regex=None, ignore_case=None, max_length=None, **kwargs):
super(StrOpt, self).__init__(name,
- type=types.String(choices=choices),
+ type=types.String(
+ choices=choices,
+ quotes=quotes,
+ regex=regex,
+ ignore_case=ignore_case,
+ max_length=max_length),
**kwargs)
@@ -971,7 +1032,7 @@
"""Boolean options.
Bool opts are set to True or False on the command line using --optname or
- --noopttname respectively.
+ --nooptname respectively.
In config files, boolean values are cast with Boolean type.
"""
@@ -1026,7 +1087,9 @@
Option with ``type`` :class:`oslo_config.types.Integer`
- `Kept for backward-compatibility with options not using Opt directly`.
+ .. versionchanged:: 1.15
+
+ Added *min* and *max* parameters.
"""
def __init__(self, name, min=None, max=None, **kwargs):
@@ -1039,8 +1102,6 @@
"""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):
@@ -1053,11 +1114,15 @@
Option with ``type`` :class:`oslo_config.types.List`
- `Kept for backward-compatibility with options not using Opt directly`.
+ .. versionchanged:: 2.5
+ Added *item_type* and *bounds* parameters.
"""
- def __init__(self, name, **kwargs):
- super(ListOpt, self).__init__(name, type=types.List(), **kwargs)
+ def __init__(self, name, item_type=None, bounds=None, **kwargs):
+ super(ListOpt, self).__init__(name,
+ type=types.List(item_type=item_type,
+ bounds=bounds),
+ **kwargs)
class DictOpt(Opt):
@@ -1066,7 +1131,7 @@
Option with ``type`` :class:`oslo_config.types.Dict`
- `Kept for backward-compatibility with options not using Opt directly`.
+ .. versionadded:: 1.2
"""
def __init__(self, name, **kwargs):
@@ -1081,6 +1146,8 @@
:param version: one of either ``4``, ``6``, or ``None`` to specify
either version.
+
+ .. versionadded:: 1.4
"""
def __init__(self, name, version=None, **kwargs):
@@ -1088,6 +1155,19 @@
**kwargs)
+class PortOpt(IntOpt):
+
+ """Option for a TCP/IP port number. Ports can range from 1 to 65535.
+
+ Option with ``type`` :class:`oslo_config.types.Integer`
+
+ .. versionadded:: 2.6
+ """
+
+ def __init__(self, name, **kwargs):
+ super(PortOpt, self).__init__(name, min=1, max=65535, **kwargs)
+
+
class MultiOpt(Opt):
"""Multi-value option.
@@ -1107,6 +1187,8 @@
The command line ``--foo=1 --foo=2`` would result in ``cfg.CONF.foo``
containing ``[1,2]``
+
+ .. versionadded:: 1.3
"""
multi = True
@@ -1129,10 +1211,6 @@
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):
@@ -1209,6 +1287,8 @@
This allows us to properly handle the precedence of --config-file
options over previous command line arguments, but not over subsequent
arguments.
+
+ .. versionadded:: 1.2
"""
class ConfigFileAction(argparse.Action):
@@ -1255,6 +1335,8 @@
_Namespace object. This allows us to properly handle the precedence of
--config-dir options over previous command line arguments, but not
over subsequent arguments.
+
+ .. versionadded:: 1.2
"""
class ConfigDirAction(argparse.Action):
@@ -1860,7 +1942,6 @@
:param usage: a usage string (%prog will be expanded)
:param default_config_files: config files to use by default
:param validate_default_values: whether to validate the default values
- :returns: the list of arguments left over after parsing options
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
ConfigFilesPermissionDeniedError,
RequiredOptError, DuplicateOptError
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/cfgfilter.py new/oslo.config-2.7.0/oslo_config/cfgfilter.py
--- old/oslo.config-2.3.0/oslo_config/cfgfilter.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/cfgfilter.py 2015-11-16 21:22:43.000000000 +0100
@@ -24,6 +24,8 @@
3. Limit the options on a Cfg object that can be accessed.
+.. versionadded:: 1.4
+
Cross-Module Option Dependencies
--------------------------------
@@ -121,8 +123,6 @@
print(restricted_conf.foo)
print(restricted_conf.bar) # raises NoSuchOptError
-
-
"""
import collections
@@ -132,7 +132,10 @@
class CliOptRegisteredError(cfg.Error):
- """Raised when registering cli opt not in original ConfigOpts."""
+ """Raised when registering cli opt not in original ConfigOpts.
+
+ .. versionadded:: 1.12
+ """
def __str__(self):
ret = "Cannot register a cli option that was not present in the" \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/generator.py new/oslo.config-2.7.0/oslo_config/generator.py
--- old/oslo.config-2.3.0/oslo_config/generator.py 2015-08-24 23:32:25.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/generator.py 2015-11-16 21:22:43.000000000 +0100
@@ -20,6 +20,7 @@
Tool for generating a sample configuration file. See
../doc/source/generator.rst for details.
+.. versionadded:: 1.4
"""
import logging
@@ -73,7 +74,8 @@
default_str = str(opt.sample_default)
elif opt.default is None:
default_str = '<None>'
- elif isinstance(opt, cfg.StrOpt):
+ elif (isinstance(opt, cfg.StrOpt) or
+ isinstance(opt, cfg.IPOpt)):
default_str = opt.default
elif isinstance(opt, cfg.BoolOpt):
default_str = str(opt.default).lower()
@@ -110,6 +112,8 @@
cfg.FloatOpt: 'floating point value',
cfg.ListOpt: 'list value',
cfg.DictOpt: 'dict value',
+ cfg.IPOpt: 'ip address value',
+ cfg.PortOpt: 'port value',
cfg.MultiStrOpt: 'multi valued',
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/tests/test_cfg.py new/oslo.config-2.7.0/oslo_config/tests/test_cfg.py
--- old/oslo.config-2.3.0/oslo_config/tests/test_cfg.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/tests/test_cfg.py 2015-11-16 21:22:43.000000000 +0100
@@ -476,6 +476,24 @@
dict(opt_class=cfg.DictOpt, default=None,
cli_args=['--old-oof', 'key1:blaa', '--old-oof', 'key2:bar'],
value={'key2': 'bar'}, deps=('oof', 'old'))),
+ ('port_default',
+ dict(opt_class=cfg.PortOpt, default=80,
+ cli_args=[], value=80, deps=(None, None))),
+ ('port_arg',
+ dict(opt_class=cfg.PortOpt, default=None,
+ cli_args=['--foo=80'], value=80, deps=(None, None))),
+ ('port_arg_deprecated_name',
+ dict(opt_class=cfg.PortOpt, default=None,
+ cli_args=['--oldfoo=80'], value=80, deps=('oldfoo', None))),
+ ('port_arg_deprecated_group',
+ dict(opt_class=cfg.PortOpt, default=None,
+ cli_args=['--old-foo=80'], value=80, deps=(None, 'old'))),
+ ('port_arg_deprecated_group_default',
+ dict(opt_class=cfg.PortOpt, default=None,
+ cli_args=['--foo=80'], value=80, deps=(None, 'DEFAULT'))),
+ ('port_arg_deprecated_group_and_name',
+ dict(opt_class=cfg.PortOpt, default=None,
+ cli_args=['--old-oof=80'], value=80, deps=('oof', 'old'))),
('multistr_default',
dict(opt_class=cfg.MultiStrOpt, default=['bar'], cli_args=[],
value=['bar'], deps=(None, None))),
@@ -623,6 +641,24 @@
['key1:blaa,key2:bar'],
{'key1': 'blaa', 'key2': 'bar'})
+ def test_positional_ip_none_default(self):
+ self._do_pos_test(cfg.IPOpt, None, [], None)
+
+ def test_positional_ip_default(self):
+ self._do_pos_test(cfg.IPOpt, '127.0.0.1', [], '127.0.0.1')
+
+ def test_positional_ip_arg(self):
+ self._do_pos_test(cfg.IPOpt, None, ['127.0.0.1'], '127.0.0.1')
+
+ def test_positional_port_none_default(self):
+ self._do_pos_test(cfg.PortOpt, None, [], None)
+
+ def test_positional_port_default(self):
+ self._do_pos_test(cfg.PortOpt, 80, [], 80)
+
+ def test_positional_port_arg(self):
+ self._do_pos_test(cfg.PortOpt, None, ['443'], 443)
+
def test_positional_multistr_none_default(self):
self._do_pos_test(cfg.MultiStrOpt, None, [], None)
@@ -833,6 +869,15 @@
def test_conf_file_str_ignore_dgroup_and_dname(self):
self._do_dgroup_and_dname_test_ignore(cfg.StrOpt, 'value2', 'value2')
+ def test_conf_file_str_value_with_good_choice_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo', choices=['bar', 'baz']))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'bar')
+
def test_conf_file_bool_default(self):
self.conf.register_opt(cfg.BoolOpt('foo', default=False))
@@ -943,10 +988,10 @@
self.assertTrue(hasattr(self.conf, 'foo'))
self.assertEqual(self.conf.foo, 666)
- @mock.patch.object(cfg, 'LOG')
- def test_conf_file_int_wrong_default(self, mock_log):
- cfg.IntOpt('foo', default='666')
- self.assertEqual(1, mock_log.debug.call_count)
+ def test_conf_file_int_string_default_type(self):
+ self.conf.register_opt(cfg.IntOpt('foo', default='666'))
+ self.conf([])
+ self.assertEqual(self.conf.foo, 666)
def test_conf_file_int_value(self):
self.conf.register_opt(cfg.IntOpt('foo'))
@@ -1022,10 +1067,9 @@
self.assertTrue(hasattr(self.conf, 'foo'))
self.assertEqual(self.conf.foo, 6.66)
- @mock.patch.object(cfg, 'LOG')
- def test_conf_file_float_default_wrong_type(self, mock_log):
- cfg.FloatOpt('foo', default='foobar6.66')
- self.assertEqual(1, mock_log.debug.call_count)
+ def test_conf_file_float_default_wrong_type(self):
+ self.assertRaises(cfg.DefaultValueError, cfg.FloatOpt, 'foo',
+ default='foobar6.66')
def test_conf_file_float_value(self):
self.conf.register_opt(cfg.FloatOpt('foo'))
@@ -1088,15 +1132,9 @@
self.assertTrue(hasattr(self.conf, 'foo'))
self.assertEqual(self.conf.foo, ['bar'])
- @mock.patch.object(cfg, 'LOG')
- def test_conf_file_list_default_wrong_type(self, mock_log):
- cfg.ListOpt('foo', default=25)
- mock_log.debug.assert_called_once_with(
- 'Expected default value of type(s) %(extypes)s but '
- 'got %(default)r of type %(deftypes)s',
- {'extypes': 'list',
- 'default': 25,
- 'deftypes': 'int'})
+ def test_conf_file_list_default_wrong_type(self):
+ self.assertRaises(cfg.DefaultValueError, cfg.ListOpt, 'foo',
+ default=25)
def test_conf_file_list_value(self):
self.conf.register_opt(cfg.ListOpt('foo'))
@@ -1127,6 +1165,31 @@
self.assertTrue(hasattr(self.conf, 'foo'))
self.assertEqual(self.conf.foo, ['b', 'a', 'r'])
+ def test_conf_file_list_item_type(self):
+ self.conf.register_cli_opt(cfg.ListOpt('foo',
+ item_type=types.Integer()))
+
+ paths = self.create_tempfiles([('1',
+ '[DEFAULT]\n'
+ 'foo = 1,2\n')])
+
+ self.conf(['--config-file', paths[0]])
+
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual([1, 2], self.conf.foo)
+
+ def test_conf_file_list_item_wrong_type(self):
+ self.assertRaises(cfg.DefaultValueError, cfg.ListOpt, 'foo',
+ default="bar", item_type=types.Integer())
+
+ def test_conf_file_list_bounds(self):
+ self.conf.register_cli_opt(cfg.ListOpt('foo',
+ item_type=types.Integer(),
+ default="[1,2]",
+ bounds=True))
+ self.conf([])
+ self.assertEqual(self.conf.foo, [1, 2])
+
def test_conf_file_list_use_dname(self):
self._do_dname_test_use(cfg.ListOpt, 'a,b,c', ['a', 'b', 'c'])
@@ -1219,7 +1282,7 @@
self.conf(['--config-file', paths[0]])
self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo')
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
+ self.assertRaises(ValueError, getattr, self.conf, 'foo')
def test_conf_file_dict_value_duplicate_key(self):
self.conf.register_opt(cfg.DictOpt('foo'))
@@ -1231,7 +1294,7 @@
self.conf(['--config-file', paths[0]])
self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo')
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
+ self.assertRaises(ValueError, getattr, self.conf, 'foo')
def test_conf_file_dict_values_override_deprecated(self):
self.conf.register_cli_opt(cfg.DictOpt('foo',
@@ -1356,6 +1419,16 @@
'k2': 'e',
'k3': 'f'})
+ def test_conf_file_port_outside_range(self):
+ self.conf.register_opt(cfg.PortOpt('foo'))
+
+ paths = self.create_tempfiles([('test',
+ '[DEFAULT]\n'
+ 'foo = 65536\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo')
+
def test_conf_file_multistr_default(self):
self.conf.register_opt(cfg.MultiStrOpt('foo', default=['bar']))
@@ -2302,6 +2375,30 @@
self.assertTrue(hasattr(self.conf.snafu, 'bell'))
self.assertEqual(self.conf.snafu.bell, 'whistle-02')
+ def test_config_dir_multistr(self):
+ # Demonstrate that values for multistr options found in
+ # different sources are combined.
+ self.conf.register_cli_opt(cfg.MultiStrOpt('foo'))
+
+ dir = tempfile.mkdtemp()
+ self.tempdirs.append(dir)
+
+ paths = self.create_tempfiles([(os.path.join(dir, '00-test'),
+ '[DEFAULT]\n'
+ 'foo = bar-00\n'),
+ (os.path.join(dir, '02-test'),
+ '[DEFAULT]\n'
+ 'foo = bar-02\n'),
+ (os.path.join(dir, '01-test'),
+ '[DEFAULT]\n'
+ 'foo = bar-01\n')])
+
+ self.conf(['--foo', 'bar',
+ '--config-dir', os.path.dirname(paths[0])])
+
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(['bar', 'bar-00', 'bar-01', 'bar-02'], self.conf.foo)
+
def test_config_dir_file_precedence(self):
snafu_group = cfg.OptGroup('snafu')
self.conf.register_group(snafu_group)
@@ -2879,7 +2976,7 @@
self.conf(['--config-file', paths[0]])
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
+ self.assertRaises(ValueError, getattr, self.conf, 'foo')
self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo')
def test_conf_file_bad_bool(self):
@@ -3592,7 +3689,7 @@
self.conf(['--config-file', paths[0]])
self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo')
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
+ self.assertRaises(ValueError, getattr, self.conf, 'foo')
def test_conf_file_choice_value_override(self):
self.conf.register_cli_opt(cfg.StrOpt('foo',
@@ -3613,14 +3710,158 @@
self.assertEqual(self.conf.foo, 'baaar')
def test_conf_file_choice_bad_default(self):
+ self.assertRaises(cfg.DefaultValueError, cfg.StrOpt, 'foo',
+ choices=['baar', 'baaar'], default='foobaz')
+
+
+class RegexTestCase(BaseTestCase):
+
+ def test_regex_good(self):
self.conf.register_cli_opt(cfg.StrOpt('foo',
- choices=['baar', 'baaar'],
- default='foobaz'))
- self.conf([])
- self.assertRaises(AttributeError,
- getattr,
- self.conf,
- 'foobaz')
+ regex='foo|bar'))
+ self.conf(['--foo', 'bar'])
+ self.assertEqual(self.conf.foo, 'bar')
+ self.conf(['--foo', 'foo'])
+ self.assertEqual(self.conf.foo, 'foo')
+ self.conf(['--foo', 'foobar'])
+ self.assertEqual(self.conf.foo, 'foobar')
+
+ def test_regex_bad(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo',
+ regex='bar'))
+ self.assertRaises(SystemExit, self.conf, ['--foo', 'foo'])
+
+ def test_conf_file_regex_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ regex='bar'))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'bar')
+
+ def test_conf_file_regex_bad_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ regex='bar'))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = other\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertRaisesRegex(cfg.ConfigFileValueError, "doesn't match regex",
+ self.conf._get, 'foo')
+ self.assertRaisesRegex(ValueError, "doesn't match regex",
+ getattr, self.conf, 'foo')
+
+ def test_regex_with_choice(self):
+ self.assertRaises(ValueError, cfg.StrOpt,
+ 'foo', choices=['bar1'], regex='bar2')
+
+
+class QuotesTestCase(BaseTestCase):
+
+ def test_quotes_good(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo',
+ quotes=True))
+ self.conf(['--foo', '"foobar1"'])
+ self.assertEqual(self.conf.foo, 'foobar1')
+ self.conf(['--foo', "'foobar2'"])
+ self.assertEqual(self.conf.foo, 'foobar2')
+ self.conf(['--foo', 'foobar3'])
+ self.assertEqual(self.conf.foo, 'foobar3')
+ self.conf(['--foo', 'foobar4"'])
+ self.assertEqual(self.conf.foo, 'foobar4"')
+
+ def test_quotes_bad(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo',
+ quotes=True))
+ self.assertRaises(SystemExit, self.conf, ['--foo', '"foobar\''])
+ self.assertRaises(SystemExit, self.conf, ['--foo', '\'foobar"'])
+ self.assertRaises(SystemExit, self.conf, ['--foo', '"foobar'])
+ self.assertRaises(SystemExit, self.conf, ['--foo', "'foobar"])
+
+ def test_conf_file_quotes_good_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ quotes=True))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = "bar"\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'bar')
+
+ def test_conf_file_quotes_bad_value(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ quotes=True))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = "bar\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertRaisesRegex(cfg.ConfigFileValueError, 'Non-closed quote:',
+ self.conf._get, 'foo')
+ self.assertRaisesRegex(ValueError, 'Non-closed quote:',
+ getattr, self.conf, 'foo')
+
+
+class IgnoreCaseTestCase(BaseTestCase):
+
+ def test_ignore_case_with_choices(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo',
+ ignore_case=True,
+ choices=['bar1',
+ 'bar2',
+ 'BAR3']))
+ self.conf(['--foo', 'bAr1'])
+ self.assertEqual(self.conf.foo, 'bAr1')
+ self.conf(['--foo', 'BaR2'])
+ self.assertEqual(self.conf.foo, 'BaR2')
+ self.conf(['--foo', 'baR3'])
+ self.assertEqual(self.conf.foo, 'baR3')
+
+ def test_ignore_case_with_regex(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo',
+ ignore_case=True,
+ regex='fOO|bar'))
+ self.conf(['--foo', 'foo'])
+ self.assertEqual(self.conf.foo, 'foo')
+ self.conf(['--foo', 'Bar'])
+ self.assertEqual(self.conf.foo, 'Bar')
+ self.conf(['--foo', 'FOObar'])
+ self.assertEqual(self.conf.foo, 'FOObar')
+
+ def test_conf_file_ignore_case_with_choices(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ ignore_case=True,
+ choices=['bar1', 'bar2', 'BAR3']))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bAr2\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'bAr2')
+
+ def test_conf_file_ignore_case_with_regex(self):
+ self.conf.register_opt(cfg.StrOpt('foo',
+ ignore_case=True,
+ regex='bAr'))
+
+ paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = BaR\n')])
+
+ self.conf(['--config-file', paths[0]])
+ self.assertTrue(hasattr(self.conf, 'foo'))
+ self.assertEqual(self.conf.foo, 'BaR')
+
+
+class StrOptMaxLengthTestCase(BaseTestCase):
+
+ def test_stropt_max_length_good(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo', max_length=5))
+ self.conf(['--foo', '12345'])
+ self.assertEqual(self.conf.foo, '12345')
+
+ def test_stropt_max_length_bad(self):
+ self.conf.register_cli_opt(cfg.StrOpt('foo', max_length=5))
+ self.assertRaises(SystemExit, self.conf, ['--foo', '123456'])
class PrintHelpTestCase(base.BaseTestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/tests/test_generator.py new/oslo.config-2.7.0/oslo_config/tests/test_generator.py
--- old/oslo.config-2.3.0/oslo_config/tests/test_generator.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/tests/test_generator.py 2015-11-16 21:22:43.000000000 +0100
@@ -104,6 +104,12 @@
'dict_opt': cfg.DictOpt('dict_opt',
default={'1': 'yes', '2': 'no'},
help='a dict'),
+ 'ip_opt': cfg.IPOpt('ip_opt',
+ default='127.0.0.1',
+ help='an ip address'),
+ 'port_opt': cfg.PortOpt('port_opt',
+ default=80,
+ help='a port'),
'multi_opt': cfg.MultiStrOpt('multi_opt',
default=['1', '2', '3'],
help='multiple strings'),
@@ -472,6 +478,30 @@
# a dict (dict value)
#dict_opt = 1:yes,2:no
''')),
+ ('ip_opt',
+ dict(opts=[('test', [(None, [opts['ip_opt']])])],
+ expected='''[DEFAULT]
+
+#
+# From test
+#
+
+# an ip address (ip address value)
+#ip_opt = 127.0.0.1
+''')),
+ ('port_opt',
+ dict(opts=[('test', [(None, [opts['port_opt']])])],
+ expected='''[DEFAULT]
+
+#
+# From test
+#
+
+# a port (port value)
+# Minimum value: 1
+# Maximum value: 65535
+#port_opt = 80
+''')),
('multi_opt',
dict(opts=[('test', [(None, [opts['multi_opt']])])],
expected='''[DEFAULT]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/tests/test_types.py new/oslo.config-2.7.0/oslo_config/tests/test_types.py
--- old/oslo.config-2.3.0/oslo_config/tests/test_types.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/tests/test_types.py 2015-11-16 21:22:43.000000000 +0100
@@ -126,6 +126,36 @@
t2 = types.String(regex=re.compile("^[a-z]"))
self.assertFalse(t1 == t2)
+ def test_ignore_case(self):
+ self.type_instance = types.String(choices=['foo', 'bar'],
+ ignore_case=True)
+ self.assertConvertedValue('Foo', 'Foo')
+ self.assertConvertedValue('bAr', 'bAr')
+
+ def test_ignore_case_raises(self):
+ self.type_instance = types.String(choices=['foo', 'bar'],
+ ignore_case=False)
+ self.assertRaises(ValueError, self.assertConvertedValue, 'Foo', 'Foo')
+
+ def test_regex_and_ignore_case(self):
+ self.type_instance = types.String(regex=re.compile("^[A-Z]"),
+ ignore_case=True)
+ self.assertConvertedValue("foo", "foo")
+
+ def test_regex_and_ignore_case_str(self):
+ self.type_instance = types.String(regex="^[A-Z]", ignore_case=True)
+ self.assertConvertedValue("foo", "foo")
+
+ def test_regex_preserve_flags(self):
+ self.type_instance = types.String(regex=re.compile("^[A-Z]", re.I),
+ ignore_case=False)
+ self.assertConvertedValue("foo", "foo")
+
+ def test_max_length(self):
+ self.type_instance = types.String(max_length=5)
+ self.assertInvalid('123456')
+ self.assertConvertedValue('12345', '12345')
+
class BooleanTypeTests(TypeTestHelper, unittest.TestCase):
type = types.Boolean()
@@ -209,6 +239,8 @@
def test_repr_with_min_and_max(self):
t = types.Integer(min=123, max=456)
self.assertEqual('Integer(min=123, max=456)', repr(t))
+ t = types.Integer(min=0, max=0)
+ self.assertEqual('Integer(min=0, max=0)', repr(t))
def test_equal(self):
self.assertTrue(types.Integer() == types.Integer())
@@ -230,6 +262,20 @@
def test_not_equal_to_other_class(self):
self.assertFalse(types.Integer() == types.String())
+ def test_min_greater_max(self):
+ self.assertRaises(ValueError,
+ types.Integer,
+ min=100, max=50)
+ self.assertRaises(ValueError,
+ types.Integer,
+ min=-50, max=-100)
+ self.assertRaises(ValueError,
+ types.Integer,
+ min=0, max=-50)
+ self.assertRaises(ValueError,
+ types.Integer,
+ min=50, max=0)
+
def test_with_max_and_min(self):
t = types.Integer(min=123, max=456)
self.assertRaises(ValueError, t, 122)
@@ -239,6 +285,26 @@
self.assertRaises(ValueError, t, 0)
self.assertRaises(ValueError, t, 457)
+ def test_with_min_zero(self):
+ t = types.Integer(min=0, max=456)
+ self.assertRaises(ValueError, t, -1)
+ t(0)
+ t(123)
+ t(300)
+ t(456)
+ self.assertRaises(ValueError, t, -201)
+ self.assertRaises(ValueError, t, 457)
+
+ def test_with_max_zero(self):
+ t = types.Integer(min=-456, max=0)
+ self.assertRaises(ValueError, t, 1)
+ t(0)
+ t(-123)
+ t(-300)
+ t(-456)
+ self.assertRaises(ValueError, t, 201)
+ self.assertRaises(ValueError, t, -457)
+
class FloatTypeTests(TypeTestHelper, unittest.TestCase):
type = types.Float()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/oslo_config/types.py new/oslo.config-2.7.0/oslo_config/types.py
--- old/oslo.config-2.3.0/oslo_config/types.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/oslo_config/types.py 2015-11-16 21:22:43.000000000 +0100
@@ -17,6 +17,7 @@
Use these classes as values for the `type` argument to
:class:`oslo_config.cfg.Opt` and its subclasses.
+.. versionadded:: 1.3
"""
import re
@@ -25,11 +26,7 @@
class ConfigType(object):
-
- BASE_TYPES = (None,)
-
- def is_base_type(self, other):
- return isinstance(other, self.BASE_TYPES)
+ pass
class String(ConfigType):
@@ -48,18 +45,48 @@
:param regex: Optional regular expression (string or compiled
regex) that the value must match on an unanchored
search. Mutually exclusive with 'choices'.
- """
+ :param ignore_case: If True case differences (uppercase vs. lowercase)
+ between 'choices' or 'regex' will be ignored;
+ defaults to False.
+ :param max_length: Optional integer. If a positive value is specified,
+ a maximum length of an option value must be less than
+ or equal to this parameter. Otherwise no length check
+ will be done.
- BASE_TYPES = six.string_types
+ .. versionchanged:: 2.1
+ Added *regex* parameter.
+
+ .. versionchanged:: 2.5
+ Added *ignore_case* parameter.
+
+ .. versionchanged:: 2.7
+ Added *max_length* parameter.
+ """
- def __init__(self, choices=None, quotes=False, regex=None):
+ def __init__(self, choices=None, quotes=False, regex=None,
+ ignore_case=False, max_length=None):
super(String, self).__init__()
if choices and regex:
raise ValueError("'choices' and 'regex' cannot both be specified")
- self.choices = choices
+ self.ignore_case = ignore_case
self.quotes = quotes
- self.regex = re.compile(regex) if regex is not None else None
+ self.max_length = max_length or 0
+
+ self.choices = choices
+ self.lower_case_choices = None
+ if self.choices is not None and self.ignore_case:
+ self.lower_case_choices = [c.lower() for c in choices]
+
+ self.regex = regex
+ if self.regex is not None:
+ re_flags = re.IGNORECASE if self.ignore_case else 0
+
+ # Check if regex is a string or an already compiled regex
+ if isinstance(regex, six.string_types):
+ self.regex = re.compile(regex, re_flags)
+ else:
+ self.regex = re.compile(regex.pattern, re_flags | regex.flags)
def __call__(self, value):
value = str(value)
@@ -69,11 +96,22 @@
raise ValueError('Non-closed quote: %s' % value)
value = value[1:-1]
+ if self.max_length > 0 and len(value) > self.max_length:
+ raise ValueError("Value '%s' exceeds maximum length %d" %
+ (value, self.max_length))
+
if self.regex and not self.regex.search(value):
raise ValueError("Value %r doesn't match regex %r" %
(value, self.regex.pattern))
- if self.choices is None or value in self.choices:
+ if self.choices is None:
+ return value
+
+ # Check for case insensitive
+ processed_value, choices = ((value.lower(), self.lower_case_choices)
+ if self.ignore_case else
+ (value, self.choices))
+ if processed_value in choices:
return value
raise ValueError(
@@ -101,8 +139,7 @@
class MultiString(String):
-
- BASE_TYPES = six.string_types + (list,)
+ pass
class Boolean(ConfigType):
@@ -115,8 +152,6 @@
TRUE_VALUES = ['true', '1', 'on', 'yes']
FALSE_VALUES = ['false', '0', 'off', 'no']
- BASE_TYPES = (bool,)
-
def __call__(self, value):
if isinstance(value, bool):
return value
@@ -145,15 +180,16 @@
:param min: Optional check that value is greater than or equal to min
:param max: Optional check that value is less than or equal to max
- """
- BASE_TYPES = six.integer_types
+ .. versionchanged:: 2.4
+ The class now honors zero for *min* and *max* parameters.
+ """
def __init__(self, min=None, max=None):
super(Integer, self).__init__()
self.min = min
self.max = max
- if min and max and max < min:
+ if min is not None and max is not None and max < min:
raise ValueError('Max value is less than min value')
def __call__(self, value):
@@ -170,17 +206,17 @@
return value
def _check_range(self, value):
- if self.min and value < self.min:
+ if self.min is not None and value < self.min:
raise ValueError('Should be greater than or equal to %d' %
self.min)
- if self.max and value > self.max:
+ if self.max is not None and value > self.max:
raise ValueError('Should be less than or equal to %d' % self.max)
def __repr__(self):
props = []
- if self.min:
+ if self.min is not None:
props.append('min=%d' % self.min)
- if self.max:
+ if self.max is not None:
props.append('max=%d' % self.max)
if props:
@@ -199,9 +235,6 @@
"""Float type."""
- # allow float to be set from int
- BASE_TYPES = six.integer_types + (float,)
-
def __call__(self, value):
if isinstance(value, float):
return value
@@ -231,8 +264,6 @@
:param bounds: if True, value should be inside "[" and "]" pair
"""
- BASE_TYPES = (list,)
-
def __init__(self, item_type=None, bounds=False):
super(List, self).__init__()
@@ -304,8 +335,6 @@
:param bounds: if True, value should be inside "{" and "}" pair
"""
- BASE_TYPES = (dict,)
-
def __init__(self, value_type=None, bounds=False):
super(Dict, self).__init__()
@@ -392,8 +421,6 @@
"""
- BASE_TYPES = six.string_types
-
def __init__(self, version=None):
super(IPAddress, self).__init__()
version_checkers = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/requirements.txt new/oslo.config-2.7.0/requirements.txt
--- old/oslo.config-2.3.0/requirements.txt 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/requirements.txt 2015-11-16 21:22:43.000000000 +0100
@@ -3,6 +3,6 @@
# process, which may cause wedges in the gate later.
argparse
-netaddr>=0.7.12
+netaddr!=0.7.16,>=0.7.12
six>=1.9.0
stevedore>=1.5.0 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/setup.cfg new/oslo.config-2.7.0/setup.cfg
--- old/oslo.config-2.3.0/setup.cfg 2015-08-24 23:32:57.000000000 +0200
+++ new/oslo.config-2.7.0/setup.cfg 2015-11-16 21:23:02.000000000 +0100
@@ -5,7 +5,7 @@
summary = Oslo Configuration API
description-file =
README.rst
-home-page = https://launchpad.net/oslo
+home-page = https://wiki.openstack.org/wiki/Oslo#oslo.config
classifier =
Development Status :: 4 - Beta
Environment :: OpenStack
@@ -40,11 +40,14 @@
[upload_sphinx]
upload-dir = doc/build/html
+[pbr]
+warnerrors = True
+
[wheel]
universal = 1
[egg_info]
-tag_build =
tag_date = 0
tag_svn_revision = 0
+tag_build =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/setup.py new/oslo.config-2.7.0/setup.py
--- old/oslo.config-2.3.0/setup.py 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/setup.py 2015-11-16 21:22:43.000000000 +0100
@@ -25,5 +25,5 @@
pass
setuptools.setup(
- setup_requires=['pbr>=1.3'],
+ setup_requires=['pbr>=1.8'],
pbr=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/oslo.config-2.3.0/tox.ini new/oslo.config-2.7.0/tox.ini
--- old/oslo.config-2.3.0/tox.ini 2015-08-24 23:32:24.000000000 +0200
+++ new/oslo.config-2.7.0/tox.ini 2015-11-16 21:22:43.000000000 +0100
@@ -14,7 +14,7 @@
[testenv:cover]
setenv = VIRTUAL_ENV={envdir}
commands =
- python setup.py testr --coverage
+ python setup.py test --coverage --coverage-package-name=oslo_config --testr-args='{posargs}'
[testenv:venv]
commands = {posargs}