Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    def testOnlyListTasks(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Task", {})
        t2 = dbutils.addTask("p1", "Note", {NOTE_KEYWORD: None})

        oldList = massedit.createEntriesForProject(prj)
        self.assertEqual(len(oldList), 1)
Пример #4
0
    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)
Пример #5
0
    def testOnlyListTasks(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Task", {})
        t2 = dbutils.addTask("p1", "Note", {NOTE_KEYWORD: None})

        oldList = massedit.createEntriesForProject(prj)
        self.assertEqual(len(oldList), 1)
Пример #6
0
    def testKList(self):
        t1 = dbutils.addTask("x", "t1", dict(k1=12, k2=None), interactive=False)
        t2 = dbutils.addTask("x", "t2", dict(k1=None, k3=None), interactive=False)

        lst = list(_listKeywords(self.session))
        lst = [(name, list(ids)) for name, ids in lst]
        self.assertEqual(lst, [("k1", [t1.id, t2.id]),
                               ("k2", [t1.id]),
                               ("k3", [t2.id]),
                               ])
Пример #7
0
    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)
Пример #8
0
    def testApplyMEditChangesUnknownIds(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Foo", {})
        t2 = dbutils.addTask("p1", "Bar", {})

        oldList = massedit.createEntriesForProject(prj)
        newList = [
            MEditEntry(t1.id, "new", t1.title, {}),
            MEditEntry(t2.id + 1, "new", t2.title, {}),
        ]

        self.assertRaises(YokadiException, massedit.applyChanges, prj, oldList,
                          newList, interactive=False)
Пример #9
0
    def testApplyMEditChangesUnknownIds(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Foo", {})
        t2 = dbutils.addTask("p1", "Bar", {})

        oldList = massedit.createEntriesForProject(prj)
        newList = [
            MEditEntry(t1.id, "new", t1.title, {}),
            MEditEntry(t2.id + 1, "new", t2.title, {}),
        ]

        self.assertRaises(YokadiException, massedit.applyChanges, prj, oldList,
                          newList, interactive=False)
Пример #10
0
    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)
Пример #11
0
    def testKEditMerge(self):
        t1 = dbutils.addTask("x", "t1", dict(k1=None, k2=None), interactive=False)
        t2 = dbutils.addTask("x", "t2", dict(k1=None), interactive=False)
        tui.addInputAnswers("k2", "y")
        self.cmd.do_k_edit("k1")

        kwDict = t1.getKeywordDict()
        self.assertTrue("k1" not in kwDict)
        self.assertTrue("k2" in kwDict)

        kwDict = t2.getKeywordDict()
        self.assertTrue("k1" not in kwDict)
        self.assertTrue("k2" in kwDict)

        self.assertRaises(YokadiException, dbutils.getKeywordFromName, "k1")
Пример #12
0
    def testTitleMapping(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        v1 = yical.createVTodoFromTask(t1)

        # Check id is here
        self.assertEqual(v1.get("summary")[-4:], " (%s)" % t1.id)

        # Title and id should not change with update
        origin_id = t1.id
        origin_title = t1.title
        yical.updateTaskFromVTodo(t1, v1)
        self.assertEqual(t1.id, origin_id)
        self.assertEqual(t1.title, origin_title)

        # Update vtodo summary and remove (id) or space before (id) info.
        # Only task title should be changed
        for new_summary in ("hello", "hello(%s)" % origin_id, "hello (%s)" % origin_id,
                            "(%s)hello" % origin_id, " (%s)hello" % origin_id):
            v1["summary"] = new_summary
            yical.updateTaskFromVTodo(t1, v1)
            self.assertEqual(t1.id, origin_id)
            self.assertEqual(t1.title, "hello")

        # Update votod with fake id info.
        # Should be present in task title
        for new_summary in ("hello", "hello()", "hello(123456)", "hello (123456)"):
            v1["summary"] = new_summary
            yical.updateTaskFromVTodo(t1, v1)
            self.assertEqual(t1.id, origin_id)
            self.assertEqual(t1.title, new_summary)
Пример #13
0
    def testTitleMapping(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        v1 = yical.createVTodoFromTask(t1)

        # Check id is here
        self.assertEqual(v1.get("summary")[-4:], " (%s)" % t1.id)

        # Title and id should not change with update
        origin_id = t1.id
        origin_title = t1.title
        yical.updateTaskFromVTodo(t1, v1)
        self.assertEqual(t1.id, origin_id)
        self.assertEqual(t1.title, origin_title)

        # Update vtodo summary and remove (id) or space before (id) info.
        # Only task title should be changed
        for new_summary in ("hello", "hello(%s)" % origin_id,
                            "hello (%s)" % origin_id, "(%s)hello" % origin_id,
                            " (%s)hello" % origin_id):
            v1["summary"] = new_summary
            yical.updateTaskFromVTodo(t1, v1)
            self.assertEqual(t1.id, origin_id)
            self.assertEqual(t1.title, "hello")

        # Update votod with fake id info.
        # Should be present in task title
        for new_summary in ("hello", "hello()", "hello(123456)",
                            "hello (123456)"):
            v1["summary"] = new_summary
            yical.updateTaskFromVTodo(t1, v1)
            self.assertEqual(t1.id, origin_id)
            self.assertEqual(t1.title, new_summary)
Пример #14
0
    def _processVTodo(self, vTodo):
        if vTodo["UID"] in self.newTask:
            # This is a recent new task but remote ical calendar tool is not
            # aware of new Yokadi UID. Update it here to avoid duplicate new tasks
            print "update UID to avoid duplicate task"
            vTodo["UID"] = TASK_UID % self.newTask[vTodo["UID"]]

        if vTodo["UID"].startswith(UID_PREFIX):
            # This is a yokadi Task.
            if vTodo["LAST-MODIFIED"].dt > vTodo["CREATED"].dt:
                # Task has been modified
                print "Modified task: %s" % vTodo["UID"]
                result = TASK_RE.match(vTodo["UID"])
                if result:
                    id = result.group(1)
                    task = dbutils.getTaskFromId(id)
                    print "Task found in yokadi db: %s" % task.title
                    updateTaskFromVTodo(task, vTodo)
                else:
                    raise YokadiException("Task %s does exist in yokadi db " %
                                          id)
        else:
            # This is a new task
            print "New task %s (%s)" % (vTodo["summary"], vTodo["UID"])
            keywordDict = {}
            task = dbutils.addTask(INBOX_PROJECT,
                                   vTodo["summary"],
                                   keywordDict,
                                   interactive=False)
            # Keep record of new task origin UID to avoid duplicate
            # if user update it right after creation without reloading the
            # yokadi UID
            # TODO: add purge for old UID
            self.newTask[vTodo["UID"]] = task.id
Пример #15
0
    def _t_add(self, cmd, line):
        """Code shared by t_add, bug_add and n_add."""
        parser = self._parser_t_add(cmd)
        args = parser.parse_args(line)

        line = " ".join(args.cmd)
        if not line:
            raise BadUsageException("Missing parameters")
        projectName, title, keywordDict = parseutils.parseLine(line)
        projectName = self._realProjectName(projectName)
        if not title:
            raise BadUsageException("Missing title")

        if args.crypt:
            # Obfuscate line in history
            length = readline.get_current_history_length()
            if length > 0:  # Ensure history is positive to avoid crash with bad readline setup
                readline.replace_history_item(length - 1, "%s %s " % (cmd,
                                                                  line.replace(title, "<...encrypted...>")))
            # Encrypt title
            title = self.cryptoMgr.encrypt(title)

        task = dbutils.addTask(projectName, title, keywordDict)
        if not task:
            tui.reinjectInRawInput("%s %s" % (cmd, line))
            return None
        self.lastTaskId = task.id

        if args.describe:
            self.do_t_describe(self.lastTaskId)
        return task
Пример #16
0
    def _t_add(self, cmd, line):
        """Code shared by t_add, bug_add and n_add."""
        parser = self._parser_t_add(cmd)
        args = parser.parse_args(line)

        line = " ".join(args.cmd)
        if not line:
            raise BadUsageException("Missing parameters")
        projectName, title, keywordDict = parseutils.parseLine(line)
        projectName = self._realProjectName(projectName)
        if not title:
            raise BadUsageException("Missing title")

        if args.crypt:
            # Obfuscate line in history
            length = readline.get_current_history_length()
            if length > 0:  # Ensure history is positive to avoid crash with bad readline setup
                readline.replace_history_item(
                    length - 1,
                    "%s %s " % (cmd, line.replace(title, "<...encrypted...>")))
            # Encrypt title
            title = self.cryptoMgr.encrypt(title)

        task = dbutils.addTask(projectName, title, keywordDict)
        if not task:
            tui.reinjectInRawInput(u"%s %s" % (cmd, line))
            return None
        self.lastTaskId = task.id

        if args.describe:
            self.do_t_describe(self.lastTaskId)

        return task
Пример #17
0
    def _processVTodo(self, vTodo):
        if vTodo["UID"] in self.newTask:
            # This is a recent new task but remote ical calendar tool is not
            # aware of new Yokadi UID. Update it here to avoid duplicate new tasks
            print "update UID to avoid duplicate task"
            vTodo["UID"] = TASK_UID % self.newTask[vTodo["UID"]]

        if vTodo["UID"].startswith(UID_PREFIX):
            # This is a yokadi Task.
            if vTodo["LAST-MODIFIED"].dt > vTodo["CREATED"].dt:
                # Task has been modified
                print "Modified task: %s" % vTodo["UID"]
                result = TASK_RE.match(vTodo["UID"])
                if result:
                    id = result.group(1)
                    task = dbutils.getTaskFromId(id)
                    print "Task found in yokadi db: %s" % task.title
                    updateTaskFromVTodo(task, vTodo)
                else:
                    raise YokadiException("Task %s does exist in yokadi db " % id)
        else:
            # This is a new task
            print "New task %s (%s)" % (vTodo["summary"], vTodo["UID"])
            keywordDict = {}
            task = dbutils.addTask(INBOX_PROJECT, vTodo["summary"], keywordDict, interactive=False)
            # Keep record of new task origin UID to avoid duplicate
            # if user update it right after creation without reloading the
            # yokadi UID
            # TODO: add purge for old UID
            self.newTask[vTodo["UID"]] = task.id
Пример #18
0
 def testKEditNoMerge(self):
     t1 = dbutils.addTask("x", "t1", dict(k1=12, k2=None), interactive=False)
     tui.addInputAnswers("newk1")
     self.cmd.do_k_edit("k1")
     kwDict = t1.getKeywordDict()
     self.assertTrue("k1" not in kwDict)
     self.assertEqual(kwDict.get("newk1"), 12)
     self.assertRaises(YokadiException, dbutils.getKeywordFromName, "k1")
Пример #19
0
 def testKRemove(self):
     t1 = dbutils.addTask("x", "t1", dict(k1=12, k2=None), interactive=False)
     tui.addInputAnswers("y")
     self.cmd.do_k_remove("k1")
     kwDict = t1.getKeywordDict()
     self.assertFalse("k1" in kwDict)
     self.assertTrue("k2" in kwDict)
     taskKeyword = self.session.query(db.TaskKeyword).filter_by(taskId=t1.id).one()
     self.assertEqual(taskKeyword.keyword.name, "k2")
Пример #20
0
    def testKEditMerge(self):
        t1 = dbutils.addTask("x",
                             "t1",
                             dict(k1=None, k2=None),
                             interactive=False)
        t2 = dbutils.addTask("x", "t2", dict(k1=None), interactive=False)
        tui.addInputAnswers("k2", "y")
        self.cmd.do_k_edit("k1")

        kwDict = t1.getKeywordDict()
        self.assertTrue("k1" not in kwDict)
        self.assertTrue("k2" in kwDict)

        kwDict = t2.getKeywordDict()
        self.assertTrue("k1" not in kwDict)
        self.assertTrue("k2" in kwDict)

        self.assertRaises(YokadiException, dbutils.getKeywordFromName, "k1")
Пример #21
0
    def testTfilter(self):
        t1 = dbutils.addTask("x", "t1", interactive=False)
        t2 = dbutils.addTask("x", "t2", keywordDict={"kw1": None, "kw2": 12}, interactive=False)
        t3 = dbutils.addTask("y", "t3", interactive=False)

        testData = [
            ("@kw1", {"x": [t2]}),
            ("x", {"x": [t1, t2]}),
            ("x @kw1", {"x": [t2]}),
            ("none", {"x": [t1, t2], "y": [t3]}),
        ]
        for filter, expectedTaskDict in testData:
            self.cmd.do_t_filter(filter)
            renderer = testutils.TestRenderer()
            self.cmd.do_t_list("", renderer=renderer)
            self.assertEqual(renderer.taskDict, expectedTaskDict)

        self.assertRaises(YokadiException, self.cmd.do_t_filter, "")
Пример #22
0
    def testSimpleFilter(self):
        t1 = dbutils.addTask("p1", "t1", interactive=False)
        t2 = dbutils.addTask("p1", "t2", keywordDict={"k1": None}, interactive=False)
        t3 = dbutils.addTask("p1", "t3", keywordDict={"k2": None}, interactive=False)
        t4 = dbutils.addTask("p1", "t4", keywordDict={"k1": None, "k2": None}, interactive=False)

        testData = [
            (KeywordFilter("k1"), {t2, t4}),
            (KeywordFilter("k%"), {t2, t3, t4}),
            (KeywordFilter("k1", negative=True), {t1, t3}),
            (KeywordFilter("k%", negative=True), {t1}),
        ]

        for flt, expected in testData:
            query = self.session.query(db.Task)
            query = flt.apply(query)
            resultSet = {x.title for x in query}
            expectedSet = {x.title for x in expected}
            self.assertEqual(resultSet, expectedSet)
Пример #23
0
 def testKEditNoMerge(self):
     t1 = dbutils.addTask("x",
                          "t1",
                          dict(k1=12, k2=None),
                          interactive=False)
     tui.addInputAnswers("newk1")
     self.cmd.do_k_edit("k1")
     kwDict = t1.getKeywordDict()
     self.assertTrue("k1" not in kwDict)
     self.assertEqual(kwDict.get("newk1"), 12)
     self.assertRaises(YokadiException, dbutils.getKeywordFromName, "k1")
Пример #24
0
    def testTfilter(self):
        t1 = dbutils.addTask("x", "t1", interactive=False)
        t2 = dbutils.addTask("x", "t2", keywordDict={"kw1": None, "kw2": 12}, interactive=False)
        t3 = dbutils.addTask("y", "t3", interactive=False)

        testData = [
            ("@kw1", {"x": [t2]}),
            ("@kw1 @kw2", {"x": [t2]}),
            ("x", {"x": [t1, t2]}),
            ("x @kw1", {"x": [t2]}),
            ("none", {"x": [t1, t2], "y": [t3]}),
        ]
        for filter, expectedTaskDict in testData:
            self.cmd.do_t_filter(filter)
            renderer = testutils.TestRenderer()
            self.cmd.do_t_list("", renderer=renderer)
            self.assertEqual(renderer.taskDict.keys(), expectedTaskDict.keys())
            for key in renderer.taskDict.keys():
                self.assertEqual([x.title for x in renderer.taskDict[key]], [x.title for x in expectedTaskDict[key]])

        self.assertRaises(YokadiException, self.cmd.do_t_filter, "")
Пример #25
0
    def testGetTaskFromId(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})

        task = dbutils.getTaskFromId(str(t1.id))
        self.assertEqual(task, t1)

        task = dbutils.getTaskFromId(t1.id)
        self.assertEqual(task, t1)

        task = dbutils.getTaskFromId(t1.uuid)
        self.assertEqual(task, t1)
Пример #26
0
    def testGetTaskFromId(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})

        task = dbutils.getTaskFromId(str(t1.id))
        self.assertEqual(task, t1)

        task = dbutils.getTaskFromId(t1.id)
        self.assertEqual(task, t1)

        task = dbutils.getTaskFromId(t1.uuid)
        self.assertEqual(task, t1)
Пример #27
0
    def testKEditCannotMerge(self):
        """
        One can't merge keywords if they have different values
        """
        t1 = dbutils.addTask("x", "t1", dict(k1=12, k2=None), interactive=False)
        tui.addInputAnswers("k2", "y")
        self.cmd.do_k_edit("k1")
        kwDict = t1.getKeywordDict()
        self.assertTrue("k1" in kwDict)
        self.assertTrue("k2" in kwDict)

        dbutils.getKeywordFromName("k1")
Пример #28
0
    def testApplyMEditChanges(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Change text", {})
        tui.addInputAnswers("y", "y")
        t2 = dbutils.addTask("p1", "Change keywords", {"k1": None, "k2": 1})
        t3 = dbutils.addTask("p1", "Done", {})
        t3.status = "started"
        self.session.merge(t3)
        t4 = dbutils.addTask("p1", "Deleted", {})
        t5 = dbutils.addTask("p1", "Moved", {})
        self.session.commit()
        deletedId = t4.id

        oldList = massedit.createEntriesForProject(prj)
        newList = [
            MEditEntry(None, "new", u"Added", {}),
            MEditEntry(t1.id, "new", u"New text", {}),
            MEditEntry(t2.id, "new", u"Change keywords", {
                "k2": 2,
                "k3": None
            }),
            MEditEntry(t5.id, "new", u"Moved", {}),
            MEditEntry(t3.id, "done", u"Done", {}),
        ]

        massedit.applyChanges(prj, oldList, newList, interactive=False)
        self.session.commit()

        newTask = self.session.query(db.Task).filter_by(title=u"Added").one()

        self.assertEqual(t1.title, u"New text")
        self.assertEqual(t2.getKeywordDict(), {"k2": 2, "k3": None})
        self.assertEqual(t3.status, "done")
        self.assertTrue(t3.doneDate)
        self.assertRaises(YokadiException, dbutils.getTaskFromId, deletedId)
        self.assertEqual(newTask.urgency, 5)
        self.assertEqual(t1.urgency, 4)
        self.assertEqual(t2.urgency, 3)
        self.assertEqual(t5.urgency, 2)
        self.assertEqual(t3.urgency, 1)
Пример #29
0
 def testKRemove(self):
     t1 = dbutils.addTask("x",
                          "t1",
                          dict(k1=12, k2=None),
                          interactive=False)
     tui.addInputAnswers("y")
     self.cmd.do_k_remove("k1")
     kwDict = t1.getKeywordDict()
     self.assertFalse("k1" in kwDict)
     self.assertTrue("k2" in kwDict)
     taskKeyword = self.session.query(
         db.TaskKeyword).filter_by(taskId=t1.id).one()
     self.assertEqual(taskKeyword.keyword.name, "k2")
Пример #30
0
    def testEdit(self):
        task = dbutils.addTask("prj", "bug", interactive=False)
        kwDict = dict(_severity=1, _likelihood=2, _bug=3)
        task.setKeywordDict(kwDict)
        self.session.commit()

        tui.addInputAnswers("bug edited", "2", "4", "6")
        self.cmd.do_bug_edit(str(task.id))

        task = dbutils.getTaskFromId(task.id)
        self.assertEqual(task.title, "bug edited")
        kwDict = task.getKeywordDict()
        self.assertEqual(kwDict, dict(_severity=2, _likelihood=4, _bug=6))
Пример #31
0
    def testMerge(self):
        COUNT = 4
        for x in range(COUNT):
            dbutils.addTask('p1', 'p1-t{}'.format(x), interactive=False)
            dbutils.addTask('p2', 'p2-t{}'.format(x), interactive=False)

        # Merge p1 into p2
        tui.addInputAnswers("y")
        self.cmd.do_p_merge("p1 p2")

        # p2 should have both its tasks and all p1 tasks now
        project = self.session.query(Project).filter_by(name="p2").one()
        tasks = set([x.title for x in project.tasks])

        expected = set()
        for x in range(COUNT):
            expected.add('p1-t{}'.format(x))
            expected.add('p2-t{}'.format(x))
        self.assertEqual(tasks, expected)

        # p1 should be gone
        testutils.assertQueryEmpty(self, self.session.query(Project).filter_by(name="p1"))
Пример #32
0
    def testRemove(self):
        # Create project p1 with one associated task
        tui.addInputAnswers("y")
        self.cmd.do_p_add("p1")
        self.session.query(Project).one()
        task = dbutils.addTask("p1", "t1", interactive=False)
        taskId = task.id

        # Remove project, its task should be removed
        tui.addInputAnswers("y")
        self.cmd.do_p_remove("p1")

        self.assertEqual(list(self.session.query(Task).filter_by(id=taskId)), [])
Пример #33
0
    def testEdit(self):
        task = dbutils.addTask("prj", "bug", interactive=False)
        kwDict = dict(_severity=1, _likelihood=2, _bug=3)
        task.setKeywordDict(kwDict)
        self.session.commit()

        tui.addInputAnswers("bug edited", "2", "4", "6")
        self.cmd.do_bug_edit(str(task.id))

        task = dbutils.getTaskFromId(task.id)
        self.assertEqual(task.title, "bug edited")
        kwDict = task.getKeywordDict()
        self.assertEqual(kwDict, dict(_severity=2, _likelihood=4, _bug=6))
Пример #34
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)
Пример #35
0
    def testRemove(self):
        # Create project p1 with one associated task
        tui.addInputAnswers("y")
        self.cmd.do_p_add("p1")
        project = self.session.query(Project).one()
        task = dbutils.addTask("p1", "t1", interactive=False)
        taskId = task.id

        # Remove project, its task should be removed
        tui.addInputAnswers("y")
        self.cmd.do_p_remove("p1")

        self.assertEqual(list(self.session.query(Task).filter_by(id=taskId)),
                         [])
Пример #36
0
    def testApplyMEditChanges(self):
        prj = dbutils.getOrCreateProject("p1", interactive=False)
        t1 = dbutils.addTask("p1", "Change text", {})
        tui.addInputAnswers("y", "y")
        t2 = dbutils.addTask("p1", "Change keywords", {"k1": None, "k2": 1})
        t3 = dbutils.addTask("p1", "Done", {})
        t3.status = "started"
        self.session.merge(t3)
        t4 = dbutils.addTask("p1", "Deleted", {})
        t5 = dbutils.addTask("p1", "Moved", {})
        self.session.commit()
        deletedId = t4.id

        oldList = massedit.createEntriesForProject(prj)
        newList = [
            MEditEntry(None, "new", u"Added", {}),
            MEditEntry(t1.id, "new", u"New text", {}),
            MEditEntry(t2.id, "new", u"Change keywords", {"k2": 2, "k3": None}),
            MEditEntry(t5.id, "new", u"Moved", {}),
            MEditEntry(t3.id, "done", u"Done", {}),
        ]

        massedit.applyChanges(prj, oldList, newList, interactive=False)
        self.session.commit()

        newTask = self.session.query(db.Task).filter_by(title=u"Added").one()

        self.assertEqual(t1.title, u"New text")
        self.assertEqual(t2.getKeywordDict(), {"k2": 2, "k3": None})
        self.assertEqual(t3.status, "done")
        self.assertTrue(t3.doneDate)
        self.assertRaises(YokadiException, dbutils.getTaskFromId, deletedId)
        self.assertEqual(newTask.urgency, 5)
        self.assertEqual(t1.urgency, 4)
        self.assertEqual(t2.urgency, 3)
        self.assertEqual(t5.urgency, 2)
        self.assertEqual(t3.urgency, 1)
Пример #37
0
    def testTaskLockManagerStaleLock(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        taskLockManager = dbutils.TaskLockManager(t1)

        # Lock the task
        taskLockManager.acquire(pid=1, now=datetime(2014, 1, 1))
        lock1 = taskLockManager._getLock()
        self.assertEqual(lock1.pid, 1)

        # Try to lock again, the stale lock should get reused
        taskLockManager.acquire(pid=2, now=datetime(2015, 1, 1))
        lock2 = taskLockManager._getLock()
        self.assertEqual(lock1.id, lock2.id)
        self.assertEqual(lock2.pid, 2)
Пример #38
0
    def testKEditCannotMerge(self):
        """
        One can't merge keywords if they have different values
        """
        t1 = dbutils.addTask("x",
                             "t1",
                             dict(k1=12, k2=None),
                             interactive=False)
        tui.addInputAnswers("k2", "y")
        self.cmd.do_k_edit("k1")
        kwDict = t1.getKeywordDict()
        self.assertTrue("k1" in kwDict)
        self.assertTrue("k2" in kwDict)

        dbutils.getKeywordFromName("k1")
Пример #39
0
    def testMerge(self):
        COUNT = 4
        for x in range(COUNT):
            dbutils.addTask('p1', 'p1-t{}'.format(x), interactive=False)
            dbutils.addTask('p2', 'p2-t{}'.format(x), interactive=False)

        # Merge p1 into p2
        tui.addInputAnswers("y")
        self.cmd.do_p_merge("p1 p2")

        # p2 should have both its tasks and all p1 tasks now
        project = self.session.query(Project).filter_by(name="p2").one()
        tasks = set([x.title for x in project.tasks])

        expected = set()
        for x in range(COUNT):
            expected.add('p1-t{}'.format(x))
            expected.add('p2-t{}'.format(x))
        self.assertEqual(tasks, expected)

        # p1 should be gone
        testutils.assertQueryEmpty(
            self,
            self.session.query(Project).filter_by(name="p1"))
Пример #40
0
    def testTaskLockManagerStaleLock(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        taskLockManager = dbutils.TaskLockManager(t1)

        # Lock the task
        taskLockManager.acquire(pid=1, now=datetime(2014, 1, 1))
        lock1 = taskLockManager._getLock()
        self.assertEqual(lock1.pid, 1)

        # Try to lock again, the stale lock should get reused
        taskLockManager.acquire(pid=2, now=datetime(2015, 1, 1))
        lock2 = taskLockManager._getLock()
        self.assertEqual(lock1.id, lock2.id)
        self.assertEqual(lock2.pid, 2)
Пример #41
0
    def testUrgencyMapping(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        v1 = yical.createVTodoFromTask(t1)

        self.assertEqual(v1.get("priority"), None)  # No priority

        t1.urgency = 45
        v1 = yical.createVTodoFromTask(t1)
        self.assertEqual(v1.get("priority"), 2)

        yical.updateTaskFromVTodo(t1, v1)
        self.assertEqual(t1.urgency, 45)  # Ensure urgency does change

        v1["priority"] = 4
        yical.updateTaskFromVTodo(t1, v1)
        self.assertEqual(t1.urgency, 20)  # Check urgency is updated
Пример #42
0
    def testUrgencyMapping(self):
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {})
        v1 = yical.createVTodoFromTask(t1)

        self.assertEquals(v1.get("priority"), None)  # No priority

        t1.urgency = 45
        v1 = yical.createVTodoFromTask(t1)
        self.assertEquals(v1.get("priority"), 2)

        yical.updateTaskFromVTodo(t1, v1)
        self.assertEquals(t1.urgency, 45)  # Ensure urgency does change

        v1["priority"] = 4
        yical.updateTaskFromVTodo(t1, v1)
        self.assertEquals(t1.urgency, 20)  # Check urgency is updated
Пример #43
0
    def testRemove(self):
        # Create project p1, with one project keyword and one associated task
        tui.addInputAnswers("y")
        self.cmd.do_p_add("p1 @kw")
        project = self.session.query(Project).one()
        task = dbutils.addTask("p1", "t1", interactive=False)
        taskId = task.id

        keyword = self.session.query(Keyword).filter_by(name="kw").one()
        self.assertEqual(keyword.projects, [project])

        # Remove project, its task should be removed and the created keyword
        # should no longer be associated with any project
        tui.addInputAnswers("y")
        self.cmd.do_p_remove("p1")

        self.assertEqual(keyword.projects, [])

        self.assertEqual(list(self.session.query(Task).filter_by(id=taskId)), [])
Пример #44
0
    def testKeywordMapping(self):
        tui.addInputAnswers("y")
        tui.addInputAnswers("y")
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {"k1": None, "k2": 123})
        v1 = yical.createVTodoFromTask(t1)

        # Check categories are created
        categories = [str(c) for c in v1.get("categories")]
        categories.sort()
        self.assertEqual(categories, ["k1", "k2=123"])

        # Check keywords are still here
        yical.updateTaskFromVTodo(t1, v1)
        keywords = list(t1.getKeywordDict().keys())
        self.session.commit()
        keywords.sort()
        self.assertEqual(keywords, ["k1", "k2"])
        self.assertEqual(t1.getKeywordDict()["k2"], 123)

        # Remove k2 category
        v1["categories"] = ["k1"]
        yical.updateTaskFromVTodo(t1, v1)
        self.session.commit()
        self.assertEqual(list(t1.getKeywordDict().keys()), [
            "k1",
        ])

        # Set k1 value
        v1["categories"] = [
            "k1=456",
        ]
        yical.updateTaskFromVTodo(t1, v1)
        self.session.commit()
        self.assertEqual(t1.getKeywordDict()["k1"], 456)

        # Create a category
        v1["categories"] = ["k1", "k4=789"]
        yical.updateTaskFromVTodo(t1, v1)
        keywords = list(t1.getKeywordDict().keys())
        keywords.sort()
        self.assertEqual(keywords, ["k1", "k4"])
        self.assertEqual(t1.getKeywordDict()["k4"], 789)
Пример #45
0
    def _t_add(self, cmd, line):
        """Code shared by t_add, bug_add and n_add."""
        parser = self._parser_t_add(cmd)
        args = parser.parse_args(line)

        line = " ".join(args.cmd)
        if not line:
            raise BadUsageException("Missing parameters")
        projectName, title, keywordDict = parseutils.parseLine(line)
        projectName = self._realProjectName(projectName)
        if not title:
            raise BadUsageException("Missing title")

        task = dbutils.addTask(projectName, title, keywordDict)
        if not task:
            tui.reinjectInRawInput("%s %s" % (cmd, line))
            return None
        self.lastTaskId = task.id

        if args.describe:
            self.do_t_describe(self.lastTaskId)
        return task
Пример #46
0
    def testKeywordMapping(self):
        tui.addInputAnswers("y")
        tui.addInputAnswers("y")
        tui.addInputAnswers("y")
        t1 = dbutils.addTask("x", "t1", {"k1": None, "k2": 123})
        v1 = yical.createVTodoFromTask(t1)

        # Check categories are created
        categories = [str(c) for c in v1.get("categories")]
        categories.sort()
        self.assertEqual(categories, ["k1", "k2=123"])

        # Check keywords are still here
        yical.updateTaskFromVTodo(t1, v1)
        keywords = list(t1.getKeywordDict().keys())
        self.session.commit()
        keywords.sort()
        self.assertEqual(keywords, ["k1", "k2"])
        self.assertEqual(t1.getKeywordDict()["k2"], 123)

        # Remove k2 category
        v1["categories"] = ["k1"]
        yical.updateTaskFromVTodo(t1, v1)
        self.session.commit()
        self.assertEqual(list(t1.getKeywordDict().keys()), ["k1", ])

        # Set k1 value
        v1["categories"] = ["k1=456", ]
        yical.updateTaskFromVTodo(t1, v1)
        self.session.commit()
        self.assertEqual(t1.getKeywordDict()["k1"], 456)

        # Create a category
        v1["categories"] = ["k1", "k4=789"]
        yical.updateTaskFromVTodo(t1, v1)
        keywords = list(t1.getKeywordDict().keys())
        keywords.sort()
        self.assertEqual(keywords, ["k1", "k4"])
        self.assertEqual(t1.getKeywordDict()["k4"], 789)
Пример #47
0
 def testTaskDoneMapping(self):
     tui.addInputAnswers("y")
     t1 = dbutils.addTask("x", "t1", {})
     v1 = yical.createVTodoFromTask(t1)
Пример #48
0
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
Пример #49
0
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()

    for name in PROJECTS:
        db.Project(name=name)

    for name in KEYWORDS:
        db.Keyword(name=name)

    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].
    """

    return 0
Пример #50
0
 def testTaskDoneMapping(self):
     tui.addInputAnswers("y")
     t1 = dbutils.addTask("x", "t1", {})
     v1 = yical.createVTodoFromTask(t1)