def do_t_due(self, line): """Set task's due date t_due <id> <date> Date can be specified as a relative offset: - +5M: in 5 minutes - +3H: in 3 hours - +1D: in 1 day - +6W: in 6 weeks As a day in the week: - tomorrow: tomorrow, same hour - tuesday 12:10: next tuesday, at 12:10 - fr 15:30: next friday, at 15:30 Or as an absolute date or time: - 10:38: at 10:38 today - 25/09/2010 12:10: on the 25th of September, 2010, at 12:10 - 23/02/2010: on the 23th of February, 2010 - 01/04: on the 1st of April - 12: on the 12th of current month To reset a due date, use "none".""" if len(line.split())<2: raise YokadiException("Give a task id and time, date or date & time") taskId, line=line.strip().split(" ", 1) task=dbutils.getTaskFromId(taskId) if line.lower()=="none": task.dueDate=None print "Due date for task '%s' reset" % task.title else: task.dueDate = dateutils.parseHumaneDateTime(line) print "Due date for task '%s' set to %s" % (task.title, task.dueDate.ctime())
def do_bug_edit(self, line): """Edit a bug. bug_edit <id>""" task = dbutils.getTaskFromId(line) # Create task line taskLine = parseutils.createLine("", task.title, task.getKeywordDict()) # Edit while True: print "(Press Ctrl+C to cancel)" try: line = tui.editLine(taskLine) if not line.strip(): tui.warning("Indicate a bug title !") continue except KeyboardInterrupt: print print "Cancelled" return foo, title, keywordDict = parseutils.parseLine(task.project.name+" "+line) if dbutils.updateTask(task, task.project.name, title, keywordDict): break editBugKeywords(keywordDict) task.setKeywordDict(keywordDict) # Update bug task.urgency = computeUrgency(keywordDict)
def do_t_describe(self, line): """Starts an editor to enter a longer description of a task. t_describe <id>""" task=dbutils.getTaskFromId(line) try: description = tui.editText(task.description) except Exception, e: raise YokadiException(e)
def getTaskFromId(self, line): line = line.strip() if line == '_': if self.lastTaskId is None: raise YokadiException("No previous task defined") line = str(self.lastTaskId) task = dbutils.getTaskFromId(line) if line != '_': self.lastTaskId = task.id return task
def do_t_project(self, line): """Set task's project. t_project <id> <project>""" tokens = line.split(" ") if len(tokens)!=2: raise YokadiException("You should give two arguments: <task id> <project>") task=dbutils.getTaskFromId(tokens[0]) projectName = tokens[1] task.project = dbutils.getOrCreateProject(projectName) if task.project: print "Moved task '%s' to project '%s'" % (task.title, projectName)
def _t_set_status(self, line, status): task=dbutils.getTaskFromId(line) if task.recurrence and status == "done": task.dueDate = task.recurrence.getNext(task.dueDate) print "Task '%s' next occurrence is scheduled at %s" % (task.title, task.dueDate) print "To *really* mark this task done and forget it, remove its recurrence first with t_recurs %s none" % task.id else: task.status = status if status == "done": task.doneDate = datetime.now() else: task.doneDate = None print "Task '%s' marked as %s" % (task.title, status)
def do_t_remove(self, line): parser = self.parser_t_remove() options, args = parser.parse_args(line) task=dbutils.getTaskFromId(' '.join(args)) if not options.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)
def do_t_add_keywords(self, line): """Add keywords to an existing task t_add_keyword <id> <keyword1> <keyword2>[=<value>]... """ tokens = line.split(" ", 1) if len(tokens) < 2: raise YokadiException("You should give at least two arguments: <task id> <keyword>") task = dbutils.getTaskFromId(tokens[0]) remainingText, newKwDict = parseutils.extractKeywords(tokens[1]) dbutils.createMissingKeywords(newKwDict.keys()) kwDict = task.getKeywordDict() kwDict.update(newKwDict) task.setKeywordDict(kwDict)
def do_t_edit(self, line): """Edit a task. t_edit <id>""" def editComplete(text, state): """ Specific completer for the edit prompt. This subfunction should stay here because it needs to access to cmd members""" if state == 0: origline = readline.get_line_buffer() line = origline.lstrip() stripped = len(origline) - len(line) begidx = readline.get_begidx() - stripped endidx = readline.get_endidx() - stripped if begidx>0: self.completion_matches = projectAndKeywordCompleter("", text, line, begidx, endidx, shift=1) else: self.completion_matches = [] try: return self.completion_matches[state] except IndexError: return None old_completer = readline.get_completer() # Backup previous completer to restore it in the end readline.set_completer(editComplete) # Switch to specific completer task = dbutils.getTaskFromId(line) # Create task line taskLine = parseutils.createLine("", task.title, task.getKeywordDict()) while True: # Edit print "(Press Ctrl+C to cancel)" try: line = tui.editLine(taskLine) if not line.strip(): tui.warning("Indicate a task title !") continue except KeyboardInterrupt: print print "Cancelled" readline.set_completer(old_completer) # Restore standard completer return foo, title, keywordDict = parseutils.parseLine(task.project.name+" "+line) if dbutils.updateTask(task, task.project.name, title, keywordDict): break readline.set_completer(old_completer) # Restore standard completer
def do_t_add_keywords(self, line): """Add keywords to an existing task t_add_keyword <id> <@keyword1> <@keyword2>[=<value>]... """ tokens = parseutils.simplifySpaces(line).split(" ", 1) if len(tokens) < 2: raise YokadiException("You should give at least two arguments: <task id> <keyword>") task = dbutils.getTaskFromId(tokens[0]) garbage, keywordFilters = parseutils.extractKeywords(tokens[1]) newKwDict = parseutils.keywordFiltersToDict(keywordFilters) if garbage: raise YokadiException("Cannot parse line, got garbage (%s). Maybe you forgot to add @ before keyword ?" % garbage) dbutils.createMissingKeywords(newKwDict.keys()) kwDict = task.getKeywordDict() kwDict.update(newKwDict) task.setKeywordDict(kwDict)
def do_t_urgency(self, line): """Defines urgency of a task. t_urgency <id> <value>""" tokens = line.split(" ") if len(tokens)!=2: raise YokadiException("You must provide a taskId and an urgency value") task = dbutils.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 YokadiException("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
def do_t_show(self, line): parser = self.parser_t_show() options, args = parser.parse_args(line) task=dbutils.getTaskFromId(' '.join(args)) if options.output in ("all", "summary"): keywordDict = task.getKeywordDict() keywordArray = [] for name, value in keywordDict.items(): txt = name if value: txt += "=" + str(value) keywordArray.append(txt) keywordArray.sort() keywords = ", ".join(keywordArray) fields = [ ("Project", task.project.name), ("Title", task.title), ("Created", task.creationDate), ("Due", task.dueDate), ("Status", task.status), ("Urgency", task.urgency), ("Recurrence", task.recurrence), ("Keywords", keywords), ] if task.status == "done": fields.append(("Done", task.doneDate)) tui.renderFields(fields) if options.output in ("all", "description") and task.description: if options.output == "all": print print task.description
def testGetTaskFromId(self): tui.addInputAnswers("y") t1 = dbutils.addTask("x", "t1", {}) task = dbutils.getTaskFromId(str(t1.id)) self.assertEquals(task, t1)
def do_t_recurs(self, line): """Make a task recurs t_recurs <id> yearly <dd/mm> <HH:MM> t_recurs <id> monthly <dd> <HH:MM> t_recurs <id> monthly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> quarterly <dd> <HH:MM> t_recurs <id> quarterly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> weekly <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> daily <HH:MM> t_recurs <id> none (remove recurrence)""" tokens = line.split() if len(tokens) < 2: raise YokadiException("You should give at least two arguments: <task id> <recurrence>") task = dbutils.getTaskFromId(tokens[0]) # Define recurrence: freq = byminute = byhour = byweekday = bymonthday = bymonth = None tokens[1] = tokens[1].lower() if tokens[1] == "none": if task.recurrence: task.recurrence.destroySelf() task.recurrence = None return elif tokens[1] == "daily": if len(tokens) != 3: raise YokadiException("You should give time for daily task") freq = rrule.DAILY byhour, byminute = dateutils.getHourAndMinute(tokens[2]) elif tokens[1] == "weekly": freq = rrule.WEEKLY if len(tokens) != 4: raise YokadiException("You should give day and time for weekly task") byweekday = dateutils.getWeekDayNumberFromDay(tokens[2].lower()) byhour, byminute = dateutils.getHourAndMinute(tokens[3]) elif tokens[1] in ("monthly","quarterly"): if tokens[1] == "monthly": freq = rrule.MONTHLY else: # quarterly freq = rrule.YEARLY bymonth = [1,4,7,10] if len(tokens) < 4: raise YokadiException("You should give day and time for %s task" % (tokens[1],)) try: bymonthday = int(tokens[2]) byhour, byminute = dateutils.getHourAndMinute(tokens[3]) except ValueError: POSITION = { "first" : 1, "second" : 2, "third" : 3, "fourth" : 4, "last" : -1 } if tokens[2].lower() in POSITION.keys() and len(tokens) == 5: byweekday = rrule.weekday(dateutils.getWeekDayNumberFromDay(tokens[3].lower()), POSITION[tokens[2]]) byhour, byminute = dateutils.getHourAndMinute(tokens[4]) bymonthday = None # Default to current day number - need to be blanked else: raise YokadiException("Unable to understand date. See help t_recurs for details") elif tokens[1] == "yearly": freq = rrule.YEARLY rDate = dateutils.parseHumaneDateTime(" ".join(tokens[2:])) bymonth = rDate.month bymonthday = rDate.day byhour = rDate.hour byminute = rDate.minute else: raise YokadiException("Unknown frequency. Available: daily, weekly, monthly and yearly") if task.recurrence is None: task.recurrence = Recurrence() rr = rrule.rrule(freq, byhour=byhour, byminute=byminute, byweekday=byweekday, bymonthday=bymonthday, bymonth=bymonth) task.recurrence.setRrule(rr) task.dueDate = task.recurrence.getNext()