954e38e50e7b0f7e21a44f0e2e3db667c4cab195
[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                 with open(self._filename, "wb") as pickleFile:
23                         pickle.dump(state, pickleFile)
24
25         def load(self):
26                 try:
27                         with open(self._filename, "rb") as pickleFile:
28                                 state = pickle.load(pickleFile)
29                 except IOError, e:
30                         if e.errno != 2:
31                                 raise
32                 self._projects = state["projects"]
33                 self._items = state["items"]
34                 self._locations = state["locations"]
35
36                 if len(self._projects) == 0:
37                         self.add_project("Inbox")
38
39         def add_project(self, name):
40                 projId = uuid.uuid4().hex
41                 projDetails = {
42                         "name": name,
43                         "id": projId,
44                         "isVisible": True,
45                         "isMeta": False,
46                 }
47                 assert projId not in self._projects, "How did uuid %r repeat?" % projId
48                 self._projects[projId] = projDetails
49                 if projId not in self._items:
50                         self._items[projId] = {}
51                 return projId
52
53         def set_project_name(self, projId, name):
54                 projDetails = self._projects[projId]
55                 projDetails["name"] = name
56
57         def set_project_visibility(self, projId, visibility):
58                 projDetails = self._projects[projId]
59                 projDetails["isVisible"] = visibility
60
61         def get_projects(self):
62                 return self._projects.itervalues()
63
64         def get_project(self, projId):
65                 return self._projects[projId]
66
67         def lookup_project(self, projName):
68                 """
69                 From a project's name, returns the project's details
70                 """
71                 todoList = [
72                         projectDetails
73                         for projectDetails in self._projects.itervalues()
74                                 if projectDetails["name"] == projName
75                 ]
76                 assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
77                 return todoList[0]
78
79         def get_locations(self):
80                 return self._locations.itervalues()
81
82         def get_tasks_with_details(self, projId):
83                 return self._items[projId].itervalues()
84
85         def get_task_details(self, taskId):
86                 projId, partialTaskId = self._unpack_ids(taskId)
87                 return self._items[projId][taskId]
88
89         def add_task(self, projId, taskName):
90                 partialTaskId = uuid.uuid4().hex
91                 taskId = self._pack_ids(projId, partialTaskId)
92                 assert taskId not in self._items, "How did uuid %r repeat?" % taskId
93                 taskDetails = {
94                         "id": taskId,
95                         "projId": projId,
96                         "name": taskName,
97                         "url": "",
98                         "locationId": toolbox.Optional(),
99                         "dueDate": toolbox.Optional(),
100                         "isCompleted": False,
101                         "completedDate": toolbox.Optional(),
102                         "priority": toolbox.Optional(),
103                         "estimate": toolbox.Optional(),
104                         "notes": {},
105                 }
106                 self._items[projId][taskId] = taskDetails
107                 return taskId
108
109         def set_project(self, taskId, newProjId):
110                 projId, partialTaskId = self._unpack_ids(taskId)
111                 taskDetails = self._items[projId][taskId]
112                 taskDetails["projId"] = newProjId
113
114         def set_name(self, taskId, name):
115                 projId, partialTaskId = self._unpack_ids(taskId)
116                 taskDetails = self._items[projId][taskId]
117                 taskDetails["name"] = name
118
119         def set_duedate(self, taskId, dueDate):
120                 projId, partialTaskId = self._unpack_ids(taskId)
121                 taskDetails = self._items[projId][taskId]
122                 taskDetails["dueDate"] = dueDate
123
124         def set_priority(self, taskId, priority):
125                 projId, partialTaskId = self._unpack_ids(taskId)
126                 taskDetails = self._items[projId][taskId]
127                 taskDetails["priority"] = priority
128
129         def complete_task(self, taskId):
130                 projId, partialTaskId = self._unpack_ids(taskId)
131                 taskDetails = self._items[projId][taskId]
132                 taskDetails["isCompleted"] = True
133                 taskDetails["completionDate"] = toolbox.Optional(datetime.datetime.now())
134
135         def add_note(self, taskId, noteTitle, noteBody):
136                 projId, partialTaskId = self._unpack_ids(taskId)
137                 partialNoteId = uuid.uuid4().hex
138                 noteId = self._pack_ids(taskId, partialNoteId)
139                 note = {
140                         "id": noteId,
141                         "title": noteTitle,
142                         "body": noteBody,
143                 }
144                 assert noteId not in self._items[projId][taskId]["notes"]
145                 self._items[projId][taskId]["notes"][noteId] = note
146                 return noteId
147
148         def update_note(self, noteId, noteTitle, noteBody):
149                 taskId, partialNoteId = self._unpack_ids(noteId)
150                 projId, partialTaskId = self._unpack_ids(taskId)
151                 self._items[projId][taskId]["notes"][noteId]["title"] = noteTitle
152                 self._items[projId][taskId]["notes"][noteId]["body"] = noteBody
153
154         def delete_note(self, noteId):
155                 taskId, partialNoteId = self._unpack_ids(noteId)
156                 projId, partialTaskId = self._unpack_ids(taskId)
157                 del self._items[projId][taskId]["notes"][noteId]
158
159         @staticmethod
160         def _pack_ids(*ids):
161                 return "-".join((str(id) for id in ids))
162
163         @staticmethod
164         def _unpack_ids(ids):
165                 return ids.split("-")