def testFullRendering(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("k1", interactive=False) dbutils.getOrCreateKeyword("k2", interactive=False) t1 = dbutils.addTask("x", "t1", {}) t2 = dbutils.addTask("x", "t2", {"k1": None, "k2": 12}) longTask = dbutils.addTask("x", "A longer task name", {}) longTask.description = "And it has a description" out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t2, longTask]) self.assertEqual(renderer.maxTitleWidth, len(longTask.title) + 1) renderer.end() out = stripColor(out.getvalue()) expected = \ " Foo \n" \ + "ID│Title │U │S│Age │Due date\n" \ + "──┼───────────────────┼───┼─┼────────┼────────\n" \ + "2 │t2 (k1, k2) │0 │N│0m │ \n" \ + "3 │A longer task name*│0 │N│0m │ \n" self.assertMultiLineEqual(out, expected)
def testTitleFormater(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("key1", interactive=False) dbutils.getOrCreateKeyword("key2", interactive=False) task = dbutils.addTask("x", "t1", {}) taskWithKeywords = dbutils.addTask("x", "t2", { "key1": None, "key2": 12 }) longTask = dbutils.addTask("x", "01234567890123456789", {}) longTask.description = "And it has a description" TEST_DATA = ( (task, 20, "t1"), (taskWithKeywords, 20, "t2 (key1, key2)"), (taskWithKeywords, 4, "t2 >"), (longTask, 10, longTask.title[:8] + ">*"), (longTask, len(longTask.title), longTask.title[:-2] + ">*"), (longTask, len(longTask.title) + 1, longTask.title + "*"), (longTask, 40, longTask.title.ljust(39) + "*"), ) for task, width, expected in TEST_DATA: with self.subTest(task=task, width=width): formater = TitleFormater(width, StubCryptoMgr()) out = formater(task)[0] out = stripColor(out) expected = expected.ljust(width) self.assertEqual(out, expected)
def testTitleFormater(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("key1", interactive=False) dbutils.getOrCreateKeyword("key2", interactive=False) task = dbutils.addTask("x", "t1", {}) taskWithKeywords = dbutils.addTask("x", "t2", {"key1": None, "key2": 12}) longTask = dbutils.addTask("x", "01234567890123456789", {}) longTask.description = "And it has a description" TEST_DATA = ( (task, 20, "t1"), (taskWithKeywords, 20, "t2 (key1, key2)"), (taskWithKeywords, 4, "t2 >"), (longTask, 10, longTask.title[:8] + ">*"), (longTask, len(longTask.title), longTask.title[:-2] + ">*"), (longTask, len(longTask.title) + 1, longTask.title + "*"), (longTask, 40, longTask.title.ljust(39) + "*"), ) for task, width, expected in TEST_DATA: with self.subTest(task=task, width=width): formater = TitleFormater(width) out = formater(task)[0] out = stripColor(out) expected = expected.ljust(width) self.assertEqual(out, expected)
def __init__(self): self.lastTaskId = None # Last id created, used self.lastProjectName = None # Last project name used self.lastTaskIds = [] # Last list of ids selected with t_list self.kFilters = [] # Permanent keyword filters (List of KeywordFilter) self.pFilter = "" # Permanent project filter (name of project) for name in bugutils.PROPERTY_NAMES: dbutils.getOrCreateKeyword(name, interactive=False) dbutils.getOrCreateKeyword(NOTE_KEYWORD, interactive=False)
def testGetOrCreateKeyword(self): # interactive tui.addInputAnswers("y") dbutils.getOrCreateKeyword("k1") self._assertOneObject(Keyword.selectBy(name="k1")) # !interactive dbutils.getOrCreateKeyword("k2", interactive=False) self._assertOneObject(Keyword.selectBy(name="k2"))
def testGetOrCreateKeyword(self): # interactive tui.addInputAnswers("y") dbutils.getOrCreateKeyword("k1") self.session.query(Keyword).filter_by(name="k1").one() # !interactive dbutils.getOrCreateKeyword("k2", interactive=False) self.session.query(Keyword).filter_by(name="k2").one()
def testTitleFormater(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("k1", interactive=False) dbutils.getOrCreateKeyword("k2", interactive=False) t1 = dbutils.addTask("x", "t1", {}) t2 = dbutils.addTask("x", "t2", {"k1": None, "k2": 12}) longerTask = dbutils.addTask("x", "A longer task name", {}) longerTask.description = "And it has a description" out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t1]) self.assertEquals(renderer.maxTitleWidth, 5) renderer.end() expected = unicode(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title|U |S|Age |Due date%(RESET)s\n" \ + "--------------------------------\n" \ + "1 |t1 %(RESET)s|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected) out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t1, t2]) self.assertEquals(renderer.maxTitleWidth, 11) renderer.end() expected = unicode(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title |U |S|Age |Due date%(RESET)s\n" \ + "--------------------------------------\n" \ + "1 |t1 %(RESET)s|0 |N|0m | \n" \ + "2 |t2 (%(BOLD)sk1, k2)%(RESET)s|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected) out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t2, longerTask]) self.assertEquals(renderer.maxTitleWidth, len(longerTask.title) + 1) renderer.end() expected = unicode(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title |U |S|Age |Due date%(RESET)s\n" \ + "----------------------------------------------\n" \ + "2 |t2 (%(BOLD)sk1, k2) %(RESET)s|0 |N|0m | \n" \ + "3 |A longer task name%(RESET)s*|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected)
def testTitleFormater(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("k1", interactive=False) dbutils.getOrCreateKeyword("k2", interactive=False) t1 = dbutils.addTask("x", "t1", {}) t2 = dbutils.addTask("x", "t2", {"k1": None, "k2": 12}) longerTask = dbutils.addTask("x", "A longer task name", {}) longerTask.description = "And it has a description" out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t1]) self.assertEqual(renderer.maxTitleWidth, 5) renderer.end() expected = str(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title|U |S|Age |Due date%(RESET)s\n" \ + "--------------------------------\n" \ + "1 |t1 %(RESET)s|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected) out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t1, t2]) self.assertEqual(renderer.maxTitleWidth, 11) renderer.end() expected = str(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title |U |S|Age |Due date%(RESET)s\n" \ + "--------------------------------------\n" \ + "1 |t1 %(RESET)s|0 |N|0m | \n" \ + "2 |t2 (%(BOLD)sk1, k2)%(RESET)s|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected) out = StringIO() renderer = TextListRenderer(out, termWidth=80, cryptoMgr=YokadiCryptoManager()) renderer.addTaskList("Foo", [t2, longerTask]) self.assertEqual(renderer.maxTitleWidth, len(longerTask.title) + 1) renderer.end() expected = str(\ "%(CYAN)s Foo %(RESET)s\n" \ + "%(BOLD)sID|Title |U |S|Age |Due date%(RESET)s\n" \ + "----------------------------------------------\n" \ + "2 |t2 (%(BOLD)sk1, k2) %(RESET)s|0 |N|0m | \n" \ + "3 |A longer task name%(RESET)s*|0 |N|0m | \n" \ ) % dict(CYAN=C.CYAN, RESET=C.RESET, BOLD=C.BOLD) testutils.multiLinesAssertEqual(self, out.getvalue(), expected)
def applyChanges(project, oldList, newList, interactive=True): """ Modify a project so that its task list is newList @param project: the project name @param oldList: a list of Task instances @param newList: a list of MEditEntry @param interactive: whether to confirm creation of new keywords """ session = db.getSession() # Sanity check: all ids in newList should be in oldList oldIds = set([x.id for x in oldList]) newIds = set([x.id for x in newList if x.id is not None]) unknownIds = newIds.difference(oldIds) if unknownIds: idString = ", ".join([str(x) for x in unknownIds]) raise YokadiException("Unknown id(s): %s" % idString) # Check keywords for entry in newList: for name in entry.keywords: dbutils.getOrCreateKeyword(name, interactive=interactive) # Remove tasks whose lines have been deleted for id in oldIds.difference(newIds): task = dbutils.getTaskFromId(id) session.delete(task) # Update existing tasks, add new ones nbTasks = len(newList) for pos, newEntry in enumerate(newList): if newEntry.id: task = dbutils.getTaskFromId(newEntry.id) else: task = Task(creationDate=datetime.now().replace(second=0, microsecond=0), project=project) task.title = newEntry.title task.setKeywordDict(newEntry.keywords) task.setStatus(newEntry.status) task.urgency = nbTasks - pos if newEntry.id: session.merge(task) else: session.add(task)
def main(): parser = ArgumentParser() parser.add_argument('db', metavar='<db>') args = parser.parse_args() dbname = args.db if os.path.exists(dbname): os.unlink(dbname) db.connectDatabase(dbname) db.setDefaultConfig() session = db.getSession() for name in PROJECTS: session.add(db.Project(name=name)) for name in KEYWORDS: dbutils.getOrCreateKeyword(name, interactive=False) dbutils.addTask("birthday", "Buy food", {"grocery": None}) dbutils.addTask("birthday", "Buy drinks", {"grocery": None}) dbutils.addTask("birthday", "Invite Bob", {"phone": None}) dbutils.addTask("birthday", "Invite Wendy", {"phone": None}) dbutils.addTask("birthday", "Bake a yummy cake") dbutils.addTask("birthday", "Decorate living-room") task = dbutils.addTask("home", "Fix leak in the roof") task.dueDate = ydateutils.parseHumaneDateTime("-2d") dbutils.addTask("home", "Buy AAA batteries for kid toys", {"grocery": None}) task = dbutils.addTask("home", "Bring the car to the garage") task.dueDate = ydateutils.parseHumaneDateTime("-1d") task.status = "done" task = dbutils.addTask("work", "Finish weekly report") task.dueDate = ydateutils.parseHumaneDateTime("+4d") task.description = """Include results from Acme department: http://acme.intranet/results. Don't forget to CC [email protected]. """ session.commit() return 0
def testFullRendering(self): dbutils.getOrCreateProject("x", interactive=False) dbutils.getOrCreateKeyword("k1", interactive=False) dbutils.getOrCreateKeyword("k2", interactive=False) dbutils.addTask("x", "t1", {}) t2 = dbutils.addTask("x", "t2", {"k1": None, "k2": 12}) longTask = dbutils.addTask("x", "A longer task name", {}) longTask.description = "And it has a description" out = StringIO() renderer = TextListRenderer(out, termWidth=80) renderer.addTaskList("Foo", [t2, longTask]) self.assertEqual(renderer.maxTitleWidth, len(longTask.title) + 1) renderer.end() out = stripColor(out.getvalue()) expected = \ " Foo \n" \ "ID│Title │U │S│Age │Due date\n" \ "──┼───────────────────┼───┼─┼────────┼────────\n" \ "2 │t2 (k1, k2) │0 │N│0m │ \n" \ "3 │A longer task name*│0 │N│0m │ \n" self.assertMultiLineEqual(out, expected)
def testGetKeywordFromName(self): tui.addInputAnswers("y") k1 = dbutils.getOrCreateKeyword("k1", self.session) self.assertRaises(YokadiException, dbutils.getKeywordFromName, "") self.assertRaises(YokadiException, dbutils.getKeywordFromName, "foo") self.assertEqual(k1, dbutils.getKeywordFromName("k1"))
def setUp(self): db.connectDatabase("", memoryDatabase=True) # FIXME: Do this in db dbutils.getOrCreateKeyword(NOTE_KEYWORD, interactive=False) self.session = db.getSession() tui.clearInputAnswers()