summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2013-02-17 15:22:44 +0000
committerMark McLoughlin <markmc@redhat.com>2013-02-17 15:44:00 +0000
commitf63ea05f7c36ece6aad0fdc8e02f4d5d30c673a3 (patch)
treefc46499db82de0829e1137b1d620bceb46cb787f
parent8ce59472653439d646309395bf195ec6163ff29a (diff)
downloadoslo-f63ea05f7c36ece6aad0fdc8e02f4d5d30c673a3.tar.gz
oslo-f63ea05f7c36ece6aad0fdc8e02f4d5d30c673a3.tar.xz
oslo-f63ea05f7c36ece6aad0fdc8e02f4d5d30c673a3.zip
Use oslo-config-2013.1b3
The cfg API is now available via the oslo-config library, so switch to it and remove the copied-and-pasted version. Add the 2013.1b3 tarball to tools/pip-requires - this will be changed to 'oslo-config>=2013.1' when oslo-config is published to pypi. This will happen in time for grizzly final. Remove the 'deps = pep8==1.3.3' and 'deps = pyflakes' from tox.ini as it means all the other deps get installed with easy_install which can't install oslo-config from the URL. Change-Id: I4815aeb8a9341a31a250e920157f15ee15cfc5bc
-rwxr-xr-xbin/oslo-rpc-zmq-receiver3
-rw-r--r--openstack/common/cfg.py1749
-rw-r--r--openstack/common/db/sqlalchemy/session.py2
-rw-r--r--openstack/common/eventlet_backdoor.py3
-rw-r--r--openstack/common/iniparser.py130
-rw-r--r--openstack/common/lockutils.py2
-rw-r--r--openstack/common/log.py3
-rw-r--r--openstack/common/notifier/api.py3
-rw-r--r--openstack/common/notifier/log_notifier.py2
-rw-r--r--openstack/common/notifier/rpc_notifier.py2
-rw-r--r--openstack/common/notifier/rpc_notifier2.py3
-rw-r--r--openstack/common/plugin/pluginmanager.py3
-rw-r--r--openstack/common/rpc/__init__.py3
-rw-r--r--openstack/common/rpc/common.py3
-rw-r--r--openstack/common/rpc/impl_kombu.py2
-rw-r--r--openstack/common/rpc/impl_qpid.py2
-rw-r--r--openstack/common/rpc/impl_zmq.py2
-rw-r--r--openstack/common/rpc/matchmaker.py3
-rw-r--r--openstack/common/service.py2
-rw-r--r--openstack/common/sslutils.py3
-rw-r--r--openstack/common/wsgi.py14
-rw-r--r--tests/testmods/bar_foo_opt.py2
-rw-r--r--tests/testmods/baz_qux_opt.py2
-rw-r--r--tests/testmods/blaa_opt.py2
-rw-r--r--tests/unit/rpc/common.py2
-rw-r--r--tests/unit/rpc/test_common.py3
-rw-r--r--tests/unit/rpc/test_fake.py3
-rw-r--r--tests/unit/rpc/test_kombu.py2
-rw-r--r--tests/unit/rpc/test_kombu_ssl.py3
-rw-r--r--tests/unit/rpc/test_qpid.py2
-rw-r--r--tests/unit/rpc/test_zmq.py2
-rw-r--r--tests/unit/test_cfg.py1785
-rw-r--r--tests/unit/test_deprecated.py3
-rw-r--r--tests/unit/test_iniparser.py127
-rw-r--r--tests/unit/test_log.py3
-rw-r--r--tests/unit/test_notifier.py3
-rw-r--r--tests/unit/test_plugin.py3
-rw-r--r--tests/unit/test_service.py2
-rw-r--r--tests/unit/test_version.py3
-rw-r--r--tests/unit/test_wsgi.py7
-rw-r--r--tests/utils.py2
-rw-r--r--tools/install_venv_common.py2
-rw-r--r--tools/pip-requires1
-rw-r--r--tools/test-requires1
-rw-r--r--tox.ini2
-rw-r--r--update.py6
-rwxr-xr-xupdate.sh13
47 files changed, 67 insertions, 3858 deletions
diff --git a/bin/oslo-rpc-zmq-receiver b/bin/oslo-rpc-zmq-receiver
index 172136b..7478c8d 100755
--- a/bin/oslo-rpc-zmq-receiver
+++ b/bin/oslo-rpc-zmq-receiver
@@ -30,7 +30,8 @@ POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'oslo', '__init__.py')):
sys.path.insert(0, POSSIBLE_TOPDIR)
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import log as logging
from openstack.common import rpc
from openstack.common.rpc import impl_zmq
diff --git a/openstack/common/cfg.py b/openstack/common/cfg.py
deleted file mode 100644
index 3088eed..0000000
--- a/openstack/common/cfg.py
+++ /dev/null
@@ -1,1749 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 Red Hat, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-r"""
-Configuration options which may be set on the command line or in config files.
-
-The schema for each option is defined using the Opt sub-classes, e.g.:
-
-::
-
- common_opts = [
- 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')
- ]
-
-Options can be strings, integers, floats, booleans, lists or 'multi strings'::
-
- enabled_apis_opt = cfg.ListOpt('enabled_apis',
- default=['ec2', 'osapi_compute'],
- help='List of APIs to enable by default')
-
- DEFAULT_EXTENSIONS = [
- 'nova.api.openstack.compute.contrib.standard_extensions'
- ]
- osapi_compute_extension_opt = cfg.MultiStrOpt('osapi_compute_extension',
- default=DEFAULT_EXTENSIONS)
-
-Option schemas are registered with the config manager at runtime, but before
-the option is referenced::
-
- class ExtensionManager(object):
-
- enabled_apis_opt = cfg.ListOpt(...)
-
- def __init__(self, conf):
- self.conf = conf
- self.conf.register_opt(enabled_apis_opt)
- ...
-
- def _load_extensions(self):
- for ext_factory in self.conf.osapi_compute_extension:
- ....
-
-A common usage pattern is for each option schema to be defined in the module or
-class which uses the option::
-
- opts = ...
-
- def add_common_opts(conf):
- conf.register_opts(opts)
-
- def get_bind_host(conf):
- return conf.bind_host
-
- def get_bind_port(conf):
- return conf.bind_port
-
-An option may optionally be made available via the command line. Such options
-must registered with the config manager before the command line is parsed (for
-the purposes of --help and CLI arg validation)::
-
- cli_opts = [
- cfg.BoolOpt('verbose',
- short='v',
- default=False,
- help='Print more verbose output'),
- cfg.BoolOpt('debug',
- short='d',
- default=False,
- help='Print debugging output'),
- ]
-
- def add_common_opts(conf):
- conf.register_cli_opts(cli_opts)
-
-The config manager has two CLI options defined by default, --config-file
-and --config-dir::
-
- class ConfigOpts(object):
-
- def __call__(self, ...):
-
- opts = [
- MultiStrOpt('config-file',
- ...),
- StrOpt('config-dir',
- ...),
- ]
-
- self.register_cli_opts(opts)
-
-Option values are parsed from any supplied config files using
-openstack.common.iniparser. If none are specified, a default set is used
-e.g. glance-api.conf and glance-common.conf::
-
- glance-api.conf:
- [DEFAULT]
- bind_port = 9292
-
- glance-common.conf:
- [DEFAULT]
- bind_host = 0.0.0.0
-
-Option values in config files override those on the command line. Config files
-are parsed in order, with values in later files overriding those in earlier
-files.
-
-The parsing of CLI args and config files is initiated by invoking the config
-manager e.g.::
-
- conf = ConfigOpts()
- conf.register_opt(BoolOpt('verbose', ...))
- conf(sys.argv[1:])
- if conf.verbose:
- ...
-
-Options can be registered as belonging to a group::
-
- rabbit_group = cfg.OptGroup(name='rabbit',
- title='RabbitMQ options')
-
- 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')
-
- def register_rabbit_opts(conf):
- conf.register_group(rabbit_group)
- # options can be registered under a group in either of these ways:
- conf.register_opt(rabbit_host_opt, group=rabbit_group)
- conf.register_opt(rabbit_port_opt, group='rabbit')
-
-If it no group attributes are required other than the group name, the group
-need not be explicitly registered e.g.
-
- def register_rabbit_opts(conf):
- # The group will automatically be created, equivalent calling::
- # conf.register_group(OptGroup(name='rabbit'))
- conf.register_opt(rabbit_port_opt, group='rabbit')
-
-If no group is specified, options belong to the 'DEFAULT' section of config
-files::
-
- glance-api.conf:
- [DEFAULT]
- bind_port = 9292
- ...
-
- [rabbit]
- host = localhost
- port = 5672
- use_ssl = False
- userid = guest
- password = guest
- virtual_host = /
-
-Command-line options in a group are automatically prefixed with the
-group name::
-
- --rabbit-host localhost --rabbit-port 9999
-
-Option values in the default group are referenced as attributes/properties on
-the config manager; groups are also attributes on the config manager, with
-attributes for each of the options associated with the group::
-
- server.start(app, conf.bind_port, conf.bind_host, conf)
-
- self.connection = kombu.connection.BrokerConnection(
- hostname=conf.rabbit.host,
- port=conf.rabbit.port,
- ...)
-
-Option values may reference other values using PEP 292 string substitution::
-
- opts = [
- cfg.StrOpt('state_path',
- default=os.path.join(os.path.dirname(__file__), '../'),
- help='Top-level directory for maintaining nova state'),
- cfg.StrOpt('sqlite_db',
- default='nova.sqlite',
- help='file name for sqlite'),
- cfg.StrOpt('sql_connection',
- default='sqlite:///$state_path/$sqlite_db',
- help='connection string for sql database'),
- ]
-
-Note that interpolation can be avoided by using '$$'.
-
-Options may be declared as required so that an error is raised if the user
-does not supply a value for the option.
-
-Options may be declared as secret so that their values are not leaked into
-log files::
-
- opts = [
- cfg.StrOpt('s3_store_access_key', secret=True),
- cfg.StrOpt('s3_store_secret_key', secret=True),
- ...
- ]
-
-This module also contains a global instance of the ConfigOpts class
-in order to support a common usage pattern in OpenStack::
-
- from openstack.common import cfg
-
- opts = [
- cfg.StrOpt('bind_host', default='0.0.0.0'),
- cfg.IntOpt('bind_port', default=9292),
- ]
-
- CONF = cfg.CONF
- CONF.register_opts(opts)
-
- def start(server, app):
- server.start(app, CONF.bind_port, CONF.bind_host)
-
-Positional command line arguments are supported via a 'positional' Opt
-constructor argument::
-
- >>> conf = ConfigOpts()
- >>> conf.register_cli_opt(MultiStrOpt('bar', positional=True))
- True
- >>> conf(['a', 'b'])
- >>> conf.bar
- ['a', 'b']
-
-It is also possible to use argparse "sub-parsers" to parse additional
-command line arguments using the SubCommandOpt class:
-
- >>> def add_parsers(subparsers):
- ... list_action = subparsers.add_parser('list')
- ... list_action.add_argument('id')
- ...
- >>> conf = ConfigOpts()
- >>> conf.register_cli_opt(SubCommandOpt('action', handler=add_parsers))
- True
- >>> conf(args=['list', '10'])
- >>> conf.action.name, conf.action.id
- ('list', '10')
-
-"""
-
-import argparse
-import collections
-import copy
-import functools
-import glob
-import os
-import string
-import sys
-
-from openstack.common import iniparser
-
-
-class Error(Exception):
- """Base class for cfg exceptions."""
-
- def __init__(self, msg=None):
- self.msg = msg
-
- def __str__(self):
- return self.msg
-
-
-class ArgsAlreadyParsedError(Error):
- """Raised if a CLI opt is registered after parsing."""
-
- def __str__(self):
- ret = "arguments already parsed"
- if self.msg:
- ret += ": " + self.msg
- return ret
-
-
-class NoSuchOptError(Error, AttributeError):
- """Raised if an opt which doesn't exist is referenced."""
-
- def __init__(self, opt_name, group=None):
- self.opt_name = opt_name
- self.group = group
-
- def __str__(self):
- if self.group is None:
- return "no such option: %s" % self.opt_name
- else:
- return "no such option in group %s: %s" % (self.group.name,
- self.opt_name)
-
-
-class NoSuchGroupError(Error):
- """Raised if a group which doesn't exist is referenced."""
-
- def __init__(self, group_name):
- self.group_name = group_name
-
- def __str__(self):
- return "no such group: %s" % self.group_name
-
-
-class DuplicateOptError(Error):
- """Raised if multiple opts with the same name are registered."""
-
- def __init__(self, opt_name):
- self.opt_name = opt_name
-
- def __str__(self):
- return "duplicate option: %s" % self.opt_name
-
-
-class RequiredOptError(Error):
- """Raised if an option is required but no value is supplied by the user."""
-
- def __init__(self, opt_name, group=None):
- self.opt_name = opt_name
- self.group = group
-
- def __str__(self):
- if self.group is None:
- return "value required for option: %s" % self.opt_name
- else:
- return "value required for option: %s.%s" % (self.group.name,
- self.opt_name)
-
-
-class TemplateSubstitutionError(Error):
- """Raised if an error occurs substituting a variable in an opt value."""
-
- def __str__(self):
- return "template substitution error: %s" % self.msg
-
-
-class ConfigFilesNotFoundError(Error):
- """Raised if one or more config files are not found."""
-
- def __init__(self, config_files):
- self.config_files = config_files
-
- def __str__(self):
- return ('Failed to read some config files: %s' %
- string.join(self.config_files, ','))
-
-
-class ConfigFileParseError(Error):
- """Raised if there is an error parsing a config file."""
-
- def __init__(self, config_file, msg):
- self.config_file = config_file
- self.msg = msg
-
- def __str__(self):
- return 'Failed to parse %s: %s' % (self.config_file, self.msg)
-
-
-class ConfigFileValueError(Error):
- """Raised if a config file value does not match its opt type."""
- pass
-
-
-def _fixpath(p):
- """Apply tilde expansion and absolutization to a path."""
- return os.path.abspath(os.path.expanduser(p))
-
-
-def _get_config_dirs(project=None):
- """Return a list of directors where config files may be located.
-
- :param project: an optional project name
-
- If a project is specified, following directories are returned::
-
- ~/.${project}/
- ~/
- /etc/${project}/
- /etc/
-
- Otherwise, these directories::
-
- ~/
- /etc/
- """
- cfg_dirs = [
- _fixpath(os.path.join('~', '.' + project)) if project else None,
- _fixpath('~'),
- os.path.join('/etc', project) if project else None,
- '/etc'
- ]
-
- return filter(bool, cfg_dirs)
-
-
-def _search_dirs(dirs, basename, extension=""):
- """Search a list of directories for a given filename.
-
- Iterator over the supplied directories, returning the first file
- found with the supplied name and extension.
-
- :param dirs: a list of directories
- :param basename: the filename, e.g. 'glance-api'
- :param extension: the file extension, e.g. '.conf'
- :returns: the path to a matching file, or None
- """
- for d in dirs:
- path = os.path.join(d, '%s%s' % (basename, extension))
- if os.path.exists(path):
- return path
-
-
-def find_config_files(project=None, prog=None, extension='.conf'):
- """Return a list of default configuration files.
-
- :param project: an optional project name
- :param prog: the program name, defaulting to the basename of sys.argv[0]
- :param extension: the type of the config file
-
- We default to two config files: [${project}.conf, ${prog}.conf]
-
- And we look for those config files in the following directories::
-
- ~/.${project}/
- ~/
- /etc/${project}/
- /etc/
-
- We return an absolute path for (at most) one of each the default config
- files, for the topmost directory it exists in.
-
- For example, if project=foo, prog=bar and /etc/foo/foo.conf, /etc/bar.conf
- and ~/.foo/bar.conf all exist, then we return ['/etc/foo/foo.conf',
- '~/.foo/bar.conf']
-
- If no project name is supplied, we only look for ${prog.conf}.
- """
- if prog is None:
- prog = os.path.basename(sys.argv[0])
-
- cfg_dirs = _get_config_dirs(project)
-
- config_files = []
- if project:
- config_files.append(_search_dirs(cfg_dirs, project, extension))
- config_files.append(_search_dirs(cfg_dirs, prog, extension))
-
- return filter(bool, config_files)
-
-
-def _is_opt_registered(opts, opt):
- """Check whether an opt with the same name is already registered.
-
- The same opt may be registered multiple times, with only the first
- registration having any effect. However, it is an error to attempt
- to register a different opt with the same name.
-
- :param opts: the set of opts already registered
- :param opt: the opt to be registered
- :returns: True if the opt was previously registered, False otherwise
- :raises: DuplicateOptError if a naming conflict is detected
- """
- if opt.dest in opts:
- if opts[opt.dest]['opt'] != opt:
- raise DuplicateOptError(opt.name)
- return True
- else:
- return False
-
-
-def set_defaults(opts, **kwargs):
- for opt in opts:
- if opt.dest in kwargs:
- opt.default = kwargs[opt.dest]
- break
-
-
-class Opt(object):
-
- """Base class for all configuration options.
-
- An Opt object has no public methods, but has a number of public string
- properties:
-
- name:
- the name of the option, which may include hyphens
- dest:
- the (hyphen-less) ConfigOpts property which contains the option value
- short:
- a single character CLI option name
- default:
- the default value of the option
- positional:
- True if the option is a positional CLI argument
- metavar:
- the name shown as the argument to a CLI option in --help output
- help:
- an string explaining how the options value is used
- """
- multi = False
-
- def __init__(self, name, dest=None, short=None, default=None,
- positional=False, metavar=None, help=None,
- secret=False, required=False, deprecated_name=None):
- """Construct an Opt object.
-
- The only required parameter is the option's name. However, it is
- common to also supply a default and help string for all options.
-
- :param name: the option's name
- :param dest: the name of the corresponding ConfigOpts property
- :param short: a single character CLI option name
- :param default: the default value of the option
- :param positional: True if the option is a positional CLI argument
- :param metavar: the option argument to show in --help
- :param help: an explanation of how the option is used
- :param secret: true iff the value should be obfuscated in log output
- :param required: true iff a value must be supplied for this option
- :param deprecated_name: deprecated name option. Acts like an alias
- """
- self.name = name
- if dest is None:
- self.dest = self.name.replace('-', '_')
- else:
- self.dest = dest
- self.short = short
- self.default = default
- self.positional = positional
- self.metavar = metavar
- self.help = help
- self.secret = secret
- self.required = required
- if deprecated_name is not None:
- self.deprecated_name = deprecated_name.replace('-', '_')
- else:
- self.deprecated_name = None
-
- def __ne__(self, another):
- return vars(self) != vars(another)
-
- def _get_from_config_parser(self, cparser, section):
- """Retrieves the option value from a MultiConfigParser object.
-
- This is the method ConfigOpts uses to look up the option value from
- config files. Most opt types override this method in order to perform
- type appropriate conversion of the returned value.
-
- :param cparser: a ConfigParser object
- :param section: a section name
- """
- return self._cparser_get_with_deprecated(cparser, section)
-
- def _cparser_get_with_deprecated(self, cparser, section):
- """If cannot find option as dest try deprecated_name alias."""
- if self.deprecated_name is not None:
- return cparser.get(section, [self.dest, self.deprecated_name])
- return cparser.get(section, [self.dest])
-
- def _add_to_cli(self, parser, group=None):
- """Makes the option available in the command line interface.
-
- This is the method ConfigOpts uses to add the opt to the CLI interface
- as appropriate for the opt type. Some opt types may extend this method,
- others may just extend the helper methods it uses.
-
- :param parser: the CLI option parser
- :param group: an optional OptGroup object
- """
- container = self._get_argparse_container(parser, group)
- kwargs = self._get_argparse_kwargs(group)
- prefix = self._get_argparse_prefix('', group)
- self._add_to_argparse(container, self.name, self.short, kwargs, prefix,
- self.positional, self.deprecated_name)
-
- def _add_to_argparse(self, container, name, short, kwargs, prefix='',
- positional=False, deprecated_name=None):
- """Add an option to an argparse parser or group.
-
- :param container: an argparse._ArgumentGroup object
- :param name: the opt name
- :param short: the short opt name
- :param kwargs: the keyword arguments for add_argument()
- :param prefix: an optional prefix to prepend to the opt name
- :param position: whether the optional is a positional CLI argument
- :raises: DuplicateOptError if a naming confict is detected
- """
- def hyphen(arg):
- return arg if not positional else ''
-
- args = [hyphen('--') + prefix + name]
- if short:
- args.append(hyphen('-') + short)
- if deprecated_name:
- args.append(hyphen('--') + prefix + deprecated_name)
-
- try:
- container.add_argument(*args, **kwargs)
- except argparse.ArgumentError as e:
- raise DuplicateOptError(e)
-
- def _get_argparse_container(self, parser, group):
- """Returns an argparse._ArgumentGroup.
-
- :param parser: an argparse.ArgumentParser
- :param group: an (optional) OptGroup object
- :returns: an argparse._ArgumentGroup if group is given, else parser
- """
- if group is not None:
- return group._get_argparse_group(parser)
- else:
- return parser
-
- def _get_argparse_kwargs(self, group, **kwargs):
- """Build a dict of keyword arguments for argparse's add_argument().
-
- Most opt types extend this method to customize the behaviour of the
- options added to argparse.
-
- :param group: an optional group
- :param kwargs: optional keyword arguments to add to
- :returns: a dict of keyword arguments
- """
- if not self.positional:
- dest = self.dest
- if group is not None:
- dest = group.name + '_' + dest
- kwargs['dest'] = dest
- else:
- kwargs['nargs'] = '?'
- kwargs.update({'default': None,
- 'metavar': self.metavar,
- 'help': self.help, })
- return kwargs
-
- def _get_argparse_prefix(self, prefix, group):
- """Build a prefix for the CLI option name, if required.
-
- CLI options in a group are prefixed with the group's name in order
- to avoid conflicts between similarly named options in different
- groups.
-
- :param prefix: an existing prefix to append to (e.g. 'no' or '')
- :param group: an optional OptGroup object
- :returns: a CLI option prefix including the group name, if appropriate
- """
- if group is not None:
- return group.name + '-' + prefix
- else:
- return prefix
-
-
-class StrOpt(Opt):
- """
- String opts do not have their values transformed and are returned as
- str objects.
- """
- pass
-
-
-class BoolOpt(Opt):
-
- """
- Bool opts are set to True or False on the command line using --optname or
- --noopttname respectively.
-
- In config files, boolean values are case insensitive and can be set using
- 1/0, yes/no, true/false or on/off.
- """
-
- _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
- '0': False, 'no': False, 'false': False, 'off': False}
-
- def __init__(self, *args, **kwargs):
- if 'positional' in kwargs:
- raise ValueError('positional boolean args not supported')
- super(BoolOpt, self).__init__(*args, **kwargs)
-
- def _get_from_config_parser(self, cparser, section):
- """Retrieve the opt value as a boolean from ConfigParser."""
- def convert_bool(v):
- value = self._boolean_states.get(v.lower())
- if value is None:
- raise ValueError('Unexpected boolean value %r' % v)
-
- return value
-
- return [convert_bool(v) for v in
- self._cparser_get_with_deprecated(cparser, section)]
-
- def _add_to_cli(self, parser, group=None):
- """Extends the base class method to add the --nooptname option."""
- super(BoolOpt, self)._add_to_cli(parser, group)
- self._add_inverse_to_argparse(parser, group)
-
- def _add_inverse_to_argparse(self, parser, group):
- """Add the --nooptname option to the option parser."""
- container = self._get_argparse_container(parser, group)
- kwargs = self._get_argparse_kwargs(group, action='store_false')
- prefix = self._get_argparse_prefix('no', group)
- kwargs["help"] = "The inverse of --" + self.name
- self._add_to_argparse(container, self.name, None, kwargs, prefix,
- self.positional, self.deprecated_name)
-
- def _get_argparse_kwargs(self, group, action='store_true', **kwargs):
- """Extends the base argparse keyword dict for boolean options."""
-
- kwargs = super(BoolOpt, self)._get_argparse_kwargs(group, **kwargs)
-
- # metavar has no effect for BoolOpt
- if 'metavar' in kwargs:
- del kwargs['metavar']
-
- if action != 'store_true':
- action = 'store_false'
-
- kwargs['action'] = action
-
- return kwargs
-
-
-class IntOpt(Opt):
-
- """Int opt values are converted to integers using the int() builtin."""
-
- def _get_from_config_parser(self, cparser, section):
- """Retrieve the opt value as a integer from ConfigParser."""
- return [int(v) for v in self._cparser_get_with_deprecated(cparser,
- section)]
-
- def _get_argparse_kwargs(self, group, **kwargs):
- """Extends the base argparse keyword dict for integer options."""
- return super(IntOpt,
- self)._get_argparse_kwargs(group, type=int, **kwargs)
-
-
-class FloatOpt(Opt):
-
- """Float opt values are converted to floats using the float() builtin."""
-
- def _get_from_config_parser(self, cparser, section):
- """Retrieve the opt value as a float from ConfigParser."""
- return [float(v) for v in
- self._cparser_get_with_deprecated(cparser, section)]
-
- def _get_argparse_kwargs(self, group, **kwargs):
- """Extends the base argparse keyword dict for float options."""
- return super(FloatOpt, self)._get_argparse_kwargs(group,
- type=float, **kwargs)
-
-
-class ListOpt(Opt):
-
- """
- List opt values are simple string values separated by commas. The opt value
- is a list containing these strings.
- """
-
- class _StoreListAction(argparse.Action):
- """
- An argparse action for parsing an option value into a list.
- """
- def __call__(self, parser, namespace, values, option_string=None):
- if values is not None:
- values = [a.strip() for a in values.split(',')]
- setattr(namespace, self.dest, values)
-
- def _get_from_config_parser(self, cparser, section):
- """Retrieve the opt value as a list from ConfigParser."""
- return [[a.strip() for a in v.split(',')] for v in
- self._cparser_get_with_deprecated(cparser, section)]
-
- def _get_argparse_kwargs(self, group, **kwargs):
- """Extends the base argparse keyword dict for list options."""
- return Opt._get_argparse_kwargs(self,
- group,
- action=ListOpt._StoreListAction,
- **kwargs)
-
-
-class MultiStrOpt(Opt):
-
- """
- Multistr opt values are string opts which may be specified multiple times.
- The opt value is a list containing all the string values specified.
- """
- multi = True
-
- def _get_argparse_kwargs(self, group, **kwargs):
- """Extends the base argparse keyword dict for multi str options."""
- kwargs = super(MultiStrOpt, self)._get_argparse_kwargs(group)
- if not self.positional:
- kwargs['action'] = 'append'
- else:
- kwargs['nargs'] = '*'
- return kwargs
-
- def _cparser_get_with_deprecated(self, cparser, section):
- """If cannot find option as dest try deprecated_name alias."""
- if self.deprecated_name is not None:
- return cparser.get(section, [self.dest, self.deprecated_name],
- multi=True)
- return cparser.get(section, [self.dest], multi=True)
-
-
-class SubCommandOpt(Opt):
-
- """
- Sub-command options allow argparse sub-parsers to be used to parse
- additional command line arguments.
-
- The handler argument to the SubCommandOpt contructor is a callable
- which is supplied an argparse subparsers object. Use this handler
- callable to add sub-parsers.
-
- The opt value is SubCommandAttr object with the name of the chosen
- sub-parser stored in the 'name' attribute and the values of other
- sub-parser arguments available as additional attributes.
- """
-
- def __init__(self, name, dest=None, handler=None,
- title=None, description=None, help=None):
- """Construct an sub-command parsing option.
-
- This behaves similarly to other Opt sub-classes but adds a
- 'handler' argument. The handler is a callable which is supplied
- an subparsers object when invoked. The add_parser() method on
- this subparsers object can be used to register parsers for
- sub-commands.
-
- :param name: the option's name
- :param dest: the name of the corresponding ConfigOpts property
- :param title: title of the sub-commands group in help output
- :param description: description of the group in help output
- :param help: a help string giving an overview of available sub-commands
- """
- super(SubCommandOpt, self).__init__(name, dest=dest, help=help)
- self.handler = handler
- self.title = title
- self.description = description
-
- def _add_to_cli(self, parser, group=None):
- """Add argparse sub-parsers and invoke the handler method."""
- dest = self.dest
- if group is not None:
- dest = group.name + '_' + dest
-
- subparsers = parser.add_subparsers(dest=dest,
- title=self.title,
- description=self.description,
- help=self.help)
-
- if self.handler is not None:
- self.handler(subparsers)
-
-
-class OptGroup(object):
-
- """
- Represents a group of opts.
-
- CLI opts in the group are automatically prefixed with the group name.
-
- Each group corresponds to a section in config files.
-
- An OptGroup object has no public methods, but has a number of public string
- properties:
-
- name:
- the name of the group
- title:
- the group title as displayed in --help
- help:
- the group description as displayed in --help
- """
-
- def __init__(self, name, title=None, help=None):
- """Constructs an OptGroup object.
-
- :param name: the group name
- :param title: the group title for --help
- :param help: the group description for --help
- """
- self.name = name
- if title is None:
- self.title = "%s options" % title
- else:
- self.title = title
- self.help = help
-
- self._opts = {} # dict of dicts of (opt:, override:, default:)
- self._argparse_group = None
-
- def _register_opt(self, opt, cli=False):
- """Add an opt to this group.
-
- :param opt: an Opt object
- :param cli: whether this is a CLI option
- :returns: False if previously registered, True otherwise
- :raises: DuplicateOptError if a naming conflict is detected
- """
- if _is_opt_registered(self._opts, opt):
- return False
-
- self._opts[opt.dest] = {'opt': opt, 'cli': cli}
-
- return True
-
- def _unregister_opt(self, opt):
- """Remove an opt from this group.
-
- :param opt: an Opt object
- """
- if opt.dest in self._opts:
- del self._opts[opt.dest]
-
- def _get_argparse_group(self, parser):
- if self._argparse_group is None:
- """Build an argparse._ArgumentGroup for this group."""
- self._argparse_group = parser.add_argument_group(self.title,
- self.help)
- return self._argparse_group
-
- def _clear(self):
- """Clear this group's option parsing state."""
- self._argparse_group = None
-
-
-class ParseError(iniparser.ParseError):
- def __init__(self, msg, lineno, line, filename):
- super(ParseError, self).__init__(msg, lineno, line)
- self.filename = filename
-
- def __str__(self):
- return 'at %s:%d, %s: %r' % (self.filename, self.lineno,
- self.msg, self.line)
-
-
-class ConfigParser(iniparser.BaseParser):
- def __init__(self, filename, sections):
- super(ConfigParser, self).__init__()
- self.filename = filename
- self.sections = sections
- self.section = None
-
- def parse(self):
- with open(self.filename) as f:
- return super(ConfigParser, self).parse(f)
-
- def new_section(self, section):
- self.section = section
- self.sections.setdefault(self.section, {})
-
- def assignment(self, key, value):
- if not self.section:
- raise self.error_no_section()
-
- self.sections[self.section].setdefault(key, [])
- self.sections[self.section][key].append('\n'.join(value))
-
- def parse_exc(self, msg, lineno, line=None):
- return ParseError(msg, lineno, line, self.filename)
-
- def error_no_section(self):
- return self.parse_exc('Section must be started before assignment',
- self.lineno)
-
-
-class MultiConfigParser(object):
- def __init__(self):
- self.parsed = []
-
- def read(self, config_files):
- read_ok = []
-
- for filename in config_files:
- sections = {}
- parser = ConfigParser(filename, sections)
-
- try:
- parser.parse()
- except IOError:
- continue
- self.parsed.insert(0, sections)
- read_ok.append(filename)
-
- return read_ok
-
- def get(self, section, names, multi=False):
- rvalue = []
- for sections in self.parsed:
- if section not in sections:
- continue
- for name in names:
- if name in sections[section]:
- if multi:
- rvalue = sections[section][name] + rvalue
- else:
- return sections[section][name]
- if multi and rvalue != []:
- return rvalue
- raise KeyError
-
-
-class ConfigOpts(collections.Mapping):
-
- """
- Config options which may be set on the command line or in config files.
-
- ConfigOpts is a configuration option manager with APIs for registering
- option schemas, grouping options, parsing option values and retrieving
- the values of options.
- """
-
- def __init__(self):
- """Construct a ConfigOpts object."""
- self._opts = {} # dict of dicts of (opt:, override:, default:)
- self._groups = {}
-
- self._args = None
-
- self._oparser = None
- self._cparser = None
- self._cli_values = {}
- self.__cache = {}
- self._config_opts = []
-
- def _pre_setup(self, project, prog, version, usage, default_config_files):
- """Initialize a ConfigCliParser object for option parsing."""
-
- if prog is None:
- prog = os.path.basename(sys.argv[0])
-
- if default_config_files is None:
- default_config_files = find_config_files(project, prog)
-
- self._oparser = argparse.ArgumentParser(prog=prog, usage=usage)
- self._oparser.add_argument('--version',
- action='version',
- version=version)
-
- return prog, default_config_files
-
- def _setup(self, project, prog, version, usage, default_config_files):
- """Initialize a ConfigOpts object for option parsing."""
-
- self._config_opts = [
- MultiStrOpt('config-file',
- default=default_config_files,
- metavar='PATH',
- help='Path to a config file to use. Multiple config '
- 'files can be specified, with values in later '
- 'files taking precedence. The default files '
- ' used are: %s' % (default_config_files, )),
- StrOpt('config-dir',
- metavar='DIR',
- help='Path to a config directory to pull *.conf '
- 'files from. This file set is sorted, so as to '
- 'provide a predictable parse order if individual '
- 'options are over-ridden. The set is parsed after '
- 'the file(s), if any, specified via --config-file, '
- 'hence over-ridden options in the directory take '
- 'precedence.'),
- ]
- self.register_cli_opts(self._config_opts)
-
- self.project = project
- self.prog = prog
- self.version = version
- self.usage = usage
- self.default_config_files = default_config_files
-
- def __clear_cache(f):
- @functools.wraps(f)
- def __inner(self, *args, **kwargs):
- if kwargs.pop('clear_cache', True):
- self.__cache.clear()
- return f(self, *args, **kwargs)
-
- return __inner
-
- def __call__(self,
- args=None,
- project=None,
- prog=None,
- version=None,
- usage=None,
- default_config_files=None):
- """Parse command line arguments and config files.
-
- Calling a ConfigOpts object causes the supplied command line arguments
- and config files to be parsed, causing opt values to be made available
- as attributes of the object.
-
- The object may be called multiple times, each time causing the previous
- set of values to be overwritten.
-
- Automatically registers the --config-file option with either a supplied
- list of default config files, or a list from find_config_files().
-
- If the --config-dir option is set, any *.conf files from this
- directory are pulled in, after all the file(s) specified by the
- --config-file option.
-
- :param args: command line arguments (defaults to sys.argv[1:])
- :param project: the toplevel project name, used to locate config files
- :param prog: the name of the program (defaults to sys.argv[0] basename)
- :param version: the program version (for --version)
- :param usage: a usage string (%prog will be expanded)
- :param default_config_files: config files to use by default
- :returns: the list of arguments left over after parsing options
- :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
- RequiredOptError, DuplicateOptError
- """
-
- self.clear()
-
- prog, default_config_files = self._pre_setup(project,
- prog,
- version,
- usage,
- default_config_files)
-
- self._setup(project, prog, version, usage, default_config_files)
-
- self._cli_values = self._parse_cli_opts(args)
-
- self._parse_config_files()
-
- self._check_required_opts()
-
- def __getattr__(self, name):
- """Look up an option value and perform string substitution.
-
- :param name: the opt name (or 'dest', more precisely)
- :returns: the option value (after string subsititution) or a GroupAttr
- :raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError
- """
- return self._get(name)
-
- def __getitem__(self, key):
- """Look up an option value and perform string substitution."""
- return self.__getattr__(key)
-
- def __contains__(self, key):
- """Return True if key is the name of a registered opt or group."""
- return key in self._opts or key in self._groups
-
- def __iter__(self):
- """Iterate over all registered opt and group names."""
- for key in self._opts.keys() + self._groups.keys():
- yield key
-
- def __len__(self):
- """Return the number of options and option groups."""
- return len(self._opts) + len(self._groups)
-
- def reset(self):
- """Clear the object state and unset overrides and defaults."""
- self._unset_defaults_and_overrides()
- self.clear()
-
- @__clear_cache
- def clear(self):
- """Clear the state of the object to before it was called.
-
- Any subparsers added using the add_cli_subparsers() will also be
- removed as a side-effect of this method.
- """
- self._args = None
- self._cli_values.clear()
- self._oparser = argparse.ArgumentParser()
- self._cparser = None
- self.unregister_opts(self._config_opts)
- for group in self._groups.values():
- group._clear()
-
- @__clear_cache
- def register_opt(self, opt, group=None, cli=False):
- """Register an option schema.
-
- Registering an option schema makes any option value which is previously
- or subsequently parsed from the command line or config files available
- as an attribute of this object.
-
- :param opt: an instance of an Opt sub-class
- :param cli: whether this is a CLI option
- :param group: an optional OptGroup object or group name
- :return: False if the opt was already register, True otherwise
- :raises: DuplicateOptError
- """
- if group is not None:
- group = self._get_group(group, autocreate=True)
- return group._register_opt(opt, cli)
-
- if _is_opt_registered(self._opts, opt):
- return False
-
- self._opts[opt.dest] = {'opt': opt, 'cli': cli}
-
- return True
-
- @__clear_cache
- def register_opts(self, opts, group=None):
- """Register multiple option schemas at once."""
- for opt in opts:
- self.register_opt(opt, group, clear_cache=False)
-
- @__clear_cache
- def register_cli_opt(self, opt, group=None):
- """Register a CLI option schema.
-
- CLI option schemas must be registered before the command line and
- config files are parsed. This is to ensure that all CLI options are
- show in --help and option validation works as expected.
-
- :param opt: an instance of an Opt sub-class
- :param group: an optional OptGroup object or group name
- :return: False if the opt was already register, True otherwise
- :raises: DuplicateOptError, ArgsAlreadyParsedError
- """
- if self._args is not None:
- raise ArgsAlreadyParsedError("cannot register CLI option")
-
- return self.register_opt(opt, group, cli=True, clear_cache=False)
-
- @__clear_cache
- def register_cli_opts(self, opts, group=None):
- """Register multiple CLI option schemas at once."""
- for opt in opts:
- self.register_cli_opt(opt, group, clear_cache=False)
-
- def register_group(self, group):
- """Register an option group.
-
- An option group must be registered before options can be registered
- with the group.
-
- :param group: an OptGroup object
- """
- if group.name in self._groups:
- return
-
- self._groups[group.name] = copy.copy(group)
-
- @__clear_cache
- def unregister_opt(self, opt, group=None):
- """Unregister an option.
-
- :param opt: an Opt object
- :param group: an optional OptGroup object or group name
- :raises: ArgsAlreadyParsedError, NoSuchGroupError
- """
- if self._args is not None:
- raise ArgsAlreadyParsedError("reset before unregistering options")
-
- if group is not None:
- self._get_group(group)._unregister_opt(opt)
- elif opt.dest in self._opts:
- del self._opts[opt.dest]
-
- @__clear_cache
- def unregister_opts(self, opts, group=None):
- """Unregister multiple CLI option schemas at once."""
- for opt in opts:
- self.unregister_opt(opt, group, clear_cache=False)
-
- def import_opt(self, name, module_str, group=None):
- """Import an option definition from a module.
-
- Import a module and check that a given option is registered.
-
- This is intended for use with global configuration objects
- like cfg.CONF where modules commonly register options with
- CONF at module load time. If one module requires an option
- defined by another module it can use this method to explicitly
- declare the dependency.
-
- :param name: the name/dest of the opt
- :param module_str: the name of a module to import
- :param group: an option OptGroup object or group name
- :raises: NoSuchOptError, NoSuchGroupError
- """
- __import__(module_str)
- self._get_opt_info(name, group)
-
- def import_group(self, group, module_str):
- """Import an option group from a module.
-
- Import a module and check that a given option group is registered.
-
- This is intended for use with global configuration objects
- like cfg.CONF where modules commonly register options with
- CONF at module load time. If one module requires an option group
- defined by another module it can use this method to explicitly
- declare the dependency.
-
- :param group: an option OptGroup object or group name
- :param module_str: the name of a module to import
- :raises: ImportError, NoSuchGroupError
- """
- __import__(module_str)
- self._get_group(group)
-
- @__clear_cache
- def set_override(self, name, override, group=None):
- """Override an opt value.
-
- Override the command line, config file and default values of a
- given option.
-
- :param name: the name/dest of the opt
- :param override: the override value
- :param group: an option OptGroup object or group name
- :raises: NoSuchOptError, NoSuchGroupError
- """
- opt_info = self._get_opt_info(name, group)
- opt_info['override'] = override
-
- @__clear_cache
- def set_default(self, name, default, group=None):
- """Override an opt's default value.
-
- Override the default value of given option. A command line or
- config file value will still take precedence over this default.
-
- :param name: the name/dest of the opt
- :param default: the default value
- :param group: an option OptGroup object or group name
- :raises: NoSuchOptError, NoSuchGroupError
- """
- opt_info = self._get_opt_info(name, group)
- opt_info['default'] = default
-
- @__clear_cache
- def clear_override(self, name, group=None):
- """Clear an override an opt value.
-
- Clear a previously set override of the command line, config file
- and default values of a given option.
-
- :param name: the name/dest of the opt
- :param group: an option OptGroup object or group name
- :raises: NoSuchOptError, NoSuchGroupError
- """
- opt_info = self._get_opt_info(name, group)
- opt_info.pop('override', None)
-
- @__clear_cache
- def clear_default(self, name, group=None):
- """Clear an override an opt's default value.
-
- Clear a previously set override of the default value of given option.
-
- :param name: the name/dest of the opt
- :param group: an option OptGroup object or group name
- :raises: NoSuchOptError, NoSuchGroupError
- """
- opt_info = self._get_opt_info(name, group)
- opt_info.pop('default', None)
-
- def _all_opt_infos(self):
- """A generator function for iteration opt infos."""
- for info in self._opts.values():
- yield info, None
- for group in self._groups.values():
- for info in group._opts.values():
- yield info, group
-
- def _all_cli_opts(self):
- """A generator function for iterating CLI opts."""
- for info, group in self._all_opt_infos():
- if info['cli']:
- yield info['opt'], group
-
- def _unset_defaults_and_overrides(self):
- """Unset any default or override on all options."""
- for info, group in self._all_opt_infos():
- info.pop('default', None)
- info.pop('override', None)
-
- def find_file(self, name):
- """Locate a file located alongside the config files.
-
- Search for a file with the supplied basename in the directories
- which we have already loaded config files from and other known
- configuration directories.
-
- The directory, if any, supplied by the config_dir option is
- searched first. Then the config_file option is iterated over
- and each of the base directories of the config_files values
- are searched. Failing both of these, the standard directories
- searched by the module level find_config_files() function is
- used. The first matching file is returned.
-
- :param basename: the filename, e.g. 'policy.json'
- :returns: the path to a matching file, or None
- """
- dirs = []
- if self.config_dir:
- dirs.append(_fixpath(self.config_dir))
-
- for cf in reversed(self.config_file):
- dirs.append(os.path.dirname(_fixpath(cf)))
-
- dirs.extend(_get_config_dirs(self.project))
-
- return _search_dirs(dirs, name)
-
- def log_opt_values(self, logger, lvl):
- """Log the value of all registered opts.
-
- It's often useful for an app to log its configuration to a log file at
- startup for debugging. This method dumps to the entire config state to
- the supplied logger at a given log level.
-
- :param logger: a logging.Logger object
- :param lvl: the log level (e.g. logging.DEBUG) arg to logger.log()
- """
- logger.log(lvl, "*" * 80)
- logger.log(lvl, "Configuration options gathered from:")
- logger.log(lvl, "command line args: %s", self._args)
- logger.log(lvl, "config files: %s", self.config_file)
- logger.log(lvl, "=" * 80)
-
- def _sanitize(opt, value):
- """Obfuscate values of options declared secret"""
- return value if not opt.secret else '*' * len(str(value))
-
- for opt_name in sorted(self._opts):
- opt = self._get_opt_info(opt_name)['opt']
- logger.log(lvl, "%-30s = %s", opt_name,
- _sanitize(opt, getattr(self, opt_name)))
-
- for group_name in self._groups:
- group_attr = self.GroupAttr(self, self._get_group(group_name))
- for opt_name in sorted(self._groups[group_name]._opts):
- opt = self._get_opt_info(opt_name, group_name)['opt']
- logger.log(lvl, "%-30s = %s",
- "%s.%s" % (group_name, opt_name),
- _sanitize(opt, getattr(group_attr, opt_name)))
-
- logger.log(lvl, "*" * 80)
-
- def print_usage(self, file=None):
- """Print the usage message for the current program."""
- self._oparser.print_usage(file)
-
- def print_help(self, file=None):
- """Print the help message for the current program."""
- self._oparser.print_help(file)
-
- def _get(self, name, group=None):
- if isinstance(group, OptGroup):
- key = (group.name, name)
- else:
- key = (group, name)
- try:
- return self.__cache[key]
- except KeyError:
- value = self._substitute(self._do_get(name, group))
- self.__cache[key] = value
- return value
-
- def _do_get(self, name, group=None):
- """Look up an option value.
-
- :param name: the opt name (or 'dest', more precisely)
- :param group: an OptGroup
- :returns: the option value, or a GroupAttr object
- :raises: NoSuchOptError, NoSuchGroupError, ConfigFileValueError,
- TemplateSubstitutionError
- """
- if group is None and name in self._groups:
- return self.GroupAttr(self, self._get_group(name))
-
- info = self._get_opt_info(name, group)
- opt = info['opt']
-
- if isinstance(opt, SubCommandOpt):
- return self.SubCommandAttr(self, group, opt.dest)
-
- if 'override' in info:
- return info['override']
-
- values = []
- if self._cparser is not None:
- section = group.name if group is not None else 'DEFAULT'
- try:
- value = opt._get_from_config_parser(self._cparser, section)
- except KeyError:
- pass
- except ValueError as ve:
- raise ConfigFileValueError(str(ve))
- else:
- if not opt.multi:
- # No need to continue since the last value wins
- return value[-1]
- values.extend(value)
-
- name = name if group is None else group.name + '_' + name
- value = self._cli_values.get(name)
- if value is not None:
- if not opt.multi:
- return value
-
- # argparse ignores default=None for nargs='*'
- if opt.positional and not value:
- value = opt.default
-
- return value + values
-
- if values:
- return values
-
- if 'default' in info:
- return info['default']
-
- return opt.default
-
- def _substitute(self, value):
- """Perform string template substitution.
-
- Substitute any template variables (e.g. $foo, ${bar}) in the supplied
- string value(s) with opt values.
-
- :param value: the string value, or list of string values
- :returns: the substituted string(s)
- """
- if isinstance(value, list):
- return [self._substitute(i) for i in value]
- elif isinstance(value, str):
- tmpl = string.Template(value)
- return tmpl.safe_substitute(self.StrSubWrapper(self))
- else:
- return value
-
- def _get_group(self, group_or_name, autocreate=False):
- """Looks up a OptGroup object.
-
- Helper function to return an OptGroup given a parameter which can
- either be the group's name or an OptGroup object.
-
- The OptGroup object returned is from the internal dict of OptGroup
- objects, which will be a copy of any OptGroup object that users of
- the API have access to.
-
- :param group_or_name: the group's name or the OptGroup object itself
- :param autocreate: whether to auto-create the group if it's not found
- :raises: NoSuchGroupError
- """
- group = group_or_name if isinstance(group_or_name, OptGroup) else None
- group_name = group.name if group else group_or_name
-
- if group_name not in self._groups:
- if group is not None or not autocreate:
- raise NoSuchGroupError(group_name)
-
- self.register_group(OptGroup(name=group_name))
-
- return self._groups[group_name]
-
- def _get_opt_info(self, opt_name, group=None):
- """Return the (opt, override, default) dict for an opt.
-
- :param opt_name: an opt name/dest
- :param group: an optional group name or OptGroup object
- :raises: NoSuchOptError, NoSuchGroupError
- """
- if group is None:
- opts = self._opts
- else:
- group = self._get_group(group)
- opts = group._opts
-
- if opt_name not in opts:
- raise NoSuchOptError(opt_name, group)
-
- return opts[opt_name]
-
- def _parse_config_files(self):
- """Parse the config files from --config-file and --config-dir.
-
- :raises: ConfigFilesNotFoundError, ConfigFileParseError
- """
- config_files = list(self.config_file)
-
- if self.config_dir:
- config_dir_glob = os.path.join(self.config_dir, '*.conf')
- config_files += sorted(glob.glob(config_dir_glob))
-
- config_files = [_fixpath(p) for p in config_files]
-
- self._cparser = MultiConfigParser()
-
- try:
- read_ok = self._cparser.read(config_files)
- except iniparser.ParseError as pe:
- raise ConfigFileParseError(pe.filename, str(pe))
-
- if read_ok != config_files:
- not_read_ok = filter(lambda f: f not in read_ok, config_files)
- raise ConfigFilesNotFoundError(not_read_ok)
-
- def _check_required_opts(self):
- """Check that all opts marked as required have values specified.
-
- :raises: RequiredOptError
- """
- for info, group in self._all_opt_infos():
- opt = info['opt']
-
- if opt.required:
- if 'default' in info or 'override' in info:
- continue
-
- if self._get(opt.dest, group) is None:
- raise RequiredOptError(opt.name, group)
-
- def _parse_cli_opts(self, args):
- """Parse command line options.
-
- Initializes the command line option parser and parses the supplied
- command line arguments.
-
- :param args: the command line arguments
- :returns: a dict of parsed option values
- :raises: SystemExit, DuplicateOptError
-
- """
- self._args = args
-
- for opt, group in sorted(self._all_cli_opts()):
- opt._add_to_cli(self._oparser, group)
-
- return vars(self._oparser.parse_args(args))
-
- class GroupAttr(collections.Mapping):
-
- """
- A helper class representing the option values of a group as a mapping
- and attributes.
- """
-
- def __init__(self, conf, group):
- """Construct a GroupAttr object.
-
- :param conf: a ConfigOpts object
- :param group: an OptGroup object
- """
- self._conf = conf
- self._group = group
-
- def __getattr__(self, name):
- """Look up an option value and perform template substitution."""
- return self._conf._get(name, self._group)
-
- def __getitem__(self, key):
- """Look up an option value and perform string substitution."""
- return self.__getattr__(key)
-
- def __contains__(self, key):
- """Return True if key is the name of a registered opt or group."""
- return key in self._group._opts
-
- def __iter__(self):
- """Iterate over all registered opt and group names."""
- for key in self._group._opts.keys():
- yield key
-
- def __len__(self):
- """Return the number of options and option groups."""
- return len(self._group._opts)
-
- class SubCommandAttr(object):
-
- """
- A helper class representing the name and arguments of an argparse
- sub-parser.
- """
-
- def __init__(self, conf, group, dest):
- """Construct a SubCommandAttr object.
-
- :param conf: a ConfigOpts object
- :param group: an OptGroup object
- :param dest: the name of the sub-parser
- """
- self._conf = conf
- self._group = group
- self._dest = dest
-
- def __getattr__(self, name):
- """Look up a sub-parser name or argument value."""
- if name == 'name':
- name = self._dest
- if self._group is not None:
- name = self._group.name + '_' + name
- return self._conf._cli_values[name]
-
- if name in self._conf:
- raise DuplicateOptError(name)
-
- try:
- return self._conf._cli_values[name]
- except KeyError:
- raise NoSuchOptError(name)
-
- class StrSubWrapper(object):
-
- """
- A helper class exposing opt values as a dict for string substitution.
- """
-
- def __init__(self, conf):
- """Construct a StrSubWrapper object.
-
- :param conf: a ConfigOpts object
- """
- self.conf = conf
-
- def __getitem__(self, key):
- """Look up an opt value from the ConfigOpts object.
-
- :param key: an opt name
- :returns: an opt value
- :raises: TemplateSubstitutionError if attribute is a group
- """
- value = getattr(self.conf, key)
- if isinstance(value, self.conf.GroupAttr):
- raise TemplateSubstitutionError(
- 'substituting group %s not supported' % key)
- return value
-
-
-CONF = ConfigOpts()
diff --git a/openstack/common/db/sqlalchemy/session.py b/openstack/common/db/sqlalchemy/session.py
index c6aeae6..1e9e123 100644
--- a/openstack/common/db/sqlalchemy/session.py
+++ b/openstack/common/db/sqlalchemy/session.py
@@ -246,13 +246,13 @@ import time
from eventlet import db_pool
from eventlet import greenthread
+from oslo.config import cfg
from sqlalchemy.exc import DisconnectionError, OperationalError, IntegrityError
import sqlalchemy.interfaces
import sqlalchemy.orm
from sqlalchemy.pool import NullPool, StaticPool
from sqlalchemy.sql.expression import literal_column
-from openstack.common import cfg
from openstack.common import importutils
from openstack.common import log as logging
from openstack.common.gettextutils import _
diff --git a/openstack/common/eventlet_backdoor.py b/openstack/common/eventlet_backdoor.py
index 035d282..61ceded 100644
--- a/openstack/common/eventlet_backdoor.py
+++ b/openstack/common/eventlet_backdoor.py
@@ -24,8 +24,7 @@ import traceback
import eventlet
import eventlet.backdoor
import greenlet
-
-from openstack.common import cfg
+from oslo.config import cfg
eventlet_backdoor_opts = [
cfg.IntOpt('backdoor_port',
diff --git a/openstack/common/iniparser.py b/openstack/common/iniparser.py
deleted file mode 100644
index 9bf399f..0000000
--- a/openstack/common/iniparser.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-class ParseError(Exception):
- def __init__(self, message, lineno, line):
- self.msg = message
- self.line = line
- self.lineno = lineno
-
- def __str__(self):
- return 'at line %d, %s: %r' % (self.lineno, self.msg, self.line)
-
-
-class BaseParser(object):
- lineno = 0
- parse_exc = ParseError
-
- def _assignment(self, key, value):
- self.assignment(key, value)
- return None, []
-
- def _get_section(self, line):
- if line[-1] != ']':
- return self.error_no_section_end_bracket(line)
- if len(line) <= 2:
- return self.error_no_section_name(line)
-
- return line[1:-1]
-
- def _split_key_value(self, line):
- colon = line.find(':')
- equal = line.find('=')
- if colon < 0 and equal < 0:
- return self.error_invalid_assignment(line)
-
- if colon < 0 or (equal >= 0 and equal < colon):
- key, value = line[:equal], line[equal + 1:]
- else:
- key, value = line[:colon], line[colon + 1:]
-
- value = value.strip()
- if ((value and value[0] == value[-1]) and
- (value[0] == "\"" or value[0] == "'")):
- value = value[1:-1]
- return key.strip(), [value]
-
- def parse(self, lineiter):
- key = None
- value = []
-
- for line in lineiter:
- self.lineno += 1
-
- line = line.rstrip()
- if not line:
- # Blank line, ends multi-line values
- if key:
- key, value = self._assignment(key, value)
- continue
- elif line[0] in (' ', '\t'):
- # Continuation of previous assignment
- if key is None:
- self.error_unexpected_continuation(line)
- else:
- value.append(line.lstrip())
- continue
-
- if key:
- # Flush previous assignment, if any
- key, value = self._assignment(key, value)
-
- if line[0] == '[':
- # Section start
- section = self._get_section(line)
- if section:
- self.new_section(section)
- elif line[0] in '#;':
- self.comment(line[1:].lstrip())
- else:
- key, value = self._split_key_value(line)
- if not key:
- return self.error_empty_key(line)
-
- if key:
- # Flush previous assignment, if any
- self._assignment(key, value)
-
- def assignment(self, key, value):
- """Called when a full assignment is parsed"""
- raise NotImplementedError()
-
- def new_section(self, section):
- """Called when a new section is started"""
- raise NotImplementedError()
-
- def comment(self, comment):
- """Called when a comment is parsed"""
- pass
-
- def error_invalid_assignment(self, line):
- raise self.parse_exc("No ':' or '=' found in assignment",
- self.lineno, line)
-
- def error_empty_key(self, line):
- raise self.parse_exc('Key cannot be empty', self.lineno, line)
-
- def error_unexpected_continuation(self, line):
- raise self.parse_exc('Unexpected continuation line',
- self.lineno, line)
-
- def error_no_section_end_bracket(self, line):
- raise self.parse_exc('Invalid section (must end with ])',
- self.lineno, line)
-
- def error_no_section_name(self, line):
- raise self.parse_exc('Empty section name', self.lineno, line)
diff --git a/openstack/common/lockutils.py b/openstack/common/lockutils.py
index 6513fd8..0c60ed7 100644
--- a/openstack/common/lockutils.py
+++ b/openstack/common/lockutils.py
@@ -25,8 +25,8 @@ import time
import weakref
from eventlet import semaphore
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import fileutils
from openstack.common.gettextutils import _
from openstack.common import local
diff --git a/openstack/common/log.py b/openstack/common/log.py
index fad5731..7d90975 100644
--- a/openstack/common/log.py
+++ b/openstack/common/log.py
@@ -40,7 +40,8 @@ import stat
import sys
import traceback
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
from openstack.common import jsonutils
from openstack.common import local
diff --git a/openstack/common/notifier/api.py b/openstack/common/notifier/api.py
index 5714306..1ca1054 100644
--- a/openstack/common/notifier/api.py
+++ b/openstack/common/notifier/api.py
@@ -15,7 +15,8 @@
import uuid
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import context
from openstack.common.gettextutils import _
from openstack.common import importutils
diff --git a/openstack/common/notifier/log_notifier.py b/openstack/common/notifier/log_notifier.py
index b333d7a..e947fa2 100644
--- a/openstack/common/notifier/log_notifier.py
+++ b/openstack/common/notifier/log_notifier.py
@@ -13,8 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import jsonutils
from openstack.common import log as logging
diff --git a/openstack/common/notifier/rpc_notifier.py b/openstack/common/notifier/rpc_notifier.py
index 7e25f47..a87a560 100644
--- a/openstack/common/notifier/rpc_notifier.py
+++ b/openstack/common/notifier/rpc_notifier.py
@@ -13,8 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import context as req_context
from openstack.common.gettextutils import _
from openstack.common import log as logging
diff --git a/openstack/common/notifier/rpc_notifier2.py b/openstack/common/notifier/rpc_notifier2.py
index b7696fd..f454723 100644
--- a/openstack/common/notifier/rpc_notifier2.py
+++ b/openstack/common/notifier/rpc_notifier2.py
@@ -15,7 +15,8 @@
'''messaging based notification driver, with message envelopes'''
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import context as req_context
from openstack.common.gettextutils import _
from openstack.common import log as logging
diff --git a/openstack/common/plugin/pluginmanager.py b/openstack/common/plugin/pluginmanager.py
index f7891cd..d3c62e6 100644
--- a/openstack/common/plugin/pluginmanager.py
+++ b/openstack/common/plugin/pluginmanager.py
@@ -15,7 +15,8 @@
import pkg_resources
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
from openstack.common import log as logging
from openstack.common.notifier import api as notifier_api
diff --git a/openstack/common/rpc/__init__.py b/openstack/common/rpc/__init__.py
index a786ae0..b429a83 100644
--- a/openstack/common/rpc/__init__.py
+++ b/openstack/common/rpc/__init__.py
@@ -28,7 +28,8 @@ For some wrappers that add message versioning to rpc, see:
import inspect
import logging
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
from openstack.common import importutils
from openstack.common import local
diff --git a/openstack/common/rpc/common.py b/openstack/common/rpc/common.py
index 55dad2d..6c52bd8 100644
--- a/openstack/common/rpc/common.py
+++ b/openstack/common/rpc/common.py
@@ -21,7 +21,8 @@ import copy
import sys
import traceback
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
from openstack.common import importutils
from openstack.common import jsonutils
diff --git a/openstack/common/rpc/impl_kombu.py b/openstack/common/rpc/impl_kombu.py
index 3094678..3f0fa1f 100644
--- a/openstack/common/rpc/impl_kombu.py
+++ b/openstack/common/rpc/impl_kombu.py
@@ -28,8 +28,8 @@ import kombu
import kombu.connection
import kombu.entity
import kombu.messaging
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common.gettextutils import _
from openstack.common import network_utils
from openstack.common.rpc import amqp as rpc_amqp
diff --git a/openstack/common/rpc/impl_qpid.py b/openstack/common/rpc/impl_qpid.py
index b3c78bb..6c5cf9b 100644
--- a/openstack/common/rpc/impl_qpid.py
+++ b/openstack/common/rpc/impl_qpid.py
@@ -22,8 +22,8 @@ import uuid
import eventlet
import greenlet
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common.gettextutils import _
from openstack.common import importutils
from openstack.common import jsonutils
diff --git a/openstack/common/rpc/impl_zmq.py b/openstack/common/rpc/impl_zmq.py
index 01114bc..822b1b5 100644
--- a/openstack/common/rpc/impl_zmq.py
+++ b/openstack/common/rpc/impl_zmq.py
@@ -23,8 +23,8 @@ import uuid
import eventlet
import greenlet
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common.gettextutils import _
from openstack.common import importutils
from openstack.common import jsonutils
diff --git a/openstack/common/rpc/matchmaker.py b/openstack/common/rpc/matchmaker.py
index 07190f0..b7e8f3b 100644
--- a/openstack/common/rpc/matchmaker.py
+++ b/openstack/common/rpc/matchmaker.py
@@ -22,7 +22,8 @@ import contextlib
import itertools
import json
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
from openstack.common import log as logging
diff --git a/openstack/common/service.py b/openstack/common/service.py
index 48aeb9d..6ebeefd 100644
--- a/openstack/common/service.py
+++ b/openstack/common/service.py
@@ -28,8 +28,8 @@ import time
import eventlet
import logging as std_logging
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import eventlet_backdoor
from openstack.common.gettextutils import _
from openstack.common import importutils
diff --git a/openstack/common/sslutils.py b/openstack/common/sslutils.py
index d813e7a..73fd641 100644
--- a/openstack/common/sslutils.py
+++ b/openstack/common/sslutils.py
@@ -17,7 +17,8 @@
import os
import ssl
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.gettextutils import _
diff --git a/openstack/common/wsgi.py b/openstack/common/wsgi.py
index f97d24e..6ffbce1 100644
--- a/openstack/common/wsgi.py
+++ b/openstack/common/wsgi.py
@@ -17,24 +17,24 @@
"""Utility methods for working with WSGI servers."""
-import datetime
-import errno
import eventlet
-import eventlet.wsgi
-
eventlet.patcher.monkey_patch(all=False, socket=True)
-import routes
-import routes.middleware
+import datetime
+import errno
import socket
import sys
import time
+
+import eventlet.wsgi
+from oslo.config import cfg
+import routes
+import routes.middleware
import webob.dec
import webob.exc
from xml.dom import minidom
from xml.parsers import expat
-from openstack.common import cfg
from openstack.common import exception
from openstack.common.gettextutils import _
from openstack.common import jsonutils
diff --git a/tests/testmods/bar_foo_opt.py b/tests/testmods/bar_foo_opt.py
index 88d0bbf..0057f11 100644
--- a/tests/testmods/bar_foo_opt.py
+++ b/tests/testmods/bar_foo_opt.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import cfg
+from oslo.config import cfg
CONF = cfg.CONF
diff --git a/tests/testmods/baz_qux_opt.py b/tests/testmods/baz_qux_opt.py
index b2c7ecb..c9814ea 100644
--- a/tests/testmods/baz_qux_opt.py
+++ b/tests/testmods/baz_qux_opt.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import cfg
+from oslo.config import cfg
CONF = cfg.CONF
diff --git a/tests/testmods/blaa_opt.py b/tests/testmods/blaa_opt.py
index b320a72..a7b06b2 100644
--- a/tests/testmods/blaa_opt.py
+++ b/tests/testmods/blaa_opt.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import cfg
+from oslo.config import cfg
CONF = cfg.CONF
diff --git a/tests/unit/rpc/common.py b/tests/unit/rpc/common.py
index 2d1e2b6..5a655c6 100644
--- a/tests/unit/rpc/common.py
+++ b/tests/unit/rpc/common.py
@@ -24,8 +24,8 @@ import time
import eventlet
from eventlet import greenthread
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import exception
from openstack.common.gettextutils import _
from openstack.common import jsonutils
diff --git a/tests/unit/rpc/test_common.py b/tests/unit/rpc/test_common.py
index fd59929..976da84 100644
--- a/tests/unit/rpc/test_common.py
+++ b/tests/unit/rpc/test_common.py
@@ -20,7 +20,8 @@ Unit Tests for 'common' functons used through rpc code.
import logging
import sys
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import exception
from openstack.common import importutils
from openstack.common import jsonutils
diff --git a/tests/unit/rpc/test_fake.py b/tests/unit/rpc/test_fake.py
index 17e4a68..a38250b 100644
--- a/tests/unit/rpc/test_fake.py
+++ b/tests/unit/rpc/test_fake.py
@@ -22,7 +22,8 @@ Unit Tests for remote procedure calls using fake_impl
import eventlet
eventlet.monkey_patch()
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import rpc
from openstack.common.rpc import impl_fake
from tests.unit.rpc import common
diff --git a/tests/unit/rpc/test_kombu.py b/tests/unit/rpc/test_kombu.py
index 1bd23d5..cadb630 100644
--- a/tests/unit/rpc/test_kombu.py
+++ b/tests/unit/rpc/test_kombu.py
@@ -27,8 +27,8 @@ import logging
import time
import mock
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import exception
from openstack.common.rpc import amqp as rpc_amqp
from openstack.common.rpc import common as rpc_common
diff --git a/tests/unit/rpc/test_kombu_ssl.py b/tests/unit/rpc/test_kombu_ssl.py
index 5507f91..688c992 100644
--- a/tests/unit/rpc/test_kombu_ssl.py
+++ b/tests/unit/rpc/test_kombu_ssl.py
@@ -22,7 +22,8 @@ Unit Tests for remote procedure calls using kombu + ssl
import eventlet
eventlet.monkey_patch()
-from openstack.common import cfg
+from oslo.config import cfg
+
from tests import utils as test_utils
diff --git a/tests/unit/rpc/test_qpid.py b/tests/unit/rpc/test_qpid.py
index 016c5b9..ea68b47 100644
--- a/tests/unit/rpc/test_qpid.py
+++ b/tests/unit/rpc/test_qpid.py
@@ -29,8 +29,8 @@ import fixtures
import time
import testtools
import mox
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import context
from openstack.common.rpc import amqp as rpc_amqp
from tests import utils
diff --git a/tests/unit/rpc/test_zmq.py b/tests/unit/rpc/test_zmq.py
index 1de78e7..8c9a966 100644
--- a/tests/unit/rpc/test_zmq.py
+++ b/tests/unit/rpc/test_zmq.py
@@ -26,8 +26,8 @@ import os
import socket
import fixtures
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common import exception
from openstack.common.gettextutils import _
from openstack.common import processutils
diff --git a/tests/unit/test_cfg.py b/tests/unit/test_cfg.py
deleted file mode 100644
index 7b6123c..0000000
--- a/tests/unit/test_cfg.py
+++ /dev/null
@@ -1,1785 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 Red Hat, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import os
-import shutil
-import StringIO
-import sys
-import tempfile
-
-import fixtures
-
-from openstack.common.cfg import *
-from tests import utils
-
-
-class ExceptionsTestCase(utils.BaseTestCase):
-
- def test_error(self):
- msg = str(Error('foobar'))
- self.assertEquals(msg, 'foobar')
-
- def test_args_already_parsed_error(self):
- msg = str(ArgsAlreadyParsedError('foobar'))
- self.assertEquals(msg, 'arguments already parsed: foobar')
-
- def test_no_such_opt_error(self):
- msg = str(NoSuchOptError('foo'))
- self.assertEquals(msg, 'no such option: foo')
-
- def test_no_such_opt_error_with_group(self):
- msg = str(NoSuchOptError('foo', OptGroup('bar')))
- self.assertEquals(msg, 'no such option in group bar: foo')
-
- def test_no_such_group_error(self):
- msg = str(NoSuchGroupError('bar'))
- self.assertEquals(msg, 'no such group: bar')
-
- def test_duplicate_opt_error(self):
- msg = str(DuplicateOptError('foo'))
- self.assertEquals(msg, 'duplicate option: foo')
-
- def test_required_opt_error(self):
- msg = str(RequiredOptError('foo'))
- self.assertEquals(msg, 'value required for option: foo')
-
- def test_required_opt_error_with_group(self):
- msg = str(RequiredOptError('foo', OptGroup('bar')))
- self.assertEquals(msg, 'value required for option: bar.foo')
-
- def test_template_substitution_error(self):
- msg = str(TemplateSubstitutionError('foobar'))
- self.assertEquals(msg, 'template substitution error: foobar')
-
- def test_config_files_not_found_error(self):
- msg = str(ConfigFilesNotFoundError(['foo', 'bar']))
- self.assertEquals(msg, 'Failed to read some config files: foo,bar')
-
- def test_config_file_parse_error(self):
- msg = str(ConfigFileParseError('foo', 'foobar'))
- self.assertEquals(msg, 'Failed to parse foo: foobar')
-
-
-class BaseTestCase(utils.BaseTestCase):
-
- class TestConfigOpts(ConfigOpts):
- def __call__(self, args=None):
- return ConfigOpts.__call__(self,
- args=args,
- prog='test',
- version='1.0',
- usage='%(prog)s FOO BAR',
- default_config_files=[])
-
- def setUp(self):
- super(BaseTestCase, self).setUp()
- self.useFixture(fixtures.NestedTempfile())
- self.conf = self.TestConfigOpts()
-
- self.tempdirs = []
-
- def create_tempfiles(self, files, ext='.conf'):
- tempfiles = []
- for (basename, contents) in files:
- if not os.path.isabs(basename):
- (fd, path) = tempfile.mkstemp(prefix=basename, suffix=ext)
- else:
- path = basename + ext
- fd = os.open(path, os.O_CREAT | os.O_WRONLY)
- tempfiles.append(path)
- try:
- os.write(fd, contents)
- finally:
- os.close(fd)
- return tempfiles
-
-
-class UsageTestCase(BaseTestCase):
-
- def test_print_usage(self):
- f = StringIO.StringIO()
- self.conf([])
- self.conf.print_usage(file=f)
- self.assertTrue('usage: test FOO BAR' in f.getvalue())
- self.assertTrue('optional:' not in f.getvalue())
-
-
-class HelpTestCase(BaseTestCase):
-
- def test_print_help(self):
- f = StringIO.StringIO()
- self.conf([])
- self.conf.print_help(file=f)
- self.assertTrue('usage: test FOO BAR' in f.getvalue())
- self.assertTrue('optional' in f.getvalue())
- self.assertTrue('-h, --help' in f.getvalue())
-
-
-class FindConfigFilesTestCase(BaseTestCase):
-
- def test_find_config_files(self):
- config_files = [os.path.expanduser('~/.blaa/blaa.conf'),
- '/etc/foo.conf']
-
- self.stubs.Set(sys, 'argv', ['foo'])
- self.stubs.Set(os.path, 'exists', lambda p: p in config_files)
-
- self.assertEquals(find_config_files(project='blaa'), config_files)
-
- def test_find_config_files_with_extension(self):
- config_files = ['/etc/foo.json']
-
- self.stubs.Set(sys, 'argv', ['foo'])
- self.stubs.Set(os.path, 'exists', lambda p: p in config_files)
-
- self.assertEquals(find_config_files(project='blaa'), [])
- self.assertEquals(find_config_files(project='blaa', extension='.json'),
- config_files)
-
-
-class CliOptsTestCase(BaseTestCase):
-
- def _do_cli_test(self, opt_class, default, cli_args, value):
- self.conf.register_cli_opt(opt_class('foo', default=default,
- deprecated_name='oldfoo'))
-
- self.conf(cli_args)
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, value)
-
- def test_str_default(self):
- self._do_cli_test(StrOpt, None, [], None)
-
- def test_str_arg(self):
- self._do_cli_test(StrOpt, None, ['--foo', 'bar'], 'bar')
-
- def test_str_arg_deprecated(self):
- self._do_cli_test(StrOpt, None, ['--oldfoo', 'bar'], 'bar')
-
- def test_bool_default(self):
- self._do_cli_test(BoolOpt, False, [], False)
-
- def test_bool_arg(self):
- self._do_cli_test(BoolOpt, None, ['--foo'], True)
-
- def test_bool_arg_deprecated(self):
- self._do_cli_test(BoolOpt, None, ['--oldfoo'], True)
-
- def test_bool_arg_inverse(self):
- self._do_cli_test(BoolOpt, None, ['--foo', '--nofoo'], False)
-
- def test_bool_arg_inverse_deprecated(self):
- self._do_cli_test(BoolOpt, None, ['--oldfoo', '--nooldfoo'], False)
-
- def test_int_default(self):
- self._do_cli_test(IntOpt, 10, [], 10)
-
- def test_int_arg(self):
- self._do_cli_test(IntOpt, None, ['--foo=20'], 20)
-
- def test_int_arg_deprecated(self):
- self._do_cli_test(IntOpt, None, ['--oldfoo=20'], 20)
-
- def test_float_default(self):
- self._do_cli_test(FloatOpt, 1.0, [], 1.0)
-
- def test_float_arg(self):
- self._do_cli_test(FloatOpt, None, ['--foo', '2.0'], 2.0)
-
- def test_float_arg_deprecated(self):
- self._do_cli_test(FloatOpt, None, ['--oldfoo', '2.0'], 2.0)
-
- def test_list_default(self):
- self._do_cli_test(ListOpt, ['bar'], [], ['bar'])
-
- def test_list_arg(self):
- self._do_cli_test(ListOpt, None,
- ['--foo', 'blaa,bar'], ['blaa', 'bar'])
-
- def test_list_arg_with_spaces(self):
- self._do_cli_test(ListOpt, None,
- ['--foo', 'blaa ,bar'], ['blaa', 'bar'])
-
- def test_list_arg_deprecated(self):
- self._do_cli_test(ListOpt, None,
- ['--oldfoo', 'blaa,bar'], ['blaa', 'bar'])
-
- def test_multistr_default(self):
- self._do_cli_test(MultiStrOpt, ['bar'], [], ['bar'])
-
- def test_multistr_arg(self):
- self._do_cli_test(MultiStrOpt, None,
- ['--foo', 'blaa', '--foo', 'bar'], ['blaa', 'bar'])
-
- def test_multistr_arg_deprecated(self):
- self._do_cli_test(MultiStrOpt, None,
- ['--oldfoo', 'blaa', '--oldfoo', 'bar'],
- ['blaa', 'bar'])
-
- def test_help(self):
- self.stubs.Set(sys, 'stdout', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, ['--help'])
- self.assertTrue('FOO BAR' in sys.stdout.getvalue())
- self.assertTrue('--version' in sys.stdout.getvalue())
- self.assertTrue('--help' in sys.stdout.getvalue())
- self.assertTrue('--config-file' in sys.stdout.getvalue())
-
- def test_version(self):
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, ['--version'])
- self.assertTrue('1.0' in sys.stderr.getvalue())
-
- def test_config_file(self):
- paths = self.create_tempfiles([('1', '[DEFAULT]'),
- ('2', '[DEFAULT]')])
-
- self.conf(['--config-file', paths[0], '--config-file', paths[1]])
-
- self.assertEquals(self.conf.config_file, paths)
-
-
-class PositionalTestCase(BaseTestCase):
-
- def _do_pos_test(self, opt_class, default, cli_args, value):
- self.conf.register_cli_opt(opt_class('foo',
- default=default,
- positional=True))
-
- self.conf(cli_args)
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, value)
-
- def test_positional_str_default(self):
- self._do_pos_test(StrOpt, None, [], None)
-
- def test_positional_str_arg(self):
- self._do_pos_test(StrOpt, None, ['bar'], 'bar')
-
- def test_positional_int_default(self):
- self._do_pos_test(IntOpt, 10, [], 10)
-
- def test_positional_int_arg(self):
- self._do_pos_test(IntOpt, None, ['20'], 20)
-
- def test_positional_float_default(self):
- self._do_pos_test(FloatOpt, 1.0, [], 1.0)
-
- def test_positional_float_arg(self):
- self._do_pos_test(FloatOpt, None, ['2.0'], 2.0)
-
- def test_positional_list_default(self):
- self._do_pos_test(ListOpt, ['bar'], [], ['bar'])
-
- def test_positional_list_arg(self):
- self._do_pos_test(ListOpt, None,
- ['blaa,bar'], ['blaa', 'bar'])
-
- def test_positional_multistr_default(self):
- self._do_pos_test(MultiStrOpt, ['bar'], [], ['bar'])
-
- def test_positional_multistr_arg(self):
- self._do_pos_test(MultiStrOpt, None,
- ['blaa', 'bar'], ['blaa', 'bar'])
-
- def test_positional_bool(self):
- self.assertRaises(ValueError, BoolOpt, 'foo', positional=True)
-
- def test_required_positional_opt(self):
- self.conf.register_cli_opt(StrOpt('foo',
- required=True,
- positional=True))
-
- self.conf(['bar'])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_missing_required_cli_opt(self):
- self.conf.register_cli_opt(StrOpt('foo',
- required=True,
- positional=True))
- self.assertRaises(RequiredOptError, self.conf, [])
-
-
-class ConfigFileOptsTestCase(BaseTestCase):
-
- def _do_deprecated_test_use(self, opt_class, value, result):
- self.conf.register_opt(opt_class('newfoo', deprecated_name='oldfoo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'oldfoo = %s\n' % value)])
-
- self.conf(['--config-file', paths[0]])
- self.assertTrue(hasattr(self.conf, 'newfoo'))
- self.assertEquals(self.conf.newfoo, result)
-
- def _do_deprecated_test_ignore(self, opt_class, value, result):
- self.conf.register_opt(opt_class('newfoo', deprecated_name='oldfoo'))
-
- paths2 = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'newfoo = %s\n' % value)])
-
- self.conf(['--config-file', paths2[0]])
- self.assertTrue(hasattr(self.conf, 'newfoo'))
- self.assertEquals(self.conf.newfoo, result)
-
- def test_conf_file_str_default(self):
- self.conf.register_opt(StrOpt('foo', default='bar'))
-
- paths = self.create_tempfiles([('test', '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_conf_file_str_value(self):
- self.conf.register_opt(StrOpt('foo'))
-
- paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_conf_file_str_value_override(self):
- self.conf.register_cli_opt(StrOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = baar\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = baaar\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'baaar')
-
- def test_conf_file_str_value_override_use_deprecated(self):
- """last option should always win, even if last uses deprecated"""
- self.conf.register_cli_opt(StrOpt('newfoo', deprecated_name='oldfoo'))
-
- paths = self.create_tempfiles([('0',
- '[DEFAULT]\n'
- 'newfoo = middle\n'),
- ('1',
- '[DEFAULT]\n'
- 'oldfoo = last\n')])
-
- self.conf(['--newfoo', 'first',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'newfoo'))
- self.assertFalse(hasattr(self.conf, 'oldfoo'))
- self.assertEquals(self.conf.newfoo, 'last')
-
- def test_conf_file_str_use_deprecated(self):
- self._do_deprecated_test_use(StrOpt, 'value1', 'value1')
-
- def test_conf_file_str_ignore_deprecated(self):
- self._do_deprecated_test_ignore(StrOpt, 'value2', 'value2')
-
- def test_conf_file_bool_default(self):
- self.conf.register_opt(BoolOpt('foo', default=False))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, False)
-
- def test_conf_file_bool_value(self):
- self.conf.register_opt(BoolOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = true\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, True)
-
- def test_conf_file_bool_value_override(self):
- self.conf.register_cli_opt(BoolOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = 0\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = yes\n')])
-
- self.conf(['--foo',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, True)
-
- def test_conf_file_bool_use_deprecated(self):
- self._do_deprecated_test_use(BoolOpt, 'yes', True)
-
- def test_conf_file_bool_ignore_deprecated(self):
- self._do_deprecated_test_ignore(BoolOpt, 'no', False)
-
- def test_conf_file_int_default(self):
- self.conf.register_opt(IntOpt('foo', default=666))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_int_value(self):
- self.conf.register_opt(IntOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = 666\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_int_value_override(self):
- self.conf.register_cli_opt(IntOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = 66\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = 666\n')])
-
- self.conf(['--foo', '6',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 666)
-
- def test_conf_file_int_use_deprecated(self):
- self._do_deprecated_test_use(IntOpt, '66', 66)
-
- def test_conf_file_int_ignore_deprecated(self):
- self._do_deprecated_test_ignore(IntOpt, '64', 64)
-
- def test_conf_file_float_default(self):
- self.conf.register_opt(FloatOpt('foo', default=6.66))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_float_value(self):
- self.conf.register_opt(FloatOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = 6.66\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_float_value_override(self):
- self.conf.register_cli_opt(FloatOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = 6.6\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = 6.66\n')])
-
- self.conf(['--foo', '6',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 6.66)
-
- def test_conf_file_float_use_deprecated(self):
- self._do_deprecated_test_use(FloatOpt, '66.54', 66.54)
-
- def test_conf_file_float_ignore_deprecated(self):
- self._do_deprecated_test_ignore(FloatOpt, '64.54', 64.54)
-
- def test_conf_file_list_default(self):
- self.conf.register_opt(ListOpt('foo', default=['bar']))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_list_value(self):
- self.conf.register_opt(ListOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_list_value_override(self):
- self.conf.register_cli_opt(ListOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = bar,bar\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = b,a,r\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['b', 'a', 'r'])
-
- def test_conf_file_list_use_deprecated(self):
- self._do_deprecated_test_use(ListOpt, 'a,b,c', ['a', 'b', 'c'])
-
- def test_conf_file_list_ignore_deprecated(self):
- self._do_deprecated_test_ignore(ListOpt, 'd,e,f', ['d', 'e', 'f'])
-
- def test_conf_file_list_spaces_use_deprecated(self):
- self._do_deprecated_test_use(ListOpt, 'a, b, c', ['a', 'b', 'c'])
-
- def test_conf_file_list_spaces_ignore_deprecated(self):
- self._do_deprecated_test_ignore(ListOpt, 'd, e, f', ['d', 'e', 'f'])
-
- def test_conf_file_multistr_default(self):
- self.conf.register_opt(MultiStrOpt('foo', default=['bar']))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_multistr_value(self):
- self.conf.register_opt(MultiStrOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, ['bar'])
-
- def test_conf_file_multistr_values_append_deprecated(self):
- self.conf.register_cli_opt(MultiStrOpt('foo',
- deprecated_name='oldfoo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = bar1\n'),
- ('2',
- '[DEFAULT]\n'
- 'oldfoo = bar2\n'
- 'oldfoo = bar3\n')])
-
- self.conf(['--foo', 'bar0',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
-
- self.assertEquals(self.conf.foo, ['bar0', 'bar1', 'bar2', 'bar3'])
-
- def test_conf_file_multistr_values_append(self):
- self.conf.register_cli_opt(MultiStrOpt('foo'))
-
- paths = self.create_tempfiles([('1',
- '[DEFAULT]\n'
- 'foo = bar1\n'),
- ('2',
- '[DEFAULT]\n'
- 'foo = bar2\n'
- 'foo = bar3\n')])
-
- self.conf(['--foo', 'bar0',
- '--config-file', paths[0],
- '--config-file', paths[1]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
-
- self.assertEquals(self.conf.foo, ['bar0', 'bar1', 'bar2', 'bar3'])
-
- def test_conf_file_multistr_deprecated(self):
- self.conf.register_opt(MultiStrOpt('newfoo', deprecated_name='oldfoo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'oldfoo= bar1\n'
- 'oldfoo = bar2\n')])
-
- self.conf(['--config-file', paths[0]])
- self.assertTrue(hasattr(self.conf, 'newfoo'))
- self.assertEquals(self.conf.newfoo, ['bar1', 'bar2'])
-
- def test_conf_file_multiple_opts(self):
- self.conf.register_opts([StrOpt('foo'), StrOpt('bar')])
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar\n'
- 'bar = foo\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
- self.assertTrue(hasattr(self.conf, 'bar'))
- self.assertEquals(self.conf.bar, 'foo')
-
- def test_conf_file_raw_value(self):
- self.conf.register_opt(StrOpt('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar-%08x\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar-%08x')
-
-
-class OptGroupsTestCase(BaseTestCase):
-
- def test_arg_group(self):
- blaa_group = OptGroup('blaa', 'blaa options')
- self.conf.register_group(blaa_group)
- self.conf.register_cli_opt(StrOpt('foo'), group=blaa_group)
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_autocreate_group(self):
- self.conf.register_cli_opt(StrOpt('foo'), group='blaa')
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_by_name(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo'), group='blaa')
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_with_default(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', default='bar'), group='blaa')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_with_conf_and_group_opts(self):
- self.conf.register_cli_opt(StrOpt('conf'), group='blaa')
- self.conf.register_cli_opt(StrOpt('group'), group='blaa')
-
- self.conf(['--blaa-conf', 'foo', '--blaa-group', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'conf'))
- self.assertEquals(self.conf.blaa.conf, 'foo')
- self.assertTrue(hasattr(self.conf.blaa, 'group'))
- self.assertEquals(self.conf.blaa.group, 'bar')
-
- def test_arg_group_in_config_file(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
-
- paths = self.create_tempfiles([('test',
- '[blaa]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_arg_group_in_config_file_with_deprecated(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo', deprecated_name='oldfoo'),
- group='blaa')
-
- paths = self.create_tempfiles([('test',
- '[blaa]\n'
- 'oldfoo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
-
-class MappingInterfaceTestCase(BaseTestCase):
-
- def test_mapping_interface(self):
- self.conf.register_cli_opt(StrOpt('foo'))
-
- self.conf(['--foo', 'bar'])
-
- self.assertTrue('foo' in self.conf)
- self.assertTrue('config_file' in self.conf)
- self.assertEquals(len(self.conf), 3)
- self.assertEquals(self.conf['foo'], 'bar')
- self.assertEquals(self.conf.get('foo'), 'bar')
- self.assertTrue('bar' in self.conf.values())
-
- def test_mapping_interface_with_group(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo'), group='blaa')
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue('blaa' in self.conf)
- self.assertTrue('foo' in self.conf['blaa'])
- self.assertEquals(len(self.conf['blaa']), 1)
- self.assertEquals(self.conf['blaa']['foo'], 'bar')
- self.assertEquals(self.conf['blaa'].get('foo'), 'bar')
- self.assertTrue('bar' in self.conf['blaa'].values())
- self.assertEquals(self.conf.blaa, self.conf['blaa'])
-
-
-class ReRegisterOptTestCase(BaseTestCase):
-
- def test_conf_file_re_register_opt(self):
- opt = StrOpt('foo')
- self.assertTrue(self.conf.register_opt(opt))
- self.assertFalse(self.conf.register_opt(opt))
-
- def test_conf_file_re_register_opt_in_group(self):
- group = OptGroup('blaa')
- self.conf.register_group(group)
- self.conf.register_group(group) # not an error
- opt = StrOpt('foo')
- self.assertTrue(self.conf.register_opt(opt, group=group))
- self.assertFalse(self.conf.register_opt(opt, group='blaa'))
-
-
-class TemplateSubstitutionTestCase(BaseTestCase):
-
- def _prep_test_str_sub(self, foo_default=None, bar_default=None):
- self.conf.register_cli_opt(StrOpt('foo', default=foo_default))
- self.conf.register_cli_opt(StrOpt('bar', default=bar_default))
-
- def _assert_str_sub(self):
- self.assertTrue(hasattr(self.conf, 'bar'))
- self.assertEquals(self.conf.bar, 'blaa')
-
- def test_str_sub_default_from_default(self):
- self._prep_test_str_sub(foo_default='blaa', bar_default='$foo')
-
- self.conf([])
-
- self._assert_str_sub()
-
- def test_str_sub_default_from_default_recurse(self):
- self.conf.register_cli_opt(StrOpt('blaa', default='blaa'))
- self._prep_test_str_sub(foo_default='$blaa', bar_default='$foo')
-
- self.conf([])
-
- self._assert_str_sub()
-
- def test_str_sub_default_from_arg(self):
- self._prep_test_str_sub(bar_default='$foo')
-
- self.conf(['--foo', 'blaa'])
-
- self._assert_str_sub()
-
- def test_str_sub_default_from_config_file(self):
- self._prep_test_str_sub(bar_default='$foo')
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_default(self):
- self._prep_test_str_sub(foo_default='blaa')
-
- self.conf(['--bar', '$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_arg(self):
- self._prep_test_str_sub()
-
- self.conf(['--foo', 'blaa', '--bar', '$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_arg_from_config_file(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0], '--bar=$foo'])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_default(self):
- self._prep_test_str_sub(foo_default='blaa')
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'bar = $foo\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_arg(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'bar = $foo\n')])
-
- self.conf(['--config-file', paths[0], '--foo=blaa'])
-
- self._assert_str_sub()
-
- def test_str_sub_config_file_from_config_file(self):
- self._prep_test_str_sub()
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'bar = $foo\n'
- 'foo = blaa\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self._assert_str_sub()
-
- def test_str_sub_group_from_default(self):
- self.conf.register_cli_opt(StrOpt('foo', default='blaa'))
- self.conf.register_group(OptGroup('ba'))
- self.conf.register_cli_opt(StrOpt('r', default='$foo'), group='ba')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'ba'))
- self.assertTrue(hasattr(self.conf.ba, 'r'))
- self.assertEquals(self.conf.ba.r, 'blaa')
-
- def test_config_dir(self):
- snafu_group = OptGroup('snafu')
- self.conf.register_group(snafu_group)
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('bell'), group=snafu_group)
-
- dir = tempfile.mkdtemp()
- self.tempdirs.append(dir)
-
- paths = self.create_tempfiles([(os.path.join(dir, '00-test'),
- '[DEFAULT]\n'
- 'foo = bar-00\n'
- '[snafu]\n'
- 'bell = whistle-00\n'),
- (os.path.join(dir, '02-test'),
- '[snafu]\n'
- 'bell = whistle-02\n'
- '[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.assertEquals(self.conf.foo, 'bar-02')
- self.assertTrue(hasattr(self.conf, 'snafu'))
- self.assertTrue(hasattr(self.conf.snafu, 'bell'))
- self.assertEquals(self.conf.snafu.bell, 'whistle-02')
-
- def test_config_dir_file_precedence(self):
- snafu_group = OptGroup('snafu')
- self.conf.register_group(snafu_group)
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('bell'), group=snafu_group)
-
- dir = tempfile.mkdtemp()
- self.tempdirs.append(dir)
-
- paths = self.create_tempfiles([(os.path.join(dir, '00-test'),
- '[DEFAULT]\n'
- 'foo = bar-00\n'),
- ('01-test',
- '[snafu]\n'
- 'bell = whistle-01\n'
- '[DEFAULT]\n'
- 'foo = bar-01\n'),
- ('03-test',
- '[snafu]\n'
- 'bell = whistle-03\n'
- '[DEFAULT]\n'
- 'foo = bar-03\n'),
- (os.path.join(dir, '02-test'),
- '[DEFAULT]\n'
- 'foo = bar-02\n')])
-
- self.conf(['--foo', 'bar',
- '--config-file', paths[1],
- '--config-dir', os.path.dirname(paths[0]),
- '--config-file', paths[2], ])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar-02')
- self.assertTrue(hasattr(self.conf, 'snafu'))
- self.assertTrue(hasattr(self.conf.snafu, 'bell'))
- self.assertEquals(self.conf.snafu.bell, 'whistle-03')
-
-
-class ReparseTestCase(BaseTestCase):
-
- def test_reparse(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', default='r'), group='blaa')
-
- paths = self.create_tempfiles([('test',
- '[blaa]\n'
- 'foo = b\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'b')
-
- self.conf(['--blaa-foo', 'a'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'a')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'r')
-
-
-class OverridesTestCase(BaseTestCase):
-
- def test_default_none(self):
- self.conf.register_opt(StrOpt('foo', default='foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, 'foo')
- self.conf.set_default('foo', None)
- self.assertEquals(self.conf.foo, None)
- self.conf.clear_default('foo')
- self.assertEquals(self.conf.foo, 'foo')
-
- def test_override_none(self):
- self.conf.register_opt(StrOpt('foo', default='foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, 'foo')
- self.conf.set_override('foo', None)
- self.assertEquals(self.conf.foo, None)
- self.conf.clear_override('foo')
- self.assertEquals(self.conf.foo, 'foo')
-
- def test_no_default_override(self):
- self.conf.register_opt(StrOpt('foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, None)
- self.conf.set_default('foo', 'bar')
- self.assertEquals(self.conf.foo, 'bar')
- self.conf.clear_default('foo')
- self.assertEquals(self.conf.foo, None)
-
- def test_default_override(self):
- self.conf.register_opt(StrOpt('foo', default='foo'))
- self.conf([])
- self.assertEquals(self.conf.foo, 'foo')
- self.conf.set_default('foo', 'bar')
- self.assertEquals(self.conf.foo, 'bar')
- self.conf.clear_default('foo')
- self.assertEquals(self.conf.foo, 'foo')
-
- def test_override(self):
- self.conf.register_opt(StrOpt('foo'))
- self.conf.set_override('foo', 'bar')
- self.conf([])
- self.assertEquals(self.conf.foo, 'bar')
- self.conf.clear_override('foo')
- self.assertEquals(self.conf.foo, None)
-
- def test_group_no_default_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, None)
- self.conf.set_default('foo', 'bar', group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'bar')
- self.conf.clear_default('foo', group='blaa')
- self.assertEquals(self.conf.blaa.foo, None)
-
- def test_group_default_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo', default='foo'), group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'foo')
- self.conf.set_default('foo', 'bar', group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'bar')
- self.conf.clear_default('foo', group='blaa')
- self.assertEquals(self.conf.blaa.foo, 'foo')
-
- def test_group_override(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo'), group='blaa')
- self.assertEquals(self.conf.blaa.foo, None)
- self.conf.set_override('foo', 'bar', group='blaa')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'bar')
- self.conf.clear_override('foo', group='blaa')
- self.assertEquals(self.conf.blaa.foo, None)
-
- def test_cli_bool_default(self):
- self.conf.register_cli_opt(BoolOpt('foo'))
- self.conf.set_default('foo', True)
- self.assertTrue(self.conf.foo)
- self.conf([])
- self.assertTrue(self.conf.foo)
- self.conf.set_default('foo', False)
- self.assertFalse(self.conf.foo)
- self.conf.clear_default('foo')
- self.assertTrue(self.conf.foo is None)
-
- def test_cli_bool_override(self):
- self.conf.register_cli_opt(BoolOpt('foo'))
- self.conf.set_override('foo', True)
- self.assertTrue(self.conf.foo)
- self.conf([])
- self.assertTrue(self.conf.foo)
- self.conf.set_override('foo', False)
- self.assertFalse(self.conf.foo)
- self.conf.clear_override('foo')
- self.assertTrue(self.conf.foo is None)
-
-
-class ResetAndClearTestCase(BaseTestCase):
-
- def test_clear(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('bar'), group='blaa')
-
- self.assertEquals(self.conf.foo, None)
- self.assertEquals(self.conf.blaa.bar, None)
-
- self.conf(['--foo', 'foo', '--blaa-bar', 'bar'])
-
- self.assertEquals(self.conf.foo, 'foo')
- self.assertEquals(self.conf.blaa.bar, 'bar')
-
- self.conf.clear()
-
- self.assertEquals(self.conf.foo, None)
- self.assertEquals(self.conf.blaa.bar, None)
-
- def test_reset_and_clear_with_defaults_and_overrides(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('bar'), group='blaa')
-
- self.conf.set_default('foo', 'foo')
- self.conf.set_override('bar', 'bar', group='blaa')
-
- self.conf(['--foo', 'foofoo'])
-
- self.assertEquals(self.conf.foo, 'foofoo')
- self.assertEquals(self.conf.blaa.bar, 'bar')
-
- self.conf.clear()
-
- self.assertEquals(self.conf.foo, 'foo')
- self.assertEquals(self.conf.blaa.bar, 'bar')
-
- self.conf.reset()
-
- self.assertEquals(self.conf.foo, None)
- self.assertEquals(self.conf.blaa.bar, None)
-
-
-class UnregisterOptTestCase(BaseTestCase):
-
- def test_unregister_opt(self):
- opts = [StrOpt('foo'), StrOpt('bar')]
-
- self.conf.register_opts(opts)
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertTrue(hasattr(self.conf, 'bar'))
-
- self.conf.unregister_opt(opts[0])
-
- self.assertFalse(hasattr(self.conf, 'foo'))
- self.assertTrue(hasattr(self.conf, 'bar'))
-
- self.conf([])
-
- self.assertRaises(ArgsAlreadyParsedError,
- self.conf.unregister_opt, opts[1])
-
- self.conf.clear()
-
- self.assertTrue(hasattr(self.conf, 'bar'))
-
- self.conf.unregister_opts(opts)
-
- def test_unregister_opt_from_group(self):
- opt = StrOpt('foo')
-
- self.conf.register_opt(opt, group='blaa')
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
-
- self.conf.unregister_opt(opt, group='blaa')
-
- self.assertFalse(hasattr(self.conf.blaa, 'foo'))
-
-
-class ImportOptTestCase(BaseTestCase):
-
- def test_import_opt(self):
- self.assertFalse(hasattr(CONF, 'blaa'))
- CONF.import_opt('blaa', 'tests.testmods.blaa_opt')
- self.assertTrue(hasattr(CONF, 'blaa'))
-
- def test_import_opt_in_group(self):
- self.assertFalse(hasattr(CONF, 'bar'))
- CONF.import_opt('foo', 'tests.testmods.bar_foo_opt', group='bar')
- self.assertTrue(hasattr(CONF, 'bar'))
- self.assertTrue(hasattr(CONF.bar, 'foo'))
-
- def test_import_opt_import_errror(self):
- self.assertRaises(ImportError, CONF.import_opt,
- 'blaa', 'tests.testmods.blaablaa_opt')
-
- def test_import_opt_no_such_opt(self):
- self.assertRaises(NoSuchOptError, CONF.import_opt,
- 'blaablaa', 'tests.testmods.blaa_opt')
-
- def test_import_opt_no_such_group(self):
- self.assertRaises(NoSuchGroupError, CONF.import_opt,
- 'blaa', 'tests.testmods.blaa_opt', group='blaa')
-
-
-class ImportGroupTestCase(BaseTestCase):
-
- def test_import_group(self):
- self.assertFalse(hasattr(CONF, 'qux'))
- CONF.import_group('qux', 'tests.testmods.baz_qux_opt')
- self.assertTrue(hasattr(CONF, 'qux'))
- self.assertTrue(hasattr(CONF.qux, 'baz'))
-
- def test_import_group_import_error(self):
- self.assertRaises(ImportError, CONF.import_group,
- 'qux', 'tests.testmods.bazzz_quxxx_opt')
-
- def test_import_group_no_such_group(self):
- self.assertRaises(NoSuchGroupError, CONF.import_group,
- 'quxxx', 'tests.testmods.baz_qux_opt')
-
-
-class RequiredOptsTestCase(BaseTestCase):
-
- def setUp(self):
- BaseTestCase.setUp(self)
- self.conf.register_opt(StrOpt('boo', required=False))
-
- def test_required_opt(self):
- self.conf.register_opt(StrOpt('foo', required=True))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar')])
-
- self.conf(['--config-file', paths[0]])
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_required_cli_opt(self):
- self.conf.register_cli_opt(StrOpt('foo', required=True))
-
- self.conf(['--foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_required_cli_opt_with_dash(self):
- self.conf.register_cli_opt(StrOpt('foo-bar', required=True))
-
- self.conf(['--foo-bar', 'baz'])
-
- self.assertTrue(hasattr(self.conf, 'foo_bar'))
- self.assertEquals(self.conf.foo_bar, 'baz')
-
- def test_missing_required_opt(self):
- self.conf.register_opt(StrOpt('foo', required=True))
- self.assertRaises(RequiredOptError, self.conf, [])
-
- def test_missing_required_cli_opt(self):
- self.conf.register_cli_opt(StrOpt('foo', required=True))
- self.assertRaises(RequiredOptError, self.conf, [])
-
- def test_required_group_opt(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo', required=True), group='blaa')
-
- paths = self.create_tempfiles([('test',
- '[blaa]\n'
- 'foo = bar')])
-
- self.conf(['--config-file', paths[0]])
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_required_cli_group_opt(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', required=True), group='blaa')
-
- self.conf(['--blaa-foo', 'bar'])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'foo'))
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_missing_required_group_opt(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_opt(StrOpt('foo', required=True), group='blaa')
- self.assertRaises(RequiredOptError, self.conf, [])
-
- def test_missing_required_cli_group_opt(self):
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('foo', required=True), group='blaa')
- self.assertRaises(RequiredOptError, self.conf, [])
-
- def test_required_opt_with_default(self):
- self.conf.register_cli_opt(StrOpt('foo', required=True))
- self.conf.set_default('foo', 'bar')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_required_opt_with_override(self):
- self.conf.register_cli_opt(StrOpt('foo', required=True))
- self.conf.set_override('foo', 'bar')
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
-
-class SadPathTestCase(BaseTestCase):
-
- def test_unknown_attr(self):
- self.conf([])
- self.assertFalse(hasattr(self.conf, 'foo'))
- self.assertRaises(NoSuchOptError, getattr, self.conf, 'foo')
-
- def test_unknown_attr_is_attr_error(self):
- self.conf([])
- self.assertFalse(hasattr(self.conf, 'foo'))
- self.assertRaises(AttributeError, getattr, self.conf, 'foo')
-
- def test_unknown_group_attr(self):
- self.conf.register_group(OptGroup('blaa'))
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertFalse(hasattr(self.conf.blaa, 'foo'))
- self.assertRaises(NoSuchOptError, getattr, self.conf.blaa, 'foo')
-
- def test_ok_duplicate(self):
- opt = StrOpt('foo')
- self.conf.register_cli_opt(opt)
- opt2 = StrOpt('foo')
- self.conf.register_cli_opt(opt2)
-
- self.conf([])
-
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, None)
-
- def test_error_duplicate(self):
- self.conf.register_cli_opt(StrOpt('foo', help='bar'))
- self.assertRaises(DuplicateOptError,
- self.conf.register_cli_opt, StrOpt('foo'))
-
- def test_error_duplicate_with_different_dest(self):
- self.conf.register_cli_opt(StrOpt('foo', dest='f'))
- self.conf.register_cli_opt(StrOpt('foo'))
- self.assertRaises(DuplicateOptError, self.conf, [])
-
- def test_error_duplicate_short(self):
- self.conf.register_cli_opt(StrOpt('foo', short='f'))
- self.conf.register_cli_opt(StrOpt('bar', short='f'))
- self.assertRaises(DuplicateOptError, self.conf, [])
-
- def test_no_such_group(self):
- group = OptGroup('blaa')
- self.assertRaises(NoSuchGroupError, self.conf.register_cli_opt,
- StrOpt('foo'), group=group)
-
- def test_already_parsed(self):
- self.conf([])
-
- self.assertRaises(ArgsAlreadyParsedError,
- self.conf.register_cli_opt, StrOpt('foo'))
-
- def test_bad_cli_arg(self):
- self.conf.register_opt(BoolOpt('foo'))
-
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
-
- self.assertRaises(SystemExit, self.conf, ['--foo'])
-
- self.assertTrue('error' in sys.stderr.getvalue())
- self.assertTrue('--foo' in sys.stderr.getvalue())
-
- def _do_test_bad_cli_value(self, opt_class):
- self.conf.register_cli_opt(opt_class('foo'))
-
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
-
- self.assertRaises(SystemExit, self.conf, ['--foo', 'bar'])
-
- self.assertTrue('foo' in sys.stderr.getvalue())
- self.assertTrue('bar' in sys.stderr.getvalue())
-
- def test_bad_int_arg(self):
- self._do_test_bad_cli_value(IntOpt)
-
- def test_bad_float_arg(self):
- self._do_test_bad_cli_value(FloatOpt)
-
- def test_conf_file_not_found(self):
- (fd, path) = tempfile.mkstemp()
-
- os.remove(path)
-
- self.assertRaises(ConfigFilesNotFoundError,
- self.conf, ['--config-file', path])
-
- def test_conf_file_broken(self):
- paths = self.create_tempfiles([('test', 'foo')])
-
- self.assertRaises(ConfigFileParseError,
- self.conf, ['--config-file', paths[0]])
-
- def _do_test_conf_file_bad_value(self, opt_class):
- self.conf.register_opt(opt_class('foo'))
-
- paths = self.create_tempfiles([('test',
- '[DEFAULT]\n'
- 'foo = bar\n')])
-
- self.conf(['--config-file', paths[0]])
-
- self.assertRaises(ConfigFileValueError, getattr, self.conf, 'foo')
-
- def test_conf_file_bad_bool(self):
- self._do_test_conf_file_bad_value(BoolOpt)
-
- def test_conf_file_bad_int(self):
- self._do_test_conf_file_bad_value(IntOpt)
-
- def test_conf_file_bad_float(self):
- self._do_test_conf_file_bad_value(FloatOpt)
-
- def test_str_sub_from_group(self):
- self.conf.register_group(OptGroup('f'))
- self.conf.register_cli_opt(StrOpt('oo', default='blaa'), group='f')
- self.conf.register_cli_opt(StrOpt('bar', default='$f.oo'))
-
- self.conf([])
-
- self.assertFalse(hasattr(self.conf, 'bar'))
- self.assertRaises(TemplateSubstitutionError, getattr, self.conf, 'bar')
-
- def test_set_default_unknown_attr(self):
- self.conf([])
- self.assertRaises(NoSuchOptError, self.conf.set_default, 'foo', 'bar')
-
- def test_set_default_unknown_group(self):
- self.conf([])
- self.assertRaises(NoSuchGroupError,
- self.conf.set_default, 'foo', 'bar', group='blaa')
-
- def test_set_override_unknown_attr(self):
- self.conf([])
- self.assertRaises(NoSuchOptError, self.conf.set_override, 'foo', 'bar')
-
- def test_set_override_unknown_group(self):
- self.conf([])
- self.assertRaises(NoSuchGroupError,
- self.conf.set_override, 'foo', 'bar', group='blaa')
-
-
-class FindFileTestCase(BaseTestCase):
-
- def test_find_policy_file(self):
- policy_file = '/etc/policy.json'
-
- self.stubs.Set(os.path, 'exists', lambda p: p == policy_file)
-
- self.conf([])
-
- self.assertEquals(self.conf.find_file('foo.json'), None)
- self.assertEquals(self.conf.find_file('policy.json'), policy_file)
-
- def test_find_policy_file_with_config_file(self):
- dir = tempfile.mkdtemp()
- self.tempdirs.append(dir)
-
- paths = self.create_tempfiles([(os.path.join(dir, 'test.conf'),
- '[DEFAULT]'),
- (os.path.join(dir, 'policy.json'),
- '{}')],
- ext='')
-
- self.conf(['--config-file', paths[0]])
-
- self.assertEquals(self.conf.find_file('policy.json'), paths[1])
-
- def test_find_policy_file_with_config_dir(self):
- dir = tempfile.mkdtemp()
- self.tempdirs.append(dir)
-
- path = self.create_tempfiles([(os.path.join(dir, 'policy.json'),
- '{}')],
- ext='')[0]
-
- self.conf(['--config-dir', dir])
-
- self.assertEquals(self.conf.find_file('policy.json'), path)
-
-
-class OptDumpingTestCase(BaseTestCase):
-
- class FakeLogger:
-
- def __init__(self, test_case, expected_lvl):
- self.test_case = test_case
- self.expected_lvl = expected_lvl
- self.logged = []
-
- def log(self, lvl, fmt, *args):
- self.test_case.assertEquals(lvl, self.expected_lvl)
- self.logged.append(fmt % args)
-
- def test_log_opt_values(self):
- self.conf.register_cli_opt(StrOpt('foo'))
- self.conf.register_cli_opt(StrOpt('passwd', secret=True))
- self.conf.register_group(OptGroup('blaa'))
- self.conf.register_cli_opt(StrOpt('bar'), 'blaa')
- self.conf.register_cli_opt(StrOpt('key', secret=True), 'blaa')
-
- self.conf(['--foo', 'this', '--blaa-bar', 'that',
- '--blaa-key', 'admin', '--passwd', 'hush'])
-
- logger = self.FakeLogger(self, 666)
-
- self.conf.log_opt_values(logger, 666)
-
- self.assertEquals(logger.logged, [
- "*" * 80,
- "Configuration options gathered from:",
- "command line args: ['--foo', 'this', '--blaa-bar', "
- "'that', '--blaa-key', 'admin', '--passwd', 'hush']",
- "config files: []",
- "=" * 80,
- "config_dir = None",
- "config_file = []",
- "foo = this",
- "passwd = ****",
- "blaa.bar = that",
- "blaa.key = *****",
- "*" * 80,
- ])
-
-
-class ConfigParserTestCase(utils.BaseTestCase):
- def test_no_section(self):
- with tempfile.NamedTemporaryFile() as tmpfile:
- tmpfile.write('foo = bar')
- tmpfile.flush()
-
- parser = ConfigParser(tmpfile.name, {})
- self.assertRaises(ParseError, parser.parse)
-
-
-class TildeExpansionTestCase(BaseTestCase):
-
- def test_config_file_tilde(self):
- homedir = os.path.expanduser('~')
- tmpfile = tempfile.mktemp(dir=homedir, prefix='cfg-', suffix='.conf')
- tmpbase = os.path.basename(tmpfile)
-
- try:
- self.conf(['--config-file', os.path.join('~', tmpbase)])
- except ConfigFilesNotFoundError, cfnfe:
- print cfnfe
- self.assertTrue(homedir in str(cfnfe))
-
- self.stubs.Set(os.path, 'exists', lambda p: p == tmpfile)
-
- self.assertEquals(self.conf.find_file(tmpbase), tmpfile)
-
- def test_config_dir_tilde(self):
- homedir = os.path.expanduser('~')
- tmpdir = tempfile.mktemp(dir=homedir,
- prefix='cfg-',
- suffix='.d')
- tmpfile = os.path.join(tmpdir, 'foo.conf')
- tmpbase = os.path.basename(tmpfile)
-
- self.stubs.Set(glob, 'glob', lambda p: [tmpfile])
-
- try:
- print ['--config-dir', os.path.join('~', os.path.basename(tmpdir))]
- self.conf(['--config-dir',
- os.path.join('~', os.path.basename(tmpdir))])
- except ConfigFilesNotFoundError, cfnfe:
- print cfnfe
- self.assertTrue(os.path.expanduser('~') in str(cfnfe))
-
- self.stubs.Set(os.path, 'exists', lambda p: p == tmpfile)
-
- self.assertEquals(self.conf.find_file(tmpbase), tmpfile)
-
-
-class SubCommandTestCase(BaseTestCase):
-
- def test_sub_command(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
- sub.add_argument('bar', type=int)
-
- self.conf.register_cli_opt(SubCommandOpt('cmd', handler=add_parsers))
- self.assertTrue(hasattr(self.conf, 'cmd'))
- self.conf(['a', '10'])
- self.assertTrue(hasattr(self.conf.cmd, 'name'))
- self.assertTrue(hasattr(self.conf.cmd, 'bar'))
- self.assertEquals(self.conf.cmd.name, 'a')
- self.assertEquals(self.conf.cmd.bar, 10)
-
- def test_sub_command_with_dest(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
-
- self.conf.register_cli_opt(SubCommandOpt('cmd', dest='command',
- handler=add_parsers))
- self.assertTrue(hasattr(self.conf, 'command'))
- self.conf(['a'])
- self.assertEquals(self.conf.command.name, 'a')
-
- def test_sub_command_with_group(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
- sub.add_argument('--bar', choices='XYZ')
-
- self.conf.register_cli_opt(SubCommandOpt('cmd', handler=add_parsers),
- group='blaa')
- self.assertTrue(hasattr(self.conf, 'blaa'))
- self.assertTrue(hasattr(self.conf.blaa, 'cmd'))
- self.conf(['a', '--bar', 'Z'])
- self.assertTrue(hasattr(self.conf.blaa.cmd, 'name'))
- self.assertTrue(hasattr(self.conf.blaa.cmd, 'bar'))
- self.assertEquals(self.conf.blaa.cmd.name, 'a')
- self.assertEquals(self.conf.blaa.cmd.bar, 'Z')
-
- def test_sub_command_not_cli(self):
- self.conf.register_opt(SubCommandOpt('cmd'))
- self.conf([])
-
- def test_sub_command_resparse(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
-
- self.conf.register_cli_opt(SubCommandOpt('cmd',
- handler=add_parsers))
-
- foo_opt = StrOpt('foo')
- self.conf.register_cli_opt(foo_opt)
-
- self.conf(['--foo=bar', 'a'])
-
- self.assertTrue(hasattr(self.conf.cmd, 'name'))
- self.assertEquals(self.conf.cmd.name, 'a')
- self.assertTrue(hasattr(self.conf, 'foo'))
- self.assertEquals(self.conf.foo, 'bar')
-
- self.conf.clear()
- self.conf.unregister_opt(foo_opt)
- self.conf(['a'])
-
- self.assertTrue(hasattr(self.conf.cmd, 'name'))
- self.assertEquals(self.conf.cmd.name, 'a')
- self.assertFalse(hasattr(self.conf, 'foo'))
-
- def test_sub_command_no_handler(self):
- self.conf.register_cli_opt(SubCommandOpt('cmd'))
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, [])
- self.assertTrue('error' in sys.stderr.getvalue())
-
- def test_sub_command_with_help(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
-
- self.conf.register_cli_opt(SubCommandOpt('cmd',
- title='foo foo',
- description='bar bar',
- help='blaa blaa',
- handler=add_parsers))
- self.stubs.Set(sys, 'stdout', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, ['--help'])
- self.assertTrue('foo foo' in sys.stdout.getvalue())
- self.assertTrue('bar bar' in sys.stdout.getvalue())
- self.assertTrue('blaa blaa' in sys.stdout.getvalue())
-
- def test_sub_command_errors(self):
- def add_parsers(subparsers):
- sub = subparsers.add_parser('a')
- sub.add_argument('--bar')
-
- self.conf.register_cli_opt(BoolOpt('bar'))
- self.conf.register_cli_opt(SubCommandOpt('cmd', handler=add_parsers))
- self.conf(['a'])
- self.assertRaises(DuplicateOptError, getattr, self.conf.cmd, 'bar')
- self.assertRaises(NoSuchOptError, getattr, self.conf.cmd, 'foo')
-
- def test_sub_command_multiple(self):
- self.conf.register_cli_opt(SubCommandOpt('cmd1'))
- self.conf.register_cli_opt(SubCommandOpt('cmd2'))
- self.stubs.Set(sys, 'stderr', StringIO.StringIO())
- self.assertRaises(SystemExit, self.conf, [])
- self.assertTrue('multiple' in sys.stderr.getvalue())
-
-
-class SetDefaultsTestCase(BaseTestCase):
-
- def test_default_to_none(self):
- opts = [StrOpt('foo', default='foo')]
- self.conf.register_opts(opts)
- set_defaults(opts, foo=None)
- self.conf([])
- self.assertEquals(self.conf.foo, None)
-
- def test_default_from_none(self):
- opts = [StrOpt('foo')]
- self.conf.register_opts(opts)
- set_defaults(opts, foo='bar')
- self.conf([])
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_change_default(self):
- opts = [StrOpt('foo', default='foo')]
- self.conf.register_opts(opts)
- set_defaults(opts, foo='bar')
- self.conf([])
- self.assertEquals(self.conf.foo, 'bar')
-
- def test_group_default_to_none(self):
- opts = [StrOpt('foo', default='foo')]
- self.conf.register_opts(opts, group='blaa')
- set_defaults(opts, foo=None)
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, None)
-
- def test_group_default_from_none(self):
- opts = [StrOpt('foo')]
- self.conf.register_opts(opts, group='blaa')
- set_defaults(opts, foo='bar')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'bar')
-
- def test_group_change_default(self):
- opts = [StrOpt('foo', default='foo')]
- self.conf.register_opts(opts, group='blaa')
- set_defaults(opts, foo='bar')
- self.conf([])
- self.assertEquals(self.conf.blaa.foo, 'bar')
diff --git a/tests/unit/test_deprecated.py b/tests/unit/test_deprecated.py
index 5c85fd9..5b17ac0 100644
--- a/tests/unit/test_deprecated.py
+++ b/tests/unit/test_deprecated.py
@@ -14,7 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import log as logging
from tests import utils as test_utils
diff --git a/tests/unit/test_iniparser.py b/tests/unit/test_iniparser.py
deleted file mode 100644
index 1dcb9a0..0000000
--- a/tests/unit/test_iniparser.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from openstack.common import iniparser
-from tests import utils
-
-
-class TestParser(iniparser.BaseParser):
- comment_called = False
- values = None
- section = ''
-
- def __init__(self):
- self.values = {}
-
- def assignment(self, key, value):
- self.values.setdefault(self.section, {})
- self.values[self.section][key] = value
-
- def new_section(self, section):
- self.section = section
-
- def comment(self, section):
- self.comment_called = True
-
-
-class BaseParserTestCase(utils.BaseTestCase):
- def setUp(self):
- super(BaseParserTestCase, self).setUp()
- self.parser = iniparser.BaseParser()
-
- def _assertParseError(self, *lines):
- self.assertRaises(iniparser.ParseError, self.parser.parse, lines)
-
- def test_invalid_assignment(self):
- self._assertParseError("foo - bar")
-
- def test_empty_key(self):
- self._assertParseError(": bar")
-
- def test_unexpected_continuation(self):
- self._assertParseError(" baz")
-
- def test_invalid_section(self):
- self._assertParseError("[section")
-
- def test_no_section_name(self):
- self._assertParseError("[]")
-
-
-class ParserTestCase(utils.BaseTestCase):
- def setUp(self):
- super(ParserTestCase, self).setUp()
- self.parser = TestParser()
-
- def test_blank_line(self):
- lines = [""]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {})
-
- def test_assignment_equal(self):
- lines = ["foo = bar"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': ['bar']}})
-
- def test_assignment_colon(self):
- lines = ["foo: bar"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': ['bar']}})
-
- def test_assignment_multiline(self):
- lines = ["foo = bar0", " bar1"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': ['bar0', 'bar1']}})
-
- def test_assignment_multline_empty(self):
- lines = ["foo = bar0", "", " bar1"]
- self.assertRaises(iniparser.ParseError, self.parser.parse, lines)
-
- def test_section_assignment(self):
- lines = ["[test]", "foo = bar"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'test': {'foo': ['bar']}})
-
- def test_new_section(self):
- lines = ["[foo]"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.section, 'foo')
-
- def test_comment(self):
- lines = ["# foobar"]
- self.parser.parse(lines)
- self.assertTrue(self.parser.comment_called)
-
- def test_empty_assignment(self):
- lines = ["foo = "]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': ['']}})
-
- def test_assignment_space_single_quote(self):
- lines = ["foo = ' bar '"]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': [' bar ']}})
-
- def test_assignment_space_double_quote(self):
- lines = ["foo = \" bar \""]
- self.parser.parse(lines)
- self.assertEquals(self.parser.values, {'': {'foo': [' bar ']}})
-
-
-class ExceptionTestCase(utils.BaseTestCase):
- def test_parseerror(self):
- exc = iniparser.ParseError('test', 42, 'example')
- self.assertEquals(str(exc), "at line 42, test: 'example'")
diff --git a/tests/unit/test_log.py b/tests/unit/test_log.py
index a0788f1..6a1eeb2 100644
--- a/tests/unit/test_log.py
+++ b/tests/unit/test_log.py
@@ -3,7 +3,8 @@ import logging
import StringIO
import sys
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import context
from openstack.common import jsonutils
from openstack.common import log
diff --git a/tests/unit/test_notifier.py b/tests/unit/test_notifier.py
index a777fe8..70746b3 100644
--- a/tests/unit/test_notifier.py
+++ b/tests/unit/test_notifier.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common import context
from openstack.common import log
from openstack.common.notifier import api as notifier_api
diff --git a/tests/unit/test_plugin.py b/tests/unit/test_plugin.py
index 510e915..42857a5 100644
--- a/tests/unit/test_plugin.py
+++ b/tests/unit/test_plugin.py
@@ -15,7 +15,8 @@
import pkg_resources
-from openstack.common import cfg
+from oslo.config import cfg
+
from openstack.common.notifier import api as notifier_api
from openstack.common.plugin import plugin
from openstack.common.plugin import pluginmanager
diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py
index 824e553..6738d8e 100644
--- a/tests/unit/test_service.py
+++ b/tests/unit/test_service.py
@@ -25,8 +25,8 @@ import time
import traceback
from eventlet import greenthread
+from oslo.config import cfg
-from openstack.common import cfg
from openstack.common.gettextutils import _
from openstack.common import log as logging
from openstack.common.notifier import api as notifier_api
diff --git a/tests/unit/test_version.py b/tests/unit/test_version.py
index b648fc4..312f328 100644
--- a/tests/unit/test_version.py
+++ b/tests/unit/test_version.py
@@ -21,7 +21,8 @@ import StringIO
import sys
import tempfile
-from openstack.common.cfg import *
+from oslo.config.cfg import *
+
from openstack.common import version
from tests import utils
diff --git a/tests/unit/test_wsgi.py b/tests/unit/test_wsgi.py
index 2dd1035..41a1f97 100644
--- a/tests/unit/test_wsgi.py
+++ b/tests/unit/test_wsgi.py
@@ -15,17 +15,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
import os
-import routes
import socket
import ssl
import urllib2
+
+import mock
+from oslo.config import cfg
+import routes
import webob
from openstack.common import exception
from openstack.common import wsgi
-from openstack.common import cfg
from tests import utils
TEST_VAR_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
diff --git a/tests/utils.py b/tests/utils.py
index 2d681ae..f9c1936 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -20,9 +20,9 @@
import subprocess
import fixtures
+from oslo.config import cfg
import testtools
-from openstack.common import cfg
from openstack.common.fixture import moxstubout
from openstack.common import exception
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index 00f73d7..7cb3968 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -32,7 +32,7 @@ if os.path.exists(os.path.join(possible_topdir, "oslo",
sys.path.insert(0, possible_topdir)
-from openstack.common import cfg
+from oslo.config import cfg
class InstallVenv(object):
diff --git a/tools/pip-requires b/tools/pip-requires
index 31be6e3..fa90b95 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -10,3 +10,4 @@ kombu==1.0.4
argparse
stevedore
SQLAlchemy>=0.7.8,<=0.7.9
+http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b3.tar.gz#egg=oslo-config
diff --git a/tools/test-requires b/tools/test-requires
index ab7df82..3c26a47 100644
--- a/tools/test-requires
+++ b/tools/test-requires
@@ -12,6 +12,7 @@ nosexcover
openstack.nose_plugin
nosehtmloutput
pep8==1.3.3
+pyflakes
pylint
pyzmq>=2.1.11
setuptools-git>=0.4
diff --git a/tox.ini b/tox.ini
index 483c545..1dc4ab3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,7 +14,6 @@ deps = -r{toxinidir}/tools/pip-requires
commands = nosetests --with-doctest --exclude-dir=tests/testmods {posargs}
[testenv:pep8]
-deps = pep8==1.3.3
commands = pep8 --repeat --show-source --exclude=.venv,.tox,dist,doc,*.egg,.update-venv .
[testenv:cover]
@@ -29,5 +28,4 @@ deps = -r{toxinidir}/tools/pip-requires
-r{toxinidir}/tools/test-options
[testenv:pyflakes]
-deps = pyflakes
commands = pyflakes openstack setup.py update.py
diff --git a/update.py b/update.py
index 9340005..5a19989 100644
--- a/update.py
+++ b/update.py
@@ -62,11 +62,7 @@ import re
import shutil
import sys
-try:
- from openstack.common import cfg
-except:
- sys.stderr.write("Try running update.sh")
- raise
+from oslo.config import cfg
opts = [
cfg.ListOpt('modules',
diff --git a/update.sh b/update.sh
deleted file mode 100755
index 37d4a02..0000000
--- a/update.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-# Make some coffee and read https://code.launchpad.net/bugs/951197
-
-VENV=.update-venv
-
-[ -d $VENV ] || virtualenv -q --no-site-packages $VENV
-
-. $VENV/bin/activate
-
-python setup.py install
-
-python update.py $*