def db_updater(self): rc = self.rc if rc.index: if rc.index >= 9900: print("WARNING: indices >= 9900 are used for milestones which " "should be finished using u_milestone and not f_todo") return if not rc.assigned_to: try: rc.assigned_to = rc.default_user_id except AttributeError: print( "Please set default_user_id in '~/.config/regolith/user.json', or you need to enter your group id " "in the command line") return person = document_by_value( all_docs_from_collection(rc.client, "todos"), "_id", rc.assigned_to) filterid = {'_id': rc.assigned_to} if not person: raise TypeError( f"Id {rc.assigned_to} can't be found in todos collection") todolist = person.get("todos", []) if len(todolist) == 0: print(f"{rc.assigned_to} doesn't have todos in todos collection.") return now = dt.date.today() if not rc.index: if not rc.date: today = now else: today = date_parser.parse(rc.date).date() if rc.filter: todolist = key_value_pair_filter(todolist, rc.filter) for todo in todolist: if type(todo["due_date"]) == str: todo["due_date"] = date_parser.parse( todo["due_date"]).date() todo["days_to_due"] = (todo.get('due_date') - today).days todo["order"] = 1 / (1 + math.exp(abs(todo["days_to_due"] - 0.5))) todolist = sorted(todolist, key=lambda k: (k['status'], k['importance'], k[ 'order'], -k.get('duration', 10000))) print( "If the indices are far from being in numerical order, please renumber them by running regolith helper u_todo -r" ) print("Please choose from one of the following to update:") print( "(index) action (days to due date|importance|expected duration (mins)|tags|assigned by)" ) print("-" * 80) print_task(todolist, stati=['started']) else: match_todo = [ i for i in todolist if i.get("running_index") == rc.index ] if len(match_todo) == 0: raise RuntimeError("Please enter a valid index.") else: todo = match_todo[0] todo["status"] = "finished" if not rc.end_date: end_date = now else: end_date = date_parser.parse(rc.end_date).date() todo["end_date"] = end_date for i in range(0, len(rc.databases)): db_name = rc.databases[i]["name"] person_update = rc.client.find_one(db_name, rc.coll, filterid) if person_update: todolist_update = person_update.get("todos", []) else: continue if len(todolist_update) != 0: for i, todo_u in enumerate(todolist_update): if rc.index == todo_u.get("running_index"): todolist_update[i] = todo rc.client.update_one( db_name, rc.coll, {'_id': rc.assigned_to}, {"todos": todolist_update}, upsert=True) print( f"The task \"({todo_u['running_index']}) {todo_u['description'].strip()}\" in {db_name} for {rc.assigned_to} has been marked as finished." ) return return
def db_updater(self): rc = self.rc if not rc.assigned_to: try: rc.assigned_to = rc.default_user_id except AttributeError: print( "Please set default_user_id in '~/.config/regolith/user.json', or you need to enter your group id " "in the command line") return filterid = {'_id': rc.assigned_to} if rc.reorder: index = 1 for i in range(0, len(rc.databases)): db_name = rc.databases[i]["name"] person_idx = rc.client.find_one(db_name, rc.coll, filterid) if isinstance(person_idx, dict): todolist_idx = person_idx.get("todos", []) else: continue if len(todolist_idx) == 0: continue else: for todo in todolist_idx: todo["running_index"] = index index += 1 person = document_by_value( all_docs_from_collection(rc.client, "people"), "_id", rc.assigned_to) if not person: raise TypeError( f"Id {rc.assigned_to} can't be found in people collection") todolist = person.get("todos", []) if len(todolist) == 0: print(f"{rc.assigned_to} doesn't have todos in people collection.") return if not rc.certain_date: today = dt.date.today() else: today = date_parser.parse(rc.certain_date).date() if not rc.index: started_todo = 0 for todo in todolist: if todo["status"] == 'started': started_todo += 1 if not todo.get('importance'): todo['importance'] = 1 if type(todo["due_date"]) == str: todo["due_date"] = date_parser.parse( todo["due_date"]).date() if type(todo.get("end_date")) == str: todo["end_date"] = date_parser.parse( todo["end_date"]).date() todo["days_to_due"] = (todo.get('due_date') - today).days todo["sort_finished"] = ( todo.get("end_date", dt.date(1900, 1, 1)) - dt.date(1900, 1, 1)).days todo["order"] = todo['importance'] + 1 / ( 1 + math.exp(abs(todo["days_to_due"] - 0.5))) - ( todo["days_to_due"] < -7) * 10 todolist = sorted( todolist, key=lambda k: (k['status'], k['order'], -k.get('duration', 10000)), reverse=True) todolist[started_todo:] = sorted(todolist[started_todo:], key=lambda k: (-k["sort_finished"])) index_match = {} if rc.reorder: new_index_started = 1 new_index_finished = -1 for todo in todolist[:started_todo]: index_match[todo["running_index"]] = new_index_started new_index_started += 1 for todo in todolist[started_todo:]: index_match[todo["running_index"]] = new_index_finished new_index_finished += -1 for i in range(0, len(rc.databases)): db_name = rc.databases[i]["name"] person_idx = rc.client.find_one(db_name, rc.coll, filterid) if isinstance(person_idx, dict): todolist_idx = person_idx.get("todos", []) else: continue if len(todolist_idx) != 0: for todo in todolist_idx: index = index_match[todo["running_index"]] todo["running_index"] = index rc.client.update_one(db_name, rc.coll, {'_id': rc.assigned_to}, {"todos": todolist_idx}, upsert=True) print( f"Indices in {db_name} for {rc.assigned_to} have been updated." ) return if rc.assigned_by: if rc.assigned_by == "default_id": rc.assigned_by = rc.default_user_id for todo in todolist[::-1]: if todo.get('assigned_by') != rc.assigned_by: print(todo.get('assigned_by')) todolist.remove(todo) elif rc.assigned_to == rc.assigned_by: todolist.remove(todo) if rc.filter: todolist = key_value_pair_filter(todolist, rc.filter) if rc.stati == ["started"]: rc.stati = ACTIVE_STATI print( "If the indices are far from being in numerical order, please reorder them by running regolith helper u_todo -r" ) print("Please choose from one of the following to update:") print( "(index) action (days to due date|importance|expected duration (mins)|assigned by)" ) print("-" * 81) print_task(todolist, stati=rc.stati) print("-" * 81) else: match_todo = [ i for i in todolist if i.get("running_index") == rc.index ] if len(match_todo) == 0: raise RuntimeError("Please enter a valid index.") else: todo = match_todo[0] if rc.description: todo["description"] = rc.description if rc.due_date: try: relative_day = int(rc.due_date) due_date = today + relativedelta(days=relative_day) except ValueError: due_date = date_parser.parse(rc.due_date).date() todo["due_date"] = due_date if rc.estimated_duration: todo["duration"] = rc.estimated_duration if rc.importance or rc.importance == 0: if rc.importance in ALLOWED_IMPORTANCE: todo["importance"] = rc.importance else: raise ValueError( f"Importance should be chosen from{ALLOWED_IMPORTANCE}." ) if rc.status: if rc.status in ALLOWED_STATI: todo["status"] = rc.status else: raise ValueError( f"Status should be chosen from {ALLOWED_STATI}.") if rc.notes: try: todo["notes"].extend(rc.notes) except KeyError: todo["notes"] = [] todo["notes"].extend(rc.notes) if rc.begin_date: todo["begin_date"] = date_parser.parse( rc.begin_date).date() if rc.end_date: todo["end_date"] = date_parser.parse(rc.end_date).date() for i in range(0, len(rc.databases)): db_name = rc.databases[i]["name"] person_update = rc.client.find_one(db_name, rc.coll, filterid) todolist_update = person_update.get("todos", []) if len(todolist_update) != 0: for i, todo_u in enumerate(todolist_update): if rc.index == todo_u.get("running_index"): todolist_update[i] = todo rc.client.update_one( db_name, rc.coll, {'_id': rc.assigned_to}, {"todos": todolist_update}, upsert=True) print( f"The task \"({todo_u['running_index']}) {todo_u['description'].strip()}\" in {db_name} for {rc.assigned_to} has been updated." ) return return
def sout(self): rc = self.rc if not rc.assigned_to: try: rc.assigned_to = rc.default_user_id except AttributeError: print( "Please set default_user_id in '~/.config/regolith/user.json', or you need to enter your group id " "in the command line") return try: person = document_by_value( all_docs_from_collection(rc.client, "todos"), "_id", rc.assigned_to) gather_todos = person.get("todos", []) except: print("The id you entered can't be found in todos.yml.") return if not rc.date: today = dt.date.today() else: today = date_parser.parse(rc.date).date() if rc.stati == ["started"]: rc.stati = PROJECTUM_ACTIVE_STATI running_index = 0 for projectum in self.gtx["projecta"]: if projectum.get('lead') != rc.assigned_to: continue if "checklist" in projectum.get('deliverable').get('scope'): continue projectum["deliverable"].update({"name": "deliverable"}) gather_miles = [projectum["deliverable"]] if projectum.get("kickoff"): projectum['kickoff'].update({"type": "meeting"}) gather_miles = [projectum["kickoff"], projectum["deliverable"]] gather_miles.extend(projectum["milestones"]) for ms in gather_miles: if projectum["status"] in PROJECTUM_ACTIVE_STATI: if ms.get('status') in PROJECTUM_ACTIVE_STATI: due_date = get_due_date(ms) ms.update({ 'status': "started", 'id': projectum.get('_id'), 'due_date': due_date, 'assigned_by': projectum.get('pi_id'), 'importance': 2, 'duration': 3600, 'running_index': 9900 + running_index }) running_index += 1 ms.update({ 'description': f'milestone: {ms.get("name")} ({ms.get("id")})' }) gather_todos.append(ms) if rc.filter: gather_todos = key_value_pair_filter(gather_todos, rc.filter) if rc.short: for todo in gather_todos[::-1]: if todo.get('duration') is None or float( todo.get('duration')) > float(rc.short): gather_todos.remove(todo) if rc.tags: for todo in gather_todos[::-1]: takeme = False for tag in rc.tags: if tag in todo.get('tags', []): takeme = True if not takeme: gather_todos.remove(todo) if rc.assigned_by: if rc.assigned_by == "default_id": rc.assigned_by = rc.default_user_id for todo in gather_todos[::-1]: if todo.get('assigned_by') != rc.assigned_by: gather_todos.remove(todo) len_of_started_tasks = 0 milestones = 0 for todo in gather_todos: if 'milestone: ' in todo['description']: milestones += 1 elif todo["status"] == 'started': len_of_started_tasks += 1 len_of_tasks = len(gather_todos) #- milestones for todo in gather_todos: _format_todos(todo, today) gather_todos[:len_of_tasks] = sorted( gather_todos[:len_of_tasks], key=lambda k: (k['status'], k['importance'], k['order'], -k.get( 'duration', 10000))) gather_todos[len_of_started_tasks:len_of_tasks] = sorted( gather_todos[len_of_started_tasks:len_of_tasks], key=lambda k: (-k["sort_finished"])) gather_todos[len_of_tasks:] = sorted( gather_todos[len_of_tasks:], key=lambda k: (k['status'], k['order'], -k.get('duration', 10000))) print( "If the indices are far from being in numerical order, please renumber them by running regolith helper u_todo -r" ) print( "(index) action (days to due date|importance|expected duration (mins)|tags|assigned by)" ) print("-" * 80) if len(gather_todos) != 0: print_task(gather_todos, stati=rc.stati) if rc.outstandingreview: prop = self.gtx['proposalReviews'] man = self.gtx['refereeReports'] outstanding_todo = [] for manuscript in man: if manuscript.get("reviewer") != rc.assigned_to: continue if manuscript.get("status") in STATI: out = f"Manuscript by {manuscript.get('first_author_last_name')} in {manuscript.get('journal')} " \ f"is due on {manuscript.get('due_date')}" outstanding_todo.append((out, manuscript.get('due_date'), manuscript.get("status"))) for proposal in prop: if proposal.get("reviewer") != rc.assigned_to: continue if proposal.get("status") in STATI: if isinstance(proposal.get('names'), str): name = HumanName(proposal.get('names')) else: name = HumanName(proposal.get('names')[0]) out = f"Proposal by {name.last} for {proposal.get('agency')} ({proposal.get('requester')})" \ f"is due on {proposal.get('due_date')}" outstanding_todo.append((out, proposal.get('due_date'), proposal.get("status"))) if len(outstanding_todo) != 0: print("-" * 30) print("Outstanding Reviews:") print("-" * 30) outstanding_todo = sorted(outstanding_todo, key=lambda k: str(k[1])) for stati in STATI: if stati in [output[2] for output in outstanding_todo]: print(f'{stati}:') else: continue for output in outstanding_todo: if output[2] == stati: print(output[0]) return
def sout(self): rc = self.rc if not rc.assigned_to: try: rc.assigned_to = rc.default_user_id except AttributeError: print( "Please set default_user_id in '~/.config/regolith/user.json', or you need to enter your group id " "in the command line") return try: person = document_by_value( all_docs_from_collection(rc.client, "people"), "_id", rc.assigned_to) gather_todos = person.get("todos", []) except: print("The id you entered can't be found in people.yml.") return if not rc.certain_date: today = dt.date.today() else: today = date_parser.parse(rc.certain_date).date() if rc.stati == ["started"]: rc.stati = ACTIVE_STATI for projectum in self.gtx["projecta"]: if projectum.get('lead') != rc.assigned_to: continue projectum["deliverable"].update({"name": "deliverable"}) gather_miles = [projectum["kickoff"], projectum["deliverable"]] gather_miles.extend(projectum["milestones"]) for ms in gather_miles: if projectum["status"] not in ["finished", "cancelled"]: if ms.get('status') not in \ ["finished", "cancelled"]: due_date = get_due_date(ms) ms.update({ 'id': projectum.get('_id'), 'due_date': due_date, 'assigned_by': projectum.get('pi_id') }) ms.update({ 'description': f'milestone: {ms.get("name")} ({ms.get("id")})' }) gather_todos.append(ms) if rc.filter: gather_todos = key_value_pair_filter(gather_todos, rc.filter) if rc.short: for todo in gather_todos[::-1]: if todo.get('duration') is None or float( todo.get('duration')) > float(rc.short): gather_todos.remove(todo) if rc.assigned_by: if rc.assigned_by == "default_id": rc.assigned_by = rc.default_user_id for todo in gather_todos[::-1]: if todo.get('assigned_by') != rc.assigned_by: gather_todos.remove(todo) elif rc.assigned_to == rc.assigned_by: gather_todos.remove(todo) len_of_started_tasks = 0 milestones = 0 for todo in gather_todos: if 'milestone: ' in todo['description']: milestones += 1 elif todo["status"] == 'started': len_of_started_tasks += 1 len_of_tasks = len(gather_todos) - milestones for todo in gather_todos: if not todo.get('importance'): todo['importance'] = 1 if type(todo["due_date"]) == str: todo["due_date"] = date_parser.parse(todo["due_date"]).date() if type(todo.get("end_date")) == str: todo["end_date"] = date_parser.parse(todo["end_date"]).date() todo["days_to_due"] = (todo.get('due_date') - today).days todo["sort_finished"] = ( todo.get("end_date", dt.date(1900, 1, 1)) - dt.date(1900, 1, 1)).days try: todo["order"] = todo['importance'] + 1 / ( 1 + math.exp(abs(todo["days_to_due"] - 0.5))) - ( todo["days_to_due"] < -7) * 10 except OverflowError: todo["order"] = float('inf') gather_todos[:len_of_tasks] = sorted( gather_todos[:len_of_tasks], key=lambda k: (k['status'], k['order'], -k.get('duration', 10000)), reverse=True) gather_todos[len_of_started_tasks:len_of_tasks] = sorted( gather_todos[len_of_started_tasks:len_of_tasks], key=lambda k: (-k["sort_finished"])) gather_todos[len_of_tasks:] = sorted( gather_todos[len_of_tasks:], key=lambda k: (k['status'], k['order'], -k.get('duration', 10000)), reverse=True) print( "If the indices are far from being in numerical order, please reorder them by running regolith helper u_todo -r" ) print( "(index) action (days to due date|importance|expected duration (mins)|assigned by)" ) print("-" * 81) if len_of_tasks != 0: print("tasks from people collection:") print("-" * 30) print_task(gather_todos[:len_of_tasks], stati=rc.stati) if milestones != 0: print("-" * 42) print("tasks from projecta and other collections:") print("-" * 42) print_task(gather_todos[len_of_tasks:], stati=rc.stati, index=False) print("-" * 81) return