Merge lp:~lderan/ubuntu-bots/meeetingology-output into lp:~ubuntu-bots/ubuntu-bots/meetingology
- meeetingology-output
- Merge into meetingology
Proposed by
Thomas Molloy
Status: | Merged |
---|---|
Merged at revision: | 12 |
Proposed branch: | lp:~lderan/ubuntu-bots/meeetingology-output |
Merge into: | lp:~ubuntu-bots/ubuntu-bots/meetingology |
Diff against target: |
274 lines (+55/-26) 5 files modified
items.py (+7/-7) meeting.py (+25/-3) meetingLocalConfig.py (+1/-1) plugin.py (+2/-2) writers.py (+20/-13) |
To merge this branch: | bzr merge lp:~lderan/ubuntu-bots/meeetingology-output |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Bell | Approve | ||
Review via email: mp+164589@code.launchpad.net |
Commit message
Description of the change
Formatting the output for the MoinMoin wikis.
Adding votes to the top of the meeting information with results
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'items.py' | |||
2 | --- items.py 2010-09-02 19:16:45 +0000 | |||
3 | +++ items.py 2013-05-18 11:54:26 +0000 | |||
4 | @@ -128,7 +128,7 @@ | |||
5 | 128 | text_template = """%(starttext)s%(topic)s%(endtext)s (%(nick)s, %(time)s)""" | 128 | text_template = """%(starttext)s%(topic)s%(endtext)s (%(nick)s, %(time)s)""" |
6 | 129 | mw_template = """%(startmw)s%(topic)s%(endmw)s (%(nick)s, %(time)s)""" | 129 | mw_template = """%(startmw)s%(topic)s%(endmw)s (%(nick)s, %(time)s)""" |
7 | 130 | moin_template = """%(startmoin)s%(topic)s%(endmoin)s (%(nick)s, %(time)s)""" | 130 | moin_template = """%(startmoin)s%(topic)s%(endmoin)s (%(nick)s, %(time)s)""" |
9 | 131 | moin_template = """ *%(topic)s""" | 131 | moin_template = """=== %(topic)s ===\nThe discussion about \"%(topic)s\" started at %(time)s.\n""" |
10 | 132 | 132 | ||
11 | 133 | startrst = '**' | 133 | startrst = '**' |
12 | 134 | endrst = '**' | 134 | endrst = '**' |
13 | @@ -140,7 +140,7 @@ | |||
14 | 140 | endmoin = '' | 140 | endmoin = '' |
15 | 141 | def __init__(self, nick, line, linenum, time_): | 141 | def __init__(self, nick, line, linenum, time_): |
16 | 142 | self.nick = nick ; self.topic = line ; self.linenum = linenum | 142 | self.nick = nick ; self.topic = line ; self.linenum = linenum |
18 | 143 | self.time = time.strftime("%H:%M:%S", time_) | 143 | self.time = time.strftime("%H:%M", time_) |
19 | 144 | def _htmlrepl(self, M): | 144 | def _htmlrepl(self, M): |
20 | 145 | repl = self.get_replacements(M, escapewith=writers.html) | 145 | repl = self.get_replacements(M, escapewith=writers.html) |
21 | 146 | repl['link'] = self.logURL(M) | 146 | repl['link'] = self.logURL(M) |
22 | @@ -186,7 +186,7 @@ | |||
23 | 186 | moin_template = """''%(itemtype)s:'' %(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)""" | 186 | moin_template = """''%(itemtype)s:'' %(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)""" |
24 | 187 | def __init__(self, nick, line, linenum, time_): | 187 | def __init__(self, nick, line, linenum, time_): |
25 | 188 | self.nick = nick ; self.line = line ; self.linenum = linenum | 188 | self.nick = nick ; self.line = line ; self.linenum = linenum |
27 | 189 | self.time = time.strftime("%H:%M:%S", time_) | 189 | self.time = time.strftime("%H:%M", time_) |
28 | 190 | def _htmlrepl(self, M): | 190 | def _htmlrepl(self, M): |
29 | 191 | repl = self.get_replacements(M, escapewith=writers.html) | 191 | repl = self.get_replacements(M, escapewith=writers.html) |
30 | 192 | repl['link'] = self.logURL(M) | 192 | repl['link'] = self.logURL(M) |
31 | @@ -211,7 +211,6 @@ | |||
32 | 211 | repl = self.get_replacements(M, escapewith=writers.moin) | 211 | repl = self.get_replacements(M, escapewith=writers.moin) |
33 | 212 | return self.moin_template%repl | 212 | return self.moin_template%repl |
34 | 213 | 213 | ||
35 | 214 | |||
36 | 215 | class Info(GenericItem): | 214 | class Info(GenericItem): |
37 | 216 | itemtype = 'INFO' | 215 | itemtype = 'INFO' |
38 | 217 | html2_template = ("""<span class="%(itemtype)s">""" | 216 | html2_template = ("""<span class="%(itemtype)s">""" |
39 | @@ -223,16 +222,17 @@ | |||
40 | 223 | rst_template = """%(startrst)s%(line)s%(endrst)s (%(rstref)s_)""" | 222 | rst_template = """%(startrst)s%(line)s%(endrst)s (%(rstref)s_)""" |
41 | 224 | text_template = """%(starttext)s%(line)s%(endtext)s (%(nick)s, %(time)s)""" | 223 | text_template = """%(starttext)s%(line)s%(endtext)s (%(nick)s, %(time)s)""" |
42 | 225 | mw_template = """%(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)""" | 224 | mw_template = """%(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)""" |
44 | 226 | moin_template = """%(startmoin)s%(line)s%(endmoin)s (%(nick)s, %(time)s)""" | 225 | moin_template = """%(startmoin)s%(line)s%(endmoin)s""" |
45 | 227 | class Idea(GenericItem): | 226 | class Idea(GenericItem): |
46 | 228 | itemtype = 'IDEA' | 227 | itemtype = 'IDEA' |
47 | 229 | class Agreed(GenericItem): | 228 | class Agreed(GenericItem): |
48 | 230 | itemtype = 'AGREED' | 229 | itemtype = 'AGREED' |
49 | 231 | class Action(GenericItem): | 230 | class Action(GenericItem): |
50 | 232 | itemtype = 'ACTION' | 231 | itemtype = 'ACTION' |
51 | 232 | moin_template = """''ACTION:'' %(line)s""" | ||
52 | 233 | class Subtopic(GenericItem): | 233 | class Subtopic(GenericItem): |
53 | 234 | itemtype = 'SUBTOPIC' | 234 | itemtype = 'SUBTOPIC' |
55 | 235 | moin_template = """ *%(line)s (%(nick)s, %(time)s)""" | 235 | moin_template = """ * '''%(line)s''' (%(time)s)""" |
56 | 236 | class Help(GenericItem): | 236 | class Help(GenericItem): |
57 | 237 | itemtype = 'HELP' | 237 | itemtype = 'HELP' |
58 | 238 | class Accepted(GenericItem): | 238 | class Accepted(GenericItem): |
59 | @@ -260,7 +260,7 @@ | |||
60 | 260 | rst_template = """*%(itemtype)s*: %(startrst)s%(url)s %(line)s%(endrst)s (%(rstref)s_)""" | 260 | rst_template = """*%(itemtype)s*: %(startrst)s%(url)s %(line)s%(endrst)s (%(rstref)s_)""" |
61 | 261 | text_template = """%(itemtype)s: %(starttext)s%(url)s %(line)s%(endtext)s (%(nick)s, %(time)s)""" | 261 | text_template = """%(itemtype)s: %(starttext)s%(url)s %(line)s%(endtext)s (%(nick)s, %(time)s)""" |
62 | 262 | mw_template = """''%(itemtype)s:'' %(startmw)s%(url)s %(line)s%(endmw)s (%(nick)s, %(time)s)""" | 262 | mw_template = """''%(itemtype)s:'' %(startmw)s%(url)s %(line)s%(endmw)s (%(nick)s, %(time)s)""" |
64 | 263 | moin_template = """''%(itemtype)s:'' %(startmw)s%(url)s %(line)s%(endmw)s (%(nick)s, %(time)s)""" | 263 | moin_template = """''%(itemtype)s:'' %(startmw)s%(url)s %(line)s%(endmw)s""" |
65 | 264 | def __init__(self, nick, line, linenum, time_): | 264 | def __init__(self, nick, line, linenum, time_): |
66 | 265 | self.nick = nick ; self.linenum = linenum | 265 | self.nick = nick ; self.linenum = linenum |
67 | 266 | self.time = time.strftime("%H:%M:%S", time_) | 266 | self.time = time.strftime("%H:%M:%S", time_) |
68 | 267 | 267 | ||
69 | === modified file 'meeting.py' | |||
70 | --- meeting.py 2011-09-20 16:35:45 +0000 | |||
71 | +++ meeting.py 2013-05-18 11:54:26 +0000 | |||
72 | @@ -37,6 +37,7 @@ | |||
73 | 37 | 37 | ||
74 | 38 | import writers | 38 | import writers |
75 | 39 | import items | 39 | import items |
76 | 40 | |||
77 | 40 | reload(writers) | 41 | reload(writers) |
78 | 41 | reload(items) | 42 | reload(items) |
79 | 42 | 43 | ||
80 | @@ -434,11 +435,16 @@ | |||
81 | 434 | self.votesrequired=0 | 435 | self.votesrequired=0 |
82 | 435 | self.reply("votes now need %s to be passed"%self.votesrequired) | 436 | self.reply("votes now need %s to be passed"%self.votesrequired) |
83 | 436 | def do_endvote(self, nick, line, **kwargs): | 437 | def do_endvote(self, nick, line, **kwargs): |
84 | 438 | |||
85 | 437 | if not self.isChair(nick): return | 439 | if not self.isChair(nick): return |
86 | 440 | |||
87 | 438 | """this vote is over, record the results""" | 441 | """this vote is over, record the results""" |
88 | 439 | if self.activeVote=="": | 442 | if self.activeVote=="": |
89 | 440 | self.reply("No vote in progress") | 443 | self.reply("No vote in progress") |
90 | 441 | return | 444 | return |
91 | 445 | |||
92 | 446 | |||
93 | 447 | |||
94 | 442 | self.reply("Voting ended on: "+self.activeVote) | 448 | self.reply("Voting ended on: "+self.activeVote) |
95 | 443 | #should probably just store the summary of the results | 449 | #should probably just store the summary of the results |
96 | 444 | vfor=0 | 450 | vfor=0 |
97 | @@ -451,20 +457,36 @@ | |||
98 | 451 | vabstain+=1 | 457 | vabstain+=1 |
99 | 452 | elif re.match("\+1",self.currentVote[v]): | 458 | elif re.match("\+1",self.currentVote[v]): |
100 | 453 | vfor+=1 | 459 | vfor+=1 |
101 | 460 | |||
102 | 461 | voteResult = "Carried" | ||
103 | 462 | |||
104 | 454 | self.reply("Votes for:"+str(vfor)+" Votes against:"+str(vagainst)+" Abstentions:"+str(vabstain)) | 463 | self.reply("Votes for:"+str(vfor)+" Votes against:"+str(vagainst)+" Abstentions:"+str(vabstain)) |
105 | 455 | if vfor-vagainst>self.votesrequired: | 464 | if vfor-vagainst>self.votesrequired: |
106 | 456 | self.reply("Motion carried") | 465 | self.reply("Motion carried") |
107 | 466 | voteResult = "Carried" | ||
108 | 457 | elif vfor-vagainst<self.votesrequired: | 467 | elif vfor-vagainst<self.votesrequired: |
109 | 458 | self.reply("Motion denied") | 468 | self.reply("Motion denied") |
110 | 469 | voteResult = "Denied" | ||
111 | 459 | else: | 470 | else: |
112 | 460 | if self.votesrequired==0: | 471 | if self.votesrequired==0: |
113 | 461 | self.reply("Deadlock, casting vote may be used") | 472 | self.reply("Deadlock, casting vote may be used") |
114 | 473 | voteResult = "Deadlock" | ||
115 | 462 | else: | 474 | else: |
116 | 463 | self.reply("Motion carried") | 475 | self.reply("Motion carried") |
117 | 476 | voteResult = "Carried" | ||
118 | 464 | self.votes[self.activeVote]=[vfor,vabstain,vagainst]#store the results | 477 | self.votes[self.activeVote]=[vfor,vabstain,vagainst]#store the results |
120 | 465 | 478 | ||
121 | 479 | """Add informational item to the minutes.""" | ||
122 | 480 | voteResultLog = "''Vote:'' "+self.activeVote+" ("+voteResult+")" | ||
123 | 481 | |||
124 | 482 | m = items.Info(nick=nick, line=voteResultLog, **kwargs) | ||
125 | 483 | self.additem(m) | ||
126 | 484 | |||
127 | 466 | self.activeVote=""#allow another vote to be called | 485 | self.activeVote=""#allow another vote to be called |
128 | 467 | self.currentVote={} | 486 | self.currentVote={} |
129 | 487 | |||
130 | 488 | |||
131 | 489 | |||
132 | 468 | def do_voters(self, nick,line,**kwargs): | 490 | def do_voters(self, nick,line,**kwargs): |
133 | 469 | if not self.isChair(nick): return | 491 | if not self.isChair(nick): return |
134 | 470 | """provide a list of authorised voters""" | 492 | """provide a list of authorised voters""" |
135 | @@ -665,10 +687,10 @@ | |||
136 | 665 | 687 | ||
137 | 666 | # Handle the logging of the line | 688 | # Handle the logging of the line |
138 | 667 | if line[:6] == 'ACTION': | 689 | if line[:6] == 'ACTION': |
140 | 668 | logline = "%s * %s %s"%(time.strftime("%H:%M:%S", time_), | 690 | logline = "%s * %s %s"%(time.strftime("%H:%M", time_), |
141 | 669 | nick, line[7:].strip()) | 691 | nick, line[7:].strip()) |
142 | 670 | else: | 692 | else: |
144 | 671 | logline = "%s <%s> %s"%(time.strftime("%H:%M:%S", time_), | 693 | logline = "%s <%s> %s"%(time.strftime("%H:%M", time_), |
145 | 672 | nick, line.strip()) | 694 | nick, line.strip()) |
146 | 673 | self.lines.append(logline) | 695 | self.lines.append(logline) |
147 | 674 | linenum = len(self.lines) | 696 | linenum = len(self.lines) |
148 | 675 | 697 | ||
149 | === modified file 'meetingLocalConfig.py' | |||
150 | --- meetingLocalConfig.py 2012-06-17 02:15:05 +0000 | |||
151 | +++ meetingLocalConfig.py 2013-05-18 11:54:26 +0000 | |||
152 | @@ -16,4 +16,4 @@ | |||
153 | 16 | '.moin.txt':writers.Moin, | 16 | '.moin.txt':writers.Moin, |
154 | 17 | #'.mw.txt':writers.MediaWiki, | 17 | #'.mw.txt':writers.MediaWiki, |
155 | 18 | } | 18 | } |
157 | 19 | command_RE = re.compile(r'[#|\[]([\w]+)[\]]?[ \t]*(.*)') | 19 | command_RE = re.compile(r'[#|\[]([\w]+)[\]]?[ \t]*(.*)') |
158 | 20 | \ No newline at end of file | 20 | \ No newline at end of file |
159 | 21 | 21 | ||
160 | === modified file 'plugin.py' | |||
161 | --- plugin.py 2011-08-29 22:42:59 +0000 | |||
162 | +++ plugin.py 2013-05-18 11:54:26 +0000 | |||
163 | @@ -90,7 +90,7 @@ | |||
164 | 90 | M = meeting_cache.get(Mkey, None) | 90 | M = meeting_cache.get(Mkey, None) |
165 | 91 | 91 | ||
166 | 92 | # Start meeting if we are requested | 92 | # Start meeting if we are requested |
168 | 93 | if payload[:13] == '#startmeeting': | 93 | if payload[:13].lower() == '#startmeeting': |
169 | 94 | if M is not None: | 94 | if M is not None: |
170 | 95 | irc.error("Can't start another meeting, one is in progress.") | 95 | irc.error("Can't start another meeting, one is in progress.") |
171 | 96 | return | 96 | return |
172 | @@ -114,7 +114,7 @@ | |||
173 | 114 | (channel, network, time.ctime())) | 114 | (channel, network, time.ctime())) |
174 | 115 | if len(recent_meetings) > 10: | 115 | if len(recent_meetings) > 10: |
175 | 116 | del recent_meetings[0] | 116 | del recent_meetings[0] |
177 | 117 | if payload[:7]=='#replay': | 117 | if payload[:7].lower() =='#replay': |
178 | 118 | if M is not None: | 118 | if M is not None: |
179 | 119 | irc.error("Can't replay logs while a meeting is in progress.") | 119 | irc.error("Can't replay logs while a meeting is in progress.") |
180 | 120 | return | 120 | return |
181 | 121 | 121 | ||
182 | === modified file 'writers.py' | |||
183 | --- writers.py 2010-09-02 19:16:45 +0000 | |||
184 | +++ writers.py 2013-05-18 11:54:26 +0000 | |||
185 | @@ -1,4 +1,4 @@ | |||
187 | 1 | # Richard Darst, June 2009 | 1 | # Richard Darst, June 2009 |
188 | 2 | 2 | ||
189 | 3 | ### | 3 | ### |
190 | 4 | # Copyright (c) 2009, Richard Darst | 4 | # Copyright (c) 2009, Richard Darst |
191 | @@ -108,7 +108,10 @@ | |||
192 | 108 | return {'pageTitle':self.pagetitle, | 108 | return {'pageTitle':self.pagetitle, |
193 | 109 | 'owner':self.M.owner, | 109 | 'owner':self.M.owner, |
194 | 110 | 'starttime':time.strftime("%H:%M:%S", self.M.starttime), | 110 | 'starttime':time.strftime("%H:%M:%S", self.M.starttime), |
195 | 111 | 'starttimeshort':time.strftime("%H:%M", self.M.starttime), | ||
196 | 112 | 'startdate':time.strftime("%d %b", self.M.starttime), | ||
197 | 111 | 'endtime':time.strftime("%H:%M:%S", self.M.endtime), | 113 | 'endtime':time.strftime("%H:%M:%S", self.M.endtime), |
198 | 114 | 'endtimeshort':time.strftime("%H:%M", self.M.endtime), | ||
199 | 112 | 'timeZone':self.M.config.timeZone, | 115 | 'timeZone':self.M.config.timeZone, |
200 | 113 | 'fullLogs':self.M.config.basename+'.log.html', | 116 | 'fullLogs':self.M.config.basename+'.log.html', |
201 | 114 | 'fullLogsFullURL':self.M.config.filename(url=True)+'.log.html', | 117 | 'fullLogsFullURL':self.M.config.filename(url=True)+'.log.html', |
202 | @@ -1189,8 +1192,10 @@ | |||
203 | 1189 | if haveTopic: | 1192 | if haveTopic: |
204 | 1190 | MeetingItems.append("") # line break | 1193 | MeetingItems.append("") # line break |
205 | 1191 | haveTopic = True | 1194 | haveTopic = True |
207 | 1192 | else: | 1195 | elif m.itemtype == "SUBTOPIC": |
208 | 1193 | if haveTopic: item = ""+item | 1196 | if haveTopic: item = ""+item |
209 | 1197 | else: | ||
210 | 1198 | if haveTopic: item = " * "+item | ||
211 | 1194 | MeetingItems.append(item) | 1199 | MeetingItems.append(item) |
212 | 1195 | MeetingItems = '\n'.join(MeetingItems) | 1200 | MeetingItems = '\n'.join(MeetingItems) |
213 | 1196 | return MeetingItems | 1201 | return MeetingItems |
214 | @@ -1208,11 +1213,17 @@ | |||
215 | 1208 | M = self.M | 1213 | M = self.M |
216 | 1209 | # Votes | 1214 | # Votes |
217 | 1210 | Votes = [ ] | 1215 | Votes = [ ] |
219 | 1211 | Votes.append(self.heading('Votes')) | 1216 | Votes.append(self.heading('Vote results')) |
220 | 1212 | for m in M.votes: | 1217 | for m in M.votes: |
221 | 1213 | #differentiate denied votes somehow, strikethrough perhaps? | 1218 | #differentiate denied votes somehow, strikethrough perhaps? |
222 | 1214 | Votes.append("\n * "+m) | 1219 | Votes.append("\n * "+m) |
224 | 1215 | Votes.append(" For: "+str(M.votes[m][0])+" Against: "+str(M.votes[m][2])+" Abstained: "+str(M.votes[m][1])) | 1220 | motion = "Deadlock" |
225 | 1221 | if(M.votes[m][0] > M.votes[m][1]): | ||
226 | 1222 | motion = "Motion carried" | ||
227 | 1223 | elif(M.votes[m][0] < M.votes[m][2]): | ||
228 | 1224 | motion = "Motion denied" | ||
229 | 1225 | |||
230 | 1226 | Votes.append(" * " + motion + " (For/Against/Abstained "+str(M.votes[m][0])+"/"+str(M.votes[m][2])+"/"+str(M.votes[m][1]) + ")") | ||
231 | 1216 | Votes = "\n".join(Votes) | 1227 | Votes = "\n".join(Votes) |
232 | 1217 | return Votes | 1228 | return Votes |
233 | 1218 | 1229 | ||
234 | @@ -1248,7 +1259,7 @@ | |||
235 | 1248 | if not headerPrinted: | 1259 | if not headerPrinted: |
236 | 1249 | ActionItemsPerson.append(" * %s"%moin(nick)) | 1260 | ActionItemsPerson.append(" * %s"%moin(nick)) |
237 | 1250 | headerPrinted = True | 1261 | headerPrinted = True |
239 | 1251 | ActionItemsPerson.append(" ** %s"%moin(m.line)) | 1262 | ActionItemsPerson.append(" * %s"%moin(m.line)) |
240 | 1252 | numberAssigned += 1 | 1263 | numberAssigned += 1 |
241 | 1253 | m.assigned = True | 1264 | m.assigned = True |
242 | 1254 | # unassigned items: | 1265 | # unassigned items: |
243 | @@ -1287,11 +1298,9 @@ | |||
244 | 1287 | 1298 | ||
245 | 1288 | 1299 | ||
246 | 1289 | body_start = textwrap.dedent("""\ | 1300 | body_start = textwrap.dedent("""\ |
252 | 1290 | %(pageTitleHeading)s | 1301 | == Meeting information == |
253 | 1291 | 1302 | * %(pageTitleHeading)s, %(startdate)s at %(starttimeshort)s — %(endtimeshort)s %(timeZone)s | |
254 | 1292 | sWRAPsMeeting started by %(owner)s at %(starttime)s | 1303 | * Full logs at [[%(fullLogsFullURL)s]]""") |
250 | 1293 | %(timeZone)s. The full logs are available at | ||
251 | 1294 | %(fullLogsFullURL)s .eWRAPe""") | ||
255 | 1295 | def format(self, extension=None): | 1304 | def format(self, extension=None): |
256 | 1296 | """Return a MoinMoin formatted minutes summary.""" | 1305 | """Return a MoinMoin formatted minutes summary.""" |
257 | 1297 | M = self.M | 1306 | M = self.M |
258 | @@ -1299,15 +1308,13 @@ | |||
259 | 1299 | # Actual formatting and replacement | 1308 | # Actual formatting and replacement |
260 | 1300 | repl = self.replacements() | 1309 | repl = self.replacements() |
261 | 1301 | repl.update({'titleBlock':('='*len(repl['pageTitle'])), | 1310 | repl.update({'titleBlock':('='*len(repl['pageTitle'])), |
263 | 1302 | 'pageTitleHeading':('#title '+repl['pageTitle']) | 1311 | 'pageTitleHeading':(repl['pageTitle']) |
264 | 1303 | }) | 1312 | }) |
265 | 1304 | 1313 | ||
266 | 1305 | 1314 | ||
267 | 1306 | body = [ ] | 1315 | body = [ ] |
268 | 1307 | body.append(self.body_start%repl) | 1316 | body.append(self.body_start%repl) |
269 | 1308 | body.append(self.meetingItems()) | 1317 | body.append(self.meetingItems()) |
270 | 1309 | body.append(textwrap.dedent("""\ | ||
271 | 1310 | Meeting ended at %(endtime)s %(timeZone)s."""%repl)) | ||
272 | 1311 | body.append(self.votes()) | 1318 | body.append(self.votes()) |
273 | 1312 | body.append(self.actionItems()) | 1319 | body.append(self.actionItems()) |
274 | 1313 | body.append(self.actionItemsPerson()) | 1320 | body.append(self.actionItemsPerson()) |
diff looks good, seems to work