0
# Task Management
1
2
Comprehensive todo/task management functionality with support for due dates, completion tracking, priority management, and task hierarchies using CalDAV VTODO components.
3
4
## Capabilities
5
6
### Todo Class
7
8
Represents CalDAV todos/tasks (VTODO components) with specialized methods for task-specific operations including completion tracking and due date management.
9
10
```python { .api }
11
class Todo(CalendarObjectResource):
12
def get_due(self):
13
"""
14
Get todo due date/time.
15
16
Returns:
17
datetime or date: Todo due date/time, or None if not set
18
"""
19
20
def get_dtstart(self):
21
"""
22
Get todo start date/time.
23
24
Returns:
25
datetime or date: Todo start date/time, or None if not set
26
"""
27
28
def get_duration(self):
29
"""
30
Get todo duration.
31
32
Returns:
33
timedelta: Todo duration, or None if not set
34
"""
35
36
def set_due(self, due):
37
"""
38
Set todo due date/time.
39
40
Parameters:
41
- due: datetime or date, new due date/time
42
"""
43
44
def set_dtstart(self, dtstart):
45
"""
46
Set todo start date/time.
47
48
Parameters:
49
- dtstart: datetime or date, new start date/time
50
"""
51
52
def set_duration(self, duration):
53
"""
54
Set todo duration.
55
56
Parameters:
57
- duration: timedelta, task duration
58
"""
59
60
def complete(self, completion_timestamp=None, handle_rrule=True):
61
"""
62
Mark todo as completed.
63
64
Parameters:
65
- completion_timestamp: datetime, completion time (default: now)
66
- handle_rrule: bool, handle recurring todos by creating next occurrence
67
68
Returns:
69
Todo: Next occurrence if recurring, or None
70
"""
71
```
72
73
**Usage Examples:**
74
75
```python
76
import caldav
77
from datetime import datetime, timedelta, timezone
78
79
# Get existing todos
80
calendar = principal.calendars()[0]
81
todos = calendar.todos()
82
83
if todos:
84
todo = todos[0]
85
86
# Get todo information
87
summary = todo.icalendar_component.get('SUMMARY', 'No title')
88
due_date = todo.get_due()
89
start_date = todo.get_dtstart()
90
status = todo.icalendar_component.get('STATUS', 'No status')
91
92
print(f"Todo: {summary}")
93
print(f"Due: {due_date}")
94
print(f"Status: {status}")
95
96
# Modify todo timing
97
new_due = datetime(2025, 9, 30, 17, 0, tzinfo=timezone.utc)
98
todo.set_due(new_due)
99
todo.set_dtstart(datetime.now(timezone.utc))
100
101
# Mark as completed
102
if status != 'COMPLETED':
103
next_occurrence = todo.complete()
104
if next_occurrence:
105
print(f"Created next occurrence: {next_occurrence.id}")
106
else:
107
print("Todo marked as completed")
108
```
109
110
### Todo Creation
111
112
Create new todos with comprehensive VTODO support including all standard properties and task-specific features.
113
114
```python { .api }
115
# Todo creation through calendar.save_todo() - see calendar-management.md
116
# Additional todo-specific creation patterns:
117
118
def create_simple_todo(summary, due_date=None, priority=None, description=None):
119
"""
120
Helper function to create simple todo iCalendar data.
121
122
Parameters:
123
- summary: str, todo title/summary
124
- due_date: datetime, optional due date
125
- priority: int, priority level (1-9, 1=highest, 9=lowest)
126
- description: str, optional todo description
127
128
Returns:
129
str: iCalendar data for the todo
130
"""
131
```
132
133
**Usage Examples:**
134
135
```python
136
from datetime import datetime, timezone
137
import uuid
138
139
# Create a simple todo
140
def create_task(title, due_date=None, priority=5, description=None):
141
task_uid = f"{uuid.uuid4()}@example.com"
142
143
ical_data = f"""BEGIN:VCALENDAR
144
VERSION:2.0
145
PRODID:-//My Task App//My Task App//EN
146
BEGIN:VTODO
147
UID:{task_uid}
148
SUMMARY:{title}
149
STATUS:NEEDS-ACTION
150
PRIORITY:{priority}
151
"""
152
153
if due_date:
154
ical_data += f"DUE:{due_date.strftime('%Y%m%dT%H%M%SZ')}\n"
155
if description:
156
ical_data += f"DESCRIPTION:{description}\n"
157
158
ical_data += f"""DTSTAMP:{datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ')}
159
END:VTODO
160
END:VCALENDAR"""
161
162
return ical_data
163
164
# Create and save a todo
165
task_due = datetime(2025, 10, 1, 17, 0, tzinfo=timezone.utc)
166
task_ical = create_task(
167
title="Complete project documentation",
168
due_date=task_due,
169
priority=2, # High priority
170
description="Finish writing user guide and API documentation"
171
)
172
173
todo = calendar.save_todo(task_ical)
174
print(f"Created todo: {todo.id}")
175
176
# Create recurring todo
177
recurring_todo_ical = """BEGIN:VCALENDAR
178
VERSION:2.0
179
PRODID:-//My App//My App//EN
180
BEGIN:VTODO
181
UID:weekly-report@example.com
182
SUMMARY:Submit weekly status report
183
DESCRIPTION:Prepare and submit weekly project status report
184
DUE:20250919T170000Z
185
STATUS:NEEDS-ACTION
186
PRIORITY:3
187
RRULE:FREQ=WEEKLY;BYDAY=FR;COUNT=12
188
END:VTODO
189
END:VCALENDAR"""
190
191
recurring_todo = calendar.save_todo(recurring_todo_ical)
192
193
# Create todo with subtasks (using RELATED-TO property)
194
parent_todo_ical = """BEGIN:VCALENDAR
195
VERSION:2.0
196
PRODID:-//My App//My App//EN
197
BEGIN:VTODO
198
UID:project-launch@example.com
199
SUMMARY:Launch new product
200
DESCRIPTION:Complete all tasks required for product launch
201
DUE:20251215T170000Z
202
STATUS:NEEDS-ACTION
203
PRIORITY:1
204
END:VTODO
205
END:VCALENDAR"""
206
207
parent_todo = calendar.save_todo(parent_todo_ical)
208
209
# Create subtask
210
subtask_ical = f"""BEGIN:VCALENDAR
211
VERSION:2.0
212
PRODID:-//My App//My App//EN
213
BEGIN:VTODO
214
UID:marketing-materials@example.com
215
SUMMARY:Create marketing materials
216
DESCRIPTION:Design and create marketing collateral
217
DUE:20251201T170000Z
218
STATUS:NEEDS-ACTION
219
PRIORITY:2
220
RELATED-TO;RELTYPE=PARENT:{parent_todo.id}
221
END:VTODO
222
END:VCALENDAR"""
223
224
subtask = calendar.save_todo(subtask_ical)
225
```
226
227
### Todo Status Management
228
229
Comprehensive status tracking and workflow management for todos with support for different completion states.
230
231
```python { .api }
232
# Todo status values (accessed via icalendar_component['STATUS'])
233
TODO_STATUS = {
234
"NEEDS-ACTION": "Task needs to be completed",
235
"COMPLETED": "Task has been completed",
236
"IN-PROCESS": "Task is currently being worked on",
237
"CANCELLED": "Task has been cancelled"
238
}
239
240
# Todo priority levels (accessed via icalendar_component['PRIORITY'])
241
TODO_PRIORITY = {
242
0: "Undefined priority",
243
1: "Highest priority",
244
2: "High priority",
245
3: "High priority",
246
4: "Medium-high priority",
247
5: "Medium priority (default)",
248
6: "Medium-low priority",
249
7: "Low priority",
250
8: "Low priority",
251
9: "Lowest priority"
252
}
253
```
254
255
**Usage Examples:**
256
257
```python
258
# Manage todo status
259
todo = calendar.todo_by_uid("project-task@example.com")
260
if todo:
261
component = todo.icalendar_component
262
263
# Check current status
264
current_status = component.get('STATUS', 'NEEDS-ACTION')
265
print(f"Current status: {current_status}")
266
267
# Start working on the task
268
component['STATUS'] = 'IN-PROCESS'
269
component['PERCENT-COMPLETE'] = 25 # 25% complete
270
todo.save()
271
272
# Update progress
273
component['PERCENT-COMPLETE'] = 75
274
todo.save()
275
276
# Complete the task
277
todo.complete() # This sets STATUS=COMPLETED and COMPLETED timestamp
278
279
# Filter todos by status
280
pending_todos = calendar.search(
281
comp_filter="VTODO",
282
prop_filter={"STATUS": "NEEDS-ACTION"}
283
)
284
285
in_progress_todos = calendar.search(
286
comp_filter="VTODO",
287
prop_filter={"STATUS": "IN-PROCESS"}
288
)
289
290
completed_todos = calendar.search(
291
comp_filter="VTODO",
292
prop_filter={"STATUS": "COMPLETED"}
293
)
294
295
print(f"Pending: {len(pending_todos)}, In Progress: {len(in_progress_todos)}, Completed: {len(completed_todos)}")
296
```
297
298
### Todo Hierarchy and Dependencies
299
300
Manage task hierarchies and dependencies using RELATED-TO properties for project organization and workflow management.
301
302
```python { .api }
303
def get_relatives(self, field_filter=None, include_self=False):
304
"""
305
Get related todos (parent/child relationships).
306
307
Parameters:
308
- field_filter: str, filter by relation type ('PARENT', 'CHILD', 'SIBLING')
309
- include_self: bool, include this todo in results
310
311
Returns:
312
list[CalendarObjectResource]: Related todos
313
"""
314
```
315
316
**Usage Examples:**
317
318
```python
319
# Create project with subtasks
320
project_ical = """BEGIN:VCALENDAR
321
VERSION:2.0
322
PRODID:-//My App//My App//EN
323
BEGIN:VTODO
324
UID:website-redesign@example.com
325
SUMMARY:Website Redesign Project
326
DESCRIPTION:Complete website redesign and launch
327
DUE:20251231T170000Z
328
STATUS:NEEDS-ACTION
329
PRIORITY:1
330
END:VTODO
331
END:VCALENDAR"""
332
333
project = calendar.save_todo(project_ical)
334
335
# Create subtasks with parent relationship
336
subtasks = [
337
("Design mockups", "Create visual designs and mockups", "20251115T170000Z"),
338
("Frontend development", "Implement frontend based on designs", "20251201T170000Z"),
339
("Backend integration", "Connect frontend to existing backend", "20251215T170000Z"),
340
("Testing and QA", "Test all functionality and fix bugs", "20251220T170000Z")
341
]
342
343
created_subtasks = []
344
for i, (summary, description, due) in enumerate(subtasks):
345
subtask_uid = f"website-subtask-{i+1}@example.com"
346
347
subtask_ical = f"""BEGIN:VCALENDAR
348
VERSION:2.0
349
PRODID:-//My App//My App//EN
350
BEGIN:VTODO
351
UID:{subtask_uid}
352
SUMMARY:{summary}
353
DESCRIPTION:{description}
354
DUE:{due}
355
STATUS:NEEDS-ACTION
356
PRIORITY:2
357
RELATED-TO;RELTYPE=PARENT:{project.id}
358
END:VTODO
359
END:VCALENDAR"""
360
361
subtask = calendar.save_todo(subtask_ical)
362
created_subtasks.append(subtask)
363
364
# Find all subtasks of the project
365
project_subtasks = project.get_relatives(field_filter="CHILD")
366
print(f"Project has {len(project_subtasks)} subtasks")
367
368
# Create dependency between subtasks (frontend depends on design)
369
design_task = created_subtasks[0]
370
frontend_task = created_subtasks[1]
371
372
# Add dependency relationship
373
frontend_component = frontend_task.icalendar_component
374
frontend_component.add('RELATED-TO', design_task.id)
375
frontend_component['RELATED-TO'].params['RELTYPE'] = 'DEPENDS-ON'
376
frontend_task.save()
377
378
print(f"Frontend task now depends on: {design_task.id}")
379
```
380
381
### Todo Queries and Filtering
382
383
Advanced todo querying with status filters, due date ranges, and priority-based searches.
384
385
```python { .api }
386
# Common todo search patterns using calendar.search() - see calendar-management.md
387
388
def find_overdue_todos(calendar):
389
"""Find todos past their due date."""
390
from datetime import datetime
391
now = datetime.now()
392
393
todos = calendar.search(comp_filter="VTODO")
394
overdue = []
395
396
for todo in todos:
397
due_date = todo.get_due()
398
status = todo.icalendar_component.get('STATUS', 'NEEDS-ACTION')
399
400
if due_date and due_date < now and status != 'COMPLETED':
401
overdue.append(todo)
402
403
return overdue
404
405
def find_high_priority_todos(calendar):
406
"""Find high priority todos."""
407
return calendar.search(
408
comp_filter="VTODO",
409
prop_filter={"PRIORITY": "1"}
410
) + calendar.search(
411
comp_filter="VTODO",
412
prop_filter={"PRIORITY": "2"}
413
)
414
415
def find_todos_due_this_week(calendar):
416
"""Find todos due in the next 7 days."""
417
from datetime import datetime, timedelta
418
419
start = datetime.now()
420
end = start + timedelta(days=7)
421
422
todos = calendar.search(comp_filter="VTODO")
423
due_this_week = []
424
425
for todo in todos:
426
due_date = todo.get_due()
427
status = todo.icalendar_component.get('STATUS', 'NEEDS-ACTION')
428
429
if due_date and start <= due_date <= end and status != 'COMPLETED':
430
due_this_week.append(todo)
431
432
return due_this_week
433
```
434
435
**Usage Examples:**
436
437
```python
438
# Find todos by various criteria
439
overdue = find_overdue_todos(calendar)
440
print(f"Overdue todos: {len(overdue)}")
441
442
high_priority = find_high_priority_todos(calendar)
443
print(f"High priority todos: {len(high_priority)}")
444
445
due_soon = find_todos_due_this_week(calendar)
446
print(f"Due this week: {len(due_soon)}")
447
448
# Search by text in summary or description
449
project_todos = calendar.search(
450
comp_filter="VTODO",
451
text_match="website"
452
)
453
454
# Find todos by specific status
455
active_todos = calendar.search(
456
comp_filter="VTODO",
457
prop_filter={"STATUS": "IN-PROCESS"}
458
)
459
460
# Complex status filtering
461
incomplete_todos = []
462
for status in ["NEEDS-ACTION", "IN-PROCESS"]:
463
todos = calendar.search(
464
comp_filter="VTODO",
465
prop_filter={"STATUS": status}
466
)
467
incomplete_todos.extend(todos)
468
469
print(f"Total incomplete todos: {len(incomplete_todos)}")
470
```
471
472
### Recurring Todos
473
474
Handle recurring todos with automatic creation of next occurrences upon completion.
475
476
```python { .api }
477
# Recurring todos use the same RRULE syntax as events
478
# When completed with handle_rrule=True, a new occurrence is automatically created
479
480
RECURRING_TODO_PATTERNS = {
481
"daily": "FREQ=DAILY",
482
"weekdays": "FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR",
483
"weekly": "FREQ=WEEKLY",
484
"monthly": "FREQ=MONTHLY",
485
"yearly": "FREQ=YEARLY"
486
}
487
```
488
489
**Usage Examples:**
490
491
```python
492
# Create daily recurring todo
493
daily_standup_ical = """BEGIN:VCALENDAR
494
VERSION:2.0
495
PRODID:-//My App//My App//EN
496
BEGIN:VTODO
497
UID:daily-standup-prep@example.com
498
SUMMARY:Prepare for daily standup
499
DESCRIPTION:Review progress and prepare standup updates
500
DUE:20250915T090000Z
501
STATUS:NEEDS-ACTION
502
PRIORITY:3
503
RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR;COUNT=50
504
END:VTODO
505
END:VCALENDAR"""
506
507
recurring_todo = calendar.save_todo(daily_standup_ical)
508
509
# Complete the recurring todo - this creates the next occurrence
510
next_occurrence = recurring_todo.complete(handle_rrule=True)
511
if next_occurrence:
512
print(f"Completed today's standup prep, created tomorrow's: {next_occurrence.id}")
513
514
# Create monthly recurring todo
515
monthly_report_ical = """BEGIN:VCALENDAR
516
VERSION:2.0
517
PRODID:-//My App//My App//EN
518
BEGIN:VTODO
519
UID:monthly-report@example.com
520
SUMMARY:Submit monthly progress report
521
DESCRIPTION:Compile and submit monthly team progress report
522
DUE:20250930T170000Z
523
STATUS:NEEDS-ACTION
524
PRIORITY:2
525
RRULE:FREQ=MONTHLY;BYMONTHDAY=-1
526
END:VTODO
527
END:VCALENDAR"""
528
529
monthly_todo = calendar.save_todo(monthly_report_ical)
530
```
531
532
## Todo Properties
533
534
```python { .api }
535
# Common todo properties that can be accessed via icalendar_component
536
TODO_PROPERTIES = {
537
"SUMMARY": "str", # Todo title/summary
538
"DESCRIPTION": "str", # Todo description
539
"DUE": "datetime", # Due date/time
540
"DTSTART": "datetime", # Start date/time
541
"DURATION": "timedelta", # Duration
542
"STATUS": "str", # NEEDS-ACTION, COMPLETED, IN-PROCESS, CANCELLED
543
"PRIORITY": "int", # Priority (0-9, 0=undefined, 1=highest, 9=lowest)
544
"PERCENT-COMPLETE": "int", # Completion percentage (0-100)
545
"COMPLETED": "datetime", # Completion timestamp (set by complete())
546
"CLASS": "str", # PUBLIC, PRIVATE, CONFIDENTIAL
547
"CATEGORIES": "list[str]", # Todo categories/tags
548
"RELATED-TO": "str", # Related todo UID
549
"RRULE": "str", # Recurrence rule
550
}
551
```