def generateCal(): cal = icalendar.Calendar() cal.add("prodid", '-//Yokadi calendar //yokadi.github.com//') cal.add("version", "2.0") # Add projects for project in Project.select(Project.q.active == True): todo = icalendar.Todo() todo.add("summary", project.name) todo["uid"] = PROJECT_UID % project.id cal.add_component(todo) # Add tasks for task in Task.select(Task.q.status != "done"): todo = icalendar.Todo() todo["uid"] = TASK_UID % task.id todo["related-to"] = PROJECT_UID % task.project.id todo.add("dtstamp", task.creationDate) todo.add("priority", task.urgency) todo.add("summary", "%s (%s)" % (task.title, task.id)) todo.add("dtstart", task.creationDate) if task.dueDate: todo.add("due", task.dueDate) if task.description: todo.add("description", task.description) categories = [task.project, ] # Add project as a keyword if task.keywords: categories.extend([k.name for k in task.keywords]) todo.add("categories", categories) cal.add_component(todo) return cal
def do_p_list(self, line): """List all projects.""" for project in Project.select(): if project.active: active = "" else: active = "(inactive)" print "%s %s %s" % (project.name, project.getKeywordsAsString(), active)
def front(): user = get_user() projects = Project.select().order_by(Project.updated.desc()) def local_is_admin(proj): return is_admin(user, proj) return render_template('index.html', user=user, projects=projects, admin=is_admin(user), is_admin=local_is_admin)
def check_project_handler(user): project = Project.select().where(Project.proj_id == user.project_id).get() state = project.status if state == 'pre': text_to_send = 'Your project has been submitted, we\'ll let you know when the first round starts!' elif state == 'round1': text_to_send = 'You\'ve been assigned '+ project.assignment + '.' elif state == 'final': text_to_send = 'Congratulations! You\'ve made it to the final round! You\'ve been assigned ' + project.assignment + '.' else: # "sorry" state text_to_send = 'Sorry you did not make it to the final round! Thank you for participating in HackATL!' return bot_messages.project_status_message(user, text_to_send)
def testAdd(self): tui.addInputAnswers("y") self.cmd.do_p_add("p1") tui.addInputAnswers("y", "y") self.cmd.do_p_add("p2 @kw1 @kw2=12") projects = list(Project.select()) result = [x.name for x in projects] expected = [u"p1", u"p2"] self.assertEqual(result, expected) kwDict = Project.get(2).getKeywordDict() self.assertEqual(kwDict, dict(kw1=None, kw2=12))
def do_t_list(self, line): doneRangeList= ["today", "thisweek", "thismonth"] def keywordDictIsSubsetOf(taskKeywordDict, wantedKeywordDict): # Returns true if taskKeywordDict is a subset of wantedKeywordDict # taskKeywordDict is considered a subset of wantedKeywordDict if: # 1. All wantedKeywordDict keys are in taskKeywordDict # 2. All wantedKeywordDict valued keywords have the same value # in taskKeywordDict for wantedKeyword, wantedValue in wantedKeywordDict.items(): if not wantedKeyword in taskKeywordDict: return False if wantedValue and taskKeywordDict[wantedKeyword] != wantedValue: return False return True def taskHasWantedKeywordDict(task, wantedKeywordDict): """ @param task: task object @param wantedKeywordDict: dict of name/value of wanted keyword # a task is considered a subset of wantedKeywordDict if: # 1. All wantedKeywordDict keys are in task or project keywords # 2. All wantedKeywordDict valued keywords have the same value # in task or project keyword""" for wantedKeyword, wantedValue in wantedKeywordDict.items(): taskFilters=[Task.q.id==task.id, TaskKeyword.q.taskID==task.id, TaskKeyword.q.keywordID==Keyword.q.id, LIKE(Keyword.q.name, wantedKeyword)] projectFilters=[Project.q.id==task.projectID, ProjectKeyword.q.projectID==Project.q.id, ProjectKeyword.q.keyword==Keyword.q.id, LIKE(Keyword.q.name, wantedKeyword)] if wantedValue: taskFilters.append(TaskKeyword.q.value==wantedValue) projectFilters.append(ProjectKeyword.q.value==wantedValue) if Task.select(AND(*taskFilters)).count()==0 and Task.select(AND(*projectFilters)).count()==0: return False # All critera were met, return ok return True def createFilterFromRange(_range): # Parse the _range string and return an SQLObject filter minDate = date.today() if _range == "today": pass elif _range == "thisweek": minDate -= timedelta(minDate.weekday()) elif _range == "thismonth": minDate = minDate.replace(day = 1) else: raise YokadiException("Invalid range value '%s'" % _range) return Task.q.doneDate>=minDate def selectRendererClass(): if options.format != "auto": return gRendererClassDict[options.format] defaultRendererClass = TextListRenderer if not options.output: return defaultRendererClass ext = os.path.splitext(options.output)[1] if not ext: return defaultRendererClass return gRendererClassDict.get(ext[1:], defaultRendererClass) #BUG: completion based on parameter position is broken when parameter is given parser = self.parser_t_list() options, args = parser.parse_args(line) if len(args) > 0: projectName, keywordDict = parseutils.extractKeywords(u" ".join(args)) else: projectName = "" keywordDict = {} if not projectName: # Take all project if none provided projectName="%" projectList = Project.select(LIKE(Project.q.name, projectName)) if projectList.count()==0: tui.error("Found no project matching '%s'" % projectName) return # Check keywords exist for keyword in keywordDict.keys(): if Keyword.select(LIKE(Keyword.q.name, keyword)).count()==0: tui.error("Keyword %s is unknown." % keyword) # Filtering and sorting according to parameters filters=[] order=-Task.q.urgency, Task.q.creationDate limit=None if options.done: filters.append(Task.q.status=='done') if options.done != "all": filters.append(createFilterFromRange(options.done)) elif not options.all: filters.append(Task.q.status!='done') if options.topUrgent: order=-Task.q.urgency limit=5 if options.topDue: filters.append(Task.q.dueDate!=None) order=Task.q.dueDate limit=5 if options.search: for word in options.search: filters.append(OR(LIKE(Task.q.title, "%"+word+"%"), LIKE(Task.q.description, "%"+word+"%"))) # Define output if options.output: out = open(options.output, "w") else: out = tui.stdout # Instantiate renderer rendererClass = selectRendererClass() renderer = rendererClass(out) # Fill the renderer if options.keyword: if options.keyword.startswith("@"): options.keyword = options.keyword[1:] for keyword in Keyword.select(LIKE(Keyword.q.name, options.keyword)): if unicode(keyword.name).startswith("_") and not options.keyword.startswith("_"): #BUG: cannot filter on db side because sqlobject does not understand ESCAPE needed whith _ continue taskList = Task.select(AND(TaskKeyword.q.taskID == Task.q.id, TaskKeyword.q.keywordID == keyword.id, *filters), orderBy=order, limit=limit) taskList = list(taskList) if keywordDict: # FIXME: factorize (see project oriented rendering below) taskList = [x for x in taskList if taskHasWantedKeywordDict(x, keywordDict)] if projectList: taskList = [x for x in taskList if x.project in projectList] if len(taskList) == 0: continue renderer.addTaskList(unicode(keyword), taskList) # Call renderer 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) if keywordDict: taskList = [x for x in taskList if taskHasWantedKeywordDict(x, keywordDict)] else: taskList = list(taskList) if len(taskList) == 0: continue renderer.addTaskList(unicode(project), taskList) renderer.end() if len(hiddenProjectNames) > 0: tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))
def do_t_list(self, line): def selectRendererClass(): if options.format != "auto": return gRendererClassDict[options.format] defaultRendererClass = TextListRenderer if not options.output: return defaultRendererClass ext = os.path.splitext(options.output)[1] if not ext: return defaultRendererClass return gRendererClassDict.get(ext[1:], defaultRendererClass) #BUG: completion based on parameter position is broken when parameter is given parser = self.parser_t_list() options, args = parser.parse_args(line) if len(args) > 0: projectName, keywordFilters = parseutils.extractKeywords(u" ".join(args)) else: projectName = "" keywordFilters = [] if self.kFilters: # Add keyword filter keywordFilters.extend(self.kFilters) if not projectName: if self.pFilter: # If a project filter is defined, use it as none was provided projectName = self.pFilter else: # Take all project if none provided projectName = "%" if projectName.startswith("!"): projectName = projectName[1:] projectList = Project.select(NOT(LIKE(Project.q.name, projectName))) else: projectList = Project.select(LIKE(Project.q.name, projectName)) if projectList.count() == 0: tui.error("Found no project matching '%s'" % projectName) return # Check keywords exist parseutils.warnIfKeywordDoesNotExist(keywordFilters) # Filtering and sorting according to parameters filters = [] # Filter on keywords for keywordFilter in keywordFilters: filters.append(keywordFilter.filter()) order = -Task.q.urgency, Task.q.creationDate limit = None if options.done: filters.append(Task.q.status == 'done') if options.done != "all": filters.append(parseutils.createFilterFromRange(options.done)) elif not options.all: filters.append(Task.q.status != 'done') if options.topUrgent: order = -Task.q.urgency limit = 5 if options.topDue: filters.append(Task.q.dueDate != None) order = Task.q.dueDate limit = 5 if options.overdue: filters.append(Task.q.dueDate < datetime.now()) order = Task.q.dueDate if options.search: for word in options.search: filters.append(OR(LIKE(Task.q.title, "%" + word + "%"), LIKE(Task.q.description, "%" + word + "%"))) # Define output if options.output: out = open(options.output, "w") else: out = tui.stdout # Instantiate renderer rendererClass = selectRendererClass() renderer = rendererClass(out) # Fill the renderer if options.keyword: if options.keyword.startswith("@"): options.keyword = options.keyword[1:] for keyword in Keyword.select(LIKE(Keyword.q.name, options.keyword)): if unicode(keyword.name).startswith("_") and not options.keyword.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: continue renderer.addTaskList(unicode(keyword), taskList) # Call renderer 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: continue renderer.addTaskList(unicode(project), taskList) renderer.end() if len(hiddenProjectNames) > 0: tui.info("hidden projects: %s" % ", ".join(hiddenProjectNames))