M tests/unit/test_shortener.py => tests/unit/test_shortener.py +8 -6
@@ 3,16 3,17 @@ from typing import List
from unittest import mock
from unittest.mock import Mock
+from trullo.normalizer import Normalizer
from trullo.shortcuttable import Shortcuttable
-from trullo.shortener import Shortener
from trullo.trl_board import TrlBoard
from trullo.trl_card import TrlCard
+from trullo.trl_label import TrlLabel
from trullo.trl_list import TrlList
class TestShortener(unittest.TestCase):
def test_matches(self):
- sh = Shortener
+ sh = Normalizer
start_match = sh.is_a_match('pil', 'pillow')
self.assertTrue(start_match)
middle_match = sh.is_a_match('grat', 'integration')
@@ 21,7 22,7 @@ class TestShortener(unittest.TestCase):
self.assertTrue(end_match)
def test_wrong_matches(self):
- sh = Shortener
+ sh = Normalizer
match = sh.is_a_match('spil', 'pillow')
self.assertFalse(match)
@@ 39,7 40,7 @@ class TestShortener(unittest.TestCase):
mock.create_autospec(Shortcuttable, spec_set=True)
short4.get_normalized_name = Mock(return_value='')
- sh = Shortener
+ sh = Normalizer
shorties = [short1, short2]
matches: List = sh.get_matches('er', shorties)
self.assertEqual(1, len(matches))
@@ 63,8 64,10 @@ class TestShortener(unittest.TestCase):
{'name': ' Implement a trim() function',
'shortLink': shortLink})
list1 = TrlList('idl1', {'name': 'To Do'})
+ label1 = TrlLabel('idlb1', lblname := 'feature',
+ {'name': lblname, 'color': 'blue'}, 'blue')
board1 = TrlBoard('idb1', shortLink := 'p01UyT', [list1],
- [card1, card2, card3],
+ [card1, card2, card3], [label1],
{'name': 'my Super Board',
'shortLink': shortLink})
@@ 103,4 106,3 @@ class TestShortener(unittest.TestCase):
self.assertNotIn('U', board1_n)
self.assertIn('mysuper', board1_n)
self.assertIn('p01u', board1_n)
-
M trullo.py => trullo.py +6 -2
@@ 5,6 5,7 @@ usage:
trl b [<board_shortcut>]
trl l [<list_shortcuts>...]
trl ll
+ trl lb
trl c <card_shortcut> [o | m <list_shortcut> | e | n <list_shortcut>]
trl c n <list_shortcut>
trl g <api_path>
@@ 59,7 60,7 @@ import tempfile
from docopt import docopt
from trullo.printer import Printer
-from trullo.shortener import Shortener
+from trullo.normalizer import Normalizer
from trullo.tclient import TClient
from trullo.tconfig import TConfig
from trullo.usecases import Usecases
@@ 79,7 80,7 @@ if __name__ == '__main__':
usecases = Usecases(TConfig(selected_board_filepath),
TClient(),
- Shortener(),
+ Normalizer(),
Printer())
selected_board_id, selected_board_name = usecases.get_selected_board()
@@ 107,6 108,9 @@ if __name__ == '__main__':
elif args['ll']:
usecases.print_board_lists()
+ elif args['lb']:
+ usecases.print_board_labels()
+
elif args['l']:
list_shortcuts = args['<list_shortcuts>']
usecases.print_lists(list_shortcuts)
A trullo/normalizer.py => trullo/normalizer.py +31 -0
@@ 0,0 1,31 @@
+from typing import List
+
+import attr
+
+from trullo.shortcuttable import Shortcuttable
+
+
+@attr.s(auto_attribs=True)
+class Normalizer:
+ @staticmethod
+ 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_matches(
+ shortcut: str,
+ shortcuttables: List[Shortcuttable]) -> List[any]:
+ return [
+ shortcuttable for shortcuttable in shortcuttables
+ if Normalizer.is_a_match(
+ shortcut,
+ shortcuttable.get_normalized_name())]
+
+ @staticmethod
+ def is_a_match(shortcut: str, normalized_name: str) -> bool:
+ return shortcut in normalized_name
M trullo/printer.py => trullo/printer.py +5 -6
@@ 2,7 2,7 @@ from typing import List, Optional
import attr
-from trullo.shortener import Shortener
+from trullo.normalizer import Normalizer
from trullo.trl_board import TrlBoard
from trullo.trl_card import TrlCard
@@ 36,17 36,16 @@ class Printer:
f"[{list_.raw_data['id'].lower()}]")
for card in board.cards:
if card.raw_data['idList'] == list_.id:
- card_output = f"\t[{card.raw_data['shortLink'].lower()}] "
+ card_output = \
+ f"\n\t{card.raw_data['name']}" \
+ f"\n\t[{card.raw_data['shortLink'].lower()}] "
for raw_label in card.raw_data['labels']:
card_output += f'({raw_label["name"]}) '
- card_output += f"{card.raw_data['name']}"
print(card_output)
print()
@staticmethod
def print_board_lists(board: TrlBoard):
- 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']}")
@@ 80,5 79,5 @@ class Printer:
def _there_is_a_match(normalized_name: str, shortcuts: List[str]) -> bool:
return len([
shortcut for shortcut in shortcuts
- if Shortener.is_a_match(shortcut, normalized_name)
+ if Normalizer.is_a_match(shortcut, normalized_name)
]) > 0
D trullo/shortener.py => trullo/shortener.py +0 -67
@@ 1,67 0,0 @@
-from typing import List
-from typing import Set
-
-import attr
-
-from trullo.shortcuttable import Shortcuttable
-
-
-@attr.s(auto_attribs=True)
-class Shortener:
- @staticmethod
- 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)
- 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
- def are_there_duplicates(list_: List[str]):
- set_: Set[str] = set()
- for elem in list_:
- if elem in set_:
- return True
- else:
- set_.add(elem)
- return False
-
- @staticmethod
- def get_longest_item_length(list_: List[str]) -> int:
- longest_length = 0
- for string in list_:
- length = len(string)
- if length > longest_length:
- longest_length = length
- return longest_length
-
- @staticmethod
- def get_matches(
- shortcut: str,
- shortcuttables: List[Shortcuttable]) -> List[any]:
- return [shortcuttable for shortcuttable in shortcuttables
- if Shortener.is_a_match(
- shortcut, shortcuttable.get_normalized_name())
- ]
-
- @staticmethod
- def is_a_match(shortcut: str, normalized_name: str) -> bool:
- return shortcut in normalized_name
M trullo/tclient.py => trullo/tclient.py +10 -2
@@ 7,6 7,7 @@ import requests
from trullo.trl_board import TrlBoard
from trullo.trl_card import TrlCard
+from trullo.trl_label import TrlLabel
from trullo.trl_list import TrlList
logger = logging.getLogger(__name__)
@@ 61,13 62,20 @@ class TClient:
def get_board(self, board_id: str) -> TrlBoard:
res = self.get(f'/batch?urls=/board/{board_id},'
+ f'/board/{board_id}/labels,'
f'/board/{board_id}/lists/open,'
f'/board/{board_id}/cards/open')
- board = TrlBoard(board_id, board_id, [], [], res[0]['200'])
+ board = TrlBoard(board_id, board_id, [], [], [], res[0]['200'])
for item in res[1]['200']:
+ label = TrlLabel(item['id'],
+ item['name'],
+ item,
+ item['color'] if 'color' in item else None)
+ board.labels.append(label)
+ for item in res[2]['200']:
list_ = TrlList(item['id'], item)
board.lists.append(list_)
- for item in res[2]['200']:
+ for item in res[3]['200']:
card = TrlCard(item['id'], item['shortLink'], item)
board.cards.append(card)
return board
M trullo/trl_board.py => trullo/trl_board.py +4 -2
@@ 2,9 2,10 @@ from typing import Dict, List
import attr
+from trullo.normalizer import Normalizer
from trullo.shortcuttable import Shortcuttable
-from trullo.shortener import Shortener
from trullo.trl_card import TrlCard
+from trullo.trl_label import TrlLabel
from trullo.trl_list import TrlList
@@ 14,9 15,10 @@ class TrlBoard(Shortcuttable):
short_link: str
lists: List[TrlList]
cards: List[TrlCard]
+ labels: List[TrlLabel]
raw_data: Dict
def get_normalized_name(self) -> str:
- return Shortener.normalize(
+ return Normalizer.normalize(
f"{self.raw_data['name']}{self.raw_data['shortLink']}"
)
M trullo/trl_card.py => trullo/trl_card.py +2 -2
@@ 3,7 3,7 @@ from typing import Dict
import attr
from trullo.shortcuttable import Shortcuttable
-from trullo.shortener import Shortener
+from trullo.normalizer import Normalizer
@attr.s(auto_attribs=True)
@@ 13,6 13,6 @@ class TrlCard(Shortcuttable):
raw_data: Dict
def get_normalized_name(self):
- return Shortener.normalize(
+ return Normalizer.normalize(
f"{self.raw_data['name']}{self.raw_data['shortLink']}"
)
A trullo/trl_label.py => trullo/trl_label.py +21 -0
@@ 0,0 1,21 @@
+from typing import Dict, Optional
+
+import attr
+
+from trullo.normalizer import Normalizer
+from trullo.shortcuttable import Shortcuttable
+
+
+@attr.s(auto_attribs=True)
+class TrlLabel(Shortcuttable):
+ id: str
+ name: str
+ raw_data: Dict
+ color: Optional[str] = attr.ib(default=None)
+
+ def get_normalized_name(self) -> str:
+ return Normalizer.normalize(
+ f"{self.raw_data['name']}"
+ f"{self.color if self.color is not None else ''}"
+ f"{self.id}"
+ )
M trullo/trl_list.py => trullo/trl_list.py +2 -2
@@ 3,7 3,7 @@ from typing import Dict
import attr
from trullo.shortcuttable import Shortcuttable
-from trullo.shortener import Shortener
+from trullo.normalizer import Normalizer
@attr.s(auto_attribs=True)
@@ 12,6 12,6 @@ class TrlList(Shortcuttable):
raw_data: Dict
def get_normalized_name(self) -> str:
- return Shortener.normalize(
+ return Normalizer.normalize(
f"{self.raw_data['name']}{self.id}"
)
M trullo/usecases.py => trullo/usecases.py +10 -5
@@ 6,8 6,8 @@ from typing import Optional, Tuple, List
import attr
+from trullo.normalizer import Normalizer
from trullo.printer import Printer
-from trullo.shortener import Shortener
from trullo.tclient import TClient
from trullo.tconfig import TConfig
from trullo.trl_board import TrlBoard
@@ 19,7 19,7 @@ from trullo.trl_list import TrlList
class Usecases:
tconfig: TConfig
tclient: TClient
- shortener: Shortener
+ shortener: Normalizer
printer: Printer
selected_board_id: Optional[str] = attr.ib(default=None)
selected_board_name: Optional[str] = attr.ib(default=None)
@@ 84,7 84,7 @@ class Usecases:
def create_card(self, target_list_shortcut: str):
board = self.tclient.get_board(self.selected_board_id)
- matching_lists: List[TrlList] = Shortener.get_matches(
+ matching_lists: List[TrlList] = Normalizer.get_matches(
target_list_shortcut,
board.lists
)
@@ 115,7 115,7 @@ class Usecases:
def move_card(self, card_shortcut: str, target_list_shortcut: str):
board = self.tclient.get_board(self.selected_board_id)
- matching_lists: List[TrlList] = Shortener.get_matches(
+ matching_lists: List[TrlList] = Normalizer.get_matches(
target_list_shortcut,
board.lists
)
@@ 143,7 143,7 @@ class Usecases:
def _get_card(self, card_shortcut):
board = self.tclient.get_board(self.selected_board_id)
- matching_cards: List[TrlCard] = Shortener.get_matches(
+ matching_cards: List[TrlCard] = Normalizer.get_matches(
card_shortcut,
board.cards
)
@@ 192,3 192,8 @@ class Usecases:
lines = fd.readlines()
return urllib.parse.quote(lines[1].replace('\n', ''), safe=''), \
urllib.parse.quote(str.join('', lines[2:]), safe='')
+
+ def print_board_labels(self):
+ board = self.tclient.get_board(self.selected_board_id)
+ for label in board.labels:
+ print('{:12} {}'.format(label.color, label.name))