def sout(self): rc = self.rc all_milestones = [] if not rc.stati: rc.stati = ['started'] for projectum in self.gtx["projecta"]: if rc.lead and projectum.get('lead') != rc.lead: continue projectum["deliverable"].update({"name": "deliverable", "objective": "deliver"}) gather_miles = [projectum["kickoff"], projectum["deliverable"]] gather_miles.extend(projectum["milestones"]) for ms in gather_miles: if projectum["status"] in rc.stati or \ 'all' in rc.stati: if ms.get('status') not in \ ["finished", "cancelled"]: due_date = get_due_date(ms) ms.update({ 'lead': projectum.get('lead'), 'group_members': projectum.get('group_members'), 'collaborators': projectum.get('collaborators'), 'id': projectum.get('_id'), 'due_date': due_date, 'log_url': projectum.get('log_url'), 'pi': projectum.get('pi_id') }) all_milestones.append(ms) all_milestones.sort(key=lambda x: x['due_date'], reverse=True) for ms in all_milestones: if rc.verbose: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, status: {ms.get('status')}") print(f" Title: {ms.get('name')}") print(f" log url: {ms.get('log_url')}") print(f" Purpose: {ms.get('objective')}") audience = [] for i in ms.get('audience'): if isinstance(ms.get(i,i), str): audience.append(ms.get(i,i)) else: if ms.get(i): audience.extend(ms.get(i)) out = ", ".join(audience) print(f" Audience: {out}") else: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, {ms.get('name')}, status: {ms.get('status')}") 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 db_updater(self): rc = self.rc key = rc.projectum_id if rc.date: now = date_parser.parse(rc.date).date() else: now = dt.date.today() filterid = {'_id': key} target_prum = rc.client.find_one(rc.database, rc.coll, filterid) if not target_prum: pra = fragment_retrieval(self.gtx["projecta"], ["_id"], rc.projectum_id) if len(pra) == 0: raise RuntimeError( "Please input a valid projectum id or a valid fragment of a projectum id" ) print("Projecta not found. Projecta with similar names: ") for i in range(len(pra)): print(f"{pra[i].get('_id')}") print("Please rerun the helper specifying the complete ID.") return milestones = target_prum.get('milestones') deliverable = target_prum.get('deliverable') kickoff = target_prum.get('kickoff') deliverable['identifier'] = 'deliverable' kickoff['identifier'] = 'kickoff' for item in milestones: item['identifier'] = 'milestones' all_milestones = [deliverable, kickoff] all_milestones.extend(milestones) for i in all_milestones: i['due_date'] = get_due_date(i) all_milestones.sort(key=lambda x: x['due_date'], reverse=False) index_list = list(range(2, (len(all_milestones) + 2))) if not rc.index: deliverable['name'] = 'deliverable' print("Please choose from one of the following to update/add:") print("1. new milestone") for i, j in zip(index_list, all_milestones): if rc.current: if j.get("status") not in CURRENT_STATI: del j['identifier'] continue print(f"{i}. {j.get('name')} due date: {j.get('due_date')}" f" status: {j.get('status')}") if rc.verbose: if j.get("audience"): print(f" audience: {j.get('audience')}") if j.get("objective"): print(f" objective: {j.get('objective')}") if j.get("type"): print(f" type: {j.get('type')}") if j.get('notes'): print(f" notes:") for note in j.get('notes', []): print(f" - {note}") if j.get('identifier') == 'deliverable': del j['name'] del j['identifier'] return if rc.type and rc.type not in (list( chain.from_iterable( (k, v) for k, v in ALLOWED_TYPES.items()))): raise KeyError( f"please rerun specifying --type with a value from {ALLOWED_TYPES}" ) if rc.status and rc.status not in (list( chain.from_iterable( (k, v) for k, v in ALLOWED_STATI.items()))): raise KeyError( f"please rerun specifying --status with a value from {ALLOWED_STATI}" ) rc.index = rc.index.replace(" ", "") if "-" in rc.index: idx_parsed = [ i for i in range(int(rc.index.split('-')[0]), int(rc.index.split('-')[1]) + 1) ] elif "," in rc.index: idx_parsed = [int(i) for i in rc.index.split(',')] else: idx_parsed = [int(rc.index)] for idx in idx_parsed: pdoc = {} if idx == 1: mil = {} if not rc.due_date or not rc.name or not rc.objective: raise RuntimeError( "name, objective, and due date are required for a new milestone" ) mil.update({'due_date': rc.due_date}) mil['due_date'] = get_due_date(mil) mil.update({'objective': rc.objective, 'name': rc.name}) if rc.audience: mil.update({'audience': rc.audience}) else: mil.update({'audience': ['lead', 'pi', 'group_members']}) if rc.type: if rc.type in ALLOWED_TYPES: mil.update({'type': ALLOWED_TYPES.get(rc.type)}) else: mil.update({'type': rc.type}) else: mil.update({'status': 'proposed'}) if rc.status: if rc.status in ALLOWED_STATI: mil.update({'status': ALLOWED_STATI.get(rc.status)}) else: mil.update({'status': rc.status}) else: mil.update({'type': 'meeting'}) if rc.notes: mil.update({'notes': rc.notes}) milestones.append(mil) pdoc = {'milestones': milestones} if idx > 1: doc = all_milestones[idx - 2] identifier = doc['identifier'] if not doc.get( 'type') and not rc.type and identifier == 'milestones': raise RuntimeError( "ERROR: This milestone does not have a type set and this is required. " "Please rerun your command adding '--type' " f"and typing a type from this list: {ALLOWED_TYPES}") if rc.type: if rc.type in ALLOWED_TYPES: doc.update({'type': ALLOWED_TYPES.get(rc.type)}) else: doc.update({'type': rc.type}) if rc.finish: rc.status = "f" doc.update({'end_date': now}) if identifier == 'deliverable': name = 'deliverable' else: name = doc['name'] print( "The milestone {} has been marked as finished in prum {}" .format(name, key)) if rc.status: if rc.status in ALLOWED_STATI: doc.update({'status': ALLOWED_STATI.get(rc.status)}) else: doc.update({'status': rc.status}) if rc.audience: doc.update({'audience': rc.audience}) if rc.due_date: doc.update({'due_date': rc.due_date}) doc['due_date'] = get_due_date(doc) if rc.notes: notes = doc.get("notes", []) notes.extend(rc.notes) doc["notes"] = notes if identifier == 'milestones': if rc.name: doc.update({'name': rc.name}) if rc.objective: doc.update({'objective': rc.objective}) new_mil = [] for i, j in zip(index_list, all_milestones): if j['identifier'] == 'milestones' and i != idx: new_mil.append(j) new_mil.append(doc) pdoc.update({'milestones': new_mil}) else: pdoc.update({identifier: doc}) rc.client.update_one(rc.database, rc.coll, filterid, pdoc) for i in all_milestones: del i['identifier'] print("{} has been updated in projecta".format(key)) return
def sout(self): rc = self.rc # This if statement should be in all listers. Make sure to change self.gtx to get the database the lister needs if rc.filter: collection = key_value_pair_filter(self.gtx["projecta"], rc.filter) else: collection = self.gtx["projecta"] if (not rc.lead) and (not rc.verbose) and (not rc.stati) and ( not rc.current) and (not rc.person) and (not rc.all): return # fixme there must be a better way, but for now use magic to # to remove checklists # print(collection) collection = [ prum for prum in collection if "checklist" not in prum.get('deliverable', {}).get('scope', []) ] if rc.lead: if rc.person: raise RuntimeError( f"please specify either lead or person, not both") collection = [ prum for prum in collection if prum.get('lead') == rc.lead ] if rc.person: if isinstance(rc.person, str): rc.person = [rc.person] collection = [ prum for prum in collection if prum.get('lead') in rc.person or bool( set(prum.get('group_members', [])).intersection( set(rc.person))) or bool( set(prum.get('collaborators', [])).intersection( set(rc.person))) ] if not rc.all: collection = [ prum for prum in collection if prum.get('status') not in INACTIVE_STATI ] all_milestones = [] if not rc.stati and not rc.all and not rc.finished: rc.stati = PROJECTUM_ACTIVE_STATI elif rc.finished: rc.stati = PROJECTUM_FINISHED_STATI elif rc.all: rc.stati = PROJECTUM_STATI for projectum in collection: projectum["deliverable"].update({ "name": "deliverable", "objective": "deliver" }) milestones = [projectum["deliverable"]] if projectum.get("kickoff"): projectum["kickoff"].update({"type": "meeting"}) milestones = [projectum["kickoff"], projectum["deliverable"]] milestones.extend(projectum["milestones"]) milestones = [ ms for ms in milestones if ms.get('status') in rc.stati ] for ms in milestones: due_date = get_due_date(ms) ms.update({ 'lead': projectum.get('lead'), 'group_members': projectum.get('group_members'), 'collaborators': projectum.get('collaborators'), 'id': projectum.get('_id'), 'due_date': due_date, 'log_url': projectum.get('log_url'), 'pi': projectum.get('pi_id') }) milestones.sort(key=lambda x: x['due_date'], reverse=True) all_milestones.extend(milestones) if rc.keys: results = (collection_str(all_milestones, rc.keys)) print(results, end="") return if not rc.by_prum: all_milestones.sort(key=lambda x: x['due_date'], reverse=True) prum = "" for ms in all_milestones: if rc.by_prum: if prum != ms.get("id"): print("-" * 50) prum = ms.get("id") if rc.verbose: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, status: {ms.get('status')}" ) print(f" Type: {ms.get('type', '')}") print(f" Title: {ms.get('name')}") print(f" log url: {ms.get('log_url')}") print(f" Purpose: {ms.get('objective')}") audience = [] for i in ms.get('audience', []): if isinstance(ms.get(i, i), str): audience.append(ms.get(i, i)) else: if ms.get(i): audience.extend(ms.get(i)) out = ", ".join(audience) print(f" Audience: {out}") if ms.get("notes"): print(f" Notes:") for note in ms.get("notes"): print(f" - {note}") else: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, {ms.get('name')}, status: {ms.get('status')}" ) return
def test_get_due_date(input, expected): with pytest.raises(Exception): assert get_due_date(input) == expected
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
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() 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, }) ms.update({ 'description': f'milestone: {ms.get("name")} ({ms.get("id")})' }) gather_todos.append(ms) 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() todo["days_to_due"] = (todo.get('due_date') - today).days todo["order"] = todo['importance'] + 1 / ( 1 + math.exp(abs(todo["days_to_due"]))) gather_todos = sorted(gather_todos, key=lambda k: (-k['order'])) if rc.short_tasks: for todo in gather_todos[::-1]: if todo.get('duration') is None or float( todo.get('duration')) > float(rc.short_tasks): gather_todos.remove(t) num = 1 print("-" * 50) print( " action (days to due date|importance|expected duration(mins))") for todo in gather_todos: if todo.get('status') not in ["finished", "cancelled"]: print( f"{num:>2}. {todo.get('description')}({todo.get('days_to_due')}|{todo.get('importance')}|{str(todo.get('duration'))})" ) if todo.get('notes'): for note in todo.get('notes'): print(f" - {note}") num += 1 if rc.all: for todo in person.get("todos", []): if todo.get('status') in ["finished", "cancelled"]: print( f"{num:>2}. ({todo.get('status')}) {todo.get('description')}" ) if todo.get('notes'): for note in todo.get('notes'): print(f" - {note}") num += 1 print("-" * 50) return
def sout(self): rc = self.rc # This if statement should be in all listers. Make sure to change self.gtx to get the database the lister needs if rc.filter: collection = key_value_pair_filter(self.gtx["projecta"], rc.filter) else: collection = self.gtx["projecta"] all_milestones = [] if not rc.stati: rc.stati = ['started'] for projectum in collection: if rc.lead and projectum.get('lead') != rc.lead: continue projectum["deliverable"].update({ "name": "deliverable", "objective": "deliver" }) 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 rc.stati or \ 'all' in rc.stati: if ms.get('status') not in \ ["finished", "cancelled"]: due_date = get_due_date(ms) ms.update({ 'lead': projectum.get('lead'), 'group_members': projectum.get('group_members'), 'collaborators': projectum.get('collaborators'), 'id': projectum.get('_id'), 'due_date': due_date, 'log_url': projectum.get('log_url'), 'pi': projectum.get('pi_id') }) all_milestones.append(ms) all_milestones.sort(key=lambda x: x['due_date'], reverse=True) if rc.keys: results = (collection_str(all_milestones, rc.keys)) print(results, end="") return for ms in all_milestones: if rc.verbose: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, status: {ms.get('status')}" ) print(f" Type: {ms.get('type', '')}") print(f" Title: {ms.get('name')}") print(f" log url: {ms.get('log_url')}") print(f" Purpose: {ms.get('objective')}") audience = [] for i in ms.get('audience'): if isinstance(ms.get(i, i), str): audience.append(ms.get(i, i)) else: if ms.get(i): audience.extend(ms.get(i)) out = ", ".join(audience) print(f" Audience: {out}") else: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, {ms.get('name')}, status: {ms.get('status')}" ) return
def sout(self): rc = self.rc # This if statement should be in all listers. Make sure to change self.gtx to get the database the lister needs if rc.filter: collection = key_value_pair_filter(self.gtx["projecta"], rc.filter) else: collection = self.gtx["projecta"] if (not rc.lead) and (not rc.verbose) and (not rc.stati) and ( not rc.current) and (not rc.person) and (not rc.all): return if rc.lead: if rc.person: raise RuntimeError( f"please specify either lead or person, not both") collection = [ prum for prum in collection if prum.get('lead') == rc.lead ] if rc.person: if isinstance(rc.person, str): rc.person = [rc.person] collection = [ prum for prum in collection if prum.get('lead') in rc.person or bool( set(prum.get('group_members', [])).intersection( set(rc.person))) ] # if rc.current: # collection = [prum for prum in collection if # prum.get('status') in ACTIVE_STATI] # if rc.finished: # collection = [prum for prum in collection if # prum.get('status') in FINISHED_STATI] if not rc.all: collection = [ prum for prum in collection if prum.get('status') not in INACTIVE_STATI ] all_milestones = [] if not rc.stati: rc.stati = ['started'] for projectum in collection: projectum["deliverable"].update({ "name": "deliverable", "objective": "deliver" }) projectum["kickoff"].update({"type": "meeting"}) milestones = [projectum["kickoff"], projectum["deliverable"]] milestones.extend(projectum["milestones"]) if rc.current: milestones = [ ms for ms in milestones if ms.get('status') in ACTIVE_STATI ] if rc.finished: milestones = [ ms for ms in milestones if ms.get('status') in FINISHED_STATI ] if not rc.all: milestones = [ ms for ms in milestones if ms.get('status') not in INACTIVE_STATI ] for ms in milestones: due_date = get_due_date(ms) ms.update({ 'lead': projectum.get('lead'), 'group_members': projectum.get('group_members'), 'collaborators': projectum.get('collaborators'), 'id': projectum.get('_id'), 'due_date': due_date, 'log_url': projectum.get('log_url'), 'pi': projectum.get('pi_id') }) all_milestones.append(ms) all_milestones.sort(key=lambda x: x['due_date'], reverse=True) if rc.keys: results = (collection_str(all_milestones, rc.keys)) print(results, end="") return for ms in all_milestones: if rc.verbose: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, status: {ms.get('status')}" ) print(f" Type: {ms.get('type', '')}") print(f" Title: {ms.get('name')}") print(f" log url: {ms.get('log_url')}") print(f" Purpose: {ms.get('objective')}") audience = [] for i in ms.get('audience'): if isinstance(ms.get(i, i), str): audience.append(ms.get(i, i)) else: if ms.get(i): audience.extend(ms.get(i)) out = ", ".join(audience) print(f" Audience: {out}") else: print( f"{ms.get('due_date')}: lead: {ms.get('lead')}, {ms.get('id')}, {ms.get('name')}, status: {ms.get('status')}" ) return