~mapperr/trl

3af86c0080c0675344c7940f9cb7003f1274dde1 — mapperr 2 years ago 9a4dbb0
Use names as bases for shortcuts
M trullo.py => trullo.py +61 -8
@@ 87,7 87,7 @@ def edit_card(card_to_edit: TrlCard = None) -> (str, str):
    with open(tmpfile_path, 'r') as fd:
        lines = fd.readlines()
    return urllib.parse.quote(lines[1].replace('\n', ''), safe=''), \
        urllib.parse.quote(str.join('', lines[2:]), safe='')
           urllib.parse.quote(str.join('', lines[2:]), safe='')


if __name__ == '__main__':


@@ 99,7 99,8 @@ if __name__ == '__main__':
    selected_board_filepath = f'{tmpdir}/.trl-selected-board'
    if os.path.exists(selected_board_filepath):
        with open(selected_board_filepath, 'r') as fh:
            selected_board_id, selected_board_name = fh.readline().split(' ', 1)
            selected_board_id, selected_board_name = fh.readline().split(
                ' ', 1)

    if args['g']:
        api_path = args['<api_path>']


@@ 109,8 110,18 @@ if __name__ == '__main__':
    if args['b']:
        boards = tclient.get_boards()
        if args['<board_shortcut>']:
            board = [board for board in boards
                     if board.shortcut.lower().startswith(args['<board_shortcut>'])][0]
            board_shortcut = args['<board_shortcut>']
            matching_boards = [board for board in boards
                               if board.get_normalized_name()
                                   .startswith(board_shortcut)]
            if len(matching_boards) > 1:
                matching_names = \
                    [board.get_normalized_name() for board in matching_boards]
                print(
                    f'shortcut [{board_shortcut}] matches more than one board: '
                    f'{matching_names}')
                exit(1)
            board = matching_boards[0]
            print(f'selected board {board.raw_data["name"]}')
            with open(selected_board_filepath, 'w') as fh:
                fh.write(f'{board.id} {board.raw_data["name"]}')


@@ 143,13 154,41 @@ if __name__ == '__main__':
        new_command = args['n']
        if new_command:
            target_list_shortcut = args['<list_shortcut>']
            list_id = [list_.id for list_ in board.lists if list_.id.lower().endswith(target_list_shortcut)][0]
            matching_lists = [list_ for list_ in board.lists if
                              list_.get_normalized_name().startswith(
                                  target_list_shortcut)]
            if len(matching_lists) > 1:
                matching_names = \
                    [list_.get_normalized_name() for list_ in matching_lists]
                print(
                    f'shortcut [{target_list_shortcut}] '
                    f'matches more than one list: '
                    f'{matching_names}')
                exit(1)
            list_id = matching_lists[0].id

            new_card_name, new_card_desc = edit_card()
            tclient.new_card(list_id, new_card_name, new_card_desc)
        else:
            card_shortcut = args['<card_shortcut>']
            card = tclient.get_card(
                [card.id for card in board.cards if card.shortcut.lower().startswith(card_shortcut)][0])
            matching_cards = [
                card
                for card in board.cards
                if card.get_normalized_name().startswith(card_shortcut)
            ]

            if len(matching_cards) > 1:
                matching_names = \
                    [matching_card.get_normalized_name()
                     for matching_card in matching_cards]
                print(
                    f'shortcut [{card_shortcut}] '
                    f'matches more than one card: '
                    f'{matching_names}')
                exit(1)

            selected_card = matching_cards[0]
            card = tclient.get_card(selected_card.id)

            open_command = args['o']
            move_command = args['m']


@@ 158,7 197,21 @@ if __name__ == '__main__':
                subprocess.Popen(['xdg-open', card.raw_data['shortUrl']])
            elif move_command:
                target_list_shortcut = args['<list_shortcut>']
                list_id = [list_.id for list_ in board.lists if list_.id.lower().endswith(target_list_shortcut)][0]

                matching_lists = [list_ for list_ in board.lists if
                                  list_.get_normalized_name().startswith(
                                      target_list_shortcut)]
                if len(matching_lists) > 1:
                    matching_names = \
                        [list_.get_normalized_name() for list_ in
                         matching_lists]
                    print(
                        f'shortcut [{target_list_shortcut}] '
                        f'matches more than one list: '
                        f'{matching_names}')
                    exit(1)
                list_id = matching_lists[0].id

                tclient.move_card(card.id, list_id)
            elif edit_command:
                card_new_name, card_new_desc = edit_card(card)

