def synchronize(runlog, issue_generator, conf, main_section): store = runlog.config.store 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(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) static_fields = ['priority'] if conf.has_option(main_section, 'static_fields'): static_fields = conf.get(main_section, 'static_fields').split(',') all_config_overrides = copy.deepcopy(uda_list) all_config_overrides['uda'].update( settings.TASKWARRIOR_CONFIG_OVERRIDES.get('uda', {}) ) tw = TaskwarriorClient( store.taskrc.path, config_overrides=all_config_overrides, ) legacy_matching = False issue_updates = { 'new': [], 'existing': [], 'changed': [], 'closed': get_managed_task_uuids(tw, key_list, legacy_matching), } for issue in issue_generator: if isinstance(issue, tuple) and issue[0] == ABORT_PROCESSING: runlog.add_output(str(issue[1])) raise RuntimeError(issue[1]) try: existing_uuid = find_local_uuid( tw, key_list, issue, legacy_matching=legacy_matching ) issue_dict = dict(issue) _, task = tw.get_task(uuid=existing_uuid) # Drop static fields from the upstream issue. We don't want to # overwrite local changes to fields we declare static. for field in static_fields: del issue_dict[field] # Merge annotations & tags from online into our task object merge_left('annotations', task, issue_dict, hamming=True) merge_left('tags', task, issue_dict) issue_dict.pop('annotations', None) issue_dict.pop('tags', None) task.update(issue_dict) if task.get_changes(keep=True): issue_updates['changed'].append(task) else: issue_updates['existing'].append(task) if existing_uuid in issue_updates['closed']: issue_updates['closed'].remove(existing_uuid) except MultipleMatches as e: runlog.add_output('Multiple matches: %s' % unicode(e)) except NotFound: issue_updates['new'].append(dict(issue)) # Add new issues runlog.add_output("Adding %s tasks" % len(issue_updates['new'])) for issue in issue_updates['new']: runlog.add_output( "Adding task %s" % issue['description'].encode("utf-8"), ) try: tw.task_add(**issue) except TaskwarriorError as e: runlog.add_output( "Unable to add task: %s" % e.stderr ) runlog.add_output( "Updating %s tasks" % len(issue_updates['changed']) ) for issue in issue_updates['changed']: changes = '; '.join([ '{field}: {f} -> {t}'.format( field=field, f=repr(ch[0]), t=repr(ch[1]) ) for field, ch in issue.get_changes(keep=True).items() ]) runlog.add_output( "Updating task %s, %s; %s" % ( unicode(issue['uuid']).encode("utf-8"), issue['description'].encode("utf-8"), changes, ) ) try: tw.task_update(issue) except TaskwarriorError as e: runlog.add_output( "Unable to modify task: %s" % e.stderr ) runlog.add_output("Closing %s tasks" % len(issue_updates['closed'])) for issue in issue_updates['closed']: _, task_info = tw.get_task(uuid=issue) runlog.add_output( "Completing task %s %s" % ( issue, task_info.get('description', '').encode('utf-8'), ) ) try: tw.task_done(uuid=issue) except TaskwarriorError as e: runlog.add_output( "Unable to close task: %s" % e.stderr )
def assertMerged(self, local, remote, **kwargs): db.merge_left('annotations', local, remote, **kwargs) self.assertEqual(local, remote)
def test_rough_equality_hamming_true(self): """ When hamming=True, rough equivalents are not duplicated. """ remote = {'annotations': ['\n testing \n']} db.merge_left('annotations', self.issue_dict, remote, hamming=True) self.assertEqual(len(self.issue_dict['annotations']), 1)
def synchronize(runlog, issue_generator, conf, main_section): store = runlog.config.store 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(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) static_fields = ['priority'] if conf.has_option(main_section, 'static_fields'): static_fields = conf.get(main_section, 'static_fields').split(',') all_config_overrides = copy.deepcopy(uda_list) all_config_overrides['uda'].update( settings.TASKWARRIOR_CONFIG_OVERRIDES.get('uda', {})) tw = TaskwarriorClient( store.taskrc.path, config_overrides=all_config_overrides, ) legacy_matching = False issue_updates = { 'new': [], 'existing': [], 'changed': [], 'closed': get_managed_task_uuids(tw, key_list, legacy_matching), } for issue in issue_generator: if isinstance(issue, tuple) and issue[0] == ABORT_PROCESSING: runlog.add_output(str(issue[1])) raise RuntimeError(issue[1]) try: existing_uuid = find_local_uuid(tw, key_list, issue, legacy_matching=legacy_matching) issue_dict = dict(issue) _, task = tw.get_task(uuid=existing_uuid) # Drop static fields from the upstream issue. We don't want to # overwrite local changes to fields we declare static. for field in static_fields: del issue_dict[field] # Merge annotations & tags from online into our task object merge_left('annotations', task, issue_dict, hamming=True) merge_left('tags', task, issue_dict) issue_dict.pop('annotations', None) issue_dict.pop('tags', None) task.update(issue_dict) if task.get_changes(keep=True): issue_updates['changed'].append(task) else: issue_updates['existing'].append(task) if existing_uuid in issue_updates['closed']: issue_updates['closed'].remove(existing_uuid) except MultipleMatches as e: runlog.add_output('Multiple matches: %s' % unicode(e)) except NotFound: issue_updates['new'].append(dict(issue)) # Add new issues runlog.add_output("Adding %s tasks" % len(issue_updates['new'])) for issue in issue_updates['new']: runlog.add_output( "Adding task %s" % issue['description'].encode("utf-8"), ) try: tw.task_add(**issue) except TaskwarriorError as e: runlog.add_output("Unable to add task: %s" % e.stderr) runlog.add_output("Updating %s tasks" % len(issue_updates['changed'])) for issue in issue_updates['changed']: changes = '; '.join([ '{field}: {f} -> {t}'.format(field=field, f=repr(ch[0]), t=repr(ch[1])) for field, ch in issue.get_changes(keep=True).items() ]) runlog.add_output("Updating task %s, %s; %s" % ( unicode(issue['uuid']).encode("utf-8"), issue['description'].encode("utf-8"), changes, )) try: tw.task_update(issue) except TaskwarriorError as e: runlog.add_output("Unable to modify task: %s" % e.stderr) runlog.add_output("Closing %s tasks" % len(issue_updates['closed'])) for issue in issue_updates['closed']: _, task_info = tw.get_task(uuid=issue) runlog.add_output("Completing task %s %s" % ( issue, task_info.get('description', '').encode('utf-8'), )) try: tw.task_done(uuid=issue) except TaskwarriorError as e: runlog.add_output("Unable to close task: %s" % e.stderr)
def test_merge_left_with_taskw(self): task = taskw.task.Task({}) merge_left('annotations', task, self.issue_dict) self.assertEquals(task, self.issue_dict)
def test_merge_left_with_dict(self): task = {} merge_left('annotations', task, self.issue_dict) self.assertEquals(task, self.issue_dict)