예제 #1
0
    def testGetOrCreateKeyword(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateKeyword("k1")
        self._assertOneObject(Keyword.selectBy(name="k1"))

        # !interactive
        dbutils.getOrCreateKeyword("k2", interactive=False)
        self._assertOneObject(Keyword.selectBy(name="k2"))
예제 #2
0
    def testGetOrCreateKeyword(self):
        # interactive
        tui.addInputAnswers("y")
        dbutils.getOrCreateKeyword("k1")
        self._assertOneObject(Keyword.selectBy(name="k1"))

        # !interactive
        dbutils.getOrCreateKeyword("k2", interactive=False)
        self._assertOneObject(Keyword.selectBy(name="k2"))
예제 #3
0
파일: dbutils.py 프로젝트: bport/yokadi
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
예제 #4
0
파일: parseutils.py 프로젝트: bport/yokadi
def warnIfKeywordDoesNotExist(keywordFilters):
    """Warn user is keyword does not exist
    @return: True if at least one keyword does not exist, else False"""
    doesNotExist = False
    for keyword in [k.name for k in keywordFilters]:
        if Keyword.select(LIKE(Keyword.q.name, keyword)).count() == 0:
            tui.error("Keyword %s is unknown." % keyword)
            doesNotExist = True
    return doesNotExist
예제 #5
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
예제 #6
0
파일: dbutils.py 프로젝트: bport/yokadi
def getKeywordFromName(name):
    """Returns a keyword from its name, which may start with "@"
    raises a YokadiException if not found
    @param name: the keyword name
    @return: The keyword"""
    if not name:
        raise YokadiException("No keyword supplied")
    if name.startswith("@"):
        name = name[1:]
    lst = list(Keyword.selectBy(name=name))
    if len(lst) == 0:
        raise YokadiException("No keyword named '%s' found" % name)
    return lst[0]
예제 #7
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)
예제 #8
0
파일: taskcmd.py 프로젝트: bport/yokadi
    def _renderList(self, renderer, projectList, filters, order,
                    limit=None, groupKeyword=None):
        """
        Render a list using renderer, according to the restrictions set by the
        other parameters
        @param renderer: renderer class (for example: TextListRenderer)
        @param projectList: list of project name (as unicode string)
        @param filters: filters in sqlobject format (example: Task.q.status == 'done')
        @param order: ordering in sqlobject format (example: -Task.q.urgency)
        @param limit: limit number tasks (int) or None for no limit
        @param groupKeyword: keyword used for grouping (as unicode string) or None
        """
        if groupKeyword:
            if groupKeyword.startswith("@"):
                groupKeyword = groupKeyword[1:]
            for keyword in Keyword.select(LIKE(Keyword.q.name, groupKeyword)):
                if unicode(keyword.name).startswith("_") and not groupKeyword.startswith("_"):
                    # BUG: cannot filter on db side because sqlobject does not understand ESCAPE needed whith _
                    continue
                taskList = Task.select(AND(TaskKeyword.q.keywordID == keyword.id,
                                           *filters),
                                       orderBy=order, limit=limit, distinct=True,
                                       join=LEFTJOINOn(Task, TaskKeyword, Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)
                if projectList:
                    taskList = [x for x in taskList if x.project in projectList]
                if len(taskList) > 0:
                    self.lastTaskIds.extend([t.id for t in taskList])  # Keep selected id for further use
                    renderer.addTaskList(unicode(keyword), taskList)
            renderer.end()
        else:
            hiddenProjectNames = []
            for project in projectList:
                if not project.active:
                    hiddenProjectNames.append(project.name)
                    continue
                taskList = Task.select(AND(Task.q.projectID == project.id, *filters),
                                       orderBy=order, limit=limit, distinct=True,
                                       join=LEFTJOINOn(Task, TaskKeyword, Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)

                if len(taskList) > 0:
                    self.lastTaskIds.extend([t.id for t in taskList])  # Keep selected id for further use
                    renderer.addTaskList(unicode(project), taskList)
            renderer.end()

            if len(hiddenProjectNames) > 0:
                tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))
