Пример #1
0
def decryptEncryptedTasks(cursor):
    sql = "select id, title, description from task where title like ?"

    rows = cursor.execute(sql, (CRYPTO_PREFIX + "%",)).fetchall()
    if not rows:
        return

    if CRYPTO_ALGO is None:
        msg = ("This database contains encrypted data but pycrypto is not"
               " installed.\n"
               "Please install pycrypto and try again.")
        raise updateutils.UpdateError(msg)

    if not tui.confirm("This database contains encrypted tasks, but Yokadi no "
                       "longer supports encryption.\n"
                       "These tasks need to be decrypted to continue using "
                       "Yokadi.\n"
                       "Do you want to decrypt your tasks?"):
        raise updateutils.UpdateCanceledError()

    checkText = getCheckText(cursor)
    while True:
        phrase = getPassphrase()
        cypher = CRYPTO_ALGO.new(phrase)
        if checkPassphrase(cypher, checkText):
            break
        else:
            if not tui.confirm("Wrong passphrase, try again?"):
                raise updateutils.UpdateCanceledError()
    for row in rows:
        decryptTask(cursor, cypher, row)
Пример #2
0
    def testConfirm(self):
        tui.addInputAnswers("zog", "y")
        value = tui.confirm("bla")
        self.assertTrue(value)

        tui.addInputAnswers("zog", "n")
        value = tui.confirm("bla")
        self.assertFalse(value)
Пример #3
0
    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
Пример #4
0
    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
