示例#1
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)
示例#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)
    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)
示例#4
0
    def testGetOrCreateProject(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateProject("p1")
        self.session.query(Project).filter_by(name="p1").one()

        # !interactive
        dbutils.getOrCreateProject("p2", interactive=False)
        self.session.query(Project).filter_by(name="p2").one()
示例#5
0
    def testGetOrCreateProject(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateProject("p1")
        self._assertOneObject(Project.selectBy(name="p1"))

        # !interactive
        dbutils.getOrCreateProject("p2", interactive=False)
        self._assertOneObject(Project.selectBy(name="p2"))
示例#6
0
    def testGetOrCreateProject(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateProject("p1")
        self._assertOneObject(Project.selectBy(name="p1"))

        # !interactive
        dbutils.getOrCreateProject("p2", interactive=False)
        self._assertOneObject(Project.selectBy(name="p2"))
示例#7
0
    def testGetOrCreateProject(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateProject("p1")
        self.session.query(Project).filter_by(name="p1").one()

        # !interactive
        dbutils.getOrCreateProject("p2", interactive=False)
        self.session.query(Project).filter_by(name="p2").one()
示例#8
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)
示例#9
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)
示例#10
0
    def do_p_edit(self, line):
        """Edit a project.
        p_edit <project name>"""
        session = db.getSession()
        project = dbutils.getOrCreateProject(line, createIfNeeded=False)

        if not project:
            raise YokadiException("Project does not exist.")

        # Create project line
        projectLine = parseutils.createLine(project.name, "", project.getKeywordDict())

        # Edit
        line = tui.editLine(projectLine)

        # Update project
        projectName, garbage, keywordDict = parseutils.parseLine(line)
        if garbage:
            raise BadUsageException("Cannot parse line, got garbage (%s)" % garbage)
        if not dbutils.createMissingKeywords(list(keywordDict.keys())):
            return
        try:
            project.name = projectName
            project.setKeywordDict(keywordDict)
            session.merge(project)
            session.commit()
        except IntegrityError:
            session.rollback()
            raise YokadiException("A project named %s already exists. Please find another name" % projectName)
示例#11
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)
示例#12
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)
示例#13
0
    def do_p_edit(self, line):
        """Edit a project.
        p_edit <project name>"""
        project = dbutils.getOrCreateProject(line, createIfNeeded=False)

        if not project:
            raise YokadiException("Project does not exist.")

        # Create project line
        projectLine = parseutils.createLine(project.name, "",
                                            project.getKeywordDict())

        # Edit
        line = tui.editLine(projectLine)

        # Update project
        projectName, garbage, keywordDict = parseutils.parseLine(line)
        if garbage:
            raise BadUsageException("Cannot parse line, got garbage (%s)" %
                                    garbage)
        if not dbutils.createMissingKeywords(keywordDict.keys()):
            return
        try:
            project.name = projectName
        except DuplicateEntryError:
            raise YokadiException(
                "A project named %s already exists. Please find another name" %
                projectName)
        project.setKeywordDict(keywordDict)
示例#14
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)
示例#15
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)
示例#16
0
文件: taskcmd.py 项目: bport/yokadi
    def do_t_project(self, line):
        """Set task's project.
        t_project <id> <project>"""
        tokens = parseutils.simplifySpaces(line).split(" ")
        if len(tokens) != 2:
            raise YokadiException("You should give two arguments: <task id> <project>")
        task = self.getTaskFromId(tokens[0])
        projectName = tokens[1]
        projectName = self._realProjectName(projectName)

        task.project = dbutils.getOrCreateProject(projectName)
        if task.project:
            print "Moved task '%s' to project '%s'" % (task.title, projectName)
示例#17
0
文件: taskcmd.py 项目: bport/yokadi
    def do_t_project(self, line):
        """Set task's project.
        t_project <id> <project>"""
        tokens = parseutils.simplifySpaces(line).split(" ")
        if len(tokens) != 2:
            raise YokadiException(
                "You should give two arguments: <task id> <project>")
        task = self.getTaskFromId(tokens[0])
        projectName = tokens[1]
        projectName = self._realProjectName(projectName)

        task.project = dbutils.getOrCreateProject(projectName)
        if task.project:
            print "Moved task '%s' to project '%s'" % (task.title, projectName)
示例#18
0
文件: taskcmd.py 项目: agateau/yokadi
    def do_t_medit(self, line):
        """Mass edit tasks of a project.
        t_medit <project_name>

        Starts a text editor with the task list, you can then:
        - edit tasks text and keywords
        - mark tasks as done or started
        - add new tasks
        - adjust urgency
        - delete tasks
        """
        if not line:
            raise BadUsageException("Missing parameters")
        projectName = parseOneWordName(line)
        projectName = self._realProjectName(projectName)
        project = dbutils.getOrCreateProject(projectName)
        if not project:
            return

        oldList = massedit.createEntriesForProject(project)
        oldText = massedit.createMEditText(oldList)
        newText = oldText
        while True:
            newText = tui.editText(newText, suffix=".medit")
            if newText == oldText:
                print("No changes")
                return

            try:
                newList = massedit.parseMEditText(newText)
            except massedit.ParseError as exc:
                print(exc)
                print()
                if tui.confirm("Modify text and try again"):
                    lst = newText.splitlines()
                    lst.insert(exc.lineNumber, "# ^ " + exc.message)
                    newText = "\n".join(lst)
                    continue
                else:
                    return

            try:
                massedit.applyChanges(project, oldList, newList)
                self.session.commit()
                break
            except YokadiException as exc:
                print(exc)
                print()
                if not tui.confirm("Modify text and try again"):
                    return
示例#19
0
文件: taskcmd.py 项目: semtle/yokadi
    def do_t_medit(self, line):
        """Mass edit tasks of a project.
        t_medit <project_name>

        Starts a text editor with the task list, you can then:
        - edit tasks text and keywords
        - mark tasks as done or started
        - add new tasks
        - adjust urgency
        - delete tasks
        """
        if not line:
            raise BadUsageException("Missing parameters")
        projectName = parseutils.parseOneWordName(line)
        projectName = self._realProjectName(projectName)
        project = dbutils.getOrCreateProject(projectName)
        if not project:
            return

        oldList = massedit.createEntriesForProject(project)
        oldText = massedit.createMEditText(oldList)
        newText = oldText
        while True:
            newText = tui.editText(newText, suffix=".medit")
            if newText == oldText:
                print("No changes")
                return

            try:
                newList = massedit.parseMEditText(newText)
            except massedit.ParseError as exc:
                print(exc)
                print()
                if tui.confirm("Modify text and try again"):
                    lst = newText.splitlines()
                    lst.insert(exc.lineNumber, "# ^ " + exc.message)
                    newText = "\n".join(lst)
                    continue
                else:
                    return

            try:
                massedit.applyChanges(project, oldList, newList)
                self.session.commit()
                break
            except YokadiException as exc:
                print(exc)
                print()
                if not tui.confirm("Modify text and try again"):
                    return
示例#20
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)
示例#21
0
    def do_p_edit(self, line):
        """Edit a project.
        p_edit <project name>"""
        session = db.getSession()
        project = dbutils.getOrCreateProject(line, createIfNeeded=False)

        if not project:
            raise YokadiException("Project does not exist.")

        # Edit
        line = tui.editLine(project.name)

        # Update project
        projectName = parseutils.parseOneWordName(line)
        try:
            project.name = projectName
            session.commit()
        except IntegrityError:
            session.rollback()
            raise YokadiException("A project named %s already exists. Please find another name" % projectName)
示例#22
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)
示例#23
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)