Skip to content

Commit

Permalink
Merge "Sync to newer openstack-common"
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed May 3, 2012
2 parents 352839b + 8dc3baa commit a1c2dd1
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 33 deletions.
112 changes: 86 additions & 26 deletions keystone/openstack/common/cfg.py
Expand Up @@ -90,16 +90,21 @@ def get_bind_port(conf):
def add_common_opts(conf):
conf.register_cli_opts(cli_opts)
The config manager has a single CLI option defined by default, --config-file::
The config manager has two CLI options defined by default, --config-file
and --config-dir::
class ConfigOpts(object):
config_file_opt = MultiStrOpt('config-file',
...
def __init__(self, ...):
...
self.register_cli_opt(self.config_file_opt)
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
Expand Down Expand Up @@ -221,6 +226,8 @@ def register_rabbit_opts(conf):

import collections
import copy
import glob
import functools
import optparse
import os
import string
Expand Down Expand Up @@ -318,11 +325,12 @@ class ConfigFileValueError(Error):
pass


def find_config_files(project=None, prog=None):
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]
Expand Down Expand Up @@ -355,16 +363,16 @@ def find_config_files(project=None, prog=None):
]
cfg_dirs = filter(bool, cfg_dirs)

def search_dirs(dirs, basename):
def search_dirs(dirs, basename, extension):
for d in dirs:
path = os.path.join(d, basename)
path = os.path.join(d, '%s%s' % (basename, extension))
if os.path.exists(path):
return path

config_files = []
if project:
config_files.append(search_dirs(cfg_dirs, '%s.conf' % project))
config_files.append(search_dirs(cfg_dirs, '%s.conf' % prog))
config_files.append(search_dirs(cfg_dirs, project, extension))
config_files.append(search_dirs(cfg_dirs, prog, extension))

return filter(bool, config_files)

Expand Down Expand Up @@ -821,14 +829,37 @@ def __init__(self,
usage=self.usage)
self._cparser = None

self.register_cli_opt(
MultiStrOpt('config-file',
default=self.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' % (self.default_config_files, )))
self.__cache = {}

opts = [
MultiStrOpt('config-file',
default=self.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' %
(self.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(opts)

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):
"""Parse command line arguments and config files.
Expand All @@ -840,6 +871,10 @@ def __call__(self, args=None):
The object may be called multiple times, each time causing the previous
set of values to be overwritten.
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.
:params args: command line arguments (defaults to sys.argv[1:])
:returns: the list of arguments left over after parsing options
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError
Expand All @@ -852,8 +887,14 @@ def __call__(self, args=None):

self._cli_values = vars(values)

if self.config_file:
self._parse_config_files(self.config_file)
def _list_config_dir():
return sorted(glob.glob(os.path.join(self.config_dir, '*.conf')))

from_file = list(self.config_file)

from_dir = _list_config_dir() if self.config_dir else []

self._parse_config_files(from_file + from_dir)

return args

Expand All @@ -864,7 +905,7 @@ def __getattr__(self, name):
:returns: the option value (after string subsititution) or a GroupAttr
:raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError
"""
return self._substitute(self._get(name))
return self._get(name)

def __getitem__(self, key):
"""Look up an option value and perform string substitution."""
Expand All @@ -883,12 +924,14 @@ def __len__(self):
"""Return the number of options and option groups."""
return len(self._opts) + len(self._groups)

@__clear_cache
def reset(self):
"""Reset the state of the object to before it was called."""
self._args = None
self._cli_values = None
self._cparser = None

@__clear_cache
def register_opt(self, opt, group=None):
"""Register an option schema.
Expand All @@ -911,11 +954,13 @@ def register_opt(self, opt, group=None):

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)
self.register_opt(opt, group, clear_cache=False)

@__clear_cache
def register_cli_opt(self, opt, group=None):
"""Register a CLI option schema.
Expand All @@ -931,7 +976,7 @@ def register_cli_opt(self, opt, group=None):
if self._args is not None:
raise ArgsAlreadyParsedError("cannot register CLI option")

if not self.register_opt(opt, group):
if not self.register_opt(opt, group, clear_cache=False):
return False

if group is not None:
Expand All @@ -941,10 +986,11 @@ def register_cli_opt(self, opt, group=None):

return True

@__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)
self.register_cli_opt(opt, group, clear_cache=False)

def register_group(self, group):
"""Register an option group.
Expand All @@ -959,6 +1005,7 @@ def register_group(self, group):

self._groups[group.name] = copy.copy(group)

@__clear_cache
def set_override(self, name, override, group=None):
"""Override an opt value.
Expand All @@ -973,6 +1020,7 @@ def set_override(self, name, override, group=None):
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.
Expand Down Expand Up @@ -1056,6 +1104,18 @@ def print_help(self, file=None):
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)
Expand Down Expand Up @@ -1196,7 +1256,7 @@ def __init__(self, conf, group):

def __getattr__(self, name):
"""Look up an option value and perform template substitution."""
return self.conf._substitute(self.conf._get(name, self.group))
return self.conf._get(name, self.group)

def __getitem__(self, key):
"""Look up an option value and perform string substitution."""
Expand Down
12 changes: 5 additions & 7 deletions keystone/openstack/common/setup.py
Expand Up @@ -138,10 +138,8 @@ def generate_authors():
"grep -v " + jenkins_email
changelog = _run_shell_command(git_log_cmd)
mailmap = parse_mailmap()
new_authors_fh = open(new_authors, "w")
new_authors_fh.write(canonicalize_emails(changelog, mailmap))
if os.path.exists(old_authors):
new_authors_fh.write("\n")
with open(old_authors, "r") as old_authors_fh:
new_authors_fh.write(''.join(old_authors_fh.readlines()))
new_authors_fh.close()
with open(new_authors, 'w') as new_authors_fh:
new_authors_fh.write(canonicalize_emails(changelog, mailmap))
if os.path.exists(old_authors):
with open(old_authors, "r") as old_authors_fh:
new_authors_fh.write('\n' + old_authors_fh.read())

0 comments on commit a1c2dd1

Please sign in to comment.