Skip to content

Commit

Permalink
Merge pull request #192 from mathstuf/configuration-option
Browse files Browse the repository at this point in the history
config: add --flavor option
  • Loading branch information
ralphbean committed Feb 7, 2015
2 parents c1d54e9 + 6af8b6f commit 063d03d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 49 deletions.
32 changes: 22 additions & 10 deletions bugwarrior/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,28 @@
lst = list


def _get_section_name(flavor):
if flavor:
return 'flavor.' + flavor
return 'general'


@click.command()
@click.option('--dry-run', is_flag=True)
def pull(dry_run):
@click.option('--flavor', default=None, help='The flavor to use')
def pull(dry_run, flavor):
""" Pull down tasks from forges and add them to your taskwarrior tasks.
Relies on configuration in ~/.bugwarriorrc
"""
twiggy.quickSetup()
try:
main_section = _get_section_name(flavor)

# Load our config file
config = load_config()
config = load_config(main_section)

tw_config = TaskWarriorBase.load_config(get_taskrc_path(config))
tw_config = TaskWarriorBase.load_config(get_taskrc_path(config, main_section))
lockfile_path = os.path.join(
os.path.expanduser(
tw_config['data']['location']
Expand All @@ -47,10 +56,10 @@ def pull(dry_run):
lockfile.acquire(timeout=10)
try:
# Get all the issues. This can take a while.
issue_generator = aggregate_issues(config)
issue_generator = aggregate_issues(config, main_section)

# Stuff them in the taskwarrior db as necessary
synchronize(issue_generator, config, dry_run)
synchronize(issue_generator, config, main_section, dry_run)
finally:
lockfile.release()
except LockTimeout:
Expand All @@ -76,9 +85,10 @@ def vault():


def targets():
config = load_config()
config = load_config('general')
for section in config.sections():
if section in ['general']:
if section in ['general'] or \
section.startswith('flavor.'):
continue
service_name = config.get(section, 'service')
service_class = SERVICES[service_name]
Expand Down Expand Up @@ -126,9 +136,11 @@ def set(target, username):


@click.command()
def uda():
conf = load_config()
@click.option('--flavor', default=None, help='The flavor to use')
def uda(flavor):
main_section = _get_section_name(flavor)
conf = load_config(main_section)
print "# Bugwarrior UDAs"
for uda in get_defined_udas_as_strings(conf):
for uda in get_defined_udas_as_strings(conf, main_section):
print uda
print "# END Bugwarrior UDAs"
26 changes: 13 additions & 13 deletions bugwarrior/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,19 @@ def die(msg):
sys.exit(1)


def validate_config(config):
if not config.has_section('general'):
die("No [general] section found.")
def validate_config(config, main_section):
if not config.has_section(main_section):
die("No [%s] section found." % main_section)

twiggy.quickSetup(
name2level(config.get('general', 'log.level')),
config.get('general', 'log.file')
name2level(config.get(main_section, 'log.level')),
config.get(main_section, 'log.file')
)

if not config.has_option('general', 'targets'):
die("No targets= item in [general] found.")
if not config.has_option(main_section, 'targets'):
die("No targets= item in [%s] found." % main_section)

targets = config.get('general', 'targets')
targets = config.get(main_section, 'targets')
targets = [t.strip() for t in targets.split(",")]

for target in targets:
Expand All @@ -129,7 +129,7 @@ def validate_config(config):
SERVICES[service].validate_config(config, target)


def load_config():
def load_config(main_section):
config = ConfigParser({'log.level': "DEBUG", 'log.file': None})
config.readfp(
codecs.open(
Expand All @@ -139,15 +139,15 @@ def load_config():
)
)
config.interactive = False # TODO: make this a command-line option
validate_config(config)
validate_config(config, main_section)

return config


def get_taskrc_path(conf):
def get_taskrc_path(conf, main_section):
path = '~/.taskrc'
if conf.has_option('general', 'taskrc'):
path = conf.get('general', 'taskrc')
if conf.has_option(main_section, 'taskrc'):
path = conf.get(main_section, 'taskrc')
return os.path.normpath(
os.path.expanduser(path)
)
Expand Down
14 changes: 7 additions & 7 deletions bugwarrior/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,15 @@ def run_hooks(conf, name):
raise RuntimeError(msg)


def synchronize(issue_generator, conf, dry_run=False):
def synchronize(issue_generator, conf, main_section, dry_run=False):
def _bool_option(section, option, default):
try:
return section in conf.sections() and \
asbool(conf.get(section, option, default))
except NoOptionError:
return default

targets = [t.strip() for t in conf.get('general', 'targets').split(',')]
targets = [t.strip() for t in conf.get(main_section, 'targets').split(',')]
services = set([conf.get(target, 'service') for target in targets])
key_list = build_key_list(services)
uda_list = build_uda_config_overrides(services)
Expand All @@ -306,8 +306,8 @@ def _bool_option(section, option, default):
)

static_fields = static_fields_default = ['priority']
if conf.has_option('general', 'static_fields'):
static_fields = conf.get('general', 'static_fields').split(',')
if conf.has_option(main_section, 'static_fields'):
static_fields = conf.get(main_section, 'static_fields').split(',')

# Before running CRUD operations, call the pre_import hook(s).
run_hooks(conf, 'pre_import')
Expand All @@ -320,7 +320,7 @@ def _bool_option(section, option, default):
marshal=True,
)