예제 #9
0
    def testRenderListSectionOrderKeywords(self):
        prj = Project(name="prj")
        keywordNames = ["kw_" + x for x in ("ccc", "aaa", "UPPER_CASE", "zzz", "mmm")]
        keywordList = []
        for name in keywordNames:
            keyword = Keyword(name=name)
            task = Task(project=prj, title="Hello")
            TaskKeyword(task=task, keyword=keyword)
            self.session.add(task)
            keywordList.append(prj)
        self.session.flush()

        renderer = testutils.TestRenderer()
        self.cmd._renderList(renderer, [prj], filters=[], order=[], groupKeyword="kw_%")

        self.assertEqual(list(renderer.taskDict.keys()), sorted(keywordNames, key=lambda x: x.lower()))
예제 #10
0
파일: dbutils.py 프로젝트: semtle/yokadi
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
예제 #11
0
    def do_k_edit(self, line):
        """Edit a keyword
        k_edit @<keyword>"""
        keyword = dbutils.getKeywordFromName(line)
        oldName = keyword.name
        newName = tui.editLine(oldName)
        if newName == "":
            print "Cancelled"
            return

        lst = list(Keyword.selectBy(name=newName))
        if len(lst) == 0:
            # Simple case: newName does not exist, just rename the existing keyword
            keyword.name = newName
            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 not newName in kwDict:
                kwDict[newName] = kwDict[oldName]
            del kwDict[oldName]
            task.setKeywordDict(kwDict)
        keyword.destroySelf()
        print "Keyword %s has been merged with %s" % (oldName, newName)
예제 #12
0
 def do_k_list(self, line):
     """List all keywords."""
     for keyword in Keyword.select():
         tasks = ", ".join(str(task.id) for task in keyword.tasks)
         print "%s (tasks: %s)" % (keyword.name, tasks)
예제 #13
0
파일: taskcmd.py 프로젝트: bport/yokadi
    def _renderList(self,
                    renderer,
                    projectList,
                    filters,
                    order,
                    limit=None,
                    groupKeyword=None):
        """
        Render a list using renderer, according to the restrictions set by the
        other parameters
        @param renderer: renderer class (for example: TextListRenderer)
        @param projectList: list of project name (as unicode string)
        @param filters: filters in sqlobject format (example: Task.q.status == 'done')
        @param order: ordering in sqlobject format (example: -Task.q.urgency)
        @param limit: limit number tasks (int) or None for no limit
        @param groupKeyword: keyword used for grouping (as unicode string) or None
        """
        if groupKeyword:
            if groupKeyword.startswith("@"):
                groupKeyword = groupKeyword[1:]
            for keyword in Keyword.select(LIKE(Keyword.q.name, groupKeyword)):
                if unicode(keyword.name).startswith(
                        "_") and not groupKeyword.startswith("_"):
                    # BUG: cannot filter on db side because sqlobject does not understand ESCAPE needed whith _
                    continue
                taskList = Task.select(
                    AND(TaskKeyword.q.keywordID == keyword.id, *filters),
                    orderBy=order,
                    limit=limit,
                    distinct=True,
                    join=LEFTJOINOn(Task, TaskKeyword,
                                    Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)
                if projectList:
                    taskList = [
                        x for x in taskList if x.project in projectList
                    ]
                if len(taskList) > 0:
                    self.lastTaskIds.extend([
                        t.id for t in taskList
                    ])  # Keep selected id for further use
                    renderer.addTaskList(unicode(keyword), taskList)
            renderer.end()
        else:
            hiddenProjectNames = []
            for project in projectList:
                if not project.active:
                    hiddenProjectNames.append(project.name)
                    continue
                taskList = Task.select(AND(Task.q.projectID == project.id,
                                           *filters),
                                       orderBy=order,
                                       limit=limit,
                                       distinct=True,
                                       join=LEFTJOINOn(
                                           Task, TaskKeyword,
                                           Task.q.id == TaskKeyword.q.taskID))
                taskList = list(taskList)

                if len(taskList) > 0:
                    self.lastTaskIds.extend([
                        t.id for t in taskList
                    ])  # Keep selected id for further use
                    renderer.addTaskList(unicode(project), taskList)
            renderer.end()

            if len(hiddenProjectNames) > 0:
                tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))