Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
trello.py170 linesDownload Raw Back to document_loaders
1from __future__ import annotations2 3from typing import TYPE_CHECKING, Any, Iterator, Literal, Optional, Tuple4 5from langchain_core.documents import Document6from langchain_core.utils import get_from_env7 8from langchain_community.document_loaders.base import BaseLoader9 10if TYPE_CHECKING:11    from trello import Board, Card, TrelloClient12 13 14class TrelloLoader(BaseLoader):15    """Load cards from a `Trello` board."""16 17    def __init__(18        self,19        client: TrelloClient,20        board_name: str,21        *,22        include_card_name: bool = True,23        include_comments: bool = True,24        include_checklist: bool = True,25        card_filter: Literal["closed", "open", "all"] = "all",26        extra_metadata: Tuple[str, ...] = ("due_date", "labels", "list", "closed"),27    ):28        """Initialize Trello loader.29 30        Args:31            client: Trello API client.32            board_name: The name of the Trello board.33            include_card_name: Whether to include the name of the card in the document.34            include_comments: Whether to include the comments on the card in the35                document.36            include_checklist: Whether to include the checklist on the card in the37                document.38            card_filter: Filter on card status. Valid values are "closed", "open",39                "all".40            extra_metadata: List of additional metadata fields to include as document41                metadata.Valid values are "due_date", "labels", "list", "closed".42 43        """44        self.client = client45        self.board_name = board_name46        self.include_card_name = include_card_name47        self.include_comments = include_comments48        self.include_checklist = include_checklist49        self.extra_metadata = extra_metadata50        self.card_filter = card_filter51 52    @classmethod53    def from_credentials(54        cls,55        board_name: str,56        *,57        api_key: Optional[str] = None,58        token: Optional[str] = None,59        **kwargs: Any,60    ) -> TrelloLoader:61        """Convenience constructor that builds TrelloClient init param for you.62 63        Args:64            board_name: The name of the Trello board.65            api_key: Trello API key. Can also be specified as environment variable66                TRELLO_API_KEY.67            token: Trello token. Can also be specified as environment variable68                TRELLO_TOKEN.69            include_card_name: Whether to include the name of the card in the document.70            include_comments: Whether to include the comments on the card in the71                document.72            include_checklist: Whether to include the checklist on the card in the73                document.74            card_filter: Filter on card status. Valid values are "closed", "open",75                "all".76            extra_metadata: List of additional metadata fields to include as document77                metadata.Valid values are "due_date", "labels", "list", "closed".78        """79 80        try:81            from trello import TrelloClient82        except ImportError as ex:83            raise ImportError(84                "Could not import trello python package. "85                "Please install it with `pip install py-trello`."86            ) from ex87        api_key = api_key or get_from_env("api_key", "TRELLO_API_KEY")88        token = token or get_from_env("token", "TRELLO_TOKEN")89        client = TrelloClient(api_key=api_key, token=token)90        return cls(client, board_name, **kwargs)91 92    def lazy_load(self) -> Iterator[Document]:93        """Loads all cards from the specified Trello board.94 95        You can filter the cards, metadata and text included by using the optional96            parameters.97 98         Returns:99            A list of documents, one for each card in the board.100        """101        try:102            from bs4 import BeautifulSoup  # noqa: F401103        except ImportError as ex:104            raise ImportError(105                "`beautifulsoup4` package not found, please run"106                " `pip install beautifulsoup4`"107            ) from ex108 109        board = self._get_board()110        # Create a dictionary with the list IDs as keys and the list names as values111        list_dict = {list_item.id: list_item.name for list_item in board.list_lists()}112        # Get Cards on the board113        cards = board.get_cards(card_filter=self.card_filter)114        for card in cards:115            yield self._card_to_doc(card, list_dict)116 117    def _get_board(self) -> Board:118        # Find the first board with a matching name119        board = next(120            (b for b in self.client.list_boards() if b.name == self.board_name), None121        )122        if not board:123            raise ValueError(f"Board `{self.board_name}` not found.")124        return board125 126    def _card_to_doc(self, card: Card, list_dict: dict) -> Document:127        from bs4 import BeautifulSoup128 129        text_content = ""130        if self.include_card_name:131            text_content = card.name + "\n"132        if card.description.strip():133            text_content += BeautifulSoup(card.description, "lxml").get_text()134        if self.include_checklist:135            # Get all the checklist items on the card136            for checklist in card.checklists:137                if checklist.items:138                    items = [139                        f"{item['name']}:{item['state']}" for item in checklist.items140                    ]141                    text_content += f"\n{checklist.name}\n" + "\n".join(items)142 143        if self.include_comments:144            # Get all the comments on the card145            comments = [146                BeautifulSoup(comment["data"]["text"], "lxml").get_text()147                for comment in card.comments148            ]149            text_content += "Comments:" + "\n".join(comments)150 151        # Default metadata fields152        metadata = {153            "title": card.name,154            "id": card.id,155            "url": card.url,156        }157 158        # Extra metadata fields. Card object is not subscriptable.159        if "labels" in self.extra_metadata:160            metadata["labels"] = [label.name for label in card.labels]161        if "list" in self.extra_metadata:162            if card.list_id in list_dict:163                metadata["list"] = list_dict[card.list_id]164        if "closed" in self.extra_metadata:165            metadata["closed"] = card.closed166        if "due_date" in self.extra_metadata:167            metadata["due_date"] = card.due_date168 169        return Document(page_content=text_content, metadata=metadata)170 
codekingpro/portable-devtools · Team Ai