Skip to content

Commit edc2f0e

Browse files
committedNov 2, 2015
Several changes and improvements
- Use ConfigParser for config - Can define project-board name equivalence - Can define default lists - Much better code
1 parent 9847360 commit edc2f0e

File tree

3 files changed

+194
-113
lines changed

3 files changed

+194
-113
lines changed
 

‎.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# Local files
7+
local*

‎trellowarrior.conf

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[DEFAULT]
2+
3+
# Set TaskWarrior
4+
taskwarrior_taskrc_location = ~/.taskrc
5+
taskwarrior_data_location = ~/.task
6+
7+
# Set Trello auth
8+
trello_api_key = YOUR_API_KEY
9+
trello_api_secret = YOUR_API_SECRET
10+
trello_token = YOUR_TOKEN
11+
trello_token_secret = YOUR_TOKEN_SECRET
12+
13+
# Set what projects are active and sync
14+
sync_projects = connectical
15+
16+
[connectical]
17+
# Define proyect-board equivalence and default list names
18+
tw_project_name = Connectical
19+
trello_board_name = Connectical
20+
trello_todo_list = To Do
21+
trello_doing_list = Doing
22+
trello_done_list = Done

‎trellowarrior.py

+165-113
Original file line numberDiff line numberDiff line change
@@ -6,139 +6,191 @@
66
#
77
# Distributed under terms of the MIT license.
88

9+
from ConfigParser import RawConfigParser
910
from tasklib.task import TaskWarrior
1011
from trello import TrelloClient
1112

12-
### BEGIN OF CONFIG ### (In next version this go to to configfile)
13+
def parse_config(config_file):
14+
"""
15+
Parse config file and return true if all ok
16+
All config settings are stored in globar vars
17+
18+
:config_file: config file name
19+
"""
20+
global trello_api_key, trello_api_secret, trello_token, trello_token_secret
21+
global taskwarrior_taskrc_location, taskwarrior_data_location
22+
global sync_projects
23+
sync_projects = []
24+
conf = RawConfigParser()
25+
try:
26+
conf.read(config_file)
27+
except Exception:
28+
return False
29+
if (not conf.has_option('DEFAULT', 'trello_api_key') or
30+
not conf.has_option('DEFAULT', 'trello_api_secret') or
31+
not conf.has_option('DEFAULT', 'trello_token') or
32+
not conf.has_option('DEFAULT', 'trello_token_secret') or
33+
not conf.has_option('DEFAULT', 'sync_projects')):
34+
return False
35+
for sync_project in conf.get('DEFAULT', 'sync_projects').split():
36+
if conf.has_section(sync_project):
37+
if conf.has_option(sync_project, 'tw_project_name') and conf.has_option(sync_project, 'trello_board_name'):
38+
project = {}
39+
project['tw_project_name'] = conf.get(sync_project, 'tw_project_name')
40+
project['trello_board_name'] = conf.get(sync_project, 'trello_board_name')
41+
if conf.has_option(sync_project, 'trello_todo_list'):
42+
project['trello_todo_list'] = conf.get(sync_project, 'trello_todo_list')
43+
else:
44+
project['trello_todo_list'] = 'To Do'
45+
if conf.has_option(sync_project, 'trello_doing_list'):
46+
project['trello_doing_list'] = conf.get(sync_project, 'trello_doing_list')
47+
else:
48+
project['trello_doing_list'] = 'Doing'
49+
if conf.has_option(sync_project, 'trello_done_list'):
50+
project['trello_done_list'] = conf.get(sync_project, 'trello_done_list')
51+
else:
52+
project['trello_done_list'] = 'Done'
53+
sync_projects.append(project)
54+
else:
55+
return False
56+
else:
57+
return False
58+
trello_api_key = conf.get('DEFAULT', 'trello_api_key')
59+
trello_api_secret = conf.get('DEFAULT', 'trello_api_secret')
60+
trello_token = conf.get('DEFAULT', 'trello_token')
61+
trello_token_secret = conf.get('DEFAULT', 'trello_token_secret')
62+
if conf.has_option('DEFAULT', 'taskwarrior_taskrc_location'):
63+
taskwarrior_taskrc_location = conf.get('DEFAULT', 'taskwarrior_taskrc_location')
64+
else:
65+
taskwarrior_taskrc_location = '~/.taskrc'
66+
if conf.has_option('DEFAULT', 'taskwarrior_data_location'):
67+
taskwarrior_data_location = conf.get('DEFAULT', 'taskwarrior_data_location')
68+
else:
69+
taskwarrior_data_location = '~/.task'
70+
return True
1371

