From cf3f671a050f5cb5a2acc8c8c4b0b6b7a3a0d892 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 31 Jan 2012 13:39:36 -0500 Subject: [PATCH 1/3] Fix pep8 violations. Change-Id: I12e304c567b92178e193c60599c3be606cc70d38 --- bin/keystone-manage | 14 +- keystone/cli.py | 463 +++++++++++++++++++------------------ keystone/common/logging.py | 16 +- keystone/common/utils.py | 54 ++--- setup.py | 3 +- 5 files changed, 276 insertions(+), 274 deletions(-) diff --git a/bin/keystone-manage b/bin/keystone-manage index bcc27195eb..e551c47e2f 100755 --- a/bin/keystone-manage +++ b/bin/keystone-manage @@ -18,11 +18,11 @@ from keystone import cli if __name__ == '__main__': - dev_conf = os.path.join(possible_topdir, - 'etc', - 'keystone.conf') - config_files = None - if os.path.exists(dev_conf): - config_files = [dev_conf] + dev_conf = os.path.join(possible_topdir, + 'etc', + 'keystone.conf') + config_files = None + if os.path.exists(dev_conf): + config_files = [dev_conf] - cli.main(argv=sys.argv, config_files=config_files) + cli.main(argv=sys.argv, config_files=config_files) diff --git a/keystone/cli.py b/keystone/cli.py index 93e3620564..e178a31b64 100644 --- a/keystone/cli.py +++ b/keystone/cli.py @@ -33,316 +33,317 @@ config.register_cli_bool('id-only', class BaseApp(cli.log.LoggingApp): - def __init__(self, *args, **kw): - kw.setdefault('name', self.__class__.__name__.lower()) - super(BaseApp, self).__init__(*args, **kw) + def __init__(self, *args, **kw): + kw.setdefault('name', self.__class__.__name__.lower()) + super(BaseApp, self).__init__(*args, **kw) - def add_default_params(self): - for args, kw in DEFAULT_PARAMS: - self.add_param(*args, **kw) + def add_default_params(self): + for args, kw in DEFAULT_PARAMS: + self.add_param(*args, **kw) - def _parse_keyvalues(self, args): - kv = {} - for x in args: - key, value = x.split('=', 1) - # make lists if there are multiple values - if key.endswith('[]'): - key = key[:-2] - existing = kv.get(key, []) - existing.append(value) - kv[key] = existing - else: - kv[key] = value - return kv + def _parse_keyvalues(self, args): + kv = {} + for x in args: + key, value = x.split('=', 1) + # make lists if there are multiple values + if key.endswith('[]'): + key = key[:-2] + existing = kv.get(key, []) + existing.append(value) + kv[key] = existing + else: + kv[key] = value + return kv class DbSync(BaseApp): - """Sync the database.""" + """Sync the database.""" - name = 'db_sync' + name = 'db_sync' - def __init__(self, *args, **kw): - super(DbSync, self).__init__(*args, **kw) + def __init__(self, *args, **kw): + super(DbSync, self).__init__(*args, **kw) - def main(self): - for k in ['identity', 'catalog', 'policy', 'token']: - driver = utils.import_object(getattr(CONF, k).driver) - if hasattr(driver, 'db_sync'): - driver.db_sync() + def main(self): + for k in ['identity', 'catalog', 'policy', 'token']: + driver = utils.import_object(getattr(CONF, k).driver) + if hasattr(driver, 'db_sync'): + driver.db_sync() class ClientCommand(BaseApp): - ACTION_MAP = None + ACTION_MAP = None - def _attr_name(self): - return '%ss' % self.__class__.__name__.lower() + def _attr_name(self): + return '%ss' % self.__class__.__name__.lower() - def _cmd_name(self): - return self.__class__.__name__.lower() + def _cmd_name(self): + return self.__class__.__name__.lower() - def __init__(self, *args, **kw): - super(ClientCommand, self).__init__(*args, **kw) - if not self.ACTION_MAP: - self.ACTION_MAP = {'help': 'help'} - self.add_param('action', nargs='?', default='help') - self.add_param('keyvalues', nargs='*') - self.client = kc.Client(CONF.endpoint, token=CONF.auth_token) - self.handle = getattr(self.client, self._attr_name()) - self._build_action_map() + def __init__(self, *args, **kw): + super(ClientCommand, self).__init__(*args, **kw) + if not self.ACTION_MAP: + self.ACTION_MAP = {'help': 'help'} + self.add_param('action', nargs='?', default='help') + self.add_param('keyvalues', nargs='*') + self.client = kc.Client(CONF.endpoint, token=CONF.auth_token) + self.handle = getattr(self.client, self._attr_name()) + self._build_action_map() - def _build_action_map(self): - actions = {} - for k in dir(self.handle): - if not k.startswith('_'): - actions[k] = k - self.ACTION_MAP.update(actions) + def _build_action_map(self): + actions = {} + for k in dir(self.handle): + if not k.startswith('_'): + actions[k] = k + self.ACTION_MAP.update(actions) - def main(self): - """Given some keyvalues create the appropriate data in Keystone.""" - action_name = self.ACTION_MAP[self.params.action] - if action_name == 'help': - self.print_help() - sys.exit(1) + def main(self): + """Given some keyvalues create the appropriate data in Keystone.""" + action_name = self.ACTION_MAP[self.params.action] + if action_name == 'help': + self.print_help() + sys.exit(1) - kv = self._parse_keyvalues(self.params.keyvalues) - try: - f = getattr(self.handle, action_name) - resp = f(**kv) - except Exception: - logging.exception('') - raise + kv = self._parse_keyvalues(self.params.keyvalues) + try: + f = getattr(self.handle, action_name) + resp = f(**kv) + except Exception: + logging.exception('') + raise - if CONF.id_only and getattr(resp, 'id'): - print resp.id - return + if CONF.id_only and getattr(resp, 'id'): + print resp.id + return - if resp is None: - return + if resp is None: + return - # NOTE(termie): this is ugly but it is mostly because the keystoneclient - # code doesn't give us very serializable instance objects - if type(resp) in [type(list()), type(tuple())]: - o = [] - for r in resp: - d = {} - for k, v in sorted(r.__dict__.iteritems()): - if k[0] == '_' or k == 'manager': - continue - d[k] = v - o.append(d) - else: - o = {} - for k, v in sorted(resp.__dict__.iteritems()): - if k[0] == '_' or k == 'manager': - continue - o[k] = v + # NOTE(termie): this is ugly but it is mostly because the + # keystoneclient code doesn't give us very + # serializable instance objects + if type(resp) in [type(list()), type(tuple())]: + o = [] + for r in resp: + d = {} + for k, v in sorted(r.__dict__.iteritems()): + if k[0] == '_' or k == 'manager': + continue + d[k] = v + o.append(d) + else: + o = {} + for k, v in sorted(resp.__dict__.iteritems()): + if k[0] == '_' or k == 'manager': + continue + o[k] = v - print json.dumps(o) + print json.dumps(o) - def print_help(self): - CONF.set_usage(CONF.usage.replace( - 'COMMAND', '%s SUBCOMMAND' % self._cmd_name())) - CONF.print_help() + def print_help(self): + CONF.set_usage(CONF.usage.replace( + 'COMMAND', '%s SUBCOMMAND' % self._cmd_name())) + CONF.print_help() - methods = self._get_methods() - print_commands(methods) + methods = self._get_methods() + print_commands(methods) - def _get_methods(self): - o = {} - for k in dir(self.handle): - if k.startswith('_'): - continue - if k in ('find', 'findall', 'api', 'resource_class'): - continue - o[k] = getattr(self.handle, k) - return o + def _get_methods(self): + o = {} + for k in dir(self.handle): + if k.startswith('_'): + continue + if k in ('find', 'findall', 'api', 'resource_class'): + continue + o[k] = getattr(self.handle, k) + return o class Role(ClientCommand): - """Role CRUD functions.""" - pass + """Role CRUD functions.""" + pass class Service(ClientCommand): - """Service CRUD functions.""" - pass + """Service CRUD functions.""" + pass class Token(ClientCommand): - """Token CRUD functions.""" - pass + """Token CRUD functions.""" + pass class Tenant(ClientCommand): - """Tenant CRUD functions.""" - pass + """Tenant CRUD functions.""" + pass class User(ClientCommand): - """User CRUD functions.""" + """User CRUD functions.""" - pass + pass class Ec2(ClientCommand): - def _attr_name(self): - return self.__class__.__name__.lower() + def _attr_name(self): + return self.__class__.__name__.lower() CMDS = {'db_sync': DbSync, - 'role': Role, - 'service': Service, - 'token': Token, - 'tenant': Tenant, - 'user': User, - 'ec2': Ec2, - } + 'role': Role, + 'service': Service, + 'token': Token, + 'tenant': Tenant, + 'user': User, + 'ec2': Ec2, + } class CommandLineGenerator(object): - """A keystoneclient lookalike to generate keystone-manage commands. + """A keystoneclient lookalike to generate keystone-manage commands. - One would use it like so: + One would use it like so: - >>> gen = CommandLineGenerator(id_only=None) - >>> cl = gen.ec2.create(user_id='foo', tenant_id='foo') - >>> cl.to_argv() - ... ['keystone-manage', - '--id-only', - 'ec2', - 'create', - 'user_id=foo', - 'tenant_id=foo'] + >>> gen = CommandLineGenerator(id_only=None) + >>> cl = gen.ec2.create(user_id='foo', tenant_id='foo') + >>> cl.to_argv() + ... ['keystone-manage', + '--id-only', + 'ec2', + 'create', + 'user_id=foo', + 'tenant_id=foo'] - """ + """ - cmd = 'keystone-manage' + cmd = 'keystone-manage' - def __init__(self, cmd=None, execute=False, **kw): - if cmd: - self.cmd = cmd - self.flags = kw - self.execute = execute + def __init__(self, cmd=None, execute=False, **kw): + if cmd: + self.cmd = cmd + self.flags = kw + self.execute = execute - def __getattr__(self, key): - return _Manager(self, key) + def __getattr__(self, key): + return _Manager(self, key) class _Manager(object): - def __init__(self, parent, name): - self.parent = parent - self.name = name + def __init__(self, parent, name): + self.parent = parent + self.name = name - def __getattr__(self, key): - return _CommandLine(cmd=self.parent.cmd, - flags=self.parent.flags, - manager=self.name, - method=key, - execute=self.parent.execute) + def __getattr__(self, key): + return _CommandLine(cmd=self.parent.cmd, + flags=self.parent.flags, + manager=self.name, + method=key, + execute=self.parent.execute) class _CommandLine(object): - def __init__(self, cmd, flags, manager, method, execute=False): - self.cmd = cmd - self.flags = flags - self.manager = manager - self.method = method - self.execute = execute - self.kw = {} + def __init__(self, cmd, flags, manager, method, execute=False): + self.cmd = cmd + self.flags = flags + self.manager = manager + self.method = method + self.execute = execute + self.kw = {} - def __call__(self, **kw): - self.kw = kw - if self.execute: - logging.debug('generated cli: %s', str(self)) - out = StringIO.StringIO() - old_out = sys.stdout - sys.stdout = out - try: - main(self.to_argv()) - except SystemExit as e: - pass - finally: - sys.stdout = old_out - rv = out.getvalue().strip().split('\n')[-1] - try: - loaded = json.loads(rv) - if type(loaded) in [type(list()), type(tuple())]: - return [DictWrapper(**x) for x in loaded] - elif type(loaded) is type(dict()): - return DictWrapper(**loaded) - except Exception: - logging.exception('Could not parse JSON: %s', rv) - return rv - return self + def __call__(self, **kw): + self.kw = kw + if self.execute: + logging.debug('generated cli: %s', str(self)) + out = StringIO.StringIO() + old_out = sys.stdout + sys.stdout = out + try: + main(self.to_argv()) + except SystemExit as e: + pass + finally: + sys.stdout = old_out + rv = out.getvalue().strip().split('\n')[-1] + try: + loaded = json.loads(rv) + if type(loaded) in [type(list()), type(tuple())]: + return [DictWrapper(**x) for x in loaded] + elif type(loaded) is type(dict()): + return DictWrapper(**loaded) + except Exception: + logging.exception('Could not parse JSON: %s', rv) + return rv + return self - def __flags(self): - o = [] - for k, v in self.flags.iteritems(): - k = k.replace('_', '-') - if v is None: - o.append('--%s' % k) - else: - o.append('--%s=%s' % (k, str(v))) - return o + def __flags(self): + o = [] + for k, v in self.flags.iteritems(): + k = k.replace('_', '-') + if v is None: + o.append('--%s' % k) + else: + o.append('--%s=%s' % (k, str(v))) + return o - def __manager(self): - if self.manager.endswith('s'): - return self.manager[:-1] - return self.manager + def __manager(self): + if self.manager.endswith('s'): + return self.manager[:-1] + return self.manager - def __kw(self): - o = [] - for k, v in self.kw.iteritems(): - o.append('%s=%s' % (k, str(v))) - return o + def __kw(self): + o = [] + for k, v in self.kw.iteritems(): + o.append('%s=%s' % (k, str(v))) + return o - def to_argv(self): - return ([self.cmd] - + self.__flags() - + [self.__manager(), self.method] - + self.__kw()) + def to_argv(self): + return ([self.cmd] + + self.__flags() + + [self.__manager(), self.method] + + self.__kw()) - def __str__(self): - args = self.to_argv() - return ' '.join(args[:1] + ['"%s"' % x for x in args[1:]]) + def __str__(self): + args = self.to_argv() + return ' '.join(args[:1] + ['"%s"' % x for x in args[1:]]) class DictWrapper(dict): - def __getattr__(self, key): - try: - return self[key] - except KeyError: - raise AttributeError(key) + def __getattr__(self, key): + try: + return self[key] + except KeyError: + raise AttributeError(key) def print_commands(cmds): - print - print "Available commands:" - o = [] - max_length = max([len(k) for k in cmds]) + 2 - for k, cmd in sorted(cmds.iteritems()): - initial_indent = '%s%s: ' % (' ' * (max_length - len(k)), k) - tw = textwrap.TextWrapper(initial_indent=initial_indent, - subsequent_indent=' ' * (max_length + 2), - width=80) - o.extend(tw.wrap( - (cmd.__doc__ and cmd.__doc__ or 'no docs').strip().split('\n')[0])) - print '\n'.join(o) + print + print "Available commands:" + o = [] + max_length = max([len(k) for k in cmds]) + 2 + for k, cmd in sorted(cmds.iteritems()): + initial_indent = '%s%s: ' % (' ' * (max_length - len(k)), k) + tw = textwrap.TextWrapper(initial_indent=initial_indent, + subsequent_indent=' ' * (max_length + 2), + width=80) + o.extend(tw.wrap( + (cmd.__doc__ and cmd.__doc__ or 'no docs').strip().split('\n')[0])) + print '\n'.join(o) def run(cmd, args): - return CMDS[cmd](argv=args).run() + return CMDS[cmd](argv=args).run() def main(argv=None, config_files=None): - CONF.reset() - args = CONF(config_files=config_files, args=argv) + CONF.reset() + args = CONF(config_files=config_files, args=argv) - if len(args) < 2: - CONF.print_help() - print_commands(CMDS) - sys.exit(1) + if len(args) < 2: + CONF.print_help() + print_commands(CMDS) + sys.exit(1) - cmd = args[1] - if cmd in CMDS: - return run(cmd, (args[:1] + args[2:])) + cmd = args[1] + if cmd in CMDS: + return run(cmd, (args[:1] + args[2:])) diff --git a/keystone/common/logging.py b/keystone/common/logging.py index 7ef073763b..a9aaccfced 100644 --- a/keystone/common/logging.py +++ b/keystone/common/logging.py @@ -45,11 +45,11 @@ SysLogHandler = SysLogHandler def log_debug(f): - @functools.wraps(f) - def wrapper(*args, **kw): - logging.debug('%s(%s, %s) ->', f.func_name, str(args), str(kw)) - rv = f(*args, **kw) - logging.debug(pprint.pformat(rv, indent=2)) - logging.debug('') - return rv - return wrapper + @functools.wraps(f) + def wrapper(*args, **kw): + logging.debug('%s(%s, %s) ->', f.func_name, str(args), str(kw)) + rv = f(*args, **kw) + logging.debug(pprint.pformat(rv, indent=2)) + logging.debug('') + return rv + return wrapper diff --git a/keystone/common/utils.py b/keystone/common/utils.py index 3ee9489441..95a1b97103 100644 --- a/keystone/common/utils.py +++ b/keystone/common/utils.py @@ -161,38 +161,38 @@ def check_password(password, hashed): # From python 2.7 def check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. + r"""Run command with arguments and return its output as a byte string. - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. + If the exit code was non-zero it raises a CalledProcessError. The + CalledProcessError object will have the return code in the returncode + attribute and output in the output attribute. - The arguments are the same as for the Popen constructor. Example: + The arguments are the same as for the Popen constructor. Example: - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' + >>> check_output(["ls", "-l", "/dev/null"]) + 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. + The stdout argument is not allowed as it is used internally. + To capture standard error in the result, use stderr=STDOUT. - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - logging.debug(' '.join(popenargs[0])) - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd) - return output + >>> check_output(["/bin/sh", "-c", + ... "ls -l non_existent_file ; exit 0"], + ... stderr=STDOUT) + 'ls: non_existent_file: No such file or directory\n' + """ + if 'stdout' in kwargs: + raise ValueError('stdout argument not allowed, it will be overridden.') + logging.debug(' '.join(popenargs[0])) + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise subprocess.CalledProcessError(retcode, cmd) + return output def git(*args): - return check_output(['git'] + list(args)) + return check_output(['git'] + list(args)) diff --git a/setup.py b/setup.py index 6c1ce8486d..5f52c70252 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ from setuptools import setup, find_packages + setup(name='keystone', version='2012.1', description="Authentication service for OpenStack", @@ -10,5 +11,5 @@ setup(name='keystone', packages=find_packages(exclude=['test', 'bin']), scripts=['bin/keystone', 'bin/keystone-manage'], zip_safe=False, - install_requires = ['setuptools', 'python-keystoneclient'], + install_requires=['setuptools', 'python-keystoneclient'], ) From fc3de2491d15f446d6223ff494bbeaef06fda8ac Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 31 Jan 2012 13:40:29 -0500 Subject: [PATCH 2/3] Use gerrit instead of github When we run gating tests in jenkins, any access of network resources is a potential source of false-negative on the test due to intermittent service failures on systems that are out of our control. We observe that this is actually quite frequent when things want to access PyPI or github. With pypi, we pre-create virtualenvs and cache the eggs so that an individual test run doesn't fail due to pypi not responding. For repos, if at all possible, we direct them all at the gerrit instance, because since gerrit is driving the test run in the first place, it's indicative of a much larger problem if jenkins can't talk to it - and it's one that we can fix if it does come up. Change-Id: I9f54133f7f2025d15a9d0b270d2466438cbc6dd5 --- tests/test_keystoneclient.py | 3 ++- tests/test_legacy_compat.py | 8 ++++---- tests/test_novaclient_compat.py | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/test_keystoneclient.py b/tests/test_keystoneclient.py index 9766108ad4..d7748649d9 100644 --- a/tests/test_keystoneclient.py +++ b/tests/test_keystoneclient.py @@ -7,7 +7,8 @@ from keystone import test import default_fixtures CONF = config.CONF -KEYSTONECLIENT_REPO = 'git://github.com/openstack/python-keystoneclient.git' +OPENSTACK_REPO = 'https://review.openstack.org/p/openstack' +KEYSTONECLIENT_REPO = '%s/python-keystoneclient.git' % OPENSTACK_REPO class CompatTestCase(test.TestCase): diff --git a/tests/test_legacy_compat.py b/tests/test_legacy_compat.py index ff6b7fdbc2..e9d9ebc0f3 100644 --- a/tests/test_legacy_compat.py +++ b/tests/test_legacy_compat.py @@ -13,11 +13,11 @@ from keystone.common import utils CONF = config.CONF +OPENSTACK_REPO = 'https://review.openstack.org/p/openstack/' -IDENTITY_API_REPO = 'git://github.com/openstack/identity-api.git' -KEYSTONE_REPO = 'git://github.com/openstack/keystone.git' -NOVACLIENT_REPO = 'git://github.com/rackspace/python-novaclient.git' - +IDENTITY_API_REPO = '%s/identity-api.git' % OPENSTACK_REPO +KEYSTONE_REPO = '%s/keystone.git' % OPENSTACK_REPO +NOVACLIENT_REPO = '%s/python-novaclient.git' % OPENSTACK_REPO IDENTITY_SAMPLE_DIR = 'openstack-identity-api/src/docbkx/samples' KEYSTONE_SAMPLE_DIR = 'keystone/content/common/samples' diff --git a/tests/test_novaclient_compat.py b/tests/test_novaclient_compat.py index b4f6dc7928..5578e4f784 100644 --- a/tests/test_novaclient_compat.py +++ b/tests/test_novaclient_compat.py @@ -12,7 +12,8 @@ import default_fixtures CONF = config.CONF -NOVACLIENT_REPO = 'git://github.com/openstack/python-novaclient.git' +OPENSTACK_REPO = 'https://review.openstack.org/p/openstack' +NOVACLIENT_REPO = '%s/python-novaclient.git' % OPENSTACK_REPO class CompatTestCase(test.TestCase): From 3da657555d801a487fbfbc97778e2664e50f8434 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 31 Jan 2012 13:45:53 -0500 Subject: [PATCH 3/3] Normalize build files with current jenkins. Change-Id: I528c3cc4e16dfa1465c8e3ac1062c65dc2ddc2f0 --- .gitignore | 3 +++ run_tests.sh | 3 +-- tools/install_venv.py | 4 ++-- tools/pip-requires | 23 ++++++++++++++++++++++- tools/with_venv.sh | 2 +- tox.ini | 26 ++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 6dc19a6eb0..cd78247219 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ *.swp vendor .ksl-venv +.venv +.tox +keystone.egg-info/ run_tests.log .coverage covhtml diff --git a/run_tests.sh b/run_tests.sh index 825d9501b1..c55a0cd9e5 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -40,7 +40,7 @@ function process_option { esac } -venv=.ksl-venv +venv=.venv with_venv=tools/with_venv.sh always_venv=0 never_venv=0 @@ -89,7 +89,6 @@ function run_pep8 { srcfiles+=" keystone" # Just run PEP8 in current environment ${wrapper} pep8 --repeat --show-pep8 --show-source \ - --ignore=E202,E111 \ --exclude=vcsversion.py ${srcfiles} | tee pep8.txt } diff --git a/tools/install_venv.py b/tools/install_venv.py index c2489f29e1..11f682b63d 100644 --- a/tools/install_venv.py +++ b/tools/install_venv.py @@ -28,8 +28,8 @@ import sys ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -VENV = os.path.join(ROOT, '.ksl-venv') -PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires-test') +VENV = os.path.join(ROOT, '.venv') +PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires') PY_VERSION = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) diff --git a/tools/pip-requires b/tools/pip-requires index c075d369ee..94ab44ba2c 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,3 +1,4 @@ +# keystonelight dependencies pam==0.1.4 WebOb==0.9.8 eventlet==0.9.12 @@ -9,4 +10,24 @@ sqlalchemy sqlalchemy-migrate py-bcrypt --e git+https://github.com/openstack/python-keystoneclient.git#egg=python-keystoneclient +# for python-novaclient +prettytable + +# Optional backend: Memcache +python-memcached # increases performance of token validation calls + +# Development +Sphinx>=1.1.2 # required to build documentation +coverage # computes code coverage percentages + +# Testing +nose # for test discovery and console feedback +nosexcover +unittest2 # backport of unittest lib in python 2.7 +webtest # test wsgi apps without starting an http server +pylint # static code analysis +pep8==0.6.1 # checks for PEP8 code style compliance +mox # mock object framework + +-e git+https://review.openstack.org/p/openstack/python-keystoneclient.git#egg=python-keystoneclient +-e git+https://review.openstack.org/p/openstack-dev/openstack-nose.git#egg=openstack.nose_plugin diff --git a/tools/with_venv.sh b/tools/with_venv.sh index 0ed2ef7268..c8d2940fc7 100755 --- a/tools/with_venv.sh +++ b/tools/with_venv.sh @@ -1,4 +1,4 @@ #!/bin/bash TOOLS=`dirname $0` -VENV=$TOOLS/../.ksl-venv +VENV=$TOOLS/../.venv source $VENV/bin/activate && $@ diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000000..e9a2fb389b --- /dev/null +++ b/tox.ini @@ -0,0 +1,26 @@ +[tox] +envlist = py26,py27,pep8 + +[testenv] +deps = -r{toxinidir}/tools/pip-requires +commands = nosetests + +[testenv:pep8] +commands = pep8 --exclude=vcsversion.py,*.pyc --repeat --show-source bin keystone setup.py + +[testenv:hudson] +downloadcache = ~/cache/pip + +[testenv:jenkins26] +basepython = python2.6 +deps = file://{toxinidir}/.cache.bundle + +[testenv:jenkins27] +basepython = python2.7 +deps = file://{toxinidir}/.cache.bundle + +[testenv:jenkinspep8] +deps = file://{toxinidir}/.cache.bundle +commands = pep8 --exclude=vcsversion.py,*.pyc --repeat --show-source bin keystone setup.py + +