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"))
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
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
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
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]
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)
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))
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()))
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
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)
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)
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))