14-
# Set TaskWarrior
15-
taskwarrior_taskrc_location = '~/.taskrc'
16-
taskwarrior_data_location = '~/.task'
1772

18-
# Set Trello auth
19-
trello_api_key = ''
20-
trello_api_secret = ''
21-
trello_token = ''
22-
trello_token_secret = ''
73+
def get_trello_boards():
74+
""" Get all Trello boards """
75+
trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret)
76+
return trello_client.list_boards()
77+
78+
def get_trello_board(board_name):
79+
"""
80+
Returns Trello board from name
81+
If does not exist create it and returns new board
2382
24-
# Set sync projects/boards
25-
sync_projects = ['Connectical']
83+
:board_name: the board name
84+
"""
85+
trello_boards = get_trello_boards()
86+
for trello_board in trello_boards:
87+
if trello_board.name == board_name:
88+
return trello_board
89+
return create_trello_board(board_name)
2690

27-
### END OF CONFIG ###
91+
def create_trello_board(board_name):
92+
"""
93+
Create Trello board and returns it
2894
29-
# Create a trello client
30-
trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret)
95+
:board_name: the board name
96+
"""
97+
trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret)
98+
return trello_client.add_board(board_name)
3199

32-
def get_trello_boards():
33-
""" Get all Trello boards """
34-
trello_boards = trello_client.list_boards()
35-
if len(trello_boards) > 0:
36-
return trello_boards
37-
else:
38-
return None
100+
def get_trello_lists(board_name):
101+
"""
102+
Returns a set of list objects
39103
40-
def get_tw_project_tasks(project):
104+
:board_name: the board name
105+
"""
106+
return get_trello_board(board_name).open_lists()
107+
108+
def get_trello_list(board_name, trello_lists, list_name):
109+
"""
110+
Returns a list object
111+
112+
:board_name: the board name
113+
:trello_lists: the set of lists
114+
:list_name: the list name
115+
"""
116+
for trello_list in trello_lists:
117+
if trello_list.name == list_name:
118+
return trello_list
119+
return create_trello_list(board_name, list_name)
120+
121+
def create_trello_list(board_name, list_name):
122+
"""
123+
Returns a new list object from project name and listname
124+
125+
:board_name: the board name
126+
:list_name: the list name
127+
"""
128+
trello_board = get_trello_board(board_name)
129+
return trello_board.add_list(list_name)
130+
131+
def upload_tw_task(tw_task, trello_list):
132+
"""
133+
Upload all contents of task to list creating a new card and storing cardid
134+
135+
:tw_task: TaskWarrior task object
136+
:trello_list: Trello list object
137+
"""
138+
new_trello_card = trello_list.add_card(tw_task['description'])
139+
if tw_task['due']:
140+
new_trello_card.set_due(tw_task['due'])
141+
# Save the Trello Card ID into Task
142+
tw_task['trelloid'] = new_trello_card.id
143+
tw_task.save()
144+
145+
def get_tw_project_tasks(project_name):
41146
"""
42147
Fetch all tasks from a project
43148
44-
:project: the project name
149+
:project_name: the project name
45150
"""
46-
tw_project_tasks = TaskWarrior(taskrc_location=taskwarrior_taskrc_location, data_location=taskwarrior_data_location).tasks.filter(project=project)
47-
if len(project_tasks) > 0:
48-
return tw_project_tasks
49-
else:
50-
return None
151+
return TaskWarrior(taskrc_location=taskwarrior_taskrc_location, data_location=taskwarrior_data_location).tasks.filter(project=project_name)
51152

