def _check_card(self, card: Card, done_list: List, used_resources: dict): print(f"Checking card {card.name}") pid = None uid = None for comment in card.fetch_comments(): comment_text = comment["data"]["text"] if "PID:" in comment_text: pid = int(comment_text.split("PID:")[1].strip()) if "UID:" in comment_text: uid = comment_text.split("UID:")[1].strip() if pid is None: raise ValueError(f"PID not found in card {card.name}") if uid is None: raise ValueError(f"UID not found in card {card.name}") if not psutil.pid_exists(pid): card.comment( f"⚠️ Warning: Could not find the process, assuming it finised." ) return self._finish_card(card, done_list, used_resources, uid) process = psutil.Process(int(pid)) if process.status() in [psutil.STATUS_RUNNING, psutil.STATUS_SLEEPING]: return self._finish_card(card, done_list, used_resources, uid)
def change_task_list(request, task): p = request.user.profile trello_key = p.trello_api_key trello_secret = p.trello_api_secret client = TrelloClient(api_key=trello_key, api_secret=trello_secret) todo_board = client.get_board(board_id=task.trello_id) last_list = todo_board.list_lists()[-1] card = Card(card_id=str(task.task_id), parent=todo_board) card.change_list(list_id=str(last_list.id))
def _update_task_card(self, card: Card, task: Task): self._update_remaining(task, card) url_str = str(task.url) task_attachments = [ att for att in card.attachments if att.url == url_str ] for att in task_attachments: logger.debug("Removing attachment %s", att.name) card.remove_attachment(att.id) card.attach("Task URL", url=url_str)
def update_card(card: trello.Card, desc_changes: dict, card_changes: dict) -> trello.Card: """ Updates given card's description and other properties. """ card_data: dict = json.loads(card.desc) card_data.update(desc_changes) card.set_description(json.dumps(card_data)) for property, value in card_changes.items(): setter = attrgetter(f"set_{property}")(card) setter(value) return card
def copy_card(card: Card, to_list: List, labels, assign): labels_str = "" if labels: for label in labels: labels_str += label + "," members_str = "" if assign: for assignee in assign: members_str += assignee + "," post_args = { 'name': card.name, 'idList': to_list.id, 'desc': card.desc, 'idLabels': labels_str[:-1], 'due': card.due, 'idMembers': members_str[:-1], 'idCardSource': card.id, 'keepFromSource': 'attachments,checklists,comments,stickers' } created_card = to_list.client.fetch_json('/cards', http_method='POST', post_args=post_args) return Card.from_json(to_list, created_card)
def trello_card_get_or_create(package): """ Get the card object for a package, if no card is available create one. NOTE: Packages with no status are assumes to be in "-- NO STATUS --". """ if not package.is_package: raise ValueError('Must be a valid package') # Make sure the package has a status, if it dose not assing the default one. if not package.status: package.status = list(package.STATUS)[0][0] package.save() trello_list = trello_list_get_or_create(package.status) if not package.project_card_id: # No card listed, creating a new one. trello_card = trello_list.add_card( package.name, desc=trello_card_desc(package, package.properties.all()[0].prop.TABS), position='top') for cl in checklists: trello_card.add_checklist(cl['name'], [x['name'] for x in cl['items']]) package.project_card_id = trello_card.id package.save() return trello_card else: # Get the card and return it, if the card is not found raise ValueError try: card = Card(trello_board(), package.project_card_id) card.fetch() except ResourceUnavailable: raise ValueError('Probided card ID is invalid.') return card
def get_open_cards(board): filters = { 'filter': 'all', 'fields': 'all' } json_obj = board.client.fetch_json( '/boards/' + board.id + '/cards', query_params=filters ) ret = [] for json in json_obj: card = Card.from_json(board, json) if json.get('due',''): card.due = json['due'] else: card.due = False card.actual_list_id = json.get('idList', '') ret.append(card) return ret
def _schedule_card( self, card: Card, board_config: dict, ongoing_list: List, used_resources: dict, ): resources = board_config.get("resources", {}) uses_resources = [] labels = card.labels or [] limit = board_config.get('limit', 0) if limit and ongoing_list.cardsCnt() >= limit: return for label in labels: if label.name in resources: uses_resources.append(label.name) for label in uses_resources: if used_resources[label] >= resources[label]: return for label in uses_resources: used_resources[label] += 1 uid = str(uuid.uuid4()) cmd = board_config["command"].format(msg=card.description, uid=uid) print(f"Scheduling card {card.name}") process = subprocess.Popen(cmd, shell=True, start_new_session=True) card.change_list(ongoing_list.id) card.comment(f"⏲ Started: {datetime.datetime.now()}") card.comment(f"💻 PID: {process.pid}") card.comment(f"🔑 UID: {uid}")
def _finish_card(self, card: Card, done_list: List, used_resources: dict, uid: str): print(f"Finished card {card.name}") card.comment(f"✔️ Finished: {datetime.datetime.now()}") card.change_list(done_list.id) labels = card.labels or [] for label in labels: if label.name in used_resources: used_resources[label.name] -= 1 log_file = Path(f"{uid}.log") if log_file.exists(): with open(log_file) as fp: card.attach(name=f"{uid}.log", file=fp)
def run_task_copy(self, card: Card, to_list: trello.List): card_labels = card.labels if card_labels is None: card_labels = [] # find all labels need to apply after moving labels_to_apply: List[Label] = [] for label in card_labels: label_list = self.label_mapping.get(label, []) labels_to_apply += label_list labels_to_apply = set([x.id for x in labels_to_apply]) # find all members need to assign after moving members_to_assign: List[str] = [] for label in card_labels: member_list = self.member_via_label.get(label.id, []) members_to_assign += member_list members_to_assign = set(members_to_assign) # find all comments need to make after moving comments_to_make: List[str] = [] for label in card_labels: comment_list = self.comment_via_label.get(label.id, []) comments_to_make += comment_list # copy card new_card = copy_card(card, to_list, labels_to_apply, members_to_assign) # comments for comment in comments_to_make: new_card.comment(comment) if self.config.get('comment_original_card_share_link_to_copied_card', False): new_card.comment(card.short_url) card.comment(new_card.short_url) # remove mapping labels and add label via labels_to_change_with_label_mapping_labels if present labels_to_remove = [label for label in card_labels if label.id in self.label_to_list_mapping] change_label_mapping = self.config.get('labels_to_change_with_label_mapping_labels', {}) for label in labels_to_remove: card.remove_label(label) if change_label_mapping.get(label.id, None): try: card.add_label(Label(self.client, change_label_mapping.get(label.id, None), '')) except: pass
def run_task_move(self, card: Card, to_list: trello.List): card_labels = card.labels if card_labels is None: card_labels = [] # find all labels need to apply after moving labels_to_apply: List[Label] = [] for label in card_labels: label_list = self.label_mapping.get(label, []) labels_to_apply += label_list # find all members need to assign after moving members_to_assign: List[str] = [] for label in card_labels: member_list = self.member_via_label.get(label.id, []) members_to_assign += member_list # find all comments need to make after moving comments_to_make: List[str] = [] for label in card_labels: comment_list = self.comment_via_label.get(label.id, []) comments_to_make += comment_list # remove all members for member in card.idMembers: card.unassign(member) # remove all labels for label in card_labels: card.remove_label(label) # find comment for list comments_via_list = self.comment_from_list.get(card.list_id, []) comments_to_make += comments_via_list # move card card.change_board(to_list.board.id, to_list.id) # assign members for member in members_to_assign: card.assign(member) # label for label in labels_to_apply: try: card.add_label(label) except: pass # comment for comment in comments_to_make: card.comment(comment)
def _update_remaining(self, task: Task, card: Card): logger.debug("Setting custom remaining field") remaining_sec = str(task.remaining.total_seconds() / 3600) card.set_custom_field(remaining_sec, self.custom_fields["Time (h)"])
def _update_calendar_card(self, card: Card, event: CalendarEvent): logger.debug("Setting due date") card.set_due(event.start.strftime(iso_8601)) logger.debug("Setting custom task field") card.set_custom_field(event.id, self.custom_fields["CalendarId"])