def __init__(self): # API = "9cc1470c039f9f1bf8fe3ce35689a127" # TOKEN = "2093b976115e83e07b33321b359aa53a74d612aeec6373218d15796bd78a45b1" API = get_credentials()["api"] TOKEN = get_credentials()["token"] client = TrelloClient(api_key=API, token=TOKEN) self.boards = client.list_boards()
def post(self): """ Collect data from the HTML form to fill in a Trello card. That card will be uploaded to Suggestion Box board, on the corresponding list, determined by the "System" attribute given in the form. """ # Get form data date = datetime.now() title = self.get_argument('title') area = self.get_argument('area') system = self.get_argument('system') importance = self.get_argument('importance') difficulty = self.get_argument('difficulty') user = self.get_current_user_name() description = self.get_argument('description') suggestion = self.get_argument('suggestion') client = TrelloClient(api_key = self.application.trello_api_key, api_secret = self.application.trello_api_secret, token = self.application.trello_token) # Get Suggestion Box board boards = client.list_boards() suggestion_box = None for b in boards: if b.name == 'Suggestion Box': suggestion_box = client.get_board(b.id) break # Get the board lists (which correspond to System in the form data) and # concretely get the list where the card will go lists = b.all_lists() card_list = None for l in lists: if l.name == system: card_list = l break # Create new card using the info from the form new_card = card_list.add_card(TITLE_TEMPLATE.format(title=title, area=area)) new_card.set_description(DESCRIPTION_TEMPLATE.format(date = date.ctime(), area=area, system=system, importance=importance, difficulty=difficulty, user=user, description=description, suggestion=suggestion)) # Save the information of the card in the database self.application.suggestions_db.create({'date': date.isoformat(), 'card_id': new_card.id, 'description': new_card.description, 'name': new_card.name, 'url': new_card.url, 'archived': False}) self.set_status(200)
class TrelloClass: def __init__(self, api_key, token): self.client = TrelloClient(api_key=api_key, token=token) def get_client(self): return self.client def get_open_boards(self): return self.client.list_boards(board_filter="open") def get_board(self, board_name): return next(self.get_board_gen(board_name)) def get_board_gen(self, board_name): for board in self.client.list_boards(): if board.name == board_name: yield board def create_board(self, board_name): return self.client.add_board(board_name) def close_board(self, board_name): self.get_board(board_name).close() def get_open_lists(self, board_name): return self.get_board(board_name).open_lists() def create_list(self, board_name, list_name): return self.get_board(board_name).add_list(list_name) def get_list(self, board_name, list_name): return next(self.get_list_gen(board_name, list_name)) def get_list_gen(self, board_name, list_name): for trello_list in self.get_open_lists(board_name): if trello_list.name == list_name: yield trello_list def close_list(self, board_name, list_name): self.get_list(board_name, list_name).close() def get_cards_on_board(self, board_name): return self.get_board(board_name).open_cards() def get_cards_on_list(self, board_name, list_name): return self.get_list(board_name, list_name).list_cards() def add_card(self, board_name, list_name, card_name): return self.get_list(board_name, list_name).add_card(card_name) def get_card(self, card_name, board_name): return next(self.get_card_gen(card_name, board_name)) def get_card_gen(self, card_name, board_name): for card in self.get_board(board_name).open_cards(): if card.name == card_name: yield card
def get_tasks_from_trello(key, token, board_id): #возвращает список списков [имя,id,board_id] client = TrelloClient(api_key=key, api_secret=token) lists = client.list_boards(board_id) result = [] for board in client.list_boards(): if board.id == board_id: current_list = board.list_lists()[0] for card in current_list.list_cards(): result.append([(str(card)).strip('<>'),card.id, board_id]) return(result)
class Trello(): def __init__(self): # self.process_eq_board() cred = read_credentials('trello') self.client = TrelloClient(api_key=cred['trello']['api_key'], api_secret=cred['trello']['api_secret'], token=cred['trello']['api_token']) def set_active_board(self, board): self.active_board = self.client.get_board( [b for b in self.client.list_boards() if b.name == board][0].id) def set_active_list(self, _list): # try: self.active_list = [ l for l in self.active_board.all_lists() if _list in l.name ][0] # except: # print('Active Board is not set') def create_card(self, title, description, board=None, _list=None): if board and _list: self.set_active_board(board) self.set_active_list(_list) # create a new card with title and description new_card = self.active_list.add_card(title, description) return str(new_card) def get_comment_text(self, card): return [c['data']['text'] for c in card.get_comments()] def process_eq_board(self): boards = self.client.list_boards() eq_board = self.client.get_board( [b for b in boards if b.name == 'Elders Quorum'][0].id) # all lists lists = eq_board.all_lists() news_list = [l for l in lists if 'Announcements' in l.name][0] # callings_list = [l for l in lists if 'Callings' in l.name][0] # delegated_list = [l for l in lists if 'Delegated' in l.name][0] # wip_list = [l for l in lists if 'Work in Progress' in l.name][0] # task_list = [l for l in lists if 'Tasks' in l.name][0] # announcements announcements = news_list.list_cards() for card in announcements: print(card.name, card.description, self.get_comment_text(card))
class connectionJASON(): def setUp(self): self._trello = TrelloClient(api_key='f8fd231446c1fd27f49e0d8f933252f3', api_secret='338b8eef2cc489ce5cfc9f2252c73f5cf51b44a41cc6cb790be20feb9ed19f2d', token='8004f00bc94627ac6eb98333492a76315821ed06e9d04eec4b6480d1f575758b', token_secret='a528cdd05a0dd7314f45995fdf457c45') def getCards(self): boards = [board for board in self._trello.list_boards() if 'Proy Industria' in str(board.name) ] board = boards[0] cards = board.get_cards() return cards def arrangeCards(self,cards): resultTree = AVLTree(); for i in cards: if resultTree.rootNode == None: resultTree.insert(i,0) else: #resultTree.rootNode.text currentNode = resultTree.rootNode done = True while(done): moreImportant = (input(str(i)+" is more important than "+str(currentNode.text)+" y/n ")) if moreImportant == "y": if(currentNode.rightChild == None): resultTree.add_as_child2(i,currentNode,1) done = False else: currentNode = currentNode.rightChild else: if(currentNode.leftChild == None): resultTree.add_as_child2(i,currentNode,0) done = False else: currentNode = currentNode.leftChild print(resultTree.as_list(1)) #print(resultTree.rebalance_count) #print (resultTree.out()) return resultTree def sendCards(self,cards): boards = [board for board in self._trello.list_boards() if 'Proy Industria' in str(board.name) ] board = boards[0] cards = board.get_cards() return cards
def handle(self, *args, **options): trello = TrelloClient(settings.TRELLO_API_KEY, settings.TRELLO_TOKEN) boards = trello.list_boards() ####################################################################### # INSTALL THE MASTER BOARD ############################################ ####################################################################### # check if the board exists m = self.__search_board_by_name(settings.TRELLO_MASTER, boards) # if not create it if m is None: m = trello.add_board(settings.TRELLO_MASTER, default_lists=False) try: master = Board.objects.get(remoteid=m.id) except Board.DoesNotExist: master = Board(remoteid=m.id) master.name = m.name master.closed = m.closed master.last_activity = None master.save() self.__install_lists(m, master) self.__install_labels(m, master) self.__install_members(m) ####################################################################### self.__install_projects_boards(trello, master, boards) self.__install_members_boards(trello, master, boards)
def main(): client = TrelloClient( api_key=os.environ.get('TRELLO_API_KEY'), api_secret=os.environ.get('TRELLO_API_SECRET'), ) trello_filter = 'open' open_boards = client.list_boards(board_filter=trello_filter) for board in open_boards: print board.name planner = [board for board in open_boards if board.name == 'Planner'] if planner: planner = planner[0] else: raise Exception("Planner board not found") lists = planner.list_lists(list_filter=trello_filter) for l in lists: # l.add_card("name of card", "Comment") print l.name # card_filter is 'open' by default, everything else is 'all' for c in l.list_cards(card_filter=trello_filter): print u'- {}'.format(c.name) movements = c.list_movements() print "Moved {} times".format(len(movements)) # print c.fetch_comments(force=True) print c.card_created_date print c.date_last_activity
def get_trello_boards(): """ Get all Trello boards """ trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret) return trello_client.list_boards(board_filter="open")
class TrelloWrapper(): def __init__(self, api_key, api_token): self.tc = TrelloClient(api_key, api_token) def add_card(self, list_target, card_name, card_due, desc=None): """ Add card to list with a due date card_due: time.stuct_time object, use time.localtime() """ try: # Convert to UTC datetime object card_due_utc = time.gmtime(time.mktime(card_due)) due_str = time.strftime("%Y-%m-%dT%H:%M", card_due_utc) json_obj = list_target.client.fetch_json( '/lists/' + list_target.id + '/cards', http_method='POST', post_args={'name': card_name, 'due': due_str, 'idList': list_target.id, 'desc': desc}, ) except Exception as e: print(str(e)) def smart_add_card(self, sentence): """Check date keywords in the sentence, and use as card's due date.""" # TODO Life/Inbox as default, move to config target_default = ("Life", "Inbox") t_curr = time.time() p = parser.Parser(t_curr) target = p.parse_list(sentence) if target is None: target = target_default due = p.parse_due_time(sentence) list_target = self.find_list(target[0], target[1]) if list_target is None: return False self.add_card(list_target, sentence, due.timetuple()) return True def find_list(self, board_name, list_name): """ Return list specified by board_name/list_name""" for b in self.tc.list_boards(): if b.name != board_name: continue for l in b.open_lists(): if l.name != list_name: continue return l return None
class TrelloClient(JSConfigClient): def __init__(self, instance, data={}, parent=None, interactive=False): JSConfigClient.__init__(self, instance=instance, data=data, parent=parent, template=TEMPLATE, interactive=interactive) from trello import TrelloClient if not self.config.data["token_secret_"]: print("**WILL TRY TO DO OAUTH SESSION") from trello.util import create_oauth_token access_token = create_oauth_token( key=self.config.data["api_key_"], secret=self.config.data["secret_"]) self.config.data_set("token_", access_token["oauth_token"]) self.config.data_set("token_secret_", access_token["oauth_token_secret"]) self.client = TrelloClient( api_key=self.config.data["api_key_"], api_secret=self.config.data["secret_"], token=self.config.data["token_"], token_secret=self.config.data["token_secret_"]) def test(self): boards = self.client.list_boards() print(boards)
def get(self, request): try: token = request.GET.get('token') user = request.user if token is None: boards = None return super(BoardView, self).get(request) else: trello_client = TrelloClient(api_key=settings.TRELLO_APIKEY, token=token) boards = trello_client.list_boards() if boards: result = [h.delete() for h in trello_client.list_hooks()] print("delete trello hook :: result={}".format(result)) for board in boards: print("BOARD_ID:", board.id) slug_board = slugify(board.name, allow_unicode=False) b, created = Board.objects.get_or_create( name=slug_board, user=user, trello_board_id=board.id, trello_token=token) host = getenv("MATTERLLO_HOST") or request.get_host() url = "{}://{}/callback/{}/".format( request.scheme, host, b.id) result = trello_client.create_hook(url, board.id) print( "create trello hook :: callback={} :: board={} :: result={}" .format(url, slug_board, result)) return super(BoardView, self).get(request) except Exception as e: print("unable to display board :: {}".format(e)) return super(BoardView, self).get(request)
def create_card(pedido): cliente = pedido.cliente placa_video = get_component(pedido, 'Placa de Vídeo') processador = get_component(pedido, 'Processadores') memoria = get_component(pedido, 'Memória RAM') disco = get_component(pedido, 'Disco Rígido/SSD') gabinete = get_component(pedido, 'Gabinete') placa_mae = get_component(pedido, 'Placa mãe') fonte = get_component(pedido, 'Fonte') data = { 'statu_pedido': str(pedido.statu_pedido), 'username': str(cliente.username), 'email': str(cliente.email), 'telefone': str(cliente.telefone), 'placa_video': str(placa_video), 'processador': str(processador), 'memoria': str(memoria), 'disco': str(disco), 'gabinete': str(gabinete), 'placa_mae': str(placa_mae), 'fonte': str(fonte), } client = TrelloClient(api_key=settings.API_KEY, token=settings.TRELLO_API_SECRET) if settings.BOARD_NAME: board = check_board(client.list_boards()) if client.list_hooks() == []: client.create_hook(settings.CALLBACK_DOMAIN, board.id) for lista in board.all_lists(): if lista.name == pedido.statu_pedido: lista.add_card(name=f'Pedido {pedido.id}', desc=loader.render_to_string( 'pedido_template.txt', data))
def main(): # Vars to reference api_key = "API_KEY" api_token = "API_Token" board_id = "BOARD ID" todo_list_id = "TODO LIST_ID" done_list_id = "DONE LIST ID" client = TrelloClient(api_key=api_key, token=api_token) # Get a list of boards all_boards = client.list_boards() # Print a list of boards for board in all_boards: print(board.id + ":" + board.name) # Get our board amp_board = client.get_board(board_id) print_lists(amp_board) # Get the todo list todo_list = get_todo_list(amp_board, todo_list_id) created_card = create_card(client, todo_list) done_list = get_done_list(amp_board, done_list_id) # Move the list from TODO to Done list move_card(api_key, api_token, created_card.id, done_list) exit(0)
class TrelloClient(JSConfigClient): _SCHEMATEXT = """ @url = jumpscale.trello.client name* = "" (S) api_key_ = "" (S) secret_ = "" (S) token_ = "" (S) token_secret_= "" (S) """ def _init(self): from trello import TrelloClient if not self.token_secret_: print("**WILL TRY TO DO OAUTH SESSION") from trello.util import create_oauth_token access_token = create_oauth_token(key=self.api_key_, secret=self.secret_) self.token_ = access_token["oauth_token"] self.token_secret_ = access_token["oauth_token_secret"] self.client = TrelloClient(api_key=self.api_key_, api_secret=self.secret_, token=self.token_, token_secret=self.token_secret_) def test(self): boards = self.client.list_boards() print(boards)
def update_trello(assignments): trello_api_key = os.environ['TRELLO_API_KEY'] trello_secret = os.environ['TRELLO_TOKEN'] logger.info('Connecting to Trello') client = TrelloClient(api_key=trello_api_key, api_secret=trello_secret) logger.info('Reading Trello boards') for board_obj in client.list_boards(): if board_obj.name == 'Work TODO': todo_board = board_obj logger.info('Reading Trello lists') for list_obj in todo_board.list_lists(): if list_obj.name == 'Teaching': teaching_list = list_obj for assignment in assignments: if not in_db(assignment): if not in_skipped_group(assignment): teaching_list.add_card('Grade ' + assignment.course_name + ': ' + assignment.name, 'Grade', due=str(datetime.datetime.now() + datetime.timedelta(days=7))) add_to_db(assignment) logger.info('Added Assignment {}:{}'.format( assignment.course_id, assignment.assignment_id)) else: logger.info('Skipped Assignment {}:{} (In Skip Group)'.format( assignment.course_id, assignment.assignment_id)) else: logger.info('Skipped Assignment {}:{} (In DB)'.format( assignment.course_id, assignment.assignment_id))
class CardListDatasource(object): ''' ''' METHODS = { 'title': 'get_card_title', 'members': 'get_card_members', 'duration': 'get_card_duration' } def __init__(self, api_key, api_secret, token_key, token_secret): self.client = TrelloClient(api_key, api_secret, token_key, token_secret) def get_board(self, board_name): ''' Return board by name ''' boards = self.client.list_boards() for board in boards: if board.name == board_name: return board return None def get_cards(self, board): return board.all_cards() def parse_key(self, key): key = key[1:-1] # remove {} method = key.split('[')[0] try: param = re.match(r"[^[]*\[([^]]*)\]", key).groups()[0] except AttributeError: param = None return (method, param) def get_row(self, card, keys): row = {} for key in keys: parsed_key = self.parse_key(key) method = parsed_key[0] column = parsed_key[1] kwargs = { 'card' : card } if column: kwargs['column'] = column value = getattr(self, self.METHODS[method])(**kwargs) row[key] = value return row def get_card_duration(self, card, column=None): ''' Return card duration, with called column arg return card duration inside column ''' history = card.listCardMove_date() pass
def get_trello_board(trello_board_name, api_key, token): client = TrelloClient(api_key=api_key, token=token) all_boards = client.list_boards() target_board = None for board in all_boards: if board.name == trello_board_name: target_board = board break return target_board
class BriefIntro: def __init__(self): self.client = TrelloClient( api_key=os.getenv('TRELLO_API_KEY'), api_secret=os.getenv('TRELLO_API_SECRET'), token=os.getenv('OAUTH_TOKEN'), token_secret=os.getenv('OAUTH_TOKEN_SECRET')) def get_board_by_name(self, name): r = [b for b in self.client.list_boards() if b.name == name] if r: return r[0] else: raise NotFoundError def get_list_by_name(self, board, name): r = [l for l in board.all_lists() if l.name == name] if r: return r[0] else: raise NotFoundError def build_comments(self, comments): return [{ 'name': c['memberCreator']['fullName'], 'text': c['data']['text'] } for c in comments] def build_cards(self, lst): return [self.build_card(card) for card in lst.list_cards()] def build_card(self, card): return { 'title': card.name, 'label': card.labels[0].name, 'abstract': card.description, 'comments': self.build_comments(card.comments) } def code_gen(self, board_name, list_name, title, outfile): b = self.get_board_by_name(board_name) l = self.get_list_by_name(b, list_name) cards = self.build_cards(l) with open("templates/brief_intro.md") as f: tpl = Template(f.read()) with open(outfile, "w") as g: print(tpl.render(cards=cards, title=title), file=g) def get_vote(self, board_name, list_name, topk=5): b = self.get_board_by_name(board_name) l = self.get_list_by_name(b, list_name) cards = l.list_cards() votes = [(c, len(c.member_ids)) for c in cards] votes.sort(key=lambda p: p[1], reverse=True) for c, v in votes[:topk]: print(v, c.name)
def get_trello_boards(): """ Get all Trello boards """ logger.info('Fetching Trello boards ...') trello_client = TrelloClient( api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret) logger.info('... done') return trello_client.list_boards()
def get_context_data(self, **kwargs): """Fishy way to ensure trello_client is configured.""" try: context = super(BoardView, self).get_context_data(**kwargs) token = self.request.GET.get("token") if token is None: context["board_list"] = None trello_client = TrelloClient(api_key=settings.TRELLO_APIKEY, token=token) trello_client.list_boards() user = self.request.user listboard = Board.objects.filter(trello_token=token) context["board_list"] = listboard context["trello_error"] = None except Exception as e: context["trello_error"] = "{} :: api_key={} :: token={}".format( e, settings.TRELLO_APIKEY, settings.TRELLO_TOKEN) finally: return context
def status_fabrica(trello_client: trello.TrelloClient) -> dict: ''' :param trello_client: the trello client connection :return: dictionary containing how many jobs there are ''' trello_list_dict = dict() for trello_lists in trello_client.list_boards()[-2].list_lists(): if not trello_lists.closed: trello_list_dict[trello_lists.name] = trello_lists.cardsCnt() return trello_list_dict
def main(api_key, token): """List out the boards for our client""" trello_client = TrelloClient( api_key=api_key, token=token, ) print('Boards') print('-----') print('Name: Id') for board in trello_client.list_boards(): print('{board.name}: {board.id}'.format(board=board))
def send_message_to_slack(job, name, email, contact, address, order, ticket, reason, action): """Send message in slack as well as add trello card""" import urllib2 import json if job is None: job = "NA" if name is None: name = "NA" if order is None: order = "NA" if email is None: email = "NA" if contact is None: contact = "NA" if address is None: address = "NA" if ticket is None: ticket = "NA" if reason is None: reason = "NA" if action is None: action = "NA" return_details = "Over The Counter Returns:" + "\n" + "--------------------------------" + "\n\n" + "Job Number: " + job + "\n" + "Full Name " + name + "\n" + "Email: " + email + "\n" + "Contact Number: " + contact + "\n" + "Address: " + address + "\n" + "Order number: " + order + "\n" + "Ticket Number: " + ticket + "\n\n" + "Reason: " + reason + "\n" + "Action: " + action post = {"text": "{0}".format(return_details)} try: json_data = json.dumps(post) req = urllib2.Request("", data=json_data.encode('ascii'), headers={'Content-Type': 'application/json'}) resp = urllib2.urlopen(req) except Exception as em: print("EXCEPTION: " + str(em)) client = TrelloClient( api_key='', api_secret='', token='', token_secret='None', ) trello_name = (" Job No: " + job + "-" + name) trello_descr = ( "Order Number: " + order + "\n" + "Name: " + name + "\n" + "Contact number: " + contact + "\n" + "Email: " + email + "\n" + "Ticket num: " + ticket) all_boards = client.list_boards() last_board = all_boards[1] lists = last_board.list_lists() for l in lists: if l.name == 'Repairs': card = l.add_card(trello_name, desc = trello_descr) items=['Assesment started', 'Assesment Complete/ Job card filled out', 'Quotation sent/Customer advised','Warranty job (repair/refund/replace)', 'Quote Accepted', 'Quote Rejected', 'Waiting on parts', 'Repair Started', 'Repair Complete (QC and testing done, if applicable)', 'Ready for Collection/Sent to dispatch/Customer notified'] card.add_checklist("Check", items, itemstates=None)
def get_list_of_cards(listname): card_name_list = {} client = TrelloClient(api_key='#####################################', api_secret='#####################################') all_boards = client.list_boards() last_board = all_boards[0] all_lists = last_board.list_lists() for list in all_lists: if list.name == listname: all_cards = list.list_cards() for card in all_cards: card_name_list[card.name] = listname return card_name_list
def connect_trello(api_key, api_secret, oauth_token, oauth_secret, verbose=False): client = TrelloClient(api_key=api_key, api_secret=api_secret, token=oauth_token, token_secret=oauth_secret) if verbose: print("Available boards: {}".format(client.list_boards())) return client
def __init__(self, credentials_path): with open(credentials_path, "r") as file_obj: credentials = json.load(file_obj) client = TrelloClient(**credentials) board = client.list_boards()[0] self.cards = {} for card in board.open_cards(): self.cards[card.name] = card self.lists = {} for lst in board.open_lists(): self.lists[lst.name] = lst self.labels = {lbl.color: lbl for lbl in board.get_labels()}
def get_trello_list(): # connect to trello trello_api_key = 'xxxx' trello_api_secret = 'xxxx' # this oauth token and secret are fetched using trello_oauth_util.py trello_oauth_token = "xxxx" trello_oauth_token_secret = "xxxx" trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_oauth_token, token_secret=trello_oauth_token_secret) # fetch the desired board # noinspection PyTypeChecker for board in trello_client.list_boards(): if TRELLO_BOARD_NAME == board.name: for board_list in board.all_lists(): if TRELLO_LIST_NAME == board_list.name: return board_list
def main(): """Main method""" # Get config if len(sys.argv) >= 2: config_file = sys.argv[1] else: config_file = "config.json" with open(config_file, 'r') as config: CONFIG = json.load(config) # Logging into Trello client = TrelloClient(api_key=CONFIG["api_key"], api_secret=CONFIG["api_secret"], token=CONFIG["token"]) # Have to get all boards to find working board by name all_boards = client.list_boards() # Finding working board by .name for board in all_boards: if board.name == CONFIG["working_board"]: working_board = board # Get a number of tasks from working_board tasks = get_rand_task(working_board.get_cards(), CONFIG["num_tasks"]) # Build body for daily email of tasks body = "Howdy!\n\nToday, you should accomplish the following from your board named {}:\n".format( working_board.name) for task in tasks: body = body + "{}\n".format(task.name) body = body + "\nGood luck!" # Prepare email message msg = EmailMessage() msg.set_content(body) msg['Subject'] = "Do These Things Today: {}".format(working_board.name) msg['From'] = CONFIG["from_email"] msg['To'] = CONFIG["to_email"] # Send message server = smtplib.SMTP(CONFIG["smtp_server"]) server.send_message(msg) server.quit()
def get_boards_and_users(client: TrelloClient): """ Get list of all boards and users subscribed to them. :param client: A Trello client object :return: Results of request """ boards = [] all_boards = client.list_boards() print(all_boards[0].name) print(all_boards[0].description) all_members = all_boards[0].all_members() print(all_members[0].username) print(all_members[0].id) print(all_members[0].full_name)
class TrelloAPI(object): def __init__(self, api_key, api_secret, board_id=None): self.client = TrelloClient(api_key=api_key, api_secret=api_secret) if not board_id: for aboard in self.client.list_boards(board_filter='open'): if aboard.name == ROADMAP_BOARD_NAME: board_id = aboard.id assert board_id self.board = self.client.get_board(board_id) @property def roadmap(self): return self.board.open_lists() @property def epics(self): return {c.name: c for c in self.board.open_cards()}
def request_all_comments() -> Tuple[List[str], List[str]]: key, secret, token = __get_api_keys() client = TrelloClient(api_key=key, api_secret=secret, token=token) dates = [] comments = [] for board in client.list_boards(): if board.name == 'Notizen': lists = board.get_lists('all') for l in lists: if l.name == 'Sport': cards = l.list_cards() for card in cards: if card.name == 'Laufen': for comment in card.get_comments(): dates.append(__get_date_string(comment)) comments.append(__get_comment_text(comment)) return (dates, comments)
def complete_trello(request, uid): task_todoapp = TodoItem.objects.get(id=uid) user = request.user key = user.profile.trello_key secret = user.profile.trello_secret client = TrelloClient(api_key=key, api_secret=secret) board = client.list_boards()[0] # захардкодил самую первую доску в Trello left_most = board.list_lists()[0] right_most = board.list_lists()[-1] for task in left_most.list_cards(): if task.name == task_todoapp.description: task.change_list(right_most.id) task_todoapp.is_completed = True task_todoapp.save() return HttpResponse("OK")
def main(): if len(sys.argv) < 2 or sys.argv[1].lower() != 'show': usage() return api_key = os.getenv('TRELLO_API_KEY') api_secret = os.getenv('TRELLO_API_SECRET') api_token = os.getenv('TRELLO_TOKEN') api_token_secret = os.getenv('TRELLO_TOKEN_SECRET') client = TrelloClient(api_key=api_key, api_secret=api_secret, token=api_token, token_secret=api_token_secret) try: boards = client.list_boards() except ResourceUnavailable as e: print('Fail:', e) return for b in boards: print(b.id, b.name)
def getRecruitmentBoard(configurationFileName='api.json'): api = {} # In[1]: with open(configurationFileName) as json_file: api = json.load(json_file) # In[2]: client = TrelloClient(api_key=api["api_key"], api_secret=api["api_secret"], token=api["token"]) all_boards = client.list_boards() last_board = all_boards[-1] recruitment = Board() for board in all_boards: if board.name == api["recruitment_board_name"]: recruitment = board print(recruitment.name) return recruitment
def import_task_trello(self, user, id): client = TrelloClient(api_key=user.profile.api_key, api_secret=user.profile.api_secret) tasks_Trello = client.list_boards()[id["id_board"]] to_do = tasks_Trello.list_lists()[0] cards = to_do.list_cards() card = to_do.list_cards()[0] tasks = TodoItem.objects.filter(owner=user).all() tag = [] for t in tasks: # tag.append(t.tags) t.delete() # for ta in tag: # count = TodoItem.tags.through.objects.filter(tag_id=ta).aggregate(total_tasks=Count('id')) r = 0 for i in cards: t = TodoItem(description=i.name, id_trello=i.id, owner=user) t.save() r += 1 return r
def get_board(): ''' Retourne la liste Trello indiquée dans trello.ini ''' # Chargement des paramètres et identifiants Trello depuis le fichier JSON with open("trello.json") as parameters_data: config = json.load(parameters_data) trello = TrelloClient(api_key=config['ApiKey'], api_secret=config['ApiSecret'], token=config['Token'], token_secret=config['TokenSecret']) for b in trello.list_boards(): if b.name == config['BoardName']: return b print("Board " + config['BoardName'] + " not found.") exit()
def make_trello_board(self): client = TrelloClient( api_key=self.auth["trello"]["api_key"], api_secret=self.auth["trello"]["api_secret"], token=self.auth["trello"]["token"], token_secret=self.auth["trello"]["token_secret"], ) boards = client.list_boards() template = None for board in boards: if board.name == self.trello_template: template = board new_board = client.add_board( "DP: " + self.params["title"], source_board=template, permission_level="private" ) self.params["trello_url"] = new_board.url print("Created Trello board - " + new_board.url)
class TrelloCli: def __init__(self, file='config.yml'): """ Load Trello api keys from yaml file""" with open(file, 'r') as stream: try: config = yaml.safe_load(stream) self.__client = TrelloClient( api_key = config['key'], api_secret = config['token'] ) except yaml.YAMLError as exc: print(exc) def get_board(self, board_name): """ Get the board from the board name """ boards = self.__client.list_boards() for board in boards: if board.name == board_name: return self.__client.get_board(board.id) def get_list(self, board, list_name): lists = board.all_lists() for list in lists: if list.name == list_name: return board.get_list(list.id) def get_member(self, board, member_name): members = board.all_members() for member in members: if member.full_name == member_name: return member def display_cards(self, trello_list): cards = trello_list.list_cards() for card in cards: print(card.name)
def main(): try: parser = argparse.ArgumentParser(description="Webhook helpers") parser.add_argument('--cleanup', dest='cleanup', action='store_true', help='delete webhook from your SETTINGS.') parser.add_argument('--update', dest='update', action='store_true', help='upsert webhook from your SETTINGS.') parser.add_argument('--init', dest='init', action='store_true', help='delete and create webhook from your SETTINGS.') args = parser.parse_args() if not args.cleanup and not args.update and not args.init: print parser.print_help() sys.exit(0) client = TrelloClient(api_key=SETTINGS['trello_api_key'], token=SETTINGS['trello_api_token']) trello_boards = client.list_boards() boards_name = [slugify(b['name']) for b in SETTINGS.get('boards', {}).values()] # cleanup part if args.cleanup or args.init: result = [h.delete() for h in client.list_hooks()] LOGGING.info('delete {} webhook'.format(len(result))) # update / init part if args.update or args.init: for board in trello_boards: board_name = slugify(board.name) if board_name not in boards_name: continue LOGGING.info('try to create webhook board :: {}'.format(board_name)) url = SETTINGS['callback_url'] + '/trelloCallbacks/' result = client.create_hook(url, board.id) LOGGING.info('create webhook board :: {} :: {}'.format(board_name, result)) except Exception as e: LOGGING.error('unable init webhook :: {}'.format(e)) sys.exit(1)
class TrelloCmd(Command): "Update trello board from launchpad filters" log = logging.getLogger(__name__) def get_parser(self, prog_name): parser = super(TrelloCmd, self).get_parser(prog_name) parser.add_argument( '--filter', type=str, action='append', required=True, help="List of params for searchTasks", ) parser.add_argument( '--project', type=str, action='append', required=True, help="Project" ) parser.add_argument( '--board', type=str, required=True, help="Trello board name" ) parser.add_argument( '--trello-key', type=str, required=False, help="You can get one at https://trello.com/app-key" ) parser.add_argument( '--trello-secret', type=str, required=False, help="You can get one at https://trello.com/app-key" ) parser.add_argument( '--trello-token', type=str, required=False, help="You can get one at https://trello.com/1/connect?" + "key=YOUR_TRELLO_KEY&name=bugfix-app&response_type=token&" + "scope=read,write&expiration=never" ) parser.add_argument( '--trello-token-secret', type=str, required=False, ) parser.add_argument( '--create-board', action='store_true', help='Create Trello board if not exists' ) parser.add_argument( '--use-labels', nargs='+', help='Labels for cards', default=[ 'tricky', 'low-hanging-fruit', 'tech-debt' ] ) return parser def take_action(self, parsed_args): err_count = 0 logging.getLogger("requests").setLevel(logging.WARNING) self.log.info('Connecting to Launchpad') self.lp = Launchpad.login_with( 'lp-report-bot', 'production', version='devel') self.tr = TrelloClient( api_key=parsed_args.trello_key, api_secret=parsed_args.trello_secret, token=parsed_args.trello_token, token_secret=parsed_args.trello_token_secret) try: self.board = [ board for board in self.tr.list_boards() if board.name == parsed_args.board ][0] except IndexError: if parsed_args.create_board: self.board = self.tr.add_board(parsed_args.board) # for label in self.board.all_lists(): # #label.delete() # # self.client.fetch_json( # # '/cards/' + self.id, # # http_method='DELETE') for list in self.board.open_lists(): list.close() else: raise Exception( "Board {0} doesn't exist. Use --create-board argument" + " in order to create it".format(parsed_args.board)) self.log.info("Working with board {0}".format(self.board)) self.tag_labels = parsed_args.use_labels self.cards = dict() self.untouched_cards = dict() for card in self.board.open_cards(): groups = re.search('(\d+)', card.name) if not (groups is None): bug_id = groups.group(0) if bug_id not in self.cards: self.untouched_cards[bug_id] = card self.log.debug( "Found existing card for bug {0}".format(bug_id)) self.cards[bug_id] = card else: self.log.info( "Killing duplicate card for bug {0}".format(bug_id)) card.delete() self.log.info("Found {0} existing cards".format( len(self.untouched_cards))) for prj_name in parsed_args.project: prj = self.lp.projects[prj_name] for f in parsed_args.filter: self.log.debug(f) filt = json.loads(f) if filt['milestone']: filt['milestone'] = prj.getMilestone( name=filt['milestone']) if 'assignee' in filt: filt['assignee'] = self.lp.people[filt['assignee']] if 'status' not in filt: filt['status'] = [ 'New', 'Incomplete', 'Opinion', 'Invalid', 'Won\'t Fix', 'Expired', 'Confirmed', 'Triaged', 'In Progress', 'Fix Committed', 'Fix Released' ] self.log.debug(filt) self.log.info("Searching for tasks in project %s" % prj_name) for task in prj.searchTasks(**filt): self.log.info("Proceeding task %s" % task) retries = 3 for i in range(retries): try: self.proceed_task(task) except Exception as e: if i < retries: self.log.exception(e) self.log.warning( "Got an exception for task %s, retrying" % task) continue else: self.log.exception(e) self.log.warning( "Failed to proceed task %s" % task) err_count += 1 break for series in prj.series: self.log.info("Searching for tasks in {0}:{1}".format( str(prj.name), str(series.name))) for task in series.searchTasks(**filt): self.log.info("Proceeding task %s" % task) retries = 3 for i in range(retries): try: self.proceed_task(task) except Exception as e: if i < retries: continue else: self.log.exception(e) self.log.warning( "Failed to proceed task %s" % task) err_count += 1 break if self.untouched_cards: self.log.info("%d cards are out of scope" % len( self.untouched_cards)) try: out_of_scope_list = [ list for list in self.board.open_lists() if list.name == 'Trash/Out of scope'][0] except IndexError: out_of_scope_list = self.board.add_list('Trash/Out of scope') for card in self.untouched_cards.values(): card.change_list(out_of_scope_list.id) self.log.info("Finished with %d errors" % err_count) if err_count > 0: return 1 return 0 def get_task_reviews(self, task): self.log.debug("Searching for reviews for task {0}".format(task)) bug = task.bug gerrits = [ 'https://review.openstack.org/', 'https://review.fuel-infra.org/'] reviews = [] # Message number 0 is description is_description = True for msg in bug.messages: if is_description: is_description = False continue for g in gerrits: reviews += re.findall(g + '\d+', msg.content) long_reviews = re.findall(g + '#/c/\d+', msg.content) for u in long_reviews: reviews += [u.replace('#/c/', '')] open_reviews = [] for rev_url in set(reviews): [base_url, id] = rev_url.rsplit('/', 1) rest = GerritRestAPI(base_url) try: review = rest.get('/changes/{0}/detail'.format(id)) if review['status'] == 'NEW': status = [] if 'rejected' in review['labels']['Workflow']: status.append('WIP') if 'disliked' in review['labels']['Verified']: status.append('FAIL') open_reviews.append({'url': rev_url, 'status': status}) self.log.debug("Found open review {0}".format(rev_url)) except Exception: pass return open_reviews def get_task_list(self, task): list_name = 'Bad Status' try: if task.status in ['Confirmed']: if task.assignee is None or task.assignee.is_team: list_name = 'Inbox/Need triage' else: list_name = 'Assigned/Investigating' if task.status in ['Incomplete']: list_name = 'Incomplete/Need more info' if task.status in ['Triaged']: list_name = 'Triaged/Ready to be fixed' if task.status in ['In Progress']: if self.get_task_reviews(task): list_name = 'In Progress/Need review' else: list_name = 'In Progress/Working on fix' if task.status in ['Fix Committed', 'Fix Released']: list_name = 'Fix Committed/Done' if task.status in ['Invalid', 'Opinion', 'Won\'t Fix']: list_name = 'Won\'t Fix/Done' if task.status in ['New']: list_name = 'New/Need confirmation' # if ( # not filter(lambda x: x.startswith('team-'), task.bug.tags) # and 'tech-debt' not in task.bug.tags and # task.status in [ # 'New', 'Confirmed', 'Triaged', 'In Progress', # 'Incomplete'] # ): # list_name = 'New/Need confirmation' if 'blocked' in task.bug.tags: list_name = 'Blocked/On hold' return [ list for list in self.board.open_lists() if list.name == list_name][0] except IndexError: return self.board.add_list(list_name) def get_task_labels(self, task): bug = task.bug tags = list(set(bug.tags).intersection(self.tag_labels)) # Each bug should have either team tag or no-team tag or tech-debt tag team_tags = filter(lambda x: x.startswith('team-'), bug.tags) if team_tags: tags += team_tags else: if 'tech-debt' not in bug.tags: tags += ['no-team'] if not filter(lambda x: x.startswith('area-'), task.bug.tags): tags += ['no-area'] # if task.importance in ['Critical', 'High']: # tags.append('high-priority') return tags def get_card_title(self, task): bug = task.bug assignee_id = "unassigned" if task.assignee_link is not None: assignee_id = task.assignee_link.split('~')[-1] return u'Bug {0} ({1}): {2}'.format( bug.id, assignee_id, bug.title)[:200] def get_card_description(self, task, card_list): bug = task.bug desc = "Created by {0}\n".format(bug.owner_link.split('~')[-1]) desc += bug.web_link + "\n" if card_list.name == 'In Progress/Need review': desc += "Reviews:\n" + "\n".join(map( lambda x: u"{0} {1}".format(x['url'], ':'.join(x['status'])), self.get_task_reviews(task) )) + "\n" desc += "\n----------\n" + bug.description return desc[:1000] def proceed_task(self, task): self.log.debug("Processing task {0}".format(task)) bug = task.bug card_list = self.get_task_list(task) if str(bug.id) not in self.cards: self.log.debug("Creating card for bug {0}".format(bug.id)) card = card_list.add_card( self.get_card_title(task), self.get_card_description(task, card_list)) self.cards[bug.id] = card else: self.log.debug("Getting card for task {0}".format(task)) card = self.cards[str(bug.id)] try: del self.untouched_cards[str(bug.id)] except KeyError: pass self.log.debug( ( "Updating existing card for bug {0}, moving to {1} list" ).format(bug.id, card_list)) card.change_list(card_list.id) new_name = self.get_card_title(task) if new_name != card.name.decode('utf-8'): card.set_name(new_name) new_desc = self.get_card_description(task, card_list) if new_desc != card.description: card.set_description(new_desc) tags = self.get_task_labels(task) for label in card.labels: if label.name not in tags: # delete_label is not published on pypi yet # card.delete_label(label) card.client.fetch_json( '/cards/' + card.id + '/idLabels/' + label.id, http_method='DELETE') for label_name in tags: try: label = [ l for l in self.board.get_labels() if l.name == label_name][0] except IndexError: label = self.board.add_label(label_name, 'green') try: card.add_label(label) except Exception: pass self.log.debug(task)
try: tr_id = tr.get_member(MAP_USER_LP_2_TR[lp_name]).id except: tr_id = tr.get_member("ashtokolov").id return tr_id print 'Sync started at:', datetime.datetime.now() # login to lauchpad lp = Launchpad.login_anonymously('test', 'production', LP_CACHEDIR) # login to trello tr = TrelloClient(api_key=TRELLO_KEY, api_secret=TRELLO_SECRET, token=TRELLO_TOKEN, token_secret=TRELLO_SECRET) # Extract Trello board all_boards = tr.list_boards() boards = [board for board in all_boards if board.name == TRELLO_BOARD] if len(boards) == 0: print "No Trello board found:" + TRELLO_BOARD exit(0) board = boards[0] print 'Found Board:', board # , dir(board) # Extract Trello lists lists = board.open_lists() list_new = get_trello_list(lists, TRELLO_LIST_NEW) #list_confirmed = get_trello_list(lists, TRELLO_LIST_CONFIRMED) #list_confirmed_user = get_trello_list(lists, TRELLO_LIST_CONFIRMED_USER) list_in_progress = get_trello_list(lists, TRELLO_LIST_IN_PROGRESS) list_triaged = get_trello_list(lists, TRELLO_LIST_TRIAGED)
class TrelloClientTestCase(unittest.TestCase): """ Tests for TrelloClient API. Note these test are in order to preserve dependencies, as an API integration cannot be tested independently. """ def setUp(self): self._trello = TrelloClient(os.environ['TRELLO_API_KEY'], token=os.environ['TRELLO_TOKEN']) def test01_list_boards(self): self.assertEqual( len(self._trello.list_boards(board_filter="open")), int(os.environ['TRELLO_TEST_BOARD_COUNT'])) def test10_board_attrs(self): boards = self._trello.list_boards() for b in boards: self.assertIsNotNone(b.id, msg="id not provided") self.assertIsNotNone(b.name, msg="name not provided") self.assertIsNotNone(b.description, msg="description not provided") self.assertIsNotNone(b.closed, msg="closed not provided") self.assertIsNotNone(b.url, msg="url not provided") def test20_board_all_lists(self): boards = self._trello.list_boards() for b in boards: try: b.all_lists() except Exception: self.fail("Caught Exception getting lists") def test21_board_open_lists(self): boards = self._trello.list_boards() for b in boards: try: b.open_lists() except Exception: self.fail("Caught Exception getting open lists") def test22_board_closed_lists(self): boards = self._trello.list_boards() for b in boards: try: b.closed_lists() except Exception: self.fail("Caught Exception getting closed lists") def test30_list_attrs(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): self.assertIsNotNone(l.id, msg="id not provided") self.assertIsNotNone(l.name, msg="name not provided") self.assertIsNotNone(l.closed, msg="closed not provided") break # only need to test one board's lists def test50_list_cards(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): self.assertIsNotNone(c.id, msg="id not provided") self.assertIsNotNone(c.name, msg="name not provided") self.assertIsNotNone(c.description, msg="description not provided") self.assertIsNotNone(c.closed, msg="closed not provided") self.assertIsNotNone(c.url, msg="url not provided") break break pass def test51_fetch_cards(self): """ Tests fetching all attributes for all cards """ boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): c.fetch() self.assertIsInstance(c.date_last_activity, datetime, msg='date not provided') self.assertTrue(len(c.board_id) > 0, msg='board id not provided') break break pass def test52_list_hooks(self): self.assertIsInstance(self._trello.list_hooks(), list) def test53_unauthorized(self): client = TrelloClient('a') self.assertRaises(Unauthorized, client.list_boards) def test54_resource_unavailable(self): self.assertRaises(ResourceUnavailable, self._trello.get_card, '0') def test_list_stars(self): """ Test trello client star list """ self.assertEqual(len(self._trello.list_stars()), int(os.environ["TRELLO_TEST_STAR_COUNT"]), "Number of stars does not match TRELLO_TEST_STAR_COUNT") def test_add_delete_star(self): """ Test add and delete star to/from test board """ test_board_id = self._trello.search(os.environ["TRELLO_TEST_BOARD_NAME"])[0].id new_star = self._trello.add_star(test_board_id) star_list = self._trello.list_stars() self.assertTrue(new_star in star_list, "Star id was not added in list of starred boards") deleted_star = self._trello.delete_star(new_star) star_list = self._trello.list_stars() self.assertFalse(deleted_star in star_list, "Star id was not deleted from list of starred boards")
class TrelloStats(Command): "Get board statistics from trello" log = logging.getLogger(__name__) def get_parser(self, prog_name): parser = super(TrelloStats, self).get_parser(prog_name) parser.add_argument( '--board', type=str, required=True, help="Trello board name" ) parser.add_argument( '--trello-key', type=str, required=False, help="You can get one at https://trello.com/app-key" ) parser.add_argument( '--trello-secret', type=str, required=False, help="You can get one at https://trello.com/app-key" ) parser.add_argument( '--trello-token', type=str, required=False, help="You can get one at https://trello.com/1/connect?" + "key=YOUR_TRELLO_KEY&name=bugfix-app&response_type=token&" + "scope=read,write&expiration=never" ) parser.add_argument( '--trello-token-secret', type=str, required=False, ) return parser def take_action(self, parsed_args): logging.getLogger("requests").setLevel(logging.WARNING) self.tr = TrelloClient( api_key=parsed_args.trello_key, api_secret=parsed_args.trello_secret, token=parsed_args.trello_token, token_secret=parsed_args.trello_token_secret) self.log.debug(self.tr.list_boards()) try: self.board = [ board for board in self.tr.list_boards() if board.name == parsed_args.board ][0] except IndexError: raise Exception( "Board {0} doesn't exist".format(parsed_args.board)) self.log.debug(self.board) def get_card_type(card): l_names = [l.name for l in card.labels] if 'tech-debt' in l_names: return 'tech-debt' return 'bug' def get_list_type(list): if ( 'New' in list.name or 'Inbox' in list.name or 'Assigned' in list.name or 'Triaged' in list.name or 'Blocked' in list.name ): return 'open' if ( 'In Progress' in list.name ): return 'in progress' if 'Fix Committed' in list.name: return 'done' if ( 'Incomplete' in list.name or 'Won\'t Fix' in list.name or 'Trash' in list.name ): return 'rejected' return 'unknown' stats = [ get_card_type(c) + ":" + get_list_type(c.get_list()) for c in self.board.open_cards() ] for s in sorted(set(stats)): self.log.info("{0}: {1}".format(s, stats.count(s)))
class TrelloClientTestCase(unittest.TestCase): """ Tests for TrelloClient API. Note these test are in order to preserve dependencies, as an API integration cannot be tested independently. """ def setUp(self): self._trello = TrelloClient(os.environ['TRELLO_API_KEY'], os.environ['TRELLO_TOKEN']) def tearDown(self): #self._trello.logout() pass def test01_list_boards(self): self.assertEquals( len(self._trello.list_boards()), int(os.environ['TRELLO_TEST_BOARD_COUNT'])) def test10_board_attrs(self): boards = self._trello.list_boards() for b in boards: self.assertIsNotNone(b.id, msg="id not provided") self.assertIsNotNone(b.name, msg="name not provided") self.assertIsNotNone(b.description, msg="description not provided") self.assertIsNotNone(b.closed, msg="closed not provided") self.assertIsNotNone(b.url, msg="url not provided") def test20_board_all_lists(self): boards = self._trello.list_boards() for b in boards: try: b.all_lists() except Exception as e: self.fail("Caught Exception getting lists") def test21_board_open_lists(self): boards = self._trello.list_boards() for b in boards: try: b.open_lists() except Exception as e: self.fail("Caught Exception getting open lists") def test22_board_closed_lists(self): boards = self._trello.list_boards() for b in boards: try: b.closed_lists() except Exception as e: self.fail("Caught Exception getting closed lists") def test30_list_attrs(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): self.assertIsNotNone(l.id, msg="id not provided") self.assertIsNotNone(l.name, msg="name not provided") self.assertIsNotNone(l.closed, msg="closed not provided") break # only need to test one board's lists def test40_list_cards(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): self.assertIsNotNone(c.id, msg="id not provided") self.assertIsNotNone(c.name, msg="name not provided") self.assertIsNotNone(c.description, msg="description not provided") self.assertIsNotNone(c.closed, msg="closed not provided") self.assertIsNotNone(c.url, msg="url not provided") break break pass def test50_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python - no desc" card = l.add_card(name) except Exception as e: print(str(e)) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created") def test51_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python" description = "Description goes here" card = l.add_card(name, description) except Exception as e: print(str(e)) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertEquals(card.description, description) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created")
class TrelloClientTestCase(unittest.TestCase): """ Tests for TrelloClient API. Note these test are in order to preserve dependencies, as an API integration cannot be tested independently. """ def setUp(self): self._trello = TrelloClient(os.environ['TRELLO_API_KEY'], token=os.environ['TRELLO_TOKEN']) def test01_list_boards(self): self.assertEquals( len(self._trello.list_boards()), int(os.environ['TRELLO_TEST_BOARD_COUNT'])) def test10_board_attrs(self): boards = self._trello.list_boards() for b in boards: self.assertIsNotNone(b.id, msg="id not provided") self.assertIsNotNone(b.name, msg="name not provided") self.assertIsNotNone(b.description, msg="description not provided") self.assertIsNotNone(b.closed, msg="closed not provided") self.assertIsNotNone(b.url, msg="url not provided") def test20_board_all_lists(self): boards = self._trello.list_boards() for b in boards: try: b.all_lists() except Exception as e: self.fail("Caught Exception getting lists") def test21_board_open_lists(self): boards = self._trello.list_boards() for b in boards: try: b.open_lists() except Exception as e: self.fail("Caught Exception getting open lists") def test22_board_closed_lists(self): boards = self._trello.list_boards() for b in boards: try: b.closed_lists() except Exception as e: self.fail("Caught Exception getting closed lists") def test30_list_attrs(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): self.assertIsNotNone(l.id, msg="id not provided") self.assertIsNotNone(l.name, msg="name not provided") self.assertIsNotNone(l.closed, msg="closed not provided") break # only need to test one board's lists def test40_list_cards(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): self.assertIsNotNone(c.id, msg="id not provided") self.assertIsNotNone(c.name, msg="name not provided") self.assertIsNotNone(c.description, msg="description not provided") self.assertIsNotNone(c.closed, msg="closed not provided") self.assertIsNotNone(c.url, msg="url not provided") break break pass def test50_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python - no desc" card = l.add_card(name) except Exception as e: print(str(e)) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created") def test51_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python" description = "Description goes here" card = l.add_card(name, description) except Exception as e: print(str(e)) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertEquals(card.description, description) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created") def test52_get_cards(self): boards = [board for board in self._trello.list_boards() if board.name == os.environ['TRELLO_TEST_BOARD_NAME']] self.assertEquals(len(boards), 1, msg="Test board not found") board = boards[0] cards = board.get_cards() self.assertEqual(len(cards), 2, msg="Unexpected number of cards in testboard") for card in cards: if card.name == 'Testing from Python': self.assertEqual(card.description, 'Description goes here') elif card.name == 'Testing from Python - no desc': self.assertEqual(card.description, '') else: self.fail(msg='Unexpected card found') def test60_delete_cards(self): boards = [board for board in self._trello.list_boards() if board.name == os.environ['TRELLO_TEST_BOARD_NAME']] self.assertEquals(len(boards), 1, msg="Test board not found") board = boards[0] cards = board.get_cards() for card in cards: card.delete() def test52_add_card_set_due(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python" description = "Description goes here" card = l.add_card(name, description) except Exception as e: print str(e) self.fail("Caught Exception adding card") # Set the due date to be 3 days from now today = datetime.datetime.today() day_detla = datetime.timedelta(3) due_date = today + day_detla # card.set_due(due_date) expected_due_date = card.due # Refresh the due date from cloud card.fetch() actual_due_date = card.due[:10] self.assertEquals(expected_due_date, actual_due_date) break break if not card: self.fail("No card created")
class TrelloClientTestCase(unittest.TestCase): """ Tests for TrelloClient API. Note these test are in order to preserve dependencies, as an API integration cannot be tested independently. """ def setUp(self): self._trello = TrelloClient(os.environ['TRELLO_API_KEY'], os.environ['TRELLO_TOKEN']) def tearDown(self): #self._trello.logout() pass def test01_list_boards(self): self.assertEquals( len(self._trello.list_boards()), int(os.environ['TRELLO_TEST_BOARD_COUNT'])) def test10_board_attrs(self): boards = self._trello.list_boards() for b in boards: self.assertIsNotNone(b.id, msg="id not provided") self.assertIsNotNone(b.name, msg="name not provided") self.assertIsNotNone(b.description, msg="description not provided") self.assertIsNotNone(b.closed, msg="closed not provided") self.assertIsNotNone(b.url, msg="url not provided") def test20_board_all_lists(self): boards = self._trello.list_boards() for b in boards: try: b.all_lists() except Exception as e: self.fail("Caught Exception getting lists") def test21_board_open_lists(self): boards = self._trello.list_boards() for b in boards: try: b.open_lists() except Exception as e: self.fail("Caught Exception getting open lists") def test22_board_closed_lists(self): boards = self._trello.list_boards() for b in boards: try: b.closed_lists() except Exception as e: self.fail("Caught Exception getting closed lists") def test30_list_attrs(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): self.assertIsNotNone(l.id, msg="id not provided") self.assertIsNotNone(l.name, msg="name not provided") self.assertIsNotNone(l.closed, msg="closed not provided") break # only need to test one board's lists def test40_list_cards(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): self.assertIsNotNone(c.id, msg="id not provided") self.assertIsNotNone(c.name, msg="name not provided") self.assertIsNotNone(c.description, msg="description not provided") self.assertIsNotNone(c.closed, msg="closed not provided") self.assertIsNotNone(c.url, msg="url not provided") break break pass def test50_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python - no desc" card = l.add_card(name) except Exception as e: print str(e) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created") def test51_add_card(self): boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for l in b.open_lists(): try: name = "Testing from Python" description = "Description goes here" card = l.add_card(name, description) except Exception as e: print str(e) self.fail("Caught Exception adding card") self.assertIsNotNone(card, msg="card is None") self.assertIsNotNone(card.id, msg="id not provided") self.assertEquals(card.name, name) self.assertEquals(card.description, description) self.assertIsNotNone(card.closed, msg="closed not provided") self.assertIsNotNone(card.url, msg="url not provided") break break if not card: self.fail("No card created") def test_60_get_comments(self): """ This test relies on the preexsitng contents of ALTA's test board. If a method for adding comments is ever written then this test should use that functionality instead. """ boards = self._trello.list_boards() board_id = None for b in boards: if b.name != os.environ['TRELLO_TEST_BOARD_NAME']: continue for c in b.visible_cards(): if c.name is not 'Testing Comments': continue comment = c.get_comments()[1] self.assertEquals(comment.text, u'first comment') self.assertEquals(comment.board_id, u'504e0ef92ad570121c55a3f8') self.assertEquals(comment.board_name, u'Unit Testing') self.assertEquals(comment.card_id, u'504f5f2ca164c0c42d1de16c') self.assertEquals(comment.card_idShort, 2) self.assertEquals(comment.card_name, u'Testing Comments') # excluding creator_avatarHash from the tests so that it # doesn't fail when next time I change my avatar. self.assertEquals(comment.creator_fullName, u'Philip Mallory') self.assertEquals(comment.creator_id, u'4f95bd676936b5d257022662') self.assertEquals(comment.creator_initials, u'PM') self.assertEquals(comment.creator_username, u'pmallory') self.assertEquals(comment.date, datetime.datetime(2012, 9, 11, 15, 57, 33)) self.assertEquals(comment.text, u'first comment')
class ServiceTrello(ServicesMgr): # Boards own Lists own Cards def __init__(self, token=None): # app name self.app_name = DjangoThConfig.verbose_name # expiration self.expiry = "30days" # scope define the rights access self.scope = 'read,write' base = 'https://www.trello.com' self.AUTH_URL = '{}/1/OAuthAuthorizeToken'.format(base) self.REQ_TOKEN = '{}/1/OAuthGetRequestToken'.format(base) self.ACC_TOKEN = '{}/1/OAuthGetAccessToken'.format(base) self.consumer_key = settings.TH_TRELLO['consumer_key'] self.consumer_secret = settings.TH_TRELLO['consumer_secret'] if token: token_key, token_secret = token.split('#TH#') self.trello_instance = TrelloClient(self.consumer_key, self.consumer_secret, token_key, token_secret) def read_data(self, token, trigger_id, date_triggered): """ get the data from the service as the pocket service does not have any date in its API linked to the note, add the triggered date to the dict data thus the service will be triggered when data will be found :param trigger_id: trigger ID to process :param date_triggered: the date of the last trigger :type trigger_id: int :type date_triggered: datetime :return: list of data found from the date_triggered filter :rtype: list """ data = list() cache.set('th_trello_' + str(trigger_id), data) def process_data(self, trigger_id): """ get the data from the cache :param trigger_id: trigger ID from which to save data :type trigger_id: int """ cache_data = cache.get('th_trello_' + str(trigger_id)) return PublishingLimit.get_data('th_trello_', cache_data, trigger_id) def save_data(self, token, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param **data: the data to check to be used and save :type trigger_id: int :type **data: dict :return: the status of the save statement :rtype: boolean """ from th_trello.models import Trello title = '' content = '' status = False title = self.set_card_title(data) content = self.set_card_content(data) if len(title): # get the data of this trigger t = Trello.objects.get(trigger_id=trigger_id) # 1 - we need to search the list and board where we will # store the card so ... # 1.a search the board_id by its name # by retreiving all the boards boards = self.trello_instance.list_boards() board_id = '' my_board = '' my_list = '' for board in boards: if t.board_name == board.name.decode('utf-8'): board_id = board.id break if board_id: # 1.b search the list_id by its name my_board = self.trello_instance.get_board(board_id) lists = my_board.open_lists() # just get the open list ; not all the archive ones for list_in_board in lists: # search the name of the list we set in the form if t.list_name == list_in_board.name.decode('utf-8'): # return the (trello) list object # to be able to add card at step 3 my_list = my_board.get_list(list_in_board.id) break # we didnt find the list in that board # create it if my_list == '': my_list = my_board.add_list(t.list_name) else: # 2 if board_id and/or list_id does not exist, create it/them my_board = self.trello_instance.add_board(t.board_name) # add the list that didnt exists and # return a (trello) list object my_list = my_board.add_list(t.list_name) # 3 create the card # create the Trello card my_list.add_card(title, content) sentance = str('trello {} created').format(data['link']) logger.debug(sentance) status = True else: sentance = "no token or link provided for trigger ID {}" logger.critical(sentance.format(trigger_id)) status = False return status def set_card_title(self, data): """ handle the title from the data """ title = '' # if no title provided, fallback to the URL which should be provided # by any exiting service title = (data['title'] if 'title' in data else data['link']) return title def set_card_content(self, data): """ handle the content from the data """ content = '' if 'content' in data: if type(data['content']) is list or type(data['content']) is tuple\ or type(data['content']) is dict: if 'value' in data['content'][0]: content = data['content'][0].value else: if type(data['content']) is str: content = data['content'] else: # if not str or list or tuple # or dict it could be feedparser.FeedParserDict # so get the item value content = data['content']['value'] elif 'summary_detail' in data: if type(data['summary_detail']) is list or\ type(data['summary_detail']) is tuple or\ type(data['summary_detail']) is dict: if 'value' in data['summary_detail'][0]: content = data['summary_detail'][0].value else: if type(data['summary_detail']) is str: content = data['summary_detail'] else: # if not str or list or tuple # or dict it could be feedparser.FeedParserDict # so get the item value content = data['summary_detail']['value'] elif 'description' in data: content = data['description'] return content def auth(self, request): """ let's auth the user to the Service """ callback_url = 'http://%s%s' % ( request.get_host(), reverse('trello_callback')) request_token = self.get_request_token() # Save the request token information for later request.session['oauth_token'] = request_token['oauth_token'] request.session['oauth_token_secret'] = request_token[ 'oauth_token_secret'] # URL to redirect user to, to authorize your app auth_url_str = '{auth_url}?oauth_token={token}&scope={scope}&name={name}' auth_url_str += '&expiration={expiry}&oauth_callback={callback_url}' auth_url = auth_url_str.format(auth_url=self.AUTH_URL, token=request_token['oauth_token'], scope=self.scope, name=self.app_name, expiry=self.expiry, callback_url=callback_url) return auth_url def callback(self, request): """ Called from the Service when the user accept to activate it """ try: # finally we save the user auth token # As we already stored the object ServicesActivated # from the UserServiceCreateView now we update the same # object to the database so : # 1) we get the previous objet us = UserService.objects.get( user=request.user, name=ServicesActivated.objects.get(name='ServiceTrello')) # 2) Trello API require to use 4 parms consumer_key/secret + # token_key/secret instead of usually get just the token # from an access_token request. So we need to add a string # seperator for later use to slpit on this one access_token = self.get_access_token( request.session['oauth_token'], request.session['oauth_token_secret'], request.GET.get('oauth_verifier', '') ) us.token = access_token.get('oauth_token') + \ '#TH#' + access_token.get('oauth_token_secret') # 3) and save everything us.save() except KeyError: return '/' return 'trello/callback.html' def get_request_token(self): oauth = OAuth1Session(self.consumer_key, client_secret=self.consumer_secret) return oauth.fetch_request_token(self.REQ_TOKEN) def get_access_token(self, oauth_token, oauth_token_secret, oauth_verifier): # Using OAuth1Session oauth = OAuth1Session(self.consumer_key, client_secret=self.consumer_secret, resource_owner_key=oauth_token, resource_owner_secret=oauth_token_secret, verifier=oauth_verifier) oauth_tokens = oauth.fetch_access_token(self.ACC_TOKEN) return oauth_tokens
class TrelloCollector(object): """ Class representing all Trello information required to do the SysDesEng reporting. """ def __init__(self, report_config, trello_secret): self.logger = logging.getLogger(__name__) self.client = TrelloClient(api_key = trello_secret[':consumer_key'], api_secret = trello_secret[':consumer_secret'], token = trello_secret[':oauth_token'], token_secret = trello_secret[':oauth_token_secret']) #Extract report configuration parameters trello_sources = report_config[':trello_sources']; #self.report_parameters = report_config[':output_metadata']; gen_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") self.content = { ':output_metadata' : { ':gen_date': gen_date, #Report name is built as :report_name + gen_date (where :report_name is taken from the config) ':trello_sources': { ':boards':{}, ':lists': {}, ':cards': [] }}} self.load_config(trello_sources, self.content[':output_metadata'][':trello_sources']) self.logger.debug("Report output metadata: %s" % (self.content[':output_metadata'])) def load_config(self, config_src, report_metadata): """ load all config data related to trello sources and structure them in the report_metadata""" for card_type in config_src.keys(): #card_type is project|assignment|epic for board_t in config_src[card_type].keys(): board_id = config_src[card_type][board_t][':board_id'] if not board_id in report_metadata: # initialize if the board wasn't present during the iterations over other card_type's if not board_id in report_metadata[':boards']: report_metadata[':boards'][board_id] = {}; report_metadata[':boards'][board_id][':board_id'] = config_src[card_type][board_t][':board_id'] #copy board id report_metadata[':boards'][board_id][':board_name'] = board_t if not ':lists' in report_metadata[':boards'][board_id]: report_metadata[':boards'][board_id][':lists'] = [] #iterate through all the lists and populate them for list_t in config_src[card_type][board_t][':lists'].keys(): self.logger.debug("Adding board %s, list %s to the report" % (config_src[card_type][board_t][':board_id'], config_src[card_type][board_t][':lists'][list_t])) list_id = config_src[card_type][board_t][':lists'][list_t] report_metadata[':lists'][list_id] = {}; report_metadata[':lists'][list_id][':list_id'] = list_id report_metadata[':lists'][list_id][':completed'] = False; report_metadata[':lists'][list_id][':card_type'] = card_type; report_metadata[':lists'][list_id][':board_id'] = board_id report_metadata[':boards'][board_id][':lists'].append(list_id) if ':done_lists' in config_src[card_type][board_t]: for list_t in config_src[card_type][board_t][':done_lists'].keys(): self.logger.debug("Adding board %s, Done list %s to the report" % (config_src[card_type][board_t][':board_id'], config_src[card_type][board_t][':done_lists'][list_t])) list_id = config_src[card_type][board_t][':done_lists'][list_t] report_metadata[':lists'][list_id] = {}; report_metadata[':lists'][list_id][':list_id'] = list_id report_metadata[':lists'][list_id][':completed'] = True; report_metadata[':lists'][list_id][':card_type'] = card_type; report_metadata[':lists'][list_id][':board_id'] = board_id report_metadata[':boards'][board_id][':lists'].append(list_id) def list_boards(self): syseng_boards = self.client.list_boards() for board in syseng_boards: for tlist in board.all_lists(): self.logger.info('board name: %s is here, board ID is: %s; list %s is here, list ID is: %s' % (board.name, board.id, tlist.name, tlist.id)) def parse_trello(self, deep_scan): """ :deep_scan: If deep_scan is True the scan will traverse actions, otherwise just a light scan(much faster) Main function to parse all Trello boards and lists. """ trello_sources = self.content[':output_metadata'][':trello_sources']; self.logger.debug('The sources are %s' % (trello_sources)) for board_id in trello_sources[':boards'].keys(): tr_board = self.client.get_board(board_id); tr_board.fetch(); # get all board properties members = [ (m.id, m.full_name) for m in tr_board.get_members()]; trello_sources[':boards'][board_id][':members'] = members; self.logger.info('----- querying board %s -----' % (trello_sources[':boards'][board_id][':board_name'])) self.logger.debug('Board members are %s' % (trello_sources[':boards'][board_id][':members'])) #trello_sources[board_id][':cards'] = [] cards = tr_board.get_cards(); for card in cards: card_content = {} card_content[':name'] = card.name card_content[':id'] = card.id card_content[':members'] = [] card_content[':board_id'] = tr_board.id for member_id in card.member_ids: for (m_id, m_full_name) in members: if member_id == m_id : card_content[':members'].append((m_id,m_full_name)) card_content[':desc'] = card.desc card_content[':short_url'] = card.url card_content[':labels'] = [(label.name,label.color) for label in card.labels] #self.logger.debug('Card: {0} | LABELES are {1}'.format(card_content[':name'], card_content[':labels'])) card_content[':board_name'] = tr_board.name card_content[':list_id'] = card.list_id if card.due: card_content[':due_date'] = arrow.get(card.due).format('YYYY-MM-DD HH:mm:ss') trello_sources[':cards'].append(card_content); self.logger.debug('%s cards were collected' % (len(cards))) tr_board.fetch_actions(action_filter="commentCard,updateCard:idList,createCard,copyCard,moveCardToBoard,convertToCardFromCheckItem",action_limit=1000); trello_sources[':boards'][board_id][':actions'] = sorted(tr_board.actions,key=lambda act: act['date'], reverse=True) self.logger.debug('%s actions were collected' % (len(trello_sources[':boards'][board_id][':actions']))) #self.logger.debug('Oldest action is %s' % (trello_sources[':boards'][board_id][':actions'][-1])) tr_lists = tr_board.all_lists() for tr_list in tr_lists: if tr_list.id in trello_sources[':lists']: trello_sources[':lists'][tr_list.id][':name'] = tr_list.name; self.logger.info('the lists are %s' % (tr_lists)) return self.content def parse_card_details(self, card_id): card = card_details.CardDetails(card_id, self.client, self.content[':output_metadata']) details = card.fill_details(); #self.logger.debug('Card\'s details are: %s' % (details)) return details
class TrelloWarehouse(object): """ Class representing all Trello information required to do the SysDesEng reporting. """ def __init__(self): self.logger = logging.getLogger("sysengreporting") self.client = TrelloClient(api_key = os.environ['TRELLO_API_KEY'], api_secret = os.environ['TRELLO_API_SECRET'], token = os.environ['TRELLO_TOKEN'], token_secret = os.environ['TRELLO_TOKEN_SECRET']) for board in self.client.list_boards(): if board.name == 'Systems Engineering Assignments'.encode('utf-8'): self.logger.debug('found Systems Engineering Assignments: %s' % (board.id)) self.syseng_assignments = board elif board.name == 'Private e2e Product Integration'.encode('utf-8'): self.logger.debug('found e2e Assignments: %s' % (board.id)) self.e2e_board = board elif board.name == 'Systems Design and Engineering Projects'.encode('utf-8'): self.logger.debug('found Systems Design and Engineering Projects: %s' % (board.id)) self.sysdeseng_projects = board self.syseng_members = self.syseng_assignments.all_members() self.e2e_members = self.e2e_board.all_members() for list in self.sysdeseng_projects.all_lists(): if list.name == 'In Progress'.encode('utf-8'): self.sysdeseng_projects_cards = self.sysdeseng_projects.get_list(list.id).list_cards() self.projects = dict() self.assignments = dict() def _get_title(self, short_url_id): return "UNKNOWN" # TODO get titel of card identified by short_url_id def _add_project(self, project): pass def _add_assignment(self, assignment): pass def get_projects(self): self.projects.clear() # check if there are some SysDesEng projects at all if self.sysdeseng_projects_cards is not None: # and for each project for _project in self.sysdeseng_projects_cards: self.logger.debug('fetching card: %s' % (_project.name)) _project.fetch(True) # get the details from trello.com _p = project.Project('Systems Engineering', _project.name, _project.id ) self.projects[_project.id] = _p self.logger.debug('new project: %s' % str(_p)) # if the project's card has a checklist if _project.checklists is not None: # it is per definition, the list of assignments for item in _project.checklists[0].items: try: # lets try to convert it into an Assignment _aid = item['name'].split('/')[4] self.assignments[_aid] = assignment.Assignment(_aid, self._get_title(item['name']), _p) self.logger.debug("new assignment %s" % str(self.assignments[_aid])) except IndexError: # if there is no URL in there... self.logger.warning("Assignment '%s' did not link back to a trello card." % (item['name'])) pass else: self.logger.error('sysdeseng_projects_cards was None') return self.projects def get_all_assignment_ids(self): """function returns a list of IDs of all assignments""" return self.assignments.keys() def get_unrelated_assignments(self): """function to filter out any assignment that is not related to a project""" _assignments = [] result = dict() all_known_assignments = self.get_all_assignment_ids() # lets find the SysEng 'In Progress' list and all its cards self.logger.debug('adding SysEng assignments') for list in self.syseng_assignments.all_lists(): if list.name == 'In Progress'.encode('utf-8'): _assignments = _assignments + self.syseng_assignments.get_list(list.id).list_cards() # and append the E2E 'In Progress' list's cards self.logger.debug('adding E2E assignments') for list in self.e2e_board.all_lists(): if list.name == 'In Progress'.encode('utf-8'): _assignments = _assignments + self.syseng_assignments.get_list(list.id).list_cards() # and get all cards aka assignments for _assignment in _assignments: _aid = _assignment.url.split('/')[4] if _aid in all_known_assignments: self.logger.info("we have had assignment '%s' within project '%s'" % (_aid, self.assignments[_aid].project)) else: result[_aid] = assignment.Assignment(_aid, _assignment.name, None) self.logger.debug('unrelated assignment: %s' % str(result[_aid])) return result def get_assignments(self, project_id): _assignments = [] try: _assignments = self.projects[project_id].assignments except KeyError as e: raise return _assignments def get_assignments0(self, team_name): """Return a dict() of SysEng assignments.""" _cards = [] _assignments = dict() if team_name == 'SysEng': for list in self.syseng_assignments.all_lists(): if list.name == 'In Progress'.encode('utf-8'): _cards = self.syseng_assignments.get_list(list.id).list_cards() for _card in _cards: _label = 'default' for label in _card.labels: if label.name == b'Ok': _label = 'success' if label.name == b'Issues': _label = 'warning' if label.name == b'Blocked': _label = 'danger' _assignments[_card.id] = assignment.Assignment(_card.id, _card.name, None, _status = _label) return _assignments
print(tablero) # Obtener todas las listas de un tablero print( tablero.all_lists() ) # Obtener de un tablero una lista o columna por su ID lista = tablero.get_list('57582109bba4b95e66dbf4e1') # Obtener de una lista la cantidad de tarjetas que posee lista.cardsCnt() # Obtener todas las tarjetas que posee lista.list_cards() # Listar los tableros Abiertos print( client.list_boards(board_filter="open") ) # Listar todos los tableros print( client.list_boards() ) # Listar columnas abiertos = client.list_boards(board_filter="open") for b in abiertos: b.all_lists() # Listar atributos for b in abiertos: for l in b.all_lists(): for c in l.list_cards(): print( c.fetch() )
for member_id in card.member_ids: if member_id not in cardid_by_memberid.keys(): cardid_by_memberid[member_id] = set() cardid_by_memberid[member_id].add(card.id) return cardid_by_memberid if __name__ == "__main__": logging.basicConfig(level=logging.INFO) trello = TrelloClient(os.environ["TRELLO_API_KEY"], token=os.environ["TRELLO_TOKEN"]) # lets get all the boards goern can read and filter out the Sys-Eng board for board in trello.list_boards(): if board.name == "Systems Engineering Projects and Status": syseng_board = board # now, get a list of WIP cards for list in syseng_board.all_lists(): if list.name == "Work In Progress (Committed)": wip_cards = list.list_cards() cardid_by_memberid = cardid_by_memberid(wip_cards) print(HTML_START) for member in syseng_board.get_members(): num_cards = 0
class TrelloWarehouse(object): """ Class representing all Trello information required to do the SysDesEng reporting. """ def __init__(self, report_config, trello_secret): self.logger = logging.getLogger("sysengreporting") self.client = TrelloClient(api_key = trello_secret[':consumer_key'], api_secret = trello_secret[':consumer_secret'], token = trello_secret[':oauth_token'], token_secret = trello_secret[':oauth_token_secret']) #Extract report configuration parameters trello_sources = report_config[':trello_sources']; self.special_tags = report_config[':tags']; self.report_parameters = report_config[':report']; # Populate the list of (board, lists) tuples on which to report self.report_src = [] for board_t in trello_sources.keys(): for list_t in trello_sources[board_t][':lists'].keys(): self.logger.debug("Adding board %s, list %s to the report" % (trello_sources[board_t][':board_id'], trello_sources[board_t][':lists'][list_t])) self.report_src.append( (trello_sources[board_t][':board_id'], trello_sources[board_t][':lists'][list_t]) ) def get_granular_report(self): self.group_report = report_group_assignments.GroupAssignmentsReport("syseng report", self.client, self.report_src, self.special_tags); if not self.group_report.repopulate_report(): self.logger.error('Failed to populate report from Trello'); return False; self.assignments_report = report_assignments.AssignmentsReport("Assignments Report", self.group_report) self.assignments_report.repopulate_report(); return True; def display_projects(self): """Retrun array of projects""" return self.raw_report.projects; def display_granular_report(self): "Return detailed report""" return self.gran_report.line_items; def csv_write(self, _dir_path): csv_file = open(os.path.join(_dir_path, self.gran_report.full_name + '.csv'),'w+'); csv_writer = csv.writer(csv_file); csv_writer.writerow(["Owner", "Title", "Status", "Tags", "Funding Bucket", "Detailed Status", "Last Updated"]); for line in self.gran_report.line_items: csv_writer.writerow([line.member, line.name, line.status, line.tags, line.funding_buckets, line.detailed_status, line.last_updated]); csv_file.close(); def write_gspreadsheet(self): writer = gwriter.GWriter(self.assignments_report.full_name, self.report_parameters) writer.write_headers(writer.wks_granular); writer.write_batch_data(self.assignments_report.assignments, writer.wks_granular) def list_boards(self): syseng_boards = self.client.list_boards() for board in syseng_boards: for tlist in board.all_lists(): self.logger.debug('board name: %s is here, board ID is: %s; list %s is here, list ID is: %s' % (board.name, board.id, tlist.name, tlist.id)) def get_assignment_details(self, assignment_id): gassign = group_assignment.GroupAssignment(assignment_id, self.client) gassign.get_name() gassign.get_members() gassign.get_tags(); gassign.get_status(); gassign.get_detailed_status(); logger.debug('latest move is: %s' % self.gassign.content['latest_move']) logger.debug('Card content: %s' % self.gassign.content)
return auth def load_schedule(): schedule = {} execfile("/absolute/path/to/schedule.config", schedule) return schedule if __name__ == "__main__": auth = load_auth() scheduled_tasks = load_schedule()["tasks"] client = TrelloClient(api_key=auth["key"], api_secret=auth["secret"], token=auth["oauth_token"], token_secret=auth["oauth_token_secret"]) now = datetime.datetime.now() today = now.strftime("%A") boards = client.list_boards() for task in scheduled_tasks: board_name = task["board"] card_title = task["title"] repeat_on = task["repeat_on"] if repeat_on.lower() != today.lower(): continue; for b in boards: if b.name == board_name: todo_list = get_todo_list(b) cards = todo_list.list_cards() card = get_card(cards, card_title)
class ServiceTrello(ServicesMgr): """ Serivce Trello """ # Boards own Lists own Cards def __init__(self, token=None, **kwargs): super(ServiceTrello, self).__init__(token, **kwargs) # app name self.app_name = DjangoThConfig.verbose_name # expiration self.expiry = "30days" # scope define the rights access self.scope = 'read,write' self.oauth = 'oauth1' self.service = 'ServiceTrello' base = 'https://www.trello.com' self.AUTH_URL = '{}/1/OAuthAuthorizeToken'.format(base) self.REQ_TOKEN = '{}/1/OAuthGetRequestToken'.format(base) self.ACC_TOKEN = '{}/1/OAuthGetAccessToken'.format(base) self.consumer_key = settings.TH_TRELLO_KEY['consumer_key'] self.consumer_secret = settings.TH_TRELLO_KEY['consumer_secret'] if token: token_key, token_secret = token.split('#TH#') try: self.trello_instance = TrelloClient(self.consumer_key, self.consumer_secret, token_key, token_secret) except ResourceUnavailable as e: us = UserService.objects.get(token=token) logger.error(e.msg, e.error_code) update_result(us.trigger_id, msg=e.msg, status=False) def read_data(self, **kwargs): """ get the data from the service :param kwargs: contain keyword args : trigger_id at least :type kwargs: dict """ trigger_id = kwargs.get('trigger_id') data = list() kwargs['model_name'] = 'Trello' kwargs['app_label'] = 'th_trello' super(ServiceTrello, self).read_data(**kwargs) cache.set('th_trello_' + str(trigger_id), data) return data def save_data(self, trigger_id, **data): """ let's save the data :param trigger_id: trigger ID from which to save data :param data: the data to check to be used and save :type trigger_id: int :type data: dict :return: the status of the save statement :rtype: boolean """ data['output_format'] = 'md' title, content = super(ServiceTrello, self).save_data(trigger_id, **data) if len(title): # get the data of this trigger t = Trello.objects.get(trigger_id=trigger_id) # footer of the card footer = self.set_card_footer(data, t) content += footer # 1 - we need to search the list and board where we will # store the card so ... # 1.a search the board_id by its name # by retrieving all the boards boards = self.trello_instance.list_boards() board_id = '' my_list = '' for board in boards: if t.board_name == board.name: board_id = board.id break if board_id: # 1.b search the list_id by its name my_board = self.trello_instance.get_board(board_id) lists = my_board.open_lists() # just get the open list ; not all the archive ones for list_in_board in lists: # search the name of the list we set in the form if t.list_name == list_in_board.name: # return the (trello) list object to be able to add card at step 3 my_list = my_board.get_list(list_in_board.id) break # we didnt find the list in that board -> create it if my_list == '': my_list = my_board.add_list(t.list_name) else: # 2 if board_id and/or list_id does not exist, create it/them my_board = self.trello_instance.add_board(t.board_name) # add the list that didn't exists and return a (trello) list object my_list = my_board.add_list(t.list_name) # 3 create the card my_list.add_card(title, content) logger.debug(str('trello {} created').format(data['link'])) status = True else: sentence = "no token or link provided for trigger ID {}".format(trigger_id) update_result(trigger_id, msg=sentence, status=False) status = False return status @staticmethod def set_card_footer(data, trigger): """ handle the footer of the note """ footer = '' if data.get('link'): provided_by = _('Provided by') provided_from = _('from') footer_from = "<br/><br/>{} <em>{}</em> {} <a href='{}'>{}</a>" description = trigger.trigger.description footer = footer_from.format(provided_by, description, provided_from, data.get('link'), data.get('link')) import pypandoc footer = pypandoc.convert(footer, 'md', format='html') return footer def auth(self, request): """ let's auth the user to the Service :param request: request object :return: callback url :rtype: string that contains the url to redirect after auth """ request_token = super(ServiceTrello, self).auth(request) callback_url = self.callback_url(request) # URL to redirect user to, to authorize your app auth_url_str = '{auth_url}?oauth_token={token}' auth_url_str += '&scope={scope}&name={name}' auth_url_str += '&expiration={expiry}&oauth_callback={callback_url}' auth_url = auth_url_str.format(auth_url=self.AUTH_URL, token=request_token['oauth_token'], scope=self.scope, name=self.app_name, expiry=self.expiry, callback_url=callback_url) return auth_url def callback(self, request, **kwargs): """ Called from the Service when the user accept to activate it :param request: request object :return: callback url :rtype: string , path to the template """ return super(ServiceTrello, self).callback(request, **kwargs)
api_key=strapi_key, api_secret=strapi_secret, token=strtoken ) # Store date from 7 days ago today = datetime.date.today() strToday = today.strftime('%m/%d/%Y') lastdate = today - timedelta(days=daystoreport) # Open File f = open("status.html", "wb") # HTML Header f.write("<HTML><HEAD><TITLE>" + strboardname + " - " + strToday + "</TITLE></HEAD><BODY><H1>" + strboardname + " - " + strToday + "</H1>") print "Finding Board" for b in client.list_boards(): if b.name == strboardname: print "Found Board - " + strboardname for l in b.all_lists(): if l.name == 'Information': continue f.write("<H2><U>" + l.name + "</U></H2>") #print l.name for c in l.list_cards(): print "Fetching Card Comments -", c.name c.fetch() members = '' for m in c.member_id: member = client.get_member(m) if members == '': members += member.full_name
def __init__(self): client = TrelloClient(keys.api_key,token=keys.oauth_token) #get all the boards self.boards = client.list_boards()
parser.add_argument("-p", "--secret", help='developer secret to access trello', required=False) parser.add_argument("-t", "--token", help='developer token to access trello', required=False) args = parser.parse_args() if args.devkey: key = args.devkey if args.secret: secret = args.secret if args.token: token = args.token if args.init: store_config(config_file) trello = TrelloClient(key, secret, token=token) boards = trello.list_boards() bz = None if args.listboards: boards = trello.list_boards() for b in boards: print b.name sys.exit() for b in boards: if b.name != args.board: continue firstlist = True for l in b.all_lists(): cards = l.list_cards() print_list = 0
class TrelloClientTestCase(unittest.TestCase): """ Tests for TrelloClient API. Note these test are in order to preserve dependencies, as an API integration cannot be tested independently. """ def setUp(self): self._trello = TrelloClient(os.environ["TRELLO_API_KEY"], token=os.environ["TRELLO_TOKEN"]) def test01_list_boards(self): self.assertEquals(len(self._trello.list_boards()), int(os.environ["TRELLO_TEST_BOARD_COUNT"])) def test10_board_attrs(self): boards = self._trello.list_boards() for b in boards: self.assertIsNotNone(b.id, msg="id not provided") self.assertIsNotNone(b.name, msg="name not provided") self.assertIsNotNone(b.description, msg="description not provided") self.assertIsNotNone(b.closed, msg="closed not provided") self.assertIsNotNone(b.url, msg="url not provided") def test20_board_all_lists(self): boards = self._trello.list_boards() for b in boards: try: b.all_lists() except Exception: self.fail("Caught Exception getting lists") def test21_board_open_lists(self): boards = self._trello.list_boards() for b in boards: try: b.open_lists() except Exception: self.fail("Caught Exception getting open lists") def test22_board_closed_lists(self): boards = self._trello.list_boards() for b in boards: try: b.closed_lists() except Exception: self.fail("Caught Exception getting closed lists") def test30_list_attrs(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): self.assertIsNotNone(l.id, msg="id not provided") self.assertIsNotNone(l.name, msg="name not provided") self.assertIsNotNone(l.closed, msg="closed not provided") break # only need to test one board's lists def test50_list_cards(self): boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): self.assertIsNotNone(c.id, msg="id not provided") self.assertIsNotNone(c.name, msg="name not provided") self.assertIsNotNone(c.description, msg="description not provided") self.assertIsNotNone(c.closed, msg="closed not provided") self.assertIsNotNone(c.url, msg="url not provided") break break pass def test51_fetch_cards(self): """ Tests fetching all attributes for all cards """ boards = self._trello.list_boards() for b in boards: for l in b.all_lists(): for c in l.list_cards(): c.fetch() self.assertIsInstance(c.date_last_activity, datetime, msg="date not provided") self.assertTrue(len(c.board_id) > 0, msg="board id not provided") break break pass def test52_list_hooks(self): self.assertIsInstance(self._trello.list_hooks(), list) def test53_unauthorized(self): client = TrelloClient("a") self.assertRaises(Unauthorized, client.list_boards) def test54_resource_unavailable(self): self.assertRaises(ResourceUnavailable, self._trello.get_card, "0")