コード例 #1
0
ファイル: taskcmd.py プロジェクト: semtle/yokadi
    def do_t_urgency(self, line):
        """Defines urgency of a task.
        t_urgency <id> <value>"""

        tokens = parseutils.simplifySpaces(line).split(" ")
        if len(tokens) != 2:
            raise BadUsageException(
                "You must provide a taskId and an urgency value")
        task = self.getTaskFromId(tokens[0])
        try:
            # Do not use isdigit(), so that we can set negative urgency. This
            # make it possible to stick tasks to the bottom of the list.
            urgency = int(tokens[1])
        except ValueError:
            raise BadUsageException("Task urgency must be a digit")

        if urgency > 100:
            tui.warning("Max urgency is 100")
            urgency = 100
        elif urgency < -99:
            tui.warning("Min urgency is -99")
            urgency = -99

        task.urgency = urgency
        self.session.merge(task)
        self.session.commit()
コード例 #2
0
ファイル: taskcmd.py プロジェクト: bport/yokadi
    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
コード例 #3
0
ファイル: taskcmd.py プロジェクト: bport/yokadi
    def do_t_reorder(self, line):
        """Reorder tasks of a project.
        It works by starting an editor with the task list: you can then change
        the order of the lines and save the list. The urgency field will be
        updated to match the order.
        t_reorder <project_name>"""
        try:
            project = Project.byName(line)
        except SQLObjectNotFound:
            raise BadUsageException("You must provide a valid project name")

        taskList = Task.select(AND(Task.q.projectID == project.id,
                                   Task.q.status != 'done'),
                               orderBy=-Task.q.urgency)
        lines = ["%d,%s" % (x.id, x.title) for x in taskList]
        text = tui.editText("\n".join(lines))

        ids = []
        for line in text.split("\n"):
            line = line.strip()
            if not "," in line:
                continue
            id = int(line.split(",")[0])
            ids.append(id)

        ids.reverse()
        for urgency, id in enumerate(ids):
            task = Task.get(id)
            task.urgency = urgency
コード例 #4
0
ファイル: taskcmd.py プロジェクト: semtle/yokadi
    def do_t_reorder(self, line):
        """Reorder tasks of a project.
        It works by starting an editor with the task list: you can then change
        the order of the lines and save the list. The urgency field will be
        updated to match the order.
        t_reorder <project_name>"""
        try:
            project = self.session.query(Project).filter_by(name=line).one()
        except (MultipleResultsFound, NoResultFound):
            raise BadUsageException("You must provide a valid project name")

        taskList = self.session.query(Task).filter(
            Task.projectId == project.id,
            Task.status != 'done').order_by(desc(Task.urgency))
        lines = ["%d,%s" % (x.id, x.title) for x in taskList]
        text = tui.editText("\n".join(lines))

        ids = []
        for line in text.split("\n"):
            line = line.strip()
            if not "," in line:
                continue
            ids.append(int(line.split(",")[0]))

        ids.reverse()
        for urgency, taskId in enumerate(ids):
            task = self.session.query(Task).get(taskId)
            task.urgency = urgency
            self.session.merge(task)
        self.session.commit()
コード例 #5
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)
コード例 #6
0
ファイル: taskcmd.py プロジェクト: semtle/yokadi
    def do_t_apply(self, line):
        """Apply a command to several tasks.
        t_apply <id1>[,<id2>,[<id3>]...]] <command> <args>
        Use x-y to select task range from x to y
        Use __ to select all tasks previously selected with t_list"""
        ids = []
        if "__" in line:
            if self.lastTaskIds:
                line = line.replace(
                    "__", ",".join([str(i) for i in self.lastTaskIds]))
            else:
                raise BadUsageException(
                    "You must select tasks with t_list prior to use __")
        rangeId = re.compile("(\d+)-(\d+)")
        tokens = re.split("[\s|,]", line)
        if len(tokens) < 2:
            raise BadUsageException("Give at least a task id and a command")

        idScan = True  # Indicate we are parsing ids
        cmdTokens = []  # Command that we want to apply
        for token in tokens:
            if token == "":
                continue
            if idScan:
                result = rangeId.match(token)
                if result:
                    ids.extend(
                        list(
                            range(int(result.group(1)),
                                  int(result.group(2)) + 1)))
                elif token.isdigit():
                    ids.append(int(token))
                else:
                    # Id list is finished. Grab rest of line.
                    cmdTokens.append(token)
                    idScan = False
            else:
                cmdTokens.append(token)

        if not cmdTokens:
            raise BadUsageException("Give a command to apply")
        cmd = cmdTokens.pop(0)
        for taskId in ids:
            line = " ".join([cmd, str(taskId), " ".join(cmdTokens)])
            print("Executing: %s" % line)
            self.onecmd(line.strip())
コード例 #7
0
 def do_k_add(self, line):
     """Add a keyword
     k_add @<keyword1> [@<keyword2>...]"""
     if not line:
         raise BadUsageException("You must provide at least one keyword name")
     for keyword in line.split():
         try:
             Keyword(name=keyword)
             print "Keyword %s has been created" % keyword
         except DuplicateEntryError:
             print "Keyword %s already exist" % keyword
