From 71125b576f45d3c8455876ff03e157e98c0627f4 Mon Sep 17 00:00:00 2001 From: Alexei Kornienko Date: Sat, 16 Aug 2014 19:56:36 +0300 Subject: [PATCH] Added testr profiles functionality Now you can use named sections in .testr.conf --profile parameter allows you to specify section --- testrepository/commands/__init__.py | 5 +-- testrepository/repository/__init__.py | 3 ++ testrepository/repository/file.py | 7 +++-- testrepository/testcommand.py | 44 +++++++++------------------ testrepository/ui/cli.py | 2 ++ 5 files changed, 26 insertions(+), 35 deletions(-) diff --git a/testrepository/commands/__init__.py b/testrepository/commands/__init__.py index 8863cea..c7cc41a 100644 --- a/testrepository/commands/__init__.py +++ b/testrepository/commands/__init__.py @@ -33,7 +33,7 @@ """ from inspect import getdoc -from optparse import OptionParser +import optparse import os import sys @@ -139,6 +139,7 @@ def execute(self): """ if not self.ui.set_command(self): return 1 + self.repository_factory._profile = self.ui.options.profile try: result = self.run() except Exception: @@ -201,7 +202,7 @@ def get_command_parser(cmd): :return: An OptionParser instance. """ - parser = OptionParser() + parser = optparse.OptionParser() for option in cmd.options: parser.add_option(option) usage = _u('%%prog %(cmd)s [options] %(args)s\n\n%(help)s') % { diff --git a/testrepository/repository/__init__.py b/testrepository/repository/__init__.py index b58c0a2..b2835a1 100644 --- a/testrepository/repository/__init__.py +++ b/testrepository/repository/__init__.py @@ -33,6 +33,9 @@ class AbstractRepositoryFactory(object): """Interface for making or opening repositories.""" + def __init__(self, profile='DEFAULT'): + self._profile = profile + def initialise(self, url): """Create a repository at URL. diff --git a/testrepository/repository/file.py b/testrepository/repository/file.py index 85ee1a3..66ee9e1 100644 --- a/testrepository/repository/file.py +++ b/testrepository/repository/file.py @@ -56,7 +56,7 @@ def initialise(klass, url): stream.write('1\n') finally: stream.close() - result = Repository(base) + result = Repository(base, self._profile) result._write_next_stream(0) return result @@ -71,7 +71,7 @@ def open(self, url): raise if '1\n' != stream.read(): raise ValueError(url) - return Repository(base) + return Repository(base, self._profile) class Repository(AbstractRepository): @@ -85,12 +85,13 @@ class Repository(AbstractRepository): likely to have an automatic upgrade process. """ - def __init__(self, base): + def __init__(self, base, profile): """Create a file-based repository object for the repo at 'base'. :param base: The path to the repository. """ self.base = base + self._profile = profile def _allocate(self): # XXX: lock the file. K?! diff --git a/testrepository/testcommand.py b/testrepository/testcommand.py index f5a94da..df21cdf 100644 --- a/testrepository/testcommand.py +++ b/testrepository/testcommand.py @@ -189,6 +189,7 @@ def __init__(self, test_ids, cmd_template, listopt, idoption, ui, self.parallel = parallel self._listpath = listpath self._parser = parser + self._option = lambda x: self._parser.get(repository._profile, x) self.test_filters = test_filters self._group_callback = group_callback self._instance_source = instance_source @@ -200,12 +201,12 @@ def setUp(self): list_variables = {'LISTOPT': self.listopt} cmd = self.template try: - default_idstr = self._parser.get('DEFAULT', 'test_id_list_default') + default_idstr = self._option('test_id_list_default') list_variables['IDLIST'] = default_idstr # In theory we should also support casting this into IDFILE etc - # needs this horrible class refactored. except ConfigParser.NoOptionError as e: - if e.message != "No option 'test_id_list_default' in section: 'DEFAULT'": + if "No option 'test_id_list_default'" not in e.message: raise default_idstr = None def list_subst(match): @@ -327,8 +328,7 @@ def _per_instance_command(self, cmd): instance = self._instance_source.obtain_instance(self.concurrency) if instance is not None: try: - instance_prefix = self._parser.get( - 'DEFAULT', 'instance_execute') + instance_prefix = self._option('instance_execute') variables = { 'INSTANCE_ID': instance.decode('utf8'), 'COMMAND': cmd, @@ -447,8 +447,7 @@ def consume_queue(groups): def callout_concurrency(self): """Callout for user defined concurrency.""" try: - concurrency_cmd = self._parser.get( - 'DEFAULT', 'test_run_concurrency') + concurrency_cmd = self._option('test_run_concurrency') except ConfigParser.NoOptionError: return None run_proc = self.ui.subprocess_Popen(concurrency_cmd, shell=True, @@ -495,6 +494,7 @@ def __init__(self, ui, repository): super(TestCommand, self).__init__() self.ui = ui self.repository = repository + self._option = lambda x: self.get_parser().get(repository._profile, x) self._instances = None self._allocated_instances = None @@ -511,7 +511,7 @@ def _dispose_instances(self): self._instances = None self._allocated_instances = None try: - dispose_cmd = self.get_parser().get('DEFAULT', 'instance_dispose') + dispose_cmd = self._option('instance_dispose') except (ValueError, ConfigParser.NoOptionError): return variable_regex = '\$INSTANCE_IDS' @@ -542,34 +542,19 @@ def get_run_command(self, test_ids=None, testargs=(), test_filters=None): if self._instances is None: raise TypeError('TestCommand not setUp') parser = self.get_parser() - try: - command = parser.get('DEFAULT', 'test_command') - except ConfigParser.NoOptionError as e: - if e.message != "No option 'test_command' in section: 'DEFAULT'": - raise - raise ValueError("No test_command option present in .testr.conf") + command = self._option('test_command') elements = [command] + list(testargs) cmd = ' '.join(elements) idoption = '' if '$IDOPTION' in command: # IDOPTION is used, we must have it configured. - try: - idoption = parser.get('DEFAULT', 'test_id_option') - except ConfigParser.NoOptionError as e: - if e.message != "No option 'test_id_option' in section: 'DEFAULT'": - raise - raise ValueError("No test_id_option option present in .testr.conf") + idoption = self._option('test_id_option') listopt = '' if '$LISTOPT' in command: # LISTOPT is used, test_list_option must be configured. - try: - listopt = parser.get('DEFAULT', 'test_list_option') - except ConfigParser.NoOptionError as e: - if e.message != "No option 'test_list_option' in section: 'DEFAULT'": - raise - raise ValueError("No test_list_option option present in .testr.conf") + listopt = self._option('test_list_option') try: - group_regex = parser.get('DEFAULT', 'group_regex') + group_regex = self._option('group_regex') except ConfigParser.NoOptionError: group_regex = None if group_regex: @@ -593,11 +578,10 @@ def group_callback(test_id, regex=re.compile(group_regex)): return result def get_filter_tags(self): - parser = self.get_parser() try: - tags = parser.get('DEFAULT', 'filter_tags') + tags = self._option('filter_tags') except ConfigParser.NoOptionError as e: - if e.message != "No option 'filter_tags' in section: 'DEFAULT'": + if "No option 'filter_tags'" not in e.message: raise return set() return set([tag.strip() for tag in tags.split()]) @@ -610,7 +594,7 @@ def obtain_instance(self, concurrency): """ while len(self._instances) < concurrency: try: - cmd = self.get_parser().get('DEFAULT', 'instance_provision') + cmd = self._option('instance_provision') except ConfigParser.NoOptionError: # Instance allocation not configured return None diff --git a/testrepository/ui/cli.py b/testrepository/ui/cli.py index d387b50..254edb4 100644 --- a/testrepository/ui/cli.py +++ b/testrepository/ui/cli.py @@ -267,6 +267,8 @@ def _check_cmd(self): parser.add_option("-q", "--quiet", action="store_true", default=False, help="Turn off output other than the primary output for a command " "and any errors.") + parser.add_option("-p", "--profile", action="store", + type='str', default='DEFAULT', help="Profile to use") # yank out --, as optparse makes it silly hard to just preserve it. try: where_dashdash = self._argv.index('--')