[docs]classTrelloLoader(BaseLoader):"""Load cards from a `Trello` board."""
[docs]def__init__(self,client:TrelloClient,board_name:str,*,include_card_name:bool=True,include_comments:bool=True,include_checklist:bool=True,card_filter:Literal["closed","open","all"]="all",extra_metadata:Tuple[str,...]=("due_date","labels","list","closed"),):"""Initialize Trello loader. Args: client: Trello API client. board_name: The name of the Trello board. include_card_name: Whether to include the name of the card in the document. include_comments: Whether to include the comments on the card in the document. include_checklist: Whether to include the checklist on the card in the document. card_filter: Filter on card status. Valid values are "closed", "open", "all". extra_metadata: List of additional metadata fields to include as document metadata.Valid values are "due_date", "labels", "list", "closed". """self.client=clientself.board_name=board_nameself.include_card_name=include_card_nameself.include_comments=include_commentsself.include_checklist=include_checklistself.extra_metadata=extra_metadataself.card_filter=card_filter
[docs]@classmethoddeffrom_credentials(cls,board_name:str,*,api_key:Optional[str]=None,token:Optional[str]=None,**kwargs:Any,)->TrelloLoader:"""Convenience constructor that builds TrelloClient init param for you. Args: board_name: The name of the Trello board. api_key: Trello API key. Can also be specified as environment variable TRELLO_API_KEY. token: Trello token. Can also be specified as environment variable TRELLO_TOKEN. include_card_name: Whether to include the name of the card in the document. include_comments: Whether to include the comments on the card in the document. include_checklist: Whether to include the checklist on the card in the document. card_filter: Filter on card status. Valid values are "closed", "open", "all". extra_metadata: List of additional metadata fields to include as document metadata.Valid values are "due_date", "labels", "list", "closed". """try:fromtrelloimportTrelloClient# type: ignoreexceptImportErrorasex:raiseImportError("Could not import trello python package. ""Please install it with `pip install py-trello`.")fromexapi_key=api_keyorget_from_env("api_key","TRELLO_API_KEY")token=tokenorget_from_env("token","TRELLO_TOKEN")client=TrelloClient(api_key=api_key,token=token)returncls(client,board_name,**kwargs)
[docs]deflazy_load(self)->Iterator[Document]:"""Loads all cards from the specified Trello board. You can filter the cards, metadata and text included by using the optional parameters. Returns: A list of documents, one for each card in the board. """try:frombs4importBeautifulSoup# noqa: F401exceptImportErrorasex:raiseImportError("`beautifulsoup4` package not found, please run"" `pip install beautifulsoup4`")fromexboard=self._get_board()# Create a dictionary with the list IDs as keys and the list names as valueslist_dict={list_item.id:list_item.nameforlist_iteminboard.list_lists()}# Get Cards on the boardcards=board.get_cards(card_filter=self.card_filter)forcardincards:yieldself._card_to_doc(card,list_dict)
def_get_board(self)->Board:# Find the first board with a matching nameboard=next((bforbinself.client.list_boards()ifb.name==self.board_name),None)ifnotboard:raiseValueError(f"Board `{self.board_name}` not found.")returnboarddef_card_to_doc(self,card:Card,list_dict:dict)->Document:frombs4importBeautifulSoup# type: ignoretext_content=""ifself.include_card_name:text_content=card.name+"\n"ifcard.description.strip():text_content+=BeautifulSoup(card.description,"lxml").get_text()ifself.include_checklist:# Get all the checklist items on the cardforchecklistincard.checklists:ifchecklist.items:items=[f"{item['name']}:{item['state']}"foriteminchecklist.items]text_content+=f"\n{checklist.name}\n"+"\n".join(items)ifself.include_comments:# Get all the comments on the cardcomments=[BeautifulSoup(comment["data"]["text"],"lxml").get_text()forcommentincard.comments]text_content+="Comments:"+"\n".join(comments)# Default metadata fieldsmetadata={"title":card.name,"id":card.id,"url":card.url,}# Extra metadata fields. Card object is not subscriptable.if"labels"inself.extra_metadata:metadata["labels"]=[label.nameforlabelincard.labels]if"list"inself.extra_metadata:ifcard.list_idinlist_dict:metadata["list"]=list_dict[card.list_id]if"closed"inself.extra_metadata:metadata["closed"]=card.closedif"due_date"inself.extra_metadata:metadata["due_date"]=card.due_datereturnDocument(page_content=text_content,metadata=metadata)