Пример #5
0
    def do_k_edit(self, line):
        """Edit a keyword
        k_edit @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)
        oldName = keyword.name
        newName = tui.editLine(oldName)
        if newName == "":
            print("Cancelled")
            return

        lst = session.query(Keyword).filter_by(name=newName).all()
        if len(lst) == 0:
            # Simple case: newName does not exist, just rename the existing keyword
            keyword.name = newName
            session.merge(keyword)
            session.commit()
            print("Keyword %s has been renamed to %s" % (oldName, newName))
            return

        # We already have a keyword with this name, we need to merge
        print("Keyword %s already exists" % newName)
        if not tui.confirm("Do you want to merge %s and %s" %
                           (oldName, newName)):
            return

        # Check we can merge
        conflictingTasks = []
        for task in keyword.tasks:
            kwDict = task.getKeywordDict()
            if oldName in kwDict and newName in kwDict and kwDict[
                    oldName] != kwDict[newName]:
                conflictingTasks.append(task)

        if len(conflictingTasks) > 0:
            # We cannot merge
            tui.error("Cannot merge keywords %s and %s because they are both"
                      " used with different values in these tasks:" %
                      (oldName, newName))
            for task in conflictingTasks:
                print("- %d, %s" % (task.id, task.title))
            print("Edit these tasks and try again")
            return

        # Merge
        for task in keyword.tasks:
            kwDict = task.getKeywordDict()
            if newName not in kwDict:
                kwDict[newName] = kwDict[oldName]
            del kwDict[oldName]
            task.setKeywordDict(kwDict)
        session.delete(keyword)
        session.commit()
        print("Keyword %s has been merged with %s" % (oldName, newName))
Пример #6
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            print "The keyword %s is used by the following tasks: %s" % (keyword.name,
                                                                         ", ".join(str(task.id) for task in keyword.tasks))
            if tui.confirm("Do you really want to remove this keyword"):
                keyword.destroySelf()
                print "Keyword %s has been removed" % keyword.name
Пример #7
0
    def do_p_merge(self, line):
        session = db.getSession()
        parser = self.parser_p_merge()
        args = parser.parse_args(line)

        src = getProjectFromName(args.source_project)
        dst = getProjectFromName(args.destination_project)
        if not args.force:
            if not tui.confirm("Merge project '{}' into '{}'".format(src.name, dst.name)):
                return
        dst.merge(session, src)
        print("Project '{}' merged into '{}'".format(src.name, dst.name))
Пример #8
0
 def do_p_remove(self, line):
     session = db.getSession()
     parser = self.parser_p_remove()
     args = parser.parse_args(line)
     project = getProjectFromName(args.project)
     nbTasks = len(project.tasks)
     if not args.force:
         if not tui.confirm("Remove project '%s' and its %d tasks" % (project.name, nbTasks)):
             return
     session.delete(project)
     session.commit()
     print("Project removed")
Пример #9
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            print("The keyword %s is used by the following tasks: %s" % (keyword.name,
                                                                         ", ".join(str(task.id) for task in keyword.tasks)))
            if tui.confirm("Do you really want to remove this keyword"):
                session.delete(keyword)
                session.commit()
                print("Keyword %s has been removed" % keyword.name)
Пример #10
0
    def do_p_merge(self, line):
        session = db.getSession()
        parser = self.parser_p_merge()
        args = parser.parse_args(line)

        src = getProjectFromName(args.source_project)
        dst = getProjectFromName(args.destination_project)
        if not args.force:
            if not tui.confirm("Merge project '{}' into '{}'".format(
                    src.name, dst.name)):
                return
        dst.merge(session, src)
        print("Project '{}' merged into '{}'".format(src.name, dst.name))
Пример #11
0
    def do_k_edit(self, line):
        """Edit a keyword
        k_edit @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)
        oldName = keyword.name
        newName = tui.editLine(oldName)
        if newName == "":
            print("Cancelled")
            return

        lst = session.query(Keyword).filter_by(name=newName).all()
        if len(lst) == 0:
            # Simple case: newName does not exist, just rename the existing keyword
            keyword.name = newName
            session.merge(keyword)
            session.commit()
            print("Keyword %s has been renamed to %s" % (oldName, newName))
            return

        # We already have a keyword with this name, we need to merge
        print("Keyword %s already exists" % newName)
        if not tui.confirm("Do you want to merge %s and %s" % (oldName, newName)):
            return

        # Check we can merge
        conflictingTasks = []
        for task in keyword.tasks:
            kwDict = task.getKeywordDict()
            if oldName in kwDict and newName in kwDict and kwDict[oldName] != kwDict[newName]:
                conflictingTasks.append(task)

        if len(conflictingTasks) > 0:
            # We cannot merge
            tui.error("Cannot merge keywords %s and %s because they are both"
                      " used with different values in these tasks:" % (oldName, newName))
            for task in conflictingTasks:
                print("- %d, %s" % (task.id, task.title))
            print("Edit these tasks and try again")
            return

        # Merge
        for task in keyword.tasks:
            kwDict = task.getKeywordDict()
            if newName not in kwDict:
                kwDict[newName] = kwDict[oldName]
            del kwDict[oldName]
            task.setKeywordDict(kwDict)
        session.delete(keyword)
        session.commit()
        print("Keyword %s has been merged with %s" % (oldName, newName))
Пример #12
0
    def do_t_remove(self, line):
        parser = self.parser_t_remove()
        args = parser.parse_args(line)
        task = self.getTaskFromId(args.id)
        if not args.force:
            if not tui.confirm("Remove task '%s'" % task.title):
                return
        projectId = task.project.id
        task.destroySelf()
        print "Task '%s' removed" % (task.title)

        # Delete project with no associated tasks
        if Task.select(Task.q.projectID == projectId).count() == 0:
            Project.delete(projectId)
Пример #13
0
    def do_t_remove(self, line):
        parser = self.parser_t_remove()
        args = parser.parse_args(line)
        task = self.getTaskFromId(args.id)
        if not args.force:
            if not tui.confirm("Remove task '%s'" % task.title):
                return
        projectId = task.project.id
        task.destroySelf()
        print "Task '%s' removed" % (task.title)

        # Delete project with no associated tasks
        if Task.select(Task.q.projectID == projectId).count() == 0:
            Project.delete(projectId)
Пример #14
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            taskList = ", ".join(str(task.id) for task in keyword.tasks)
            print("The keyword {} is used by the following tasks: {}".format(keyword.name, taskList))
            if not tui.confirm("Do you really want to remove this keyword"):
                return
        session.delete(keyword)
        session.commit()
        print("Keyword {} has been removed".format(keyword.name))
