TASKLIB(1) tasklib TASKLIB(1) (NAME) tasklib - tasklib tasklib taskwarrior API queryset ORM Django . Python 3.5 taskwarrior 2.4.x . taskwarrior . (REQUIREMENTS) o taskwarrior v2.4.x . (INSTALLATION) pip ( ): pip install tasklib github: git clone https://github.com/robgolding/tasklib.git cd tasklib python setup.py install (INITIALIZATION) TaskWarrior data_location ( ) . create=False . taskwarrior : >>> tw = TaskWarrior(data_location='~/.task', create=True) TaskWarrior .taskrc ( UDA task ). .taskrc taskrc_location=~/some/different/path ..SH " (CREATING TASKS)" Task : >>> new_task = Task(tw, description="throw out the trash") .save() TaskWarrior ( Django): >>> new_task.save() Task : >>> complex_task = Task(tw, description="finally fix the shower", due=datetime(2015,2,14,8,0,0), priority='H') : >>> complex_task = Task(tw) >>> complex_task['description'] = "finally fix the shower" >>> complex_task['due'] = datetime(2015,2,14,8,0,0) >>> complex_task['priority'] = 'H' (MODIFYING TASK) Task : >>> homework = tw.tasks.get(tags=['chores']) >>> homework['project'] = 'Home' save() TaskWarrior : >>> homework.save() . << >> . (TASK ATTRIBUTES) (index) : >>> task = tw.tasks.pending().get(tags__contain='work') # There is only one pending task with 'work' tag >>> task['description'] 'Upgrade Ubuntu Server' >>> task['id'] 15 >>> task['due'] datetime.datetime(2015, 2, 5, 0, 0, tzinfo=) >>> task['tags'] ['work', 'servers'] (deserialize) : o due wait scheduled until entry: datetime o annotations: TaskAnnotation o tags: o depends: Task (serialize) ..SH " (TASK PROPERTIES)" Tasklib Task : >>> t.save() >>> t.saved True >>> t.pending True >>> t.active False >>> t.start() >>> t.active True >>> t.done() >>> t.completed True >>> t.pending False >>> t.delete() >>> t.deleted True (OPERATIONS ON TASKS) save() : >>> task = tw.tasks.pending().get(tags__contain='work') >>> task['due'] = datetime(year=2014, month=1, day=5) >>> task.save() done() : >>> task = tw.tasks.pending().get(tags__contain='work') >>> task.done() >>> len(tw.tasks.pending().filter(tags__contain='work')) 0 delete() : >>> task = tw.tasks.get(description="task added by mistake") >>> task.delete() TaskWarrior refresh() . : >>> task = Task(tw, description="learn to cook") >>> task.save() >>> task['id'] 5 >>> task['tags'] [] TaskWarrior : $ task 5 modify +someday Task 5 modified. python: >>> task['tags'] [] >>> task.refresh() >>> task['tags'] ['someday'] . start() stop() : >>> task.start() >>> task['start'] datetime.datetime(2015, 7, 16, 18, 48, 28, tzinfo=) >>> task.stop() >>> task['start'] >>> task.done() >>> task['end'] datetime.datetime(2015, 7, 16, 18, 49, 2, tzinfo=) tw.tasks TaskQuerySet API Django QuerySet . ( ): >>> tw.tasks.all() ['First task', 'Completed task', 'Deleted task', ...] (FILTERING) : >>> tw.tasks.filter(status='pending', tags__contains=['work']) ['Upgrade Ubuntu Server'] task (__ ) : $ task status:pending tags.contain=work : >>> tw.tasks.filter('status:pending +work') ['Upgrade Ubuntu Server'] TaskWarrior . : >>> tw.tasks.filter('+BLOCKING', project='Home') # Gets all blocking tasks in project Home ['Fix the toilette'] tasklib . : >>> tw.tasks.filter(tags=['BLOCKING']) >>> [] . (pending) : >>> tw.tasks.pending().filter(tags__contain='work') ['Upgrade Ubuntu Server'] >>> len(tw.tasks.completed()) 227 get() TaskQuerySet : >>> tw.tasks.get(tags__contain='work')['status'] 'pending' >>> tw.tasks.get(status='completed', tags__contains='work') # Status of only task with the work tag is pending, so this should fail Traceback (most recent call last): File "", line 1, in File "tasklib/task.py", line 224, in get 'Lookup parameters were {0}'.format(kwargs)) tasklib.task.DoesNotExist: Task matching query does not exist. Lookup parameters were {'status': 'completed', 'tags__contains': ['work']} >>> tw.tasks.get(status='pending') Traceback (most recent call last): File "", line 1, in File "tasklib/task.py", line 227, in get 'Lookup parameters were {1}'.format(num, kwargs)) ValueError: get() returned more than one Task -- it returned 23! Lookup parameters were {'status': 'pending'} TaskQuerySet (stack) : >>> home_tasks = tw.tasks.filter(project='Wife') >>> home_tasks.filter(due__before=datetime(2015,2,14,14,14,14)) # What I have to do until Valentine's day ['Prepare surprise birthday party'] Task UUID : >>> task1 = Task(tw, description="Pet the dog") >>> task1.save() >>> task2 = tw.tasks.get(description="Pet the dog") >>> task1 == task2 True Python : >>> task1 = Task(tw, description="Pet the cat") >>> task2 = Task(tw, description="Pet the cat") >>> task1 == task2 False >>> task3 = task1 >>> task3 == task1 True (ACCESSING ORIGINAL VALUES) Task original : >>> t = Task(tw, description="tidy up") >>> t.save() >>> t['description'] = "tidy up the kitchen and bathroom" >>> t['description'] "tidy up the kitchen and bathroom" >>> t.original['description'] "tidy up" : >>> t.save() >>> t.original['description'] "tidy up the kitchen and bathroom" (DEALING WITH DATES AND TIME) (timestamp-like) datetime (timezone-aware) . Tasklib zoneinfo Olsen . (Daylight Saving Time) . ( ): >>> myzone = zoneinfo.ZoneInfo('Europe/Berlin') >>> midnight = datetime(2015,2,2,0,0,0,tzinfo=myzone) >>> tw.tasks.filter(due__before=midnight) . TaskWarrior tzlocal . 'Europe/Berlin' : >>> tw.tasks.filter(due__before=datetime(2015,2,2,0,0,0)) : >>> tw.tasks.filter(due__before=date(2015,2,2)) 00:00:00 . Task datetime datetime (naive) : >>> t = Task(tw, description="Buy new shoes", due=date(2015,2,5)) >>> t['due'] datetime.datetime(2015, 2, 5, 0, 0, tzinfo=) >>> t['due'] = date(2015,2,6,15,15,15) >>> t['due'] datetime.datetime(2015, 2, 6, 15, 15, 15, tzinfo=) datetime (timezone-aware) (timezone-naive) : >>> from datetime import datetime >>> now = datetime.now() >>> t = Task(tw, description="take out the trash now") >>> t['due'] = now >>> now datetime.datetime(2015, 2, 1, 19, 44, 4, 770001) >>> t['due'] datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=) >>> t['due'] == now Traceback (most recent call last): File "", line 1, in TypeError: can't compare offset-naive and offset-aware datetimes datetime (localize) : >>> from datetime import datetime >>> now = datetime.now().astimezone() >>> t['due'] = now >>> now datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=) >>> t['due'] == now True datetime : >>> import zoneinfo >>> t['due'] datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=) >>> now.astimezone(zoneinfo.ZoneInfo('UTC')) datetime.datetime(2015, 2, 1, 18, 44, 4, 770001, tzinfo=) >>> t['due'] == now.astimezone(zoneinfo.ZoneInfo('UTC')) True : TaskWarrior >= 2.4.0 . 'task calc' . datetime TaskWarrior : $ task calc now + 1d 2015-07-17T21:17:54 (syntax) : >>> t['due'] = "now + 1d" >>> t['due'] datetime.datetime(2015, 7, 17, 21, 19, 31, tzinfo=) TaskWarrior datetime . : o o 'task calc' datetime . (WORKING WITH ANNOTATIONS) tasklib TaskAnnotation . Task . >>> annotated_task = tw.tasks.get(description='Annotated task') >>> annotated_task['annotations'] [Yeah, I am annotated!] entry description : >>> annotation = annotated_task['annotations'][0] >>> annotation['entry'] datetime.datetime(2015, 1, 3, 21, 13, 55, tzinfo=) >>> annotation['description'] u'Yeah, I am annotated!' Task add_annotation() : >>> task = Task(tw, description="new task") >>> task.add_annotation("we can annotate any task") Traceback (most recent call last): File "", line 1, in File "build/bdist.linux-x86_64/egg/tasklib/task.py", line 355, in add_annotation tasklib.task.NotSaved: Task needs to be saved to add annotation Task : >>> task.save() >>> task.add_annotation("we can annotate saved tasks") >>> task['annotations'] [we can annotate saved tasks] remove_annotation() : >>> task.remove_annotation("we can annotate saved tasks") TaskAnnotation : >>> task.remove_annotation(task['annotations'][0]) (RUNNING CUSTOM COMMANDS) execute_command() TaskWarrior : >>> tw = TaskWarrior() >>> tw.execute_command(['log', 'Finish high school.']) [u'Logged task.'] config_override : >>> tw.execute_command(['3', 'done'], config_override={'gc': 'off'}) # Will mark 3 as completed and it will retain its ID return_all=True (stdout, sterr, return_code) allow_failure=False task tasklib : >>> tw.execute_command(['invalidcommand'], allow_failure=False, return_all=True) ([u''], [u'Using alternate .taskrc file /home/tbabej/.taskrc', u"[task next rc:/home/tbabej/.taskrc rc.recurrence.confirmation=no rc.json.array=off rc.confirmation=no rc.bulk=0 rc.dependency.confirmation=no description ~ 'invalidcommand']", u'Configuration override rc.recurrence.confirmation:no', u'Configuration override rc.json.array:off', u'Configuration override rc.confirmation:no', u'Configuration override rc.bulk:0', u'Configuration override rc.dependency.confirmation:no', u'No matches.', u'There are local changes. Sync required.'], 1) TaskWarrior .taskrc . (overrides) task overrides TaskWarrior : >>> tw.overrides {'confirmation': 'no', 'data.location': '/home/tbabej/.task'} : >>> tw.overrides.update({'hooks': 'off'}) # tasklib will not trigger hooks (CREATING HOOK SCRIPTS) 2.4.0 TaskWarrior (hook scripts) . tasklib . tasklib : #!/usr/bin/python from tasklib.task import Task task = Task.from_input() # ... print task.export_data() "H" : #!/usr/bin/python from tasklib.task import Task task = Task.from_input() if "!!!" in task['description']: task['priority'] = "H" print task.export_data() tasklib on-modify on-add . on-add on-modify ! on-add on-modify (symlink) . (boilerplate) . on-modify tasklib Task . ( ) original : >>> t = Task.from_input() >>> t['description'] "Modified description" >>> t.original['description'] "Original description" TaskWarrior .taskrc UDA config TaskWarrior . UDA estimate .taskrc : uda.estimate.type = numeric UDA estimate : >>> tw = TaskWarrior() >>> task = Task(tw, description="Long task", estimate=1000) >>> task.save() >>> task['id'] 1 UDA TaskWarrior : $ task 1 export {"id":1,"description":"Long task","estimate":1000, ...} UDA TaskFilter : >>> tw.tasks.filter(estimate=1000) Long task (SYNCING) .taskrc : >>> tw = TaskWarrior() >>> tw.execute_command(['sync']) / TaskWarrior . config sync execute_command() : >>> tw = TaskWarrior() >>> sync_config = { ... 'taskd.certificate': '/home/tbabej/.task/tbabej.cert.pem', ... 'taskd.credentials': 'Public/tbabej/34af54de-3cb2-4d3d-82be-33ddb8fd3e66', ... 'taskd.server': 'task.server.com:53589', ... 'taskd.ca': '/home/tbabej/.task/ca.cert.pem', ... 'taskd.trust': 'ignore hostname'} >>> tw.config.update(sync_config) >>> tw.execute_command(['sync']) Rob Golding (COPYRIGHT) 2014 - 2021, Rob Golding & Gothenburg Bit Factory 2.5.1 December 14, 2025 TASKLIB(1)