From 86eb720f505ec5c7d31643d64c3cd6962f9edc31 Mon Sep 17 00:00:00 2001 From: Hoffelhas Date: Sun, 8 Jan 2023 14:58:49 +0100 Subject: [PATCH] Overhaul labelling functionality now working on project level. Next: debug section and parentless tasks level. --- autodoist.py | 195 ++++++++++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 94 deletions(-) diff --git a/autodoist.py b/autodoist.py index 78b0514..fc23a99 100644 --- a/autodoist.py +++ b/autodoist.py @@ -15,6 +15,7 @@ from datetime import datetime, timedelta import time import sqlite3 import os +import re # Connect to SQLite database @@ -442,36 +443,38 @@ def get_all_data(self, api): # Assign current type based on settings -def check_name(args, name): - len_suffix = [len(args.pp_suffix), len(args.ss_suffix), - len(args.ps_suffix), len(args.sp_suffix)] +def check_name(args, string, num): - if name == None: - current_type = None - pass - elif name == 'Inbox': - current_type = args.inbox - elif name[-len_suffix[0]:] == args.pp_suffix: - current_type = 'parallel' - elif name[-len_suffix[1]:] == args.ss_suffix: - current_type = 'sequential' - elif name[-len_suffix[2]:] == args.ps_suffix: - current_type = 'p-s' - elif name[-len_suffix[3]:] == args.sp_suffix: - current_type = 's-p' - # TODO: Remove below workarounds if standard notation is changing. Just messy and no longer needed. - # # Workaround for section names, which don't allow '/' symbol. - # elif args.ps_suffix == '/-' and name[-2:] == '_-': - # current_type = 'p-s' - # # Workaround for section names, which don't allow '/' symbol. - # elif args.sp_suffix == '-/' and name[-2:] == '-_': - # current_type = 's-p' - # # Workaround for section names, which don't allow '/' symbol. - # elif args.pp_suffix == '//' and name[-1:] == '_': - # current_type = 'parallel' - else: + try: + # Find inbox or none section as exceptions + if string == None: + current_type = None + pass + elif string == 'Inbox': + current_type = args.inbox + pass + else: + # Find any = or - symbol at the end of the string. Look at last 3 for projects, 2 for sections, and 1 for tasks + regex = '[%s%s]{1,%s}$' % (args.s_suffix, args.p_suffix, str(num)) + re_ind = re.search(regex, string) + suffix = re_ind[0] + + # Somebody put fewer characters than intended. Take last character and apply for every missing one. + if len(suffix) < num: + suffix += suffix[-1] * (num - len(suffix)) + + current_type = '' + for s in suffix: + if s == args.s_suffix: + current_type += 's' + elif s == args.p_suffix: + current_type += 'p' + except: + logging.debug("String {} not recognised.".format(string)) current_type = None + + return current_type # Scan the end of a name to find what type it is @@ -490,12 +493,12 @@ def get_type(args, connection, model, key): # logging.debug('No defined project_type: %s' % str(e)) old_type = None - # model_name = model.name.strip() % TODO: Is this still needed? - - try: - current_type = check_name(args, model.content) # Tasks - except: - current_type = check_name(args, model.name) # Project and sections + if isinstance(model, Task): + current_type = check_name(args, model.content, 1) # Tasks + elif isinstance(model, Section): + current_type = check_name(args, model.name, 2) # Sections + elif isinstance(model, Project): + current_type = check_name(args, model.name, 3) # Projects # Check if project type changed with respect to previous run if old_type == current_type: @@ -817,20 +820,6 @@ def find_and_clean_all_children(task_ids, task, section_tasks): return task_ids -# Logic to pass label data - -def label_according_to_type(hierarchy_type, first_found, connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels): - - if hierarchy_type == 'sequential' or hierarchy_type == 's-p': - if not first_found: - add_label( - connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) - first_found = True - elif hierarchy_type == 'parallel' or hierarchy_type == 'p-s': - add_label( - connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) - - # Contains all main autodoist functionalities @@ -841,6 +830,7 @@ def autodoist_magic(args, api, connection): overview_task_labels = {} next_action_label = args.label regen_labels_id = args.regen_label_names + first_found = [False, False, False] try: projects = api.get_projects() @@ -856,9 +846,6 @@ def autodoist_magic(args, api, connection): # Check db existance db_check_existance(connection, project) - # To determine if a sequential task was found - first_found_project = False - # Check if we need to (un)header entire project header_all_in_p, unheader_all_in_p = check_header(project) @@ -866,6 +853,9 @@ def autodoist_magic(args, api, connection): if next_action_label is not None: project_type, project_type_changed = get_project_type( args, connection, project) + else: + project_type = None + project_type_changed = 0 # Get all tasks for the project try: @@ -904,6 +894,9 @@ def autodoist_magic(args, api, connection): except Exception as error: print(error) + # Reset + first_found[0] = False + for section in sections: # Check db existance @@ -912,12 +905,13 @@ def autodoist_magic(args, api, connection): # Check if we need to (un)header entire secion header_all_in_s, unheader_all_in_s = check_header(section) - # To determine if a sequential task was found - first_found_section = False - # Get section type - section_type, section_type_changed = get_section_type( - args, connection, section) + if next_action_label: + section_type, section_type_changed = get_section_type( + args, connection, section) + else: + section_type = None + section_type_changed = 0 # Get all tasks for the section section_tasks = [x for x in project_tasks if x.section_id @@ -941,6 +935,9 @@ def autodoist_magic(args, api, connection): remove_label(task, next_action_label, overview_task_ids, overview_task_labels) db_update_value(connection, task, 'task_type', None) db_update_value(connection, task, 'parent_type', None) + + # Reset + first_found[1] = False # For all tasks in this section for task in section_tasks: @@ -951,8 +948,6 @@ def autodoist_magic(args, api, connection): # Check db existance db_check_existance(connection, task) - # To determine if a sequential task was found - first_found_tasks = False # Determine which child_tasks exist, both all and the ones that have not been checked yet non_completed_tasks = list( @@ -1017,45 +1012,48 @@ def autodoist_magic(args, api, connection): hierarchy_types = [task_type, section_type, project_type] hierarchy_boolean = [type(x) != type(None) - for x in hierarchy_types] + for x in hierarchy_types] # If it is a parentless task, set task type based on hierarchy if task.parent_id == 0: - if hierarchy_boolean[0]: - # Inherit task type - dominant_type = task_type - label_according_to_type(task_type , first_found_tasks, connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) - - elif hierarchy_boolean[1]: - # Inherit section type - dominant_type = section_type - label_according_to_type(section_type, first_found_section, connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) - - elif hierarchy_boolean[2]: - # Inherit project type - dominant_type = project_type - label_according_to_type(project_type, first_found_project, connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) - - else: + if not True in hierarchy_boolean: # Parentless task has no type, so skip any children. continue + else: + if hierarchy_boolean[1]: + # Inherit task type + dominant_type = task_type + elif hierarchy_boolean[1]: + # Inherit section type + dominant_type = section_type + elif hierarchy_boolean[2]: + # Inherit project type + dominant_type = project_type - # Mark other conditions too - if first_found_tasks == False and hierarchy_boolean[0]: - first_found_tasks = True - if first_found_section == False and hierarchy_boolean[1]: - first_found_section = True - if first_found_project is False and hierarchy_boolean[2]: - first_found_project = True + # for ind, char in enumerate(dominant_type): + + if dominant_type[0] == 's': + if not first_found[0]: + + if dominant_type[1] == 's': + if not first_found[1]: + add_label(connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) + + elif dominant_type[1] == 'p': + add_label(connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) + + elif dominant_type[0] == 'p': + + if dominant_type[1] == 's': + if not first_found[1]: + add_label(connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) + + elif dominant_type[1] == 'p': + add_label(connection, task, dominant_type, next_action_label, overview_task_ids, overview_task_labels) # If a parentless or sub-task which has children if len(child_tasks) > 0: - # # Check if task state has changed, if so clean children for good measure - # if task_type_changed == 1: - # [remove_label(child_task, next_action_label, overview_task_ids, overview_task_labels) - # for child_task in child_tasks] - # If it is a sub-task with no own type, inherit the parent task type instead if task.parent_id != 0 and task_type == None: # dominant_type = task.parent_type # TODO: METADATA @@ -1066,8 +1064,12 @@ def autodoist_magic(args, api, connection): if task.parent_id != 0 and dominant_type == None: dominant_type = task_type + # Only last character is relevant + dominant_type = dominant_type[-1] + # Process sequential tagged tasks (task_type can overrule project_type) - if dominant_type == 'sequential' or dominant_type == 'p-s': + if dominant_type == 's': + for child_task in child_tasks: # Ignore headered children @@ -1090,7 +1092,8 @@ def autodoist_magic(args, api, connection): # child_task, next_action_label, overview_task_ids, overview_task_labels) # Process parallel tagged tasks or untagged parents - elif dominant_type == 'parallel' or (dominant_type == 's-p' and next_action_label in task.labels): + # elif dominant_type == 'parallel' or (dominant_type == 's-p' and next_action_label in task.labels): + elif dominant_type == 'p' and next_action_label in task.labels: remove_label( task, next_action_label, overview_task_ids, overview_task_labels) # db_update_value(connection, task, 'task_type', None) #TODO: integrate in remove_label funcionality, else a lot of duplicates. @@ -1201,6 +1204,14 @@ def autodoist_magic(args, api, connection): # 'Wrong start-date format for task: %s. Please use "start=due-"', task.content) # continue + # Mark first found task in section + if next_action_label is not None and first_found[1] == False: #TODO: is this always true? What about starred tasks? + first_found[1] = True + + # Mark first found section with tasks in project (to account for None section) + if next_action_label is not None and first_found[0] == False and section_tasks: #TODO: is this always true? What about starred tasks? + first_found[0] = True + # Return all ids and corresponding labels that need to be modified return overview_task_ids, overview_task_labels @@ -1226,13 +1237,9 @@ def main(): parser.add_argument( '-d', '--delay', help='specify the delay in seconds between syncs (default 5).', default=5, type=int) parser.add_argument( - '-pp', '--pp_suffix', help='change suffix for parallel-parallel labeling (default "==").', default='==') + '-p', '--p_suffix', help='change suffix for parallel labeling (default "=").', default='=') parser.add_argument( - '-ss', '--ss_suffix', help='change suffix for sequential-sequential labeling (default "--").', default='--') - parser.add_argument( - '-ps', '--ps_suffix', help='change suffix for parallel-sequential labeling (default "=-").', default='=-') - parser.add_argument( - '-sp', '--sp_suffix', help='change suffix for sequential-parallel labeling (default "-=").', default='-=') + '-s', '--s_suffix', help='change suffix for sequential labeling (default "-").', default='-') parser.add_argument( '-df', '--dateformat', help='strptime() format of starting date (default "%%d-%%m-%%Y").', default='%d-%m-%Y') parser.add_argument(