Пример #15
0
    def do_t_remove(self, line):
        parser = self.parser_t_remove()
        args = parser.parse_args(line)
        task = self.getTaskFromId(args.id)
        if not args.force:
            if not tui.confirm("Remove task '%s'" % task.title):
                return
        project = task.project
        self.session.delete(task)
        print("Task '%s' removed" % (task.title))

        # Delete project with no associated tasks
        if self.session.query(Task).filter_by(project=project).count() == 0:
            self.session.delete(project)
        self.session.commit()
Пример #16
0
    def do_t_remove(self, line):
        parser = self.parser_t_remove()
        args = parser.parse_args(line)
        task = self.getTaskFromId(args.id)
        if not args.force:
            if not tui.confirm("Remove task '%s'" % task.title):
                return
        project = task.project
        self.session.delete(task)
        print("Task '%s' removed" % (task.title))

        # Delete project with no associated tasks
        if self.session.query(Task).filter_by(project=project).count() == 0:
            self.session.delete(project)
        self.session.commit()
Пример #17
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            taskList = ", ".join(str(task.id) for task in keyword.tasks)
            print("The keyword {} is used by the following tasks: {}".format(
                keyword.name, taskList))
            if not tui.confirm("Do you really want to remove this keyword"):
                return
        session.delete(keyword)
        session.commit()
        print("Keyword {} has been removed".format(keyword.name))
Пример #18
0
 def do_p_remove(self, line):
     parser = self.parser_p_remove()
     args = parser.parse_args(line)
     project = getProjectFromName(args.project)
     taskList = Task.select(Task.q.projectID == project.id)
     taskList = list(taskList)
     if not args.force:
         if not tui.confirm("Remove project '%s' and its %d tasks" % (project.name, len(taskList))):
             return
     print "Removing project tasks:"
     for task in taskList:
         task.delete(task.id)
         print "- task %(id)-3s: %(title)-30s" % dict(id=str(task.id), title=str(task.title))
     project.delete(project.id)
     print "Project removed"
Пример #19
0
def getOrCreateKeyword(keywordName, interactive=True):
    """Get a keyword by its name. Create it if needed
    @param keywordName: keyword name as a string
    @param interactive: Ask user before creating keyword (this is the default)
    @type interactive: Bool
    @return: Keyword instance or None if user cancel creation"""
    session = db.getSession()
    try:
        return session.query(Keyword).filter_by(name=keywordName).one()
    except (NoResultFound, MultipleResultsFound):
        if interactive and not tui.confirm("Keyword '%s' does not exist, create it" % keywordName):
            return None
        keyword = Keyword(name=keywordName)
        session.add(keyword)
        print("Added keyword '%s'" % keywordName)
        return keyword
Пример #20
0
def getOrCreateKeyword(keywordName, interactive=True):
    """Get a keyword by its name. Create it if needed
    @param keywordName: keyword name as a string
    @param interactive: Ask user before creating keyword (this is the default)
    @type interactive: Bool
    @return: Keyword instance or None if user cancel creation"""
    result = Keyword.selectBy(name=keywordName)
    result = list(result)
    if len(result):
        return result[0]

    if interactive and not tui.confirm("Keyword '%s' does not exist, create it" % keywordName):
        return None
    keyword = Keyword(name=keywordName)
    print "Added keyword '%s'" % keywordName
    return keyword
Пример #21
0
 def do_t_purge(self, line):
     parser = self.parser_t_purge()
     args = parser.parse_args(line)
     filters = []
     filters.append(Task.q.status == "done")
     filters.append(Task.q.doneDate < (datetime.now() - timedelta(days=args.delay)))
     tasks = Task.select(AND(*filters))
     if tasks.count() == 0:
         print "No tasks need to be purged"
         return
     print "The following tasks will be removed:"
     print "\n".join(["%s: %s" % (task.id, task.title) for task in tasks])
     if args.force or tui.confirm("Do you really want to remove those tasks (this action cannot be undone)?"):
         Task.deleteMany(AND(*filters))
         print "Tasks deleted"
     else:
         print "Purge canceled"
