mirror of https://github.com/Hoffelhas/autodoist
Overhaul labelling functionality now working on project level. Next: debug section and parentless tasks level.
parent
aa274d5132
commit
86eb720f50
195
autodoist.py
195
autodoist.py
|
@ -15,6 +15,7 @@ from datetime import datetime, timedelta
|
||||||
import time
|
import time
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
# Connect to SQLite database
|
# Connect to SQLite database
|
||||||
|
|
||||||
|
@ -442,36 +443,38 @@ def get_all_data(self, api):
|
||||||
# Assign current type based on settings
|
# Assign current type based on settings
|
||||||
|
|
||||||
|
|
||||||
def check_name(args, name):
|
def check_name(args, string, num):
|
||||||
len_suffix = [len(args.pp_suffix), len(args.ss_suffix),
|
|
||||||
len(args.ps_suffix), len(args.sp_suffix)]
|
|
||||||
|
|
||||||
if name == None:
|
try:
|
||||||
current_type = None
|
# Find inbox or none section as exceptions
|
||||||
pass
|
if string == None:
|
||||||
elif name == 'Inbox':
|
current_type = None
|
||||||
current_type = args.inbox
|
pass
|
||||||
elif name[-len_suffix[0]:] == args.pp_suffix:
|
elif string == 'Inbox':
|
||||||
current_type = 'parallel'
|
current_type = args.inbox
|
||||||
elif name[-len_suffix[1]:] == args.ss_suffix:
|
pass
|
||||||
current_type = 'sequential'
|
else:
|
||||||
elif name[-len_suffix[2]:] == args.ps_suffix:
|
# Find any = or - symbol at the end of the string. Look at last 3 for projects, 2 for sections, and 1 for tasks
|
||||||
current_type = 'p-s'
|
regex = '[%s%s]{1,%s}$' % (args.s_suffix, args.p_suffix, str(num))
|
||||||
elif name[-len_suffix[3]:] == args.sp_suffix:
|
re_ind = re.search(regex, string)
|
||||||
current_type = 's-p'
|
suffix = re_ind[0]
|
||||||
# TODO: Remove below workarounds if standard notation is changing. Just messy and no longer needed.
|
|
||||||
# # Workaround for section names, which don't allow '/' symbol.
|
# Somebody put fewer characters than intended. Take last character and apply for every missing one.
|
||||||
# elif args.ps_suffix == '/-' and name[-2:] == '_-':
|
if len(suffix) < num:
|
||||||
# current_type = 'p-s'
|
suffix += suffix[-1] * (num - len(suffix))
|
||||||
# # Workaround for section names, which don't allow '/' symbol.
|
|
||||||
# elif args.sp_suffix == '-/' and name[-2:] == '-_':
|
current_type = ''
|
||||||
# current_type = 's-p'
|
for s in suffix:
|
||||||
# # Workaround for section names, which don't allow '/' symbol.
|
if s == args.s_suffix:
|
||||||
# elif args.pp_suffix == '//' and name[-1:] == '_':
|
current_type += 's'
|
||||||
# current_type = 'parallel'
|
elif s == args.p_suffix:
|
||||||
else:
|
current_type += 'p'
|
||||||
|
except:
|
||||||
|
logging.debug("String {} not recognised.".format(string))
|
||||||
current_type = None
|
current_type = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return current_type
|
return current_type
|
||||||
|
|
||||||
# Scan the end of a name to find what type it is
|
# 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))
|
# logging.debug('No defined project_type: %s' % str(e))
|
||||||
old_type = None
|
old_type = None
|
||||||
|
|
||||||
# model_name = model.name.strip() % TODO: Is this still needed?
|
if isinstance(model, Task):
|
||||||
|
current_type = check_name(args, model.content, 1) # Tasks
|
||||||
try:
|
elif isinstance(model, Section):
|
||||||
current_type = check_name(args, model.content) # Tasks
|
current_type = check_name(args, model.name, 2) # Sections
|
||||||
except:
|
elif isinstance(model, Project):
|
||||||
current_type = check_name(args, model.name) # Project and sections
|
current_type = check_name(args, model.name, 3) # Projects
|
||||||
|
|
||||||
# Check if project type changed with respect to previous run
|
# Check if project type changed with respect to previous run
|
||||||
if old_type == current_type:
|
if old_type == current_type:
|
||||||
|
@ -817,20 +820,6 @@ def find_and_clean_all_children(task_ids, task, section_tasks):
|
||||||
|
|
||||||
return task_ids
|
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
|
# Contains all main autodoist functionalities
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,6 +830,7 @@ def autodoist_magic(args, api, connection):
|
||||||
overview_task_labels = {}
|
overview_task_labels = {}
|
||||||
next_action_label = args.label
|
next_action_label = args.label
|
||||||
regen_labels_id = args.regen_label_names
|
regen_labels_id = args.regen_label_names
|
||||||
|
first_found = [False, False, False]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
projects = api.get_projects()
|
projects = api.get_projects()
|
||||||
|
@ -856,9 +846,6 @@ def autodoist_magic(args, api, connection):
|
||||||
# Check db existance
|
# Check db existance
|
||||||
db_check_existance(connection, project)
|
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
|
# Check if we need to (un)header entire project
|
||||||
header_all_in_p, unheader_all_in_p = check_header(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:
|
if next_action_label is not None:
|
||||||
project_type, project_type_changed = get_project_type(
|
project_type, project_type_changed = get_project_type(
|
||||||
args, connection, project)
|
args, connection, project)
|
||||||
|
else:
|
||||||
|
project_type = None
|
||||||
|
project_type_changed = 0
|
||||||
|
|
||||||
# Get all tasks for the project
|
# Get all tasks for the project
|
||||||
try:
|
try:
|
||||||
|
@ -904,6 +894,9 @@ def autodoist_magic(args, api, connection):
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(error)
|
print(error)
|
||||||
|
|
||||||
|
# Reset
|
||||||
|
first_found[0] = False
|
||||||
|
|
||||||
for section in sections:
|
for section in sections:
|
||||||
|
|
||||||
# Check db existance
|
# Check db existance
|
||||||
|
@ -912,12 +905,13 @@ def autodoist_magic(args, api, connection):
|
||||||
# Check if we need to (un)header entire secion
|
# Check if we need to (un)header entire secion
|
||||||
header_all_in_s, unheader_all_in_s = check_header(section)
|
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
|
# Get section type
|
||||||
section_type, section_type_changed = get_section_type(
|
if next_action_label:
|
||||||
args, connection, section)
|
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
|
# Get all tasks for the section
|
||||||
section_tasks = [x for x in project_tasks if x.section_id
|
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)
|
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, 'task_type', None)
|
||||||
db_update_value(connection, task, 'parent_type', None)
|
db_update_value(connection, task, 'parent_type', None)
|
||||||
|
|
||||||
|
# Reset
|
||||||
|
first_found[1] = False
|
||||||
|
|
||||||
# For all tasks in this section
|
# For all tasks in this section
|
||||||
for task in section_tasks:
|
for task in section_tasks:
|
||||||
|
@ -951,8 +948,6 @@ def autodoist_magic(args, api, connection):
|
||||||
# Check db existance
|
# Check db existance
|
||||||
db_check_existance(connection, task)
|
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
|
# Determine which child_tasks exist, both all and the ones that have not been checked yet
|
||||||
non_completed_tasks = list(
|
non_completed_tasks = list(
|
||||||
|
@ -1017,45 +1012,48 @@ def autodoist_magic(args, api, connection):
|
||||||
hierarchy_types = [task_type,
|
hierarchy_types = [task_type,
|
||||||
section_type, project_type]
|
section_type, project_type]
|
||||||
hierarchy_boolean = [type(x) != type(None)
|
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 it is a parentless task, set task type based on hierarchy
|
||||||
if task.parent_id == 0:
|
if task.parent_id == 0:
|
||||||
if hierarchy_boolean[0]:
|
if not True in hierarchy_boolean:
|
||||||
# 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:
|
|
||||||
# Parentless task has no type, so skip any children.
|
# Parentless task has no type, so skip any children.
|
||||||
continue
|
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
|
# for ind, char in enumerate(dominant_type):
|
||||||
if first_found_tasks == False and hierarchy_boolean[0]:
|
|
||||||
first_found_tasks = True
|
if dominant_type[0] == 's':
|
||||||
if first_found_section == False and hierarchy_boolean[1]:
|
if not first_found[0]:
|
||||||
first_found_section = True
|
|
||||||
if first_found_project is False and hierarchy_boolean[2]:
|
if dominant_type[1] == 's':
|
||||||
first_found_project = True
|
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 a parentless or sub-task which has children
|
||||||
if len(child_tasks) > 0:
|
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 it is a sub-task with no own type, inherit the parent task type instead
|
||||||
if task.parent_id != 0 and task_type == None:
|
if task.parent_id != 0 and task_type == None:
|
||||||
# dominant_type = task.parent_type # TODO: METADATA
|
# 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:
|
if task.parent_id != 0 and dominant_type == None:
|
||||||
dominant_type = task_type
|
dominant_type = task_type
|
||||||
|
|
||||||
|
# Only last character is relevant
|
||||||
|
dominant_type = dominant_type[-1]
|
||||||
|
|
||||||
# Process sequential tagged tasks (task_type can overrule project_type)
|
# 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:
|
for child_task in child_tasks:
|
||||||
|
|
||||||
# Ignore headered children
|
# Ignore headered children
|
||||||
|
@ -1090,7 +1092,8 @@ def autodoist_magic(args, api, connection):
|
||||||
# child_task, next_action_label, overview_task_ids, overview_task_labels)
|
# child_task, next_action_label, overview_task_ids, overview_task_labels)
|
||||||
|
|
||||||
# Process parallel tagged tasks or untagged parents
|
# 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(
|
remove_label(
|
||||||
task, next_action_label, overview_task_ids, overview_task_labels)
|
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.
|
# 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)
|
# 'Wrong start-date format for task: %s. Please use "start=due-<NUM><d or w>"', task.content)
|
||||||
# continue
|
# 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 all ids and corresponding labels that need to be modified
|
||||||
return overview_task_ids, overview_task_labels
|
return overview_task_ids, overview_task_labels
|
||||||
|
|
||||||
|
@ -1226,13 +1237,9 @@ def main():
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-d', '--delay', help='specify the delay in seconds between syncs (default 5).', default=5, type=int)
|
'-d', '--delay', help='specify the delay in seconds between syncs (default 5).', default=5, type=int)
|
||||||
parser.add_argument(
|
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(
|
parser.add_argument(
|
||||||
'-ss', '--ss_suffix', help='change suffix for sequential-sequential labeling (default "--").', default='--')
|
'-s', '--s_suffix', help='change suffix for 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='-=')
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-df', '--dateformat', help='strptime() format of starting date (default "%%d-%%m-%%Y").', default='%d-%m-%Y')
|
'-df', '--dateformat', help='strptime() format of starting date (default "%%d-%%m-%%Y").', default='%d-%m-%Y')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
Loading…
Reference in New Issue