Skip to content

Commit

Permalink
Unified initialization of cards from JSON data. Added optionally lazy…
Browse files Browse the repository at this point in the history
… properties for comments and checklists.
  • Loading branch information
Mathias Kahl committed Aug 7, 2014
1 parent 987e01a commit 166cd32
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 48 deletions.
43 changes: 38 additions & 5 deletions test/test_trello.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test30_list_attrs(self):
self.assertIsNotNone(l.closed, msg="closed not provided")
break # only need to test one board's lists

def test40_list_cards(self):
def test50_list_cards(self):
boards = self._trello.list_boards()
for b in boards:
for l in b.all_lists():
Expand All @@ -75,7 +75,7 @@ def test40_list_cards(self):
break
pass

def test41_fetch_cards(self):
def test51_fetch_cards(self):
"""
Tests fetching all attributes for all cards
"""
Expand All @@ -92,7 +92,7 @@ def test41_fetch_cards(self):
pass


def test50_add_card(self):
def test40_add_card(self):
boards = self._trello.list_boards()
board_id = None
for b in boards:
Expand All @@ -117,7 +117,7 @@ def test50_add_card(self):
if not card:
self.fail("No card created")

def test51_add_card(self):
def test41_add_card(self):
boards = self._trello.list_boards()
board_id = None
for b in boards:
Expand All @@ -144,20 +144,53 @@ def test51_add_card(self):
if not card:
self.fail("No card created")

def test42_add_card_with_comments(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 = "Card with comments"
comment = "Hello World!"
card = l.add_card(name)
card.comment(comment)
card.fetch(True)
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, '')
self.assertIsNotNone(card.closed, msg="closed not provided")
self.assertIsNotNone(card.url, msg="url not provided")
self.assertEquals(len(card.comments), 1)
self.assertEquals(card.comments[0]['data']['text'], comment)
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")
self.assertEqual(len(cards), 3, 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, '')
elif card.name == 'Card with comments':
self.assertEqual(card.description, '')
else:
self.fail(msg='Unexpected card found')

Expand Down
103 changes: 60 additions & 43 deletions trello/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,20 +322,7 @@ def get_cards(self, filters=None):
query_params=filters
)

cards = list()
for card_json in json_obj:
card = Card(self, card_json['id'],
name=card_json['name'])

for card_key, card_val in card_json.items():
if card_key in ['id', 'name']:
continue

setattr(card, card_key, card_val)

cards.append(card)

return cards
return list([Card.from_json(json, self) for json in json_obj])

def fetch_actions(self, action_filter):
json_obj = self.client.fetch_json(
Expand Down Expand Up @@ -373,15 +360,7 @@ def fetch(self):
def list_cards(self):
"""Lists all cards in this list"""
json_obj = self.client.fetch_json('/lists/' + self.id + '/cards')
cards = list()
for c in json_obj:
card = Card(self, c['id'], name=c['name'])
card.description = c.get('desc', '')
card.closed = c['closed']
card.url = c['url']
card.member_ids = c['idMembers']
cards.append(card)
return cards
return list([Card.from_json(json, self) for json in json_obj])

def add_card(self, name, desc=None):
"""Add a card to this list
Expand All @@ -393,13 +372,7 @@ def add_card(self, name, desc=None):
'/lists/' + self.id + '/cards',
http_method='POST',
post_args={'name': name, 'idList': self.id, 'desc': desc}, )
card = Card(self, json_obj['id'])
card.name = json_obj['name']
card.description = json_obj.get('desc', '')
card.closed = json_obj['closed']
card.url = json_obj['url']
card.member_ids = json_obj['idMembers']
return card
return Card.from_json(json_obj, self)

def fetch_actions(self, action_filter):
"""
Expand Down Expand Up @@ -453,12 +426,30 @@ def description(self):

@property
def date_last_activity(self) -> datetime:
return self._dateLastActivity
return self.dateLastActivity

@description.setter
def description(self, value):
self.desc = value

@property
def comments(self):
"""
Lazily loads and returns the comments
"""
if self._comments is None:
self._comments = self.fetch_comments()
return self._comments

@property
def checklists(self):
"""
Lazily loads and returns the checklists
"""
if self._checklists is None:
self._checklists = self.fetch_checklists()
return self._checklists

def __init__(self, trello_list, card_id, name=''):
"""
:trello_list: reference to the parent list
Expand All @@ -469,14 +460,34 @@ def __init__(self, trello_list, card_id, name=''):
self.id = card_id
self.name = name

@staticmethod
def from_json(json_obj, trello_list, eager=False):
card = Card(trello_list, json_obj['id'])
card.init(json_obj, eager)
return card

def __repr__(self):
return '<Card %s>' % self.name

def fetch(self):
"""Fetch all attributes for this card"""
def fetch(self, eager=True):
"""
Fetch all attributes for this card
:param eager: If eager is true comments and checklists will be fetched immediately, otherwise on demand
"""
json_obj = self.client.fetch_json(
'/cards/' + self.id,
query_params={'badges': False})
self.init(json_obj, eager)

def init(self, json_obj, eager=True):
"""
Initializes the card from its JSON representation as obtained through the Trello API.
:param json_obj:
:param eager: If eager is true comments and checklists will be fetched immediately, otherwise on demand
:return:
"""

self.id = json_obj['id']
self.name = json_obj['name']
self.description = json_obj.get('desc', '')
self.closed = json_obj['closed']
Expand All @@ -489,21 +500,27 @@ def fetch(self):
self.badges = json_obj['badges']
self.due = json_obj['due']
self.checked = json_obj['checkItemStates']
self._dateLastActivity = dateparser.parse(json_obj['dateLastActivity'])
self.dateLastActivity = dateparser.parse(json_obj['dateLastActivity'])

self.checklists = []
if self.badges['checkItems'] > 0:
json_obj = self.client.fetch_json(
'/cards/' + self.id + '/checklists', )
for cl in json_obj:
self.checklists.append(Checklist(self.client, self.checked, cl,
trello_card=self.id))
self._checklists = self.fetch_checklists() if eager else None
self._comments = self.fetch_comments() if eager else None

self.comments = []
def fetch_comments(self):
comments = []
if self.badges['comments'] > 0:
self.comments = self.client.fetch_json(
comments = self.client.fetch_json(
'/cards/' + self.id + '/actions',
query_params={'filter': 'commentCard'})
return comments

def fetch_checklists(self):
checklists = []
if self.badges['checkItems'] > 0:
json_obj = self.client.fetch_json(
'/cards/' + self.id + '/checklists', )
for cl in json_obj:
checklists.append(Checklist(self.client, self.checked, cl, trello_card=self.id))
return checklists

def fetch_actions(self, action_filter='createCard'):
"""
Expand Down

0 comments on commit 166cd32

Please sign in to comment.