legacy_matching = _bool_option('general', 'legacy_matching', 'True')
legacy_matching = _bool_option(main_section, 'legacy_matching', 'True')

issue_updates = {
'new': [],
Expand Down Expand Up @@ -457,8 +457,8 @@ def build_key_list(targets):
return keys


def get_defined_udas_as_strings(conf):
targets = [t.strip() for t in conf.get('general', 'targets').split(',')]
def get_defined_udas_as_strings(conf, main_section):
targets = [t.strip() for t in conf.get(main_section, 'targets').split(',')]
services = set([conf.get(target, 'service') for target in targets])
uda_list = build_uda_config_overrides(services)

Expand Down
5 changes: 5 additions & 0 deletions bugwarrior/docs/common_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Optional options include:
* ``annotation_length``: Import maximally this number of characters
of incoming annotations. Default: 45.

In addition to the ``[general]`` section, sections may be named
``[flavor.myflavor]`` and may be selected using the ``--flavor`` option to
``bugwarrior-pull``. This section will then be used rather than the
``[general]`` section.

A more-detailed example configuration can be found at :ref:`example_configuration`.

.. _common_configuration_options:
Expand Down
38 changes: 20 additions & 18 deletions bugwarrior/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,32 @@ class IssueService(object):
# What prefix should we use for this service's configuration values
CONFIG_PREFIX = ''

def __init__(self, config, target):
def __init__(self, config, main_section, target):
self.config = config
self.main_section = main_section
self.target = target

self.desc_len = 35
if config.has_option('general', 'description_length'):
self.desc_len = self.config.getint('general', 'description_length')
if config.has_option(self.main_section, 'description_length'):
self.desc_len = self.config.getint(self.main_section, 'description_length')

self.anno_len = 45
if config.has_option('general', 'annotation_length'):
self.anno_len = self.config.getint('general', 'annotation_length')
if config.has_option(self.main_section, 'annotation_length'):
self.anno_len = self.config.getint(self.main_section, 'annotation_length')

self.inline_links = True
if config.has_option('general', 'inline_links'):
self.inline_links = asbool(config.get('general', 'inline_links'))
if config.has_option(self.main_section, 'inline_links'):
self.inline_links = asbool(config.get(self.main_section, 'inline_links'))

self.annotation_links = not self.inline_links
if config.has_option('general', 'annotation_links'):
if config.has_option(self.main_section, 'annotation_links'):
self.annotation_links = asbool(
config.get('general', 'annotation_links')
config.get(self.main_section, 'annotation_links')
)

self.shorten = False
if config.has_option('general', 'shorten'):
self.shorten = asbool(config.get('general', 'shorten'))
if config.has_option(self.main_section, 'shorten'):
self.shorten = asbool(config.get(self.main_section, 'shorten'))

self.add_tags = []
if config.has_option(self.target, 'add_tags'):
Expand Down Expand Up @@ -456,7 +457,7 @@ def __repr__(self):
return '<%s>' % self.__unicode__()


def _aggregate_issues(conf, target, queue, service_name):
def _aggregate_issues(conf, main_section, target, queue, service_name):
""" This worker function is separated out from the main
:func:`aggregate_issues` func only so that we can use multiprocessing
on it for speed reasons.
Expand All @@ -465,7 +466,7 @@ def _aggregate_issues(conf, target, queue, service_name):
start = time.time()

try:
service = SERVICES[service_name](conf, target)
service = SERVICES[service_name](conf, main_section, target)
issue_count = 0
for issue in service.issues():
queue.put(issue)
Expand All @@ -486,25 +487,26 @@ def _aggregate_issues(conf, target, queue, service_name):
log.name(target).info("Done with [%s] in %fs" % (target, duration))


def aggregate_issues(conf):
def aggregate_issues(conf, main_section):
""" Return all issues from every target. """
log.name('bugwarrior').info("Starting to aggregate remote issues.")

# Create and call service objects for every target in the config
targets = [t.strip() for t in conf.get('general', 'targets').split(',')]
targets = [t.strip() for t in conf.get(main_section, 'targets').split(',')]

queue = multiprocessing.Queue()

log.name('bugwarrior').info("Spawning %i workers." % len(targets))
processes = []

if (
conf.has_option('general', 'development')
and asbool(conf.get('general', 'development'))
conf.has_option(main_section, 'development')
and asbool(conf.get(main_section, 'development'))
):
for target in targets:
_aggregate_issues(
conf,
main_section,
target,
queue,
conf.get(target, 'service')
Expand All @@ -513,7 +515,7 @@ def aggregate_issues(conf):
for target in targets:
proc = multiprocessing.Process(
target=_aggregate_issues,
args=(conf, target, queue, conf.get(target, 'service'))
args=(conf, main_section, target, queue, conf.get(target, 'service'))
)
proc.start()
processes.append(proc)
Expand Down
2 changes: 1 addition & 1 deletion tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ def get_int(section, name):
config.get = mock.Mock(side_effect=get_option)
config.getint = mock.Mock(side_effect=get_int)

service = service(config, section)
service = service(config, 'general', section)

return service

0 comments on commit 063d03d

Please sign in to comment.