M trullo/printer.py => trullo/printer.py +35 -13
@@ 11,40 11,59 @@ from trullo.trl_card import TrlCard
class Printer:
    @staticmethod
    def print_boards(boards: List[TrlBoard]):
        symbol_count = Shortener.get_min_symbols_to_uniq([board.shortcut.lower() for board in boards])
        symbol_count = Shortener. \
            get_min_symbols_to_uniq([board.get_normalized_name()
                                     for board in boards])
        print(f'symbol count is {symbol_count}')
        for board in boards:
            print(f"[{board.shortcut[0:symbol_count].lower()}] {board.raw_data['name']}")
            print(
                f"[{board.get_normalized_name()[0:symbol_count].lower()}] "
                f"{board.raw_data['name']}")

    @staticmethod
    def print_board(board: TrlBoard, list_shortcut: str = None):
        symbol_count_cards = Shortener.get_min_symbols_to_uniq([card.shortcut for card in board.cards])
        symbol_count_lists = Shortener.get_min_symbols_to_uniq([list_.id for list_ in board.lists], True)
        cards_names = [card.get_normalized_name() for card in board.cards]
        board_lists_names = \
            [list_.get_normalized_name() for list_ in board.lists]

        symbol_count_cards = Shortener.get_min_symbols_to_uniq(cards_names)
        symbol_count_lists = \
            Shortener.get_min_symbols_to_uniq(board_lists_names)

        print(f"{board.raw_data['shortUrl']}")
        print('------------------------------')
        print(f"{board.raw_data['name']}")
        print()
        if board.lists is not None:
            for list_ in board.lists:
                if list_shortcut is not None and not list_.id.lower().endswith(list_shortcut):
                if list_shortcut is not None \
                        and not \
                        list_.get_normalized_name().startswith(list_shortcut):
                    continue
                print(
                    f"[{list_.id[len(list_.id) - symbol_count_lists:len(list_.id)].lower()}] {list_.raw_data['name']}")
                shortcut = \
                    list_.get_normalized_name()[0:symbol_count_lists].lower()
                print(f"[{shortcut}] {list_.raw_data['name']}")
                for card in board.cards:
                    if card.raw_data['idList'] == list_.id:
                        print(f"\t[{card.shortcut[0:symbol_count_cards].lower()}] {card.raw_data['name']}")
                        card_shortcut = card.get_normalized_name()[
                                        0:symbol_count_cards].lower()
                        print(f"\t[{card_shortcut}] "
                              f"{card.raw_data['name']}")
        print()

    @staticmethod
    def print_board_lists(board: TrlBoard):
        symbol_count_lists = Shortener.get_min_symbols_to_uniq([list_.id for list_ in board.lists], True)
        symbol_count_lists = Shortener.get_min_symbols_to_uniq(
            [list_.get_normalized_name() for list_ in board.lists])
        print(f"{board.raw_data['shortUrl']}")
        print('------------------------------')
        print(f"{board.raw_data['name']}")
        print()
        if board.lists is not None:
            for list_ in board.lists:
                print(
                    f"[{list_.id[len(list_.id) - symbol_count_lists:len(list_.id)].lower()}] {list_.raw_data['name']}")
                list_shortcut = \
                    list_.get_normalized_name()[0:symbol_count_lists].lower()
                print(f"[{list_shortcut}] {list_.raw_data['name']}")
        print()

    @staticmethod


@@ 57,8 76,11 @@ class Printer:
        print(f'{d["name"]}')
        if len(d['labels']) > 0:
            print()
        for l in d['labels']:
            print(f'({l["name"] if l["name"] is not None and l["name"] != "" else l["color"]})  ', end='')
        for label in d['labels']:
            label_name = label["name"] \
                if label["name"] is not None and label["name"] != "" \
                else label["color"]
            print(f'({label_name})  ', end='')
        print()
        print(formatted_desc)
        print()

M trullo/shortener.py => trullo/shortener.py +21 -9
@@ 6,17 6,29 @@ import attr
@attr.s(auto_attribs=True)
class Shortener:
    @staticmethod
    def get_min_symbols_to_uniq(strings: List[str], end: bool = False) -> int:
    def normalize(string: str) -> str:
        result = ''
        for char in string:
            if char.lower() not in 'qwertyuiopasdfghjklzxcvbnm1234567890':
                continue
            result += char.lower()
        return result

    @staticmethod
    def get_min_symbols_to_uniq(strings: List[str]) -> int:
        symbol_counter = 1
        longest_item_length = Shortener.get_longest_item_length(strings)
        if end:
            while symbol_counter < longest_item_length \
                    and Shortener.are_there_duplicates([el[len(el)-symbol_counter:len(el)].lower() for el in strings]):
                symbol_counter += 1
        else:
            while symbol_counter < longest_item_length \
                    and Shortener.are_there_duplicates([el[0:symbol_counter].lower() for el in strings]):
                symbol_counter += 1
        string_list = [
            string_item[0:symbol_counter].lower()
            for string_item in strings
        ]
        while symbol_counter < longest_item_length \
                and Shortener.are_there_duplicates(string_list):
            symbol_counter += 1
            string_list = [
                string_item[0:symbol_counter].lower()
                for string_item in strings
            ]
        return symbol_counter

    @staticmethod

