diff options
author | Mark McLoughlin <markmc@redhat.com> | 2013-02-17 15:22:44 +0000 |
---|---|---|
committer | Mark McLoughlin <markmc@redhat.com> | 2013-02-17 15:44:00 +0000 |
commit | f63ea05f7c36ece6aad0fdc8e02f4d5d30c673a3 (patch) | |
tree | fc46499db82de0829e1137b1d620bceb46cb787f | |
parent | 8ce59472653439d646309395bf195ec6163ff29a (diff) | |
download | oslo-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
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 @@ -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 @@ -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 $* |