52-
def get_trello_board_id(project):
153+
def upload_new_tw_tasks(project_name, board_name, todo_list_name, doing_list_name, done_list_name):
53154
"""
54-
Returns Trello board ID from name
55-
If not exists create it and returns new ID
155+
Upload new TaskWarrior tasks that never uploaded before
56156
57-
:project: the project name
157+
:project_name: the project name
158+
:board_name: the name of Trello board
159+
:todo_list_name: name of list for todo taks
160+
:doing_list_name: name of list for active tasks
161+
:done_list_name: name of list for done tasks
58162
"""
59-
trello_boards = get_trello_boards()
60-
if trello_boards:
61-
for trello_board in trello_boards:
62-
if trello_board.name == project:
63-
return trello_board.id
64-
return create_trello_board(project)
163+
tw_tasks = get_tw_project_tasks(project_name)
164+
trello_lists = get_trello_lists(board_name)
165+
for tw_task in tw_tasks:
166+
if not tw_task['trelloid']:
167+
if tw_task.completed:
168+
upload_tw_task(tw_task, get_trello_list(board_name, trello_lists, done_list_name))
169+
tw_task['trellolistname'] = done_list_name
170+
tw_task.save()
171+
elif tw_task.active:
172+
upload_tw_task(tw_task, get_trello_list(board_name, trello_lists, doing_list_name))
173+
tw_task['trellolistname'] = doing_list_name
174+
tw_task.save()
175+
else:
176+
if tw_task['trellolistname']:
177+
upload_tw_task(tw_task, get_trello_list(board_name, trello_lists, tw_task['trellolistname']))
178+
else:
179+
upload_tw_task(tw_task, get_trello_list(board_name, trello_lists, todo_list_name))
180+
tw_task['trellolistname'] = todo_list_name
181+
tw_task.save()
65182

66183
def main():
67184
for project in sync_projects:
68-
print (get_trello_board_id(project))
185+
upload_new_tw_tasks(project['tw_project_name'],
186+
project['trello_board_name'],
187+
project['trello_todo_list'],
188+
project['trello_doing_list'],
189+
project['trello_done_list'])
190+
#print (get_trello_board_id(project))
191+
#print (get_trello_list(project, 'Movida'))
192+
# upload_new_tw_tasks(project)
69193

70194
if __name__ == "__main__":
71-
main()
72-
73-
# Import all tasks into object
74-
#tw = task.TaskWarrior()
75-
#task.TaskWarrior().tasks.filter(project='Connecticale')
76-
#all_tasks = task.TaskWarrior().tasks.all()
77-
78-
# Create a trello client
79-
#trello_client = TrelloClient(api_key=trello_api_key, api_secret=trello_api_secret, token=trello_token, token_secret=trello_token_secret)
80-
81-
# Get all boards in trello (to find tello board id)
82-
#trello_boards = trello_client.list_boards()
83-
84-
def upload_new(project, board_id):
85-
# Get tasks from project
86-
project_tasks = task.TaskWarrior().tasks.filter(project=project)
87-
if len(project_tasks) > 0:
88-
89-
# Get lists from board
90-
trello_lists = trello_client.get_board(board_id).open_lists()
91-
# Get base lists
92-
todo_list = None
93-
doing_list = None
94-
done_list = None
95-
for trello_list in trello_lists:
96-
if trello_list.name == 'To Do':
97-
todo_list = trello_list
98-
if trello_list.name == 'Doing':
99-
doing_list = trello_list
100-
if trello_list.name == 'Done':
101-
done_list = trello_list
102-
# TODO: Make base lists if not present
103-
104-
for project_task in project_tasks:
105-
# If trelloid is empty is a new task crated by taskwarrior
106-
if not project_task['trelloid']:
107-
if project_task.completed:
108-
new_card = done_list.add_card(project_task['description'])
109-
if project_task['due']:
110-
new_card.set_due(project_task['due'])
111-
print ('Completed')
112-
return
113-
if project_task.active:
114-
new_card = doing_list.add_card(project_task['description'])
115-
if project_task['due']:
116-
new_card.set_due(project_task['due'])
117-
print ('Active')
118-
return
119-
new_card = todo_list.add_card(project_task['description'])
120-
if project_task['due']:
121-
new_card.set_due(project_task['due'])
122-
print ('new')
123-
124-
125-
#def main():
126-
# Do the samba
127-
# for project in sync_projects:
128-
# Try find project - board id correspondence
129-
# board_id = None
130-
# for board in trello_boards:
131-
# if board.name == project:
132-
# board_id = board.id
133-
# if not board_id:
134-
#TODO: Create the board
135-
# print ('Board not found')
136-
# return
137-
# upload_new(project, board_id)
138-
# Get the board
139-
#trello_board = trello_client.get_board(board_id)
140-
# And get lists from board
141-
#trello_lists = trello_board.open_lists()
142-
143-
144-
195+
if parse_config('trellowarrior.conf'):
196+
main()

0 commit comments

Comments
 (0)
Please sign in to comment.