M trullo/tclient.py => trullo/tclient.py +16 -7
@@ 14,8 14,10 @@ logger = logging.getLogger(__name__)

@attr.s(auto_attribs=True)
class TClient:
    trello_token: str = attr.ib(default=os.environ['TRELLO_TOKEN'] if 'TRELLO_TOKEN' in os.environ else '')
    trello_api_key: str = attr.ib(default=os.environ['TRELLO_API_KEY'] if 'TRELLO_API_KEY' in os.environ else '')
    trello_token: str = attr.ib(default=os.environ[
        'TRELLO_TOKEN'] if 'TRELLO_TOKEN' in os.environ else '')
    trello_api_key: str = attr.ib(default=os.environ[
        'TRELLO_API_KEY'] if 'TRELLO_API_KEY' in os.environ else '')
    base_url: str = attr.ib(default='https://api.trello.com/1')

    def build_auth_params(self) -> Dict[str, str]:


@@ 26,13 28,16 @@ class TClient:
        return res.json()

    def get(self, path: str) -> Dict:
        return self.handle_res(requests.get(self.base_url + path, self.build_auth_params()))
        return self.handle_res(
            requests.get(self.base_url + path, self.build_auth_params()))

    def post(self, path: str) -> Dict:
        return self.handle_res(requests.post(self.base_url + path, self.build_auth_params()))
        return self.handle_res(
            requests.post(self.base_url + path, self.build_auth_params()))

    def put(self, path: str) -> Dict:
        return self.handle_res(requests.put(self.base_url + path, self.build_auth_params()))
        return self.handle_res(
            requests.put(self.base_url + path, self.build_auth_params()))

    def get_boards(self) -> List[TrlBoard]:
        res = self.get('/members/me/boards?lists=open')


@@ 49,11 54,15 @@ class TClient:
                if k == 'lists':
                    lists = self._extract_lists(v)
            if not board_closed:
                boards.append(TrlBoard(board_id, raw_board['shortLink'], lists, [], raw_board))
                boards.append(
                    TrlBoard(board_id, raw_board['shortLink'], lists, [],
                             raw_board))
        return boards

    def get_board(self, board_id: str) -> TrlBoard:
        res = self.get(f'/batch?urls=/board/{board_id},/board/{board_id}/lists/open,/board/{board_id}/cards/open')
        res = self.get(f'/batch?urls=/board/{board_id},'
                       f'/board/{board_id}/lists/open,'
                       f'/board/{board_id}/cards/open')
        board = TrlBoard(board_id, board_id, [], [], res[0]['200'])
        for item in res[1]['200']:
            list_ = TrlList(item['id'], item)

M trullo/trl_board.py => trullo/trl_board.py +5 -1
@@ 2,6 2,7 @@ from typing import Dict, List

import attr

from trullo.shortener import Shortener
from trullo.trl_list import TrlList
from trullo.trl_card import TrlCard



@@ 9,7 10,10 @@ from trullo.trl_card import TrlCard
@attr.s(auto_attribs=True)
class TrlBoard:
    id: str
    shortcut: str
    short_link: str
    lists: List[TrlList]
    cards: List[TrlCard]
    raw_data: Dict

    def get_normalized_name(self) -> str:
        return Shortener.normalize(self.raw_data['name'])

M trullo/trl_card.py => trullo/trl_card.py +6 -1
@@ 2,9 2,14 @@ from typing import Dict

import attr

from trullo.shortener import Shortener


@attr.s(auto_attribs=True)
class TrlCard:
    id: str
    shortcut: str
    short_link: str
    raw_data: Dict

    def get_normalized_name(self):
        return Shortener.normalize(self.raw_data['name'])

M trullo/trl_list.py => trullo/trl_list.py +5 -2
@@ 1,11 1,14 @@
from typing import List, Dict
from typing import Dict

import attr

from trullo.trl_card import TrlCard
from trullo.shortener import Shortener


@attr.s(auto_attribs=True)
class TrlList:
    id: str
    raw_data: Dict

    def get_normalized_name(self) -> str:
        return Shortener.normalize(self.raw_data['name'])