Overhaul labelling functionality now working on project level. Next: debug section and parentless tasks level.

pull/30/head
Hoffelhas 2023-01-08 14:58:49 +01:00
parent aa274d5132
commit 86eb720f50
1 changed files with 101 additions and 94 deletions

View File

@ -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-<NUM><d or w>"', 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(