Пример #22
0
 def do_p_remove(self, line):
     parser = self.parser_p_remove()
     args = parser.parse_args(line)
     project = getProjectFromName(args.project)
     taskList = Task.select(Task.q.projectID == project.id)
     taskList = list(taskList)
     if not args.force:
         if not tui.confirm("Remove project '%s' and its %d tasks" %
                            (project.name, len(taskList))):
             return
     print "Removing project tasks:"
     for task in taskList:
         task.delete(task.id)
         print "- task %(id)-3s: %(title)-30s" % dict(id=str(task.id),
                                                      title=str(task.title))
     project.delete(project.id)
     print "Project removed"
Пример #23
0
def getOrCreateKeyword(keywordName, interactive=True):
    """Get a keyword by its name. Create it if needed
    @param keywordName: keyword name as a string
    @param interactive: Ask user before creating keyword (this is the default)
    @type interactive: Bool
    @return: Keyword instance or None if user cancel creation"""
    session = db.getSession()
    try:
        return session.query(Keyword).filter_by(name=keywordName).one()
    except (NoResultFound, MultipleResultsFound):
        if interactive and not tui.confirm(
                "Keyword '%s' does not exist, create it" % keywordName):
            return None
        keyword = Keyword(name=keywordName)
        session.add(keyword)
        print("Added keyword '%s'" % keywordName)
        return keyword
Пример #24
0
 def do_t_purge(self, line):
     parser = self.parser_t_purge()
     args = parser.parse_args(line)
     filters = []
     filters.append(Task.q.status == "done")
     filters.append(
         Task.q.doneDate < (datetime.now() - timedelta(days=args.delay)))
     tasks = Task.select(AND(*filters))
     if tasks.count() == 0:
         print "No tasks need to be purged"
         return
     print "The following tasks will be removed:"
     print "\n".join(["%s: %s" % (task.id, task.title) for task in tasks])
     if args.force or tui.confirm(
             "Do you really want to remove those tasks (this action cannot be undone)?"
     ):
         Task.deleteMany(AND(*filters))
         print "Tasks deleted"
     else:
         print "Purge canceled"
Пример #25
0
def getOrCreateProject(projectName, interactive=True, createIfNeeded=True):
    """Get a project by its name. Create it if needed
    @param projectName: project name as a string
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @param createIfNeeded: create project if it does not exist (this is the default)
    @type createIfNeeded: Bool
    @return: Project instance or None if user cancel creation or createIfNeeded is False"""
    result = Project.selectBy(name=projectName)
    result = list(result)
    if len(result):
        return result[0]

    if not createIfNeeded:
        return None

    if interactive and not tui.confirm("Project '%s' does not exist, create it" % projectName):
        return None

    project = Project(name=projectName)
    print "Added project '%s'" % projectName
    return project
Пример #26
0
def getOrCreateProject(projectName, interactive=True, createIfNeeded=True):
    """Get a project by its name. Create it if needed
    @param projectName: project name as a string
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @param createIfNeeded: create project if it does not exist (this is the default)
    @type createIfNeeded: Bool
    @return: Project instance or None if user cancel creation or createIfNeeded is False"""
    session = db.getSession()
    result = session.query(Project).filter_by(name=projectName).all()
    if len(result):
        return result[0]

    if not createIfNeeded:
        return None

    if interactive and not tui.confirm("Project '%s' does not exist, create it" % projectName):
        return None

    project = Project(name=projectName)
    session.add(project)
    print("Added project '%s'" % projectName)
    return project
Пример #27
0
def getOrCreateProject(projectName, interactive=True, createIfNeeded=True):
    """Get a project by its name. Create it if needed
    @param projectName: project name as a string
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @param createIfNeeded: create project if it does not exist (this is the default)
    @type createIfNeeded: Bool
    @return: Project instance or None if user cancel creation or createIfNeeded is False"""
    session = db.getSession()
    result = session.query(Project).filter_by(name=projectName).all()
    if len(result):
        return result[0]

    if not createIfNeeded:
        return None

    if interactive and not tui.confirm(
            "Project '%s' does not exist, create it" % projectName):
        return None

    project = Project(name=projectName)
    session.add(project)
    print("Added project '%s'" % projectName)
    return project