Bug fixes for file_backend, api changes, etc
[doneit] / src / file_backend.py
1 import uuid
2 import pickle
3 import datetime
4
5 import toolbox
6
7
8 class FileBackend(object):
9
10         def __init__(self, filename):
11                 self._filename = filename
12                 self._projects = {}
13                 self._items = {}
14                 self._locations = {}
15
16         def save(self):
17                 state = {
18                         "projects": self._projects,
19                         "items": self._items,
20                         "locations": self._locations,
21                 }
22                 pickle.dump(state, self._filename)
23
24         def load(self):
25                 state = pickle.load(self._filename)
26                 self._projects = state["projects"]
27                 self._items = state["items"]
28                 self._locations = state["locations"]
29
30         def add_project(self, name):
31                 projId = uuid.uuid4().hex
32                 projDetails = {
33                         "name": name,
34                         "id": projId,
35                         "isVisible": True,
36                         "isMeta": False,
37                 }
38                 assert projId not in self._projects, "How did uuid %r repeat?" % projId
39                 self._projects[projId] = projDetails
40                 if projId not in self._items:
41                         self._items[projId] = {}
42                 return projId
43
44         def set_project_name(self, projId, name):
45                 projDetails = self._projects[projId]
46                 projDetails["name"] = name
47
48         def set_project_visibility(self, projId, visibility):
49                 projDetails = self._projects[projId]
50                 projDetails["isVisible"] = visibility
51
52         def get_projects(self):
53                 return self._projects.itervalues()
54
55         def get_project(self, projId):
56                 return self._projects[projId]
57
58         def lookup_project(self, projName):
59                 """
60                 From a project's name, returns the project's details
61                 """
62                 todoList = [
63                         projectDetails
64                         for projectDetails in self._projects.itervalues()
65                                 if projectDetails["name"] == projName
66                 ]
67                 assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
68                 return todoList[0]
69
70         def get_locations(self):
71                 return self._locations.itervalues()
72
73         def get_tasks_with_details(self, projId):
74                 return self._items[projId]
75
76         def get_task_details(self, taskId):
77                 projId, partialTaskId = self._unpack_ids(taskId)
78                 return self._items[projId][taskId]
79
80         def add_task(self, projId, taskName):
81                 partialTaskId = uuid.uuid4().hex
82                 taskId = self._pack_ids(projId, partialTaskId)
83                 assert taskId not in self._items, "How did uuid %r repeat?" % taskId
84                 taskDetails = {
85                         "id": taskId,
86                         "projId": projId,
87                         "name": taskName,
88                         "url": "",
89                         "locationId": toolbox.Optional(),
90                         "dueDate": toolbox.Optional(),
91                         "isCompleted": False,
92                         "completedDate": toolbox.Optional(),
93                         "priority": toolbox.Optional(),
94                         "estimate": toolbox.Optional(),
95                         "notes": {},
96                 }
97                 self._items[projId][taskId] = taskDetails
98                 return taskId
99
100         def set_project(self, taskId, newProjId):
101                 projId, partialTaskId = self._unpack_ids(taskId)
102                 taskDetails = self._items[projId][taskId]
103                 taskDetails["projId"] = newProjId
104
105         def set_name(self, taskId, name):
106                 projId, partialTaskId = self._unpack_ids(taskId)
107                 taskDetails = self._items[projId][taskId]
108                 taskDetails["name"] = name
109
110         def set_duedate(self, taskId, dueDate):
111                 projId, partialTaskId = self._unpack_ids(taskId)
112                 taskDetails = self._items[projId][taskId]
113                 taskDetails["dueDate"] = dueDate
114
115         def set_priority(self, taskId, priority):
116                 projId, partialTaskId = self._unpack_ids(taskId)
117                 taskDetails = self._items[projId][taskId]
118                 taskDetails["priority"] = priority
119
120         def complete_task(self, taskId):
121                 projId, partialTaskId = self._unpack_ids(taskId)
122                 taskDetails = self._items[projId][taskId]
123                 taskDetails["isCompleted"] = True
124                 taskDetails["completionDate"] = toolbox.Optional(datetime.datetime.now())
125
126         def add_note(self, taskId, noteTitle, noteBody):
127                 projId, partialTaskId = self._unpack_ids(taskId)
128                 partialNoteId = uuid.uuid4().hex
129                 noteId = self._pack_ids(taskId, partialNoteId)
130                 note = {
131                         "id": noteId,
132                         "title": noteTitle,
133                         "body": noteBody,
134                 }
135                 assert noteId not in self._items[projId][taskId]["notes"]
136                 self._items[projId][taskId]["notes"][noteId] = note
137                 return noteId
138
139         def update_note(self, noteId, noteTitle, noteBody):
140                 taskId, partialNoteId = self._unpack_ids(noteId)
141                 projId, partialTaskId = self._unpack_ids(taskId)
142                 self._items[projId][taskId]["notes"][noteId]["title"] = noteTitle
143                 self._items[projId][taskId]["notes"][noteId]["body"] = noteBody
144
145         def delete_note(self, noteId):
146                 taskId, partialNoteId = self._unpack_ids(noteId)
147                 projId, partialTaskId = self._unpack_ids(taskId)
148                 del self._items[projId][taskId]["notes"][noteId]
149
150         @staticmethod
151         def _pack_ids(*ids):
152                 return "-".join((str(id) for id in ids))
153
154         @staticmethod
155         def _unpack_ids(ids):
156                 return ids.split("-")