コード例 #8
0
def getProjectFromName(name, parameterName="project_name"):
    """
    Helper function which returns a project given its name, or raise a
    YokadiException if it does not exist.
    """
    name = name.strip()
    if len(name) == 0:
        raise BadUsageException("Missing <%s> parameter" % parameterName)

    try:
        session = db.getSession()
        return session.query(Project).filter_by(name=name).one()
    except NoResultFound:
        raise YokadiException("Project '%s' not found. Use p_list to see all projects." % name)
コード例 #9
0
 def do_k_add(self, line):
     """Add a keyword
     k_add @<keyword1> [@<keyword2>...]"""
     session = db.getSession()
     if not line:
         raise BadUsageException("You must provide at least one keyword name")
     for keyword in line.split():
         try:
             session.add(Keyword(name=keyword))
             session.commit()
             print("Keyword %s has been created" % keyword)
         except IntegrityError:
             session.rollback()
             print("Keyword %s already exist" % keyword)
コード例 #10
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
コード例 #11
0
def getProjectFromName(name, parameterName="project_name"):
    """
    Helper function which returns a project given its name, or raise a
    YokadiException if it does not exist.
    """
    name = name.strip()
    if len(name) == 0:
        raise BadUsageException("Missing <%s> parameter" % parameterName)

    try:
        return Project.byName(name)
    except SQLObjectNotFound:
        raise YokadiException(
            "Project '%s' not found. Use p_list to see all projects." % name)
コード例 #12
0
ファイル: aliascmd.py プロジェクト: semtle/yokadi
    def do_a_add(self, line):
        """Add an alias on a command
        Ex. create an alias 'la' for 't_list -a':
        a_add la t_list -a"""
        tokens = line.split()
        if len(tokens) < 2:
            raise BadUsageException("You should provide an alias name and a command")
        name = tokens[0]
        if name in self.aliases:
            raise YokadiException("There is already an alias named {}.".format(name))
        command = " ".join(tokens[1:])

        session = db.getSession()
        db.Alias.add(session, name, command)
        session.commit()
        self._updateAliasDict()
コード例 #13
0
 def do_c_set(self, line):
     """Set a configuration key to value : c_set <key> <value>"""
     line = line.split()
     if len(line) < 2:
         raise BadUsageException("You should provide two arguments : the parameter key and the value")
     name = line[0]
     value = " ".join(line[1:])
     session = db.getSession()
     p = session.query(Config).filter_by(name=name, system=False)
     if p.count() == 0:
         raise YokadiException("Sorry, no parameter match")
     else:
         if self.checkParameterValue(name, value):
             p[0].value = value
             tui.info("Parameter updated")
         else:
             raise YokadiException("Parameter value is incorrect")
コード例 #14
0
ファイル: confcmd.py プロジェクト: bport/yokadi
 def do_c_set(self, line):
     """Set a configuration key to value : c_set <key> <value>"""
     line = line.split()
     if len(line) < 2:
         raise BadUsageException(
             "You should provide two arguments : the parameter key and the value"
         )
     name = line[0]
     value = " ".join(line[1:])
     p = Config.select(AND(Config.q.name == name, Config.q.system == False))
     if p.count() == 0:
         tui.error("Sorry, no parameter match")
     else:
         if self.checkParameterValue(name, value):
             p[0].value = value
             tui.info("Parameter updated")
         else:
             tui.error("Parameter value is incorrect")
コード例 #15
0
 def do_p_add(self, line):
     """Add new project. Will prompt to create keywords if they do not exist.
     p_add <projectName> [@<keyword1>] [@<keyword2>]"""
     if not line:
         print "Give at least a project name !"
         return
     projectName, garbage, keywordDict = parseutils.parseLine(line)
     if garbage:
         raise BadUsageException("Cannot parse line, got garbage (%s)" %
                                 garbage)
     try:
         project = Project(name=projectName)
     except DuplicateEntryError:
         raise YokadiException(
             "A project named %s already exists. Please find another name" %
             projectName)
     print "Added project '%s'" % projectName
     if not dbutils.createMissingKeywords(keywordDict.keys()):
         return None
     project.setKeywordDict(keywordDict)
コード例 #16
0
ファイル: aliascmd.py プロジェクト: bport/yokadi
    def do_a_add(self, line):
        """Add an alias on a command
        Ex. create an alias 'la' for 't_list -a':
        a_add la t_list -a"""
        tokens = line.split()
        if len(tokens) < 2:
            raise BadUsageException(
                "You should provide an alias name and a command")
        name = tokens[0]
        command = " ".join(tokens[1:])
        self.aliases.update({name: command})
        try:
            aliases = Config.selectBy(name="ALIASES")[0]
        except IndexError:
            # Config entry does not exist. Create it.
            aliases = Config(name="ALIASES",
                             value="{}",
                             system=True,
                             desc="User command aliases")

        aliases.value = repr(self.aliases)