Adding a caching backend
authorEd Page <eopage@byu.net>
Sat, 18 Apr 2009 16:10:03 +0000 (11:10 -0500)
committerEd Page <eopage@byu.net>
Sat, 18 Apr 2009 16:10:03 +0000 (11:10 -0500)
src/cache_backend.py [new file with mode: 0644]

diff --git a/src/cache_backend.py b/src/cache_backend.py
new file mode 100644 (file)
index 0000000..17294d4
--- /dev/null
@@ -0,0 +1,154 @@
+class CacheBackend(object):
+
+       def __init__(self, backend):
+               self._backend = backend
+               self._projects = {}
+               self._items = {}
+               self._locations = {}
+               self._taskIdToProjId = {}
+               self._noteIdToTaskId = {}
+
+       def save(self):
+               self._backend.save()
+
+       def load(self):
+               self._backend.load()
+
+       def add_project(self, name):
+               self._backend.add_project(name)
+               self._invalidate_projects()
+
+       def set_project_name(self, projId, name):
+               self._backend.set_project_name(projId, name)
+               self._invalidate_projects()
+
+       def set_project_visibility(self, projId, visibility):
+               self._backend.set_project_visibility(projId, visibility)
+               self._invalidate_projects()
+
+       def get_projects(self):
+               self._populate_projects()
+               return self._projects.itervalues()
+
+       def get_project(self, projId):
+               self._populate_projects()
+               return self._projects[projId]
+
+       def lookup_project(self, projName):
+               """
+               From a project's name, returns the project's details
+               """
+               self._populate_projects()
+               todoList = [
+                       projectDetails
+                       for projectDetails in self._projects.itervalues()
+                               if projectDetails["name"] == projName
+               ]
+               assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
+               return todoList[0]
+
+       def get_locations(self):
+               self._populate_locations()
+               return self._locations.itervalues()
+
+       def get_tasks_with_details(self, projId):
+               self._populate_tasks(projId)
+               return self._items[projId]
+
+       def get_task_details(self, taskId):
+               projId = self._taskIdToProjId[taskId]
+               self._populate_tasks(projId)
+               return self._items[projId][taskId]
+
+       def add_task(self, projId, taskName):
+               self._backend.add_task(projId, taskName)
+               self._invalidate_projects_tasks(projId)
+               self._invalidate_metaprojects_tasks()
+
+       def set_project(self, taskId, newProjId):
+               self._backend.set_project(taskId, newProjId)
+               projId = self._taskIdToProjId[taskId]
+               self._invalidate_projects_tasks(projId)
+               self._invalidate_projects_tasks(newProjId)
+               self._invalidate_metaprojects_tasks()
+
+       def set_name(self, taskId, name):
+               self._backend.set_name(taskId, name)
+               self._invalidate_task(taskId)
+
+       def set_duedate(self, taskId, dueDate):
+               self._backend.set_duedate(taskId, dueDate)
+               self._invalidate_task(taskId)
+
+       def set_priority(self, taskId, priority):
+               self._backend.set_priority(taskId, priority)
+               self._invalidate_task(taskId)
+
+       def complete_task(self, taskId):
+               self._backend.complete_task(taskId)
+               self._invalidate_task(taskId)
+
+       def add_note(self, taskId, noteTitle, noteBody):
+               self._backend.add_note(taskId, noteTitle, noteBody)
+               self._invalidate_task(taskId)
+
+       def update_note(self, noteId, noteTitle, noteBody):
+               self._backend.update_note(noteId, noteTitle, noteBody)
+               taskId = self._noteIdToTaskId[noteId]
+               self._invalidate_task(taskId)
+
+       def delete_note(self, noteId):
+               self._backend.delete_note(noteId)
+               taskId = self._noteIdToTaskId[noteId]
+               del self._noteIdToTaskId[noteId]
+               self._invalidate_task(taskId)
+
+       def _populate_projects(self):
+               if self._projects:
+                       return
+               self._projects = dict((
+                       (proj["id"], proj)
+                       for proj in self._backend.get_projects()
+               ))
+
+       def _populate_tasks(self, projId):
+               if projId in self._items:
+                       return
+               self._items[projId] = dict((
+                       (task["id"], task)
+                       for task in self.get_tasks_with_details(projId)
+               ))
+               for taskId, task in self._items[projId].iteritems():
+                       self._taskIdToProjId[taskId] = task["projId"]
+                       for noteId, note in task.notes.iteritems():
+                               self._noteIdToTaskId[noteId] = taskId
+
+       def _populate_locations(self):
+               if self._locations:
+                       return
+               self._locations = dict((
+                       (loc["id"], loc)
+                       for loc in self._backend.get_locations()
+               ))
+
+       def _invalidate_projects(self):
+               self._projects.clear()
+
+       def _invalidate_task(self, taskId):
+               projId = self._taskIdToProjId[taskId]
+               self._invalidate_projects_tasks(projId)
+               self._invalidate_metaprojects_tasks()
+
+       def _invalidate_projects_tasks(self, projId):
+               del self._items[projId]
+
+       def _invalidate_metaprojects_tasks(self):
+               for projId in self._get_metalists():
+                       self._invalidate_projects_tasks(projId)
+
+       def _get_metalists(self):
+               return (
+                       list
+                       for list in self._projects.itervalues()
+                               if not list["isMeta"]
+               )