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