Merge lp:~allenap/launchpad/remove-xmlrpclib-marshalling-bug-254999 into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~allenap/launchpad/remove-xmlrpclib-marshalling-bug-254999
Merge into: lp:launchpad
Diff against target: 894 lines (+102/-210)
7 files modified
lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt (+13/-17)
lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt (+10/-10)
lib/lp/bugs/externalbugtracker/bugzilla.py (+18/-71)
lib/lp/bugs/externalbugtracker/xmlrpc.py (+2/-3)
lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt (+26/-41)
lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt (+22/-35)
lib/lp/bugs/tests/externalbugtracker.py (+11/-33)
To merge this branch: bzr merge lp:~allenap/launchpad/remove-xmlrpclib-marshalling-bug-254999
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+16436@code.launchpad.net

Commit message

Remove xmlrpclib.DateTime conversion hacks from external bug tracker code. Python 2.5's xmlrpclib groks datetime.datetime.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Removes the xmlrpclib.DateTime() hacks in the external bug tracker code, as it's not needed with the version of xmlrpclib in Python 2.5. I've also done a fair bit of de-linting, but it's still a small change so I haven't broken it out into a separate patch.

Revision history for this message
Brad Crittenden (bac) wrote :

Hi Gavin,

The changes you made look good but I don't think you got all of the spots that need to be fixed. What about these others?

bzr ls -VR --kind=file --null | xargs -0 grep -In 254999
lib/lp/bugs/externalbugtracker/bugzilla.py:717: # XXX 2008-08-05 gmb (bug 254999):
lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt:141: # XXX 2009-08-21 gmb (bug 254999):
lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt:210: >>> # XXX 2008-08-05 gmb (bug 254999):
lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt:238: >>> # XXX 2008-08-05 gmb (bug 254999):
lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt:276: >>> # XXX 2008-08-05 gmb (bug 254999):
lib/lp/bugs/tests/externalbugtracker.py:603: # XXX 2008-08-05 gmb (bug 254999):

review: Needs Fixing (code)
Revision history for this message
Gavin Panella (allenap) wrote :

Thanks for spotting that I'd missed those. The incremental diff is
pretty big, but a lot of it is just the same date format changes in
innumerable doctests.

1=== modified file 'lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt'
2--- lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt 2009-12-21 15:03:42 +0000
3+++ lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt 2009-12-23 10:18:19 +0000
4@@ -139,8 +139,8 @@
5 >>> def print_bugs(bugs):
6 ... for bug in sorted(bugs):
7 ... print "Bug %s:" % bug
8- ... for key in sorted(bugzilla._bugs[bug]):
9- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
10+ ... for key in sorted(bugs[bug]):
11+ ... print " %s: %s" % (key, bugs[bug][key])
12 ... print "\n"
13
14 >>> print_bugs(bugzilla._bugs)
15@@ -148,11 +148,11 @@
16 alias:
17 assigned_to: test@canonical.com
18 component: GPPSystems
19- creation_time: 20080610T16:19:53
20+ creation_time: 2008-06-10 16:19:53
21 id: 1
22 internals:...
23 is_open: True
24- last_change_time: 20080610T16:19:53
25+ last_change_time: 2008-06-10 16:19:53
26 priority: P1
27 product: Marvin
28 resolution: FIXED
29@@ -165,11 +165,11 @@
30 alias: bug-two
31 assigned_to: marvin@heartofgold.ship
32 component: Crew
33- creation_time: 20080611T09:23:12
34+ creation_time: 2008-06-11 09:23:12
35 id: 2
36 internals:...
37 is_open: True
38- last_change_time: 20080611T09:24:29
39+ last_change_time: 2008-06-11 09:24:29
40 priority: P1
41 product: HeartOfGold
42 resolution:
43@@ -194,20 +194,16 @@
44 >>> bugzilla.initializeRemoteBugDB([2, 'bug-two'])
45 CALLED Bug.get({'ids': [2, 'bug-two'], 'permissive': True})
46
47- >>> for bug in sorted(bugzilla._bugs):
48- ... print "Bug %r:" % bug
49- ... for key in sorted(bugzilla._bugs[bug]):
50- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
51- ... print "\n"
52+ >>> print_bugs(bugzilla._bugs)
53 Bug 2:
54 alias: bug-two
55 assigned_to: marvin@heartofgold.ship
56 component: Crew
57- creation_time: 20080611T09:23:12
58+ creation_time: 2008-06-11 09:23:12
59 id: 2
60 internals:...
61 is_open: True
62- last_change_time: 20080611T09:24:29
63+ last_change_time: 2008-06-11 09:24:29
64 priority: P1
65 product: HeartOfGold
66 resolution:
67@@ -450,14 +446,14 @@
68 id: 1
69 is_private: False
70 text: I'd really appreciate it if Marvin would enjoy life a bit.
71- time: 20080616T12:44:29
72+ time: 2008-06-16 12:44:29
73 Comment 3:
74 author: marvin
75 bug_id: 1
76 id: 3
77 is_private: False
78 text: Life? Don't talk to me about life.
79- time: 20080616T13:22:29
80+ time: 2008-06-16 13:22:29
81
82 If we try to fetch comments that don't belong to the current bug
83 fetchComments() will silently ignore them.
84@@ -477,7 +473,7 @@
85 id: 1
86 is_private: False
87 text: I'd really appreciate it if Marvin would enjoy life a bit.
88- time: 20080616T12:44:29
89+ time: 2008-06-16 12:44:29
90
91
92 getPosterForComment()
93@@ -521,7 +517,7 @@
94 field on the imported comment.
95
96 >>> print bugzilla._bugs[2]['comments'][2]['time']
97- 20080616T13:08:08
98+ 2008-06-16 13:08:08
99
100 >>> print message.datecreated
101 2008-06-16 13:08:08+00:00
102
103=== modified file 'lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt'
104--- lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt 2009-12-21 15:03:42 +0000
105+++ lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt 2009-12-23 10:23:47 +0000
106@@ -204,8 +204,8 @@
107 >>> def print_bugs(bugs):
108 ... for bug in sorted(bugs):
109 ... print "Bug %s:" % bug
110- ... for key in sorted(bugzilla._bugs[bug]):
111- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
112+ ... for key in sorted(bugs[bug]):
113+ ... print " %s: %s" % (key, bugs[bug][key])
114 ... print "\n"
115
116 >>> print_bugs(bugzilla._bugs)
117@@ -213,11 +213,11 @@
118 alias:
119 assigned_to: test@canonical.com
120 component: GPPSystems
121- creation_time: 20080610T16:19:53
122+ creation_time: 2008-06-10 16:19:53
123 id: 1
124 internals:...
125 is_open: True
126- last_change_time: 20080610T16:19:53
127+ last_change_time: 2008-06-10 16:19:53
128 priority: P1
129 product: Marvin
130 resolution: FIXED
131@@ -230,11 +230,11 @@
132 alias: bug-two
133 assigned_to: marvin@heartofgold.ship
134 component: Crew
135- creation_time: 20080611T09:23:12
136+ creation_time: 2008-06-11 09:23:12
137 id: 2
138 internals:...
139 is_open: True
140- last_change_time: 20080611T09:24:29
141+ last_change_time: 2008-06-11 09:24:29
142 priority: P1
143 product: HeartOfGold
144 resolution:
145@@ -416,13 +416,13 @@
146 id: 1
147 number: 1
148 text: I'd really appreciate it if Marvin would enjoy life a bit.
149- time: 20080616T12:44:29
150+ time: 2008-06-16 12:44:29
151 Comment 3:
152 author: marvin
153 id: 3
154 number: 2
155 text: Life? Don't talk to me about life.
156- time: 20080616T13:22:29
157+ time: 2008-06-16 13:22:29
158
159
160 Pushing comments to remote systems
161@@ -560,11 +560,11 @@
162 alias: bug-two
163 assigned_to: marvin@heartofgold.ship
164 component: Crew
165- creation_time: 20080611T09:23:12
166+ creation_time: 2008-06-11 09:23:12
167 id: 2
168 internals:...
169 is_open: True
170- last_change_time: 20080611T09:24:29
171+ last_change_time: 2008-06-11 09:24:29
172 priority: P1
173 product: HeartOfGold
174 resolution:
175
176=== modified file 'lib/lp/bugs/externalbugtracker/bugzilla.py'
177--- lib/lp/bugs/externalbugtracker/bugzilla.py 2009-12-22 21:08:42 +0000
178+++ lib/lp/bugs/externalbugtracker/bugzilla.py 2009-12-23 10:21:32 +0000
179@@ -12,11 +12,9 @@
180 ]
181
182 import pytz
183-import time
184 import xml.parsers.expat
185 import xmlrpclib
186
187-from datetime import datetime
188 from email.Utils import parseaddr
189 from xml.dom import minidom
190
191@@ -505,28 +503,17 @@
192 """See `IExternalBugTracker`."""
193 time_dict = self.xmlrpc_proxy.Bugzilla.time()
194
195- # Convert the XML-RPC DateTime we get back into a regular Python
196- # datetime.
197- server_db_timetuple = time.strptime(
198- str(time_dict['db_time']), '%Y%m%dT%H:%M:%S')
199- server_db_datetime = datetime(*server_db_timetuple[:6])
200-
201 # The server's DB time is the one that we want to use. However,
202 # this may not be in UTC, so we need to convert it. Since we
203 # can't guarantee that the timezone data returned by the server
204 # is sane, we work out the server's offset from UTC by looking
205 # at the difference between the web_time and the web_time_utc
206 # values.
207- server_web_time = time.strptime(
208- str(time_dict['web_time']), '%Y%m%dT%H:%M:%S')
209- server_web_datetime = datetime(*server_web_time[:6])
210- server_web_time_utc = time.strptime(
211- str(time_dict['web_time_utc']), '%Y%m%dT%H:%M:%S')
212- server_web_datetime_utc = datetime(*server_web_time_utc[:6])
213-
214+ server_web_datetime = time_dict['web_time']
215+ server_web_datetime_utc = time_dict['web_time_utc']
216 server_utc_offset = server_web_datetime - server_web_datetime_utc
217+ server_db_datetime = time_dict['db_time']
218 server_utc_datetime = server_db_datetime - server_utc_offset
219-
220 return server_utc_datetime.replace(tzinfo=pytz.timezone('UTC'))
221
222 def _getActualBugId(self, bug_id):
223@@ -715,22 +702,9 @@
224 # bug 248938).
225 comment_id = int(comment_id)
226 comment = self._bugs[actual_bug_id]['comments'][comment_id]
227-
228- # Turn the time in the comment, which is an XML-RPC datetime
229- # into something more useful to us.
230- # XXX 2008-08-05 gmb (bug 254999):
231- # We can remove these lines once we upgrade to python 2.5.
232- comment_timestamp = time.mktime(
233- time.strptime(str(comment['time']), '%Y%m%dT%H:%M:%S'))
234- comment_datetime = datetime.fromtimestamp(comment_timestamp)
235- comment_datetime = comment_datetime.replace(
236- tzinfo=pytz.timezone('UTC'))
237-
238- message = getUtility(IMessageSet).fromText(
239+ return getUtility(IMessageSet).fromText(
240 owner=poster, subject='', content=comment['text'],
241- datecreated=comment_datetime)
242-
243- return message
244+ datecreated=comment['time'].replace(tzinfo=pytz.timezone('UTC')))
245
246 @needs_authentication
247 def addRemoteComment(self, remote_bug, comment_body, rfc822msgid):
248@@ -868,10 +842,7 @@
249
250 # Return the UTC time sent by the server so that we don't have
251 # to care about timezones.
252- server_timetuple = time.strptime(
253- str(time_dict['utc_time']), '%Y%m%dT%H:%M:%S')
254-
255- server_utc_time = datetime(*server_timetuple[:6])
256+ server_utc_time = time_dict['utc_time']
257 return server_utc_time.replace(tzinfo=pytz.timezone('UTC'))
258
259 def getCommentIds(self, bug_watch):
260
261=== modified file 'lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt'
262--- lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt 2009-11-30 09:33:24 +0000
263+++ lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt 2009-12-23 10:53:40 +0000
264@@ -66,12 +66,12 @@
265 >>> time_dict = server.Bugzilla.time()
266 >>> for key in sorted(time_dict):
267 ... print "%s: %s" % (key, time_dict[key])
268- db_time: 20080501T01:01:01
269+ db_time: 2008-05-01 01:01:01
270 tz_name: UTC
271 tz_offset: +0000
272 tz_short_name: UTC
273- web_time: 20080501T01:01:01
274- web_time_utc: 20080501T01:01:01
275+ web_time: 2008-05-01 01:01:01
276+ web_time_utc: 2008-05-01 01:01:01
277
278 If the remote server is in a different timezone, the db_time and
279 web_time items will be in the server's local timezone whilst
280@@ -82,12 +82,12 @@
281 >>> time_dict = server.Bugzilla.time()
282 >>> for key in sorted(time_dict):
283 ... print "%s: %s" % (key, time_dict[key])
284- db_time: 20080501T01:01:01
285+ db_time: 2008-05-01 01:01:01
286 tz_name: CET
287 tz_offset: +0100
288 tz_short_name: CET
289- web_time: 20080501T01:01:01
290- web_time_utc: 20080501T00:01:01
291+ web_time: 2008-05-01 01:01:01
292+ web_time_utc: 2008-05-01 00:01:01
293
294
295 Getting bugs from the server
296@@ -105,11 +105,11 @@
297 alias:
298 assigned_to: test@canonical.com
299 component: GPPSystems
300- creation_time: 20080610T16:19:53
301+ creation_time: 2008-06-10 16:19:53
302 id: 1
303 internals:...
304 is_open: True
305- last_change_time: 20080610T16:19:53
306+ last_change_time: 2008-06-10 16:19:53
307 priority: P1
308 product: Marvin
309 resolution: FIXED
310@@ -135,16 +135,7 @@
311 date / time.
312
313 >>> from datetime import datetime
314- >>> from xmlrpclib import DateTime
315 >>> last_change_time = datetime(2008, 6, 11, 9, 0, 0)
316-
317- # XXX 2009-08-21 gmb (bug 254999):
318- # We can remove this once we upgrade to python 2.5. We encode
319- # last_change_time into an XML-RPC DateTime manually. This is
320- # because xmlrpclib can't handle DateTime encoding within a
321- # dict.
322- >>> last_change_time = DateTime(last_change_time.timetuple())
323-
324 >>> return_value = server.Bug.search({
325 ... 'last_change_time': last_change_time,
326 ... })
327@@ -158,11 +149,11 @@
328 alias: bug-two
329 assigned_to: marvin@heartofgold.ship
330 component: Crew
331- creation_time: 20080611T09:23:12
332+ creation_time: 2008-06-11 09:23:12
333 id: 2
334 internals:...
335 is_open: True
336- last_change_time: 20080611T09:24:29
337+ last_change_time: 2008-06-11 09:24:29
338 priority: P1
339 product: HeartOfGold
340 resolution:
341@@ -175,7 +166,6 @@
342 results to those IDs.
343
344 >>> last_change_time = datetime(2007, 6, 10, 1, 1, 1)
345- >>> last_change_time = DateTime(last_change_time.timetuple())
346 >>> return_value = server.Bug.search({
347 ... 'id': [1],
348 ... 'last_change_time': last_change_time,
349@@ -188,11 +178,11 @@
350 alias:
351 assigned_to: test@canonical.com
352 component: GPPSystems
353- creation_time: 20080610T16:19:53
354+ creation_time: 2008-06-10 16:19:53
355 id: 1
356 internals:...
357 is_open: True
358- last_change_time: 20080610T16:19:53
359+ last_change_time: 2008-06-10 16:19:53
360 priority: P1
361 product: Marvin
362 resolution: FIXED
363@@ -206,11 +196,6 @@
364
365 >>> from datetime import timedelta
366 >>> last_change_time = datetime.now() + timedelta(days=42)
367-
368- >>> # XXX 2008-08-05 gmb (bug 254999):
369- >>> # We can remove this once we upgrade to python 2.5.
370- >>> last_change_time = DateTime(last_change_time.timetuple())
371-
372 >>> return_value = server.Bug.search({
373 ... 'last_change_time': last_change_time,
374 ... })
375@@ -232,11 +217,11 @@
376 alias: bug-two
377 assigned_to: marvin@heartofgold.ship
378 component: Crew
379- creation_time: 20080611T09:23:12
380+ creation_time: 2008-06-11 09:23:12
381 id: 2
382 internals:...
383 is_open: True
384- last_change_time: 20080611T09:24:29
385+ last_change_time: 2008-06-11 09:24:29
386 priority: P1
387 product: HeartOfGold
388 resolution:
389@@ -257,11 +242,11 @@
390 alias:
391 assigned_to: test@canonical.com
392 component: GPPSystems
393- creation_time: 20080610T16:19:53
394+ creation_time: 2008-06-10 16:19:53
395 id: 1
396 internals:...
397 is_open: True
398- last_change_time: 20080610T16:19:53
399+ last_change_time: 2008-06-10 16:19:53
400 priority: P1
401 product: Marvin
402 resolution: FIXED
403@@ -272,11 +257,11 @@
404 alias: bug-two
405 assigned_to: marvin@heartofgold.ship
406 component: Crew
407- creation_time: 20080611T09:23:12
408+ creation_time: 2008-06-11 09:23:12
409 id: 2
410 internals:...
411 is_open: True
412- last_change_time: 20080611T09:24:29
413+ last_change_time: 2008-06-11 09:24:29
414 priority: P1
415 product: HeartOfGold
416 resolution:
417@@ -321,14 +306,14 @@
418 id: 1
419 is_private: False
420 text: I'd really appreciate it if Marvin would enjoy life a bit.
421- time: 20080616T12:44:29
422+ time: 2008-06-16 12:44:29
423 <BLANKLINE>
424 author: marvin
425 bug_id: 1
426 id: 3
427 is_private: False
428 text: Life? Don't talk to me about life.
429- time: 20080616T13:22:29
430+ time: 2008-06-16 13:22:29
431 <BLANKLINE>
432 <BLANKLINE>
433 Bug 2:
434@@ -337,14 +322,14 @@
435 id: 2
436 is_private: False
437 text: Bring the passengers to the bridge please Marvin.
438- time: 20080616T13:08:08
439+ time: 2008-06-16 13:08:08
440 <BLANKLINE>
441 author: Ford Prefect <ford.prefect@h2g2.com>
442 bug_id: 2
443 id: 4
444 is_private: False
445 text: I appear to have become a perfectly safe penguin.
446- time: 20080617T20:28:40
447+ time: 2008-06-17 20:28:40
448 <BLANKLINE>
449 <BLANKLINE>
450
451@@ -366,14 +351,14 @@
452 id: 1
453 is_private: False
454 text: I'd really appreciate it if Marvin would enjoy life a bit.
455- time: 20080616T12:44:29
456+ time: 2008-06-16 12:44:29
457 Comment 4:
458 author: Ford Prefect <ford.prefect@h2g2.com>
459 bug_id: 2
460 id: 4
461 is_private: False
462 text: I appear to have become a perfectly safe penguin.
463- time: 20080617T20:28:40
464+ time: 2008-06-17 20:28:40
465 <BLANKLINE>
466
467 Note that only comments have been returned when only 'comment_ids' have
468@@ -499,11 +484,11 @@
469 alias:
470 assigned_to: test@canonical.com
471 component: GPPSystems
472- creation_time: 20080610T16:19:53
473+ creation_time: 2008-06-10 16:19:53
474 id: 1
475 internals:...
476 is_open: True
477- last_change_time: 20080610T16:19:53
478+ last_change_time: 2008-06-10 16:19:53
479 priority: P1
480 product: Marvin
481 resolution: FIXED
482
483=== modified file 'lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt'
484--- lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt 2009-12-11 16:05:52 +0000
485+++ lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt 2009-12-23 10:38:25 +0000
486@@ -105,9 +105,9 @@
487 >>> time_dict = server.Launchpad.time()
488 >>> for key in sorted(time_dict):
489 ... print "%s: %s" % (key, time_dict[key])
490- local_time: 20080501T01:01:01
491+ local_time: 2008-05-01 01:01:01
492 tz_name: UTC
493- utc_time: 20080501T01:01:01
494+ utc_time: 2008-05-01 01:01:01
495
496 We can set the local time value on the remote server to make testing
497 more useful.
498@@ -122,9 +122,9 @@
499 >>> time_dict = server.Launchpad.time()
500 >>> for key in sorted(time_dict):
501 ... print "%s: %s" % (key, time_dict[key])
502- local_time: 20080515T16:19:53
503+ local_time: 2008-05-15 16:19:53
504 tz_name: US/Central
505- utc_time: 20080515T22:19:53
506+ utc_time: 2008-05-15 22:19:53
507
508
509 Launchpad.get_bugs()
510@@ -144,11 +144,11 @@
511 alias:
512 assigned_to: test@canonical.com
513 component: GPPSystems
514- creation_time: 20080610T16:19:53
515+ creation_time: 2008-06-10 16:19:53
516 id: 1
517 internals:...
518 is_open: True
519- last_change_time: 20080610T16:19:53
520+ last_change_time: 2008-06-10 16:19:53
521 priority: P1
522 product: Marvin
523 resolution: FIXED
524@@ -170,11 +170,11 @@
525 alias:
526 assigned_to: test@canonical.com
527 component: GPPSystems
528- creation_time: 20080610T16:19:53
529+ creation_time: 2008-06-10 16:19:53
530 id: 1
531 internals:...
532 is_open: True
533- last_change_time: 20080610T16:19:53
534+ last_change_time: 2008-06-10 16:19:53
535 priority: P1
536 product: Marvin
537 resolution: FIXED
538@@ -186,11 +186,11 @@
539 alias: bug-two
540 assigned_to: marvin@heartofgold.ship
541 component: Crew
542- creation_time: 20080611T09:23:12
543+ creation_time: 2008-06-11 09:23:12
544 id: 2
545 internals:...
546 is_open: True
547- last_change_time: 20080611T09:24:29
548+ last_change_time: 2008-06-11 09:24:29
549 priority: P1
550 product: HeartOfGold
551 resolution:
552@@ -209,11 +209,11 @@
553 alias: bug-two
554 assigned_to: marvin@heartofgold.ship
555 component: Crew
556- creation_time: 20080611T09:23:12
557+ creation_time: 2008-06-11 09:23:12
558 id: 2
559 internals:...
560 is_open: True
561- last_change_time: 20080611T09:24:29
562+ last_change_time: 2008-06-11 09:24:29
563 priority: P1
564 product: HeartOfGold
565 resolution:
566@@ -228,17 +228,8 @@
567 allowing Launchpad to get only the recently-updated subset of a given
568 set of remote bugs.
569
570- >>> from xmlrpclib import DateTime
571-
572 >>> changed_since = datetime(2008, 6, 11, 9, 0, 0)
573
574- >>> # We encode changed_since into an XML-RPC DateTime manually.
575- >>> # This is because xmlrpclib can't handle DateTime encoding
576- >>> # within a dict.
577- >>> # XXX 2008-08-05 gmb (bug 254999):
578- >>> # We can remove this once we upgrade to python 2.5.
579- >>> changed_since = DateTime(changed_since.timetuple())
580-
581 >>> return_value = server.Launchpad.get_bugs({
582 ... 'ids': [1, 2],
583 ... 'changed_since': changed_since,
584@@ -254,11 +245,11 @@
585 alias: bug-two
586 assigned_to: marvin@heartofgold.ship
587 component: Crew
588- creation_time: 20080611T09:23:12
589+ creation_time: 2008-06-11 09:23:12
590 id: 2
591 internals:...
592 is_open: True
593- last_change_time: 20080611T09:24:29
594+ last_change_time: 2008-06-11 09:24:29
595 priority: P1
596 product: HeartOfGold
597 resolution:
598@@ -273,10 +264,6 @@
599 >>> from datetime import timedelta
600 >>> changed_since = datetime.now() + timedelta(days=42)
601
602- >>> # XXX 2008-08-05 gmb (bug 254999):
603- >>> # We can remove this once we upgrade to python 2.5.
604- >>> changed_since = DateTime(changed_since.timetuple())
605-
606 >>> return_value = server.Launchpad.get_bugs({
607 ... 'ids': [1, 2],
608 ... 'changed_since': changed_since,
609@@ -304,11 +291,11 @@
610 alias: bug-two
611 assigned_to: marvin@heartofgold.ship
612 component: Crew
613- creation_time: 20080611T09:23:12
614+ creation_time: 2008-06-11 09:23:12
615 id: 2
616 internals:...
617 is_open: True
618- last_change_time: 20080611T09:24:29
619+ last_change_time: 2008-06-11 09:24:29
620 priority: P1
621 product: HeartOfGold
622 resolution:
623@@ -366,13 +353,13 @@
624 id: 1
625 number: 1
626 text: I'd really appreciate it if Marvin would enjoy life a bit.
627- time: 20080616T12:44:29
628+ time: 2008-06-16 12:44:29
629 <BLANKLINE>
630 author: marvin
631 id: 3
632 number: 2
633 text: Life? Don't talk to me about life.
634- time: 20080616T13:22:29
635+ time: 2008-06-16 13:22:29
636 <BLANKLINE>
637 <BLANKLINE>
638 Bug 2:
639@@ -380,13 +367,13 @@
640 id: 2
641 number: 1
642 text: Bring the passengers to the bridge please Marvin.
643- time: 20080616T13:08:08
644+ time: 2008-06-16 13:08:08
645 <BLANKLINE>
646 author: Ford Prefect <ford.prefect@h2g2.com>
647 id: 4
648 number: 2
649 text: I appear to have become a perfectly safe penguin.
650- time: 20080617T20:28:40
651+ time: 2008-06-17 20:28:40
652
653 If an ids parameter is specified along with bug_ids, only the comments
654 whose IDs are in the list of IDs passed will be returned.
655@@ -401,7 +388,7 @@
656 id: 1
657 number: 1
658 text: I'd really appreciate it if Marvin would enjoy life a bit.
659- time: 20080616T12:44:29
660+ time: 2008-06-16 12:44:29
661 <BLANKLINE>
662 <BLANKLINE>
663 Bug 2:
664@@ -409,7 +396,7 @@
665 id: 2
666 number: 1
667 text: Bring the passengers to the bridge please Marvin.
668- time: 20080616T13:08:08
669+ time: 2008-06-16 13:08:08
670
671 Passing an include_fields parameter allows us to limit which fields are
672 returned for each comment.
673
674=== modified file 'lib/lp/bugs/tests/externalbugtracker.py'
675--- lib/lp/bugs/tests/externalbugtracker.py 2009-12-18 17:40:01 +0000
676+++ lib/lp/bugs/tests/externalbugtracker.py 2009-12-23 12:09:36 +0000
677@@ -526,17 +526,12 @@
678 if local_datetime is None:
679 local_datetime = datetime(2008, 5, 1, 1, 1, 1)
680
681- # We return xmlrpc dateTimes rather than doubles since that's
682- # what BugZilla will return.
683- local_time = xmlrpclib.DateTime(local_datetime.timetuple())
684-
685 utc_offset_delta = timedelta(seconds=self.utc_offset)
686 utc_date_time = local_datetime - utc_offset_delta
687
688- utc_time = xmlrpclib.DateTime(utc_date_time.timetuple())
689 return {
690- 'local_time': local_time,
691- 'utc_time': utc_time,
692+ 'local_time': local_datetime,
693+ 'utc_time': utc_date_time,
694 'tz_name': self.timezone,
695 }
696
697@@ -599,14 +594,14 @@
698 assert permissive, "get_bugs() must be called with permissive=True"
699
700 # If a changed_since argument is specified, marshall it into a
701- # datetime so that we can use it for comparisons.
702- # XXX 2008-08-05 gmb (bug 254999):
703- # We can remove these lines once we upgrade to python 2.5.
704+ # datetime so that we can use it for comparisons. Even though
705+ # xmlrpclib in Python 2.5 groks datetime, by the time this
706+ # method is called xmlrpclib has already converted all
707+ # datetimes to xmlrpclib.DateTime.
708 changed_since = arguments.get('changed_since')
709 if changed_since is not None:
710- changed_since_timetuple = time.strptime(
711- str(changed_since), '%Y%m%dT%H:%M:%S')
712- changed_since = datetime(*changed_since_timetuple[:6])
713+ changed_since = datetime.strptime(
714+ changed_since.value, '%Y%m%dT%H:%M:%S')
715
716 # If we have some products but no bug_ids we just get all the
717 # bug IDs for those products and stuff them in the bug_ids list
718@@ -642,14 +637,6 @@
719 bug_dict['product'] not in products):
720 continue
721
722- # Update the DateTime fields of the bug dict so that they
723- # look like ones that would be sent over XML-RPC.
724- for time_field in ('creation_time', 'last_change_time'):
725- datetime_value = bug_dict[time_field]
726- timestamp = time.mktime(datetime_value.timetuple())
727- xmlrpc_datetime = xmlrpclib.DateTime(timestamp)
728- bug_dict[time_field] = xmlrpc_datetime
729-
730 bugs_to_return.append(bug_dict)
731
732 # "Why are you returning a list here?" I hear you cry. Well,
733@@ -660,15 +647,9 @@
734
735 def _copy_comment(self, comment, fields_to_return=None):
736 # Copy wanted fields.
737- comment = dict(
738+ return dict(
739 (key, value) for (key, value) in comment.iteritems()
740 if fields_to_return is None or key in fields_to_return)
741- # Replace the time field with an XML-RPC DateTime.
742- if 'time' in comment:
743- comment['time'] = xmlrpclib.DateTime(
744- comment['time'].timetuple())
745- return comment
746-
747
748 def comments(self, arguments):
749 """Return comments for a given set of bugs."""
Revision history for this message
Brad Crittenden (bac) wrote :

Thanks for the additional changes Gavin. It looks good now.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt'
2--- lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt 2009-12-21 15:03:42 +0000
3+++ lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt 2009-12-23 12:17:18 +0000
4@@ -139,8 +139,8 @@
5 >>> def print_bugs(bugs):
6 ... for bug in sorted(bugs):
7 ... print "Bug %s:" % bug
8- ... for key in sorted(bugzilla._bugs[bug]):
9- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
10+ ... for key in sorted(bugs[bug]):
11+ ... print " %s: %s" % (key, bugs[bug][key])
12 ... print "\n"
13
14 >>> print_bugs(bugzilla._bugs)
15@@ -148,11 +148,11 @@
16 alias:
17 assigned_to: test@canonical.com
18 component: GPPSystems
19- creation_time: 20080610T16:19:53
20+ creation_time: 2008-06-10 16:19:53
21 id: 1
22 internals:...
23 is_open: True
24- last_change_time: 20080610T16:19:53
25+ last_change_time: 2008-06-10 16:19:53
26 priority: P1
27 product: Marvin
28 resolution: FIXED
29@@ -165,11 +165,11 @@
30 alias: bug-two
31 assigned_to: marvin@heartofgold.ship
32 component: Crew
33- creation_time: 20080611T09:23:12
34+ creation_time: 2008-06-11 09:23:12
35 id: 2
36 internals:...
37 is_open: True
38- last_change_time: 20080611T09:24:29
39+ last_change_time: 2008-06-11 09:24:29
40 priority: P1
41 product: HeartOfGold
42 resolution:
43@@ -194,20 +194,16 @@
44 >>> bugzilla.initializeRemoteBugDB([2, 'bug-two'])
45 CALLED Bug.get({'ids': [2, 'bug-two'], 'permissive': True})
46
47- >>> for bug in sorted(bugzilla._bugs):
48- ... print "Bug %r:" % bug
49- ... for key in sorted(bugzilla._bugs[bug]):
50- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
51- ... print "\n"
52+ >>> print_bugs(bugzilla._bugs)
53 Bug 2:
54 alias: bug-two
55 assigned_to: marvin@heartofgold.ship
56 component: Crew
57- creation_time: 20080611T09:23:12
58+ creation_time: 2008-06-11 09:23:12
59 id: 2
60 internals:...
61 is_open: True
62- last_change_time: 20080611T09:24:29
63+ last_change_time: 2008-06-11 09:24:29
64 priority: P1
65 product: HeartOfGold
66 resolution:
67@@ -450,14 +446,14 @@
68 id: 1
69 is_private: False
70 text: I'd really appreciate it if Marvin would enjoy life a bit.
71- time: 20080616T12:44:29
72+ time: 2008-06-16 12:44:29
73 Comment 3:
74 author: marvin
75 bug_id: 1
76 id: 3
77 is_private: False
78 text: Life? Don't talk to me about life.
79- time: 20080616T13:22:29
80+ time: 2008-06-16 13:22:29
81
82 If we try to fetch comments that don't belong to the current bug
83 fetchComments() will silently ignore them.
84@@ -477,7 +473,7 @@
85 id: 1
86 is_private: False
87 text: I'd really appreciate it if Marvin would enjoy life a bit.
88- time: 20080616T12:44:29
89+ time: 2008-06-16 12:44:29
90
91
92 getPosterForComment()
93@@ -521,7 +517,7 @@
94 field on the imported comment.
95
96 >>> print bugzilla._bugs[2]['comments'][2]['time']
97- 20080616T13:08:08
98+ 2008-06-16 13:08:08
99
100 >>> print message.datecreated
101 2008-06-16 13:08:08+00:00
102
103=== modified file 'lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt'
104--- lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt 2009-12-21 15:03:42 +0000
105+++ lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt 2009-12-23 12:17:18 +0000
106@@ -204,8 +204,8 @@
107 >>> def print_bugs(bugs):
108 ... for bug in sorted(bugs):
109 ... print "Bug %s:" % bug
110- ... for key in sorted(bugzilla._bugs[bug]):
111- ... print " %s: %s" % (key, bugzilla._bugs[bug][key])
112+ ... for key in sorted(bugs[bug]):
113+ ... print " %s: %s" % (key, bugs[bug][key])
114 ... print "\n"
115
116 >>> print_bugs(bugzilla._bugs)
117@@ -213,11 +213,11 @@
118 alias:
119 assigned_to: test@canonical.com
120 component: GPPSystems
121- creation_time: 20080610T16:19:53
122+ creation_time: 2008-06-10 16:19:53
123 id: 1
124 internals:...
125 is_open: True
126- last_change_time: 20080610T16:19:53
127+ last_change_time: 2008-06-10 16:19:53
128 priority: P1
129 product: Marvin
130 resolution: FIXED
131@@ -230,11 +230,11 @@
132 alias: bug-two
133 assigned_to: marvin@heartofgold.ship
134 component: Crew
135- creation_time: 20080611T09:23:12
136+ creation_time: 2008-06-11 09:23:12
137 id: 2
138 internals:...
139 is_open: True
140- last_change_time: 20080611T09:24:29
141+ last_change_time: 2008-06-11 09:24:29
142 priority: P1
143 product: HeartOfGold
144 resolution:
145@@ -416,13 +416,13 @@
146 id: 1
147 number: 1
148 text: I'd really appreciate it if Marvin would enjoy life a bit.
149- time: 20080616T12:44:29
150+ time: 2008-06-16 12:44:29
151 Comment 3:
152 author: marvin
153 id: 3
154 number: 2
155 text: Life? Don't talk to me about life.
156- time: 20080616T13:22:29
157+ time: 2008-06-16 13:22:29
158
159
160 Pushing comments to remote systems
161@@ -560,11 +560,11 @@
162 alias: bug-two
163 assigned_to: marvin@heartofgold.ship
164 component: Crew
165- creation_time: 20080611T09:23:12
166+ creation_time: 2008-06-11 09:23:12
167 id: 2
168 internals:...
169 is_open: True
170- last_change_time: 20080611T09:24:29
171+ last_change_time: 2008-06-11 09:24:29
172 priority: P1
173 product: HeartOfGold
174 resolution:
175
176=== modified file 'lib/lp/bugs/externalbugtracker/bugzilla.py'
177--- lib/lp/bugs/externalbugtracker/bugzilla.py 2009-12-21 14:46:05 +0000
178+++ lib/lp/bugs/externalbugtracker/bugzilla.py 2009-12-23 12:17:18 +0000
179@@ -12,11 +12,9 @@
180 ]
181
182 import pytz
183-import time
184 import xml.parsers.expat
185 import xmlrpclib
186
187-from datetime import datetime
188 from email.Utils import parseaddr
189 from xml.dom import minidom
190
191@@ -505,28 +503,17 @@
192 """See `IExternalBugTracker`."""
193 time_dict = self.xmlrpc_proxy.Bugzilla.time()
194
195- # Convert the XML-RPC DateTime we get back into a regular Python
196- # datetime.
197- server_db_timetuple = time.strptime(
198- str(time_dict['db_time']), '%Y%m%dT%H:%M:%S')
199- server_db_datetime = datetime(*server_db_timetuple[:6])
200-
201 # The server's DB time is the one that we want to use. However,
202 # this may not be in UTC, so we need to convert it. Since we
203 # can't guarantee that the timezone data returned by the server
204 # is sane, we work out the server's offset from UTC by looking
205 # at the difference between the web_time and the web_time_utc
206 # values.
207- server_web_time = time.strptime(
208- str(time_dict['web_time']), '%Y%m%dT%H:%M:%S')
209- server_web_datetime = datetime(*server_web_time[:6])
210- server_web_time_utc = time.strptime(
211- str(time_dict['web_time_utc']), '%Y%m%dT%H:%M:%S')
212- server_web_datetime_utc = datetime(*server_web_time_utc[:6])
213-
214+ server_web_datetime = time_dict['web_time']
215+ server_web_datetime_utc = time_dict['web_time_utc']
216 server_utc_offset = server_web_datetime - server_web_datetime_utc
217+ server_db_datetime = time_dict['db_time']
218 server_utc_datetime = server_db_datetime - server_utc_offset
219-
220 return server_utc_datetime.replace(tzinfo=pytz.timezone('UTC'))
221
222 def _getActualBugId(self, bug_id):
223@@ -558,7 +545,7 @@
224 bug_ids_to_retrieve = []
225 for bug_id in bug_ids:
226 try:
227- actual_bug_id = self._getActualBugId(bug_id)
228+ self._getActualBugId(bug_id)
229 except BugNotFound:
230 bug_ids_to_retrieve.append(bug_id)
231
232@@ -590,7 +577,7 @@
233 try:
234 status = self._bugs[actual_bug_id]['status']
235 resolution = self._bugs[actual_bug_id]['resolution']
236- except KeyError, error:
237+ except KeyError:
238 raise UnparseableBugData
239
240 if resolution != '':
241@@ -600,27 +587,14 @@
242
243 def getModifiedRemoteBugs(self, bug_ids, last_checked):
244 """See `IExternalBugTracker`."""
245- # We marshal last_checked into an xmlrpclib.DateTime since
246- # xmlrpclib can't do so cleanly itself.
247- # XXX 2009-08-21 gmb (bug 254999):
248- # We can remove this once we upgrade to python 2.5.
249- changed_since = xmlrpclib.DateTime(last_checked.timetuple())
250-
251- search_args = {
252- 'id': bug_ids,
253- 'last_change_time': changed_since,
254- }
255- response_dict = self.xmlrpc_proxy.Bug.search(search_args)
256+ response_dict = self.xmlrpc_proxy.Bug.search(
257+ {'id': bug_ids, 'last_change_time': last_checked})
258 remote_bugs = response_dict['bugs']
259-
260 # Store the bugs we've imported and return only their IDs.
261 self._storeBugs(remote_bugs)
262-
263 # Marshal the bug IDs into strings before returning them since
264 # the remote Bugzilla may return ints rather than strings.
265- bug_ids = [str(remote_bug['id']) for remote_bug in remote_bugs]
266-
267- return bug_ids
268+ return [str(remote_bug['id']) for remote_bug in remote_bugs]
269
270 def getRemoteProduct(self, remote_bug):
271 """See `IExternalBugTracker`."""
272@@ -728,22 +702,9 @@
273 # bug 248938).
274 comment_id = int(comment_id)
275 comment = self._bugs[actual_bug_id]['comments'][comment_id]
276-
277- # Turn the time in the comment, which is an XML-RPC datetime
278- # into something more useful to us.
279- # XXX 2008-08-05 gmb (bug 254999):
280- # We can remove these lines once we upgrade to python 2.5.
281- comment_timestamp = time.mktime(
282- time.strptime(str(comment['time']), '%Y%m%dT%H:%M:%S'))
283- comment_datetime = datetime.fromtimestamp(comment_timestamp)
284- comment_datetime = comment_datetime.replace(
285- tzinfo=pytz.timezone('UTC'))
286-
287- message = getUtility(IMessageSet).fromText(
288+ return getUtility(IMessageSet).fromText(
289 owner=poster, subject='', content=comment['text'],
290- datecreated=comment_datetime)
291-
292- return message
293+ datecreated=comment['time'].replace(tzinfo=pytz.timezone('UTC')))
294
295 @needs_authentication
296 def addRemoteComment(self, remote_bug, comment_body, rfc822msgid):
297@@ -826,7 +787,7 @@
298 token_text = internal_xmlrpc_server.newBugTrackerToken()
299
300 try:
301- user_id = self.xmlrpc_proxy.Launchpad.login(
302+ self.xmlrpc_proxy.Launchpad.login(
303 {'token': token_text})
304 except xmlrpclib.Fault, fault:
305 message = 'XML-RPC Fault: %s "%s"' % (
306@@ -841,28 +802,17 @@
307
308 def getModifiedRemoteBugs(self, bug_ids, last_checked):
309 """See `IExternalBugTracker`."""
310- # We marshal last_checked into an xmlrpclib.DateTime since
311- # xmlrpclib can't do so cleanly itself.
312- # XXX 2008-08-05 gmb (bug 254999):
313- # We can remove this once we upgrade to python 2.5.
314- changed_since = xmlrpclib.DateTime(last_checked.timetuple())
315-
316- # Create the arguments that we're going to send to the remote
317- # server. We pass permissive=True to ensure that Bugzilla won't
318- # error if we ask for a bug that doesn't exist.
319- request_args = {
320+ # We pass permissive=True to ensure that Bugzilla won't error
321+ # if we ask for a bug that doesn't exist.
322+ response_dict = self.xmlrpc_proxy.Launchpad.get_bugs({
323 'ids': bug_ids,
324- 'changed_since': changed_since,
325+ 'changed_since': last_checked,
326 'permissive': True,
327- }
328- response_dict = self.xmlrpc_proxy.Launchpad.get_bugs(request_args)
329+ })
330 remote_bugs = response_dict['bugs']
331-
332 # Store the bugs we've imported and return only their IDs.
333 self._storeBugs(remote_bugs)
334- bug_ids = [remote_bug['id'] for remote_bug in remote_bugs]
335-
336- return bug_ids
337+ return [remote_bug['id'] for remote_bug in remote_bugs]
338
339 def initializeRemoteBugDB(self, bug_ids, products=None):
340 """See `IExternalBugTracker`."""
341@@ -892,10 +842,7 @@
342
343 # Return the UTC time sent by the server so that we don't have
344 # to care about timezones.
345- server_timetuple = time.strptime(
346- str(time_dict['utc_time']), '%Y%m%dT%H:%M:%S')
347-
348- server_utc_time = datetime(*server_timetuple[:6])
349+ server_utc_time = time_dict['utc_time']
350 return server_utc_time.replace(tzinfo=pytz.timezone('UTC'))
351
352 def getCommentIds(self, bug_watch):
353
354=== modified file 'lib/lp/bugs/externalbugtracker/xmlrpc.py'
355--- lib/lp/bugs/externalbugtracker/xmlrpc.py 2009-10-16 22:00:45 +0000
356+++ lib/lp/bugs/externalbugtracker/xmlrpc.py 2009-12-23 12:17:18 +0000
357@@ -64,10 +64,9 @@
358 verbose = False
359
360 def __init__(self, endpoint, cookie_jar=None):
361- Transport.__init__(self)
362+ Transport.__init__(self, use_datetime=True)
363 self.scheme, self.host = urlparse(endpoint)[:2]
364- assert (
365- self.scheme in ('http', 'https'),
366+ assert self.scheme in ('http', 'https'), (
367 "Unsupported URL scheme: %s" % self.scheme)
368 self.cookie_processor = HTTPCookieProcessor(cookie_jar)
369 self.redirect_handler = XMLRPCRedirectHandler()
370
371=== modified file 'lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt'
372--- lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt 2009-11-30 09:33:24 +0000
373+++ lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt 2009-12-23 12:17:18 +0000
374@@ -66,12 +66,12 @@
375 >>> time_dict = server.Bugzilla.time()
376 >>> for key in sorted(time_dict):
377 ... print "%s: %s" % (key, time_dict[key])
378- db_time: 20080501T01:01:01
379+ db_time: 2008-05-01 01:01:01
380 tz_name: UTC
381 tz_offset: +0000
382 tz_short_name: UTC
383- web_time: 20080501T01:01:01
384- web_time_utc: 20080501T01:01:01
385+ web_time: 2008-05-01 01:01:01
386+ web_time_utc: 2008-05-01 01:01:01
387
388 If the remote server is in a different timezone, the db_time and
389 web_time items will be in the server's local timezone whilst
390@@ -82,12 +82,12 @@
391 >>> time_dict = server.Bugzilla.time()
392 >>> for key in sorted(time_dict):
393 ... print "%s: %s" % (key, time_dict[key])
394- db_time: 20080501T01:01:01
395+ db_time: 2008-05-01 01:01:01
396 tz_name: CET
397 tz_offset: +0100
398 tz_short_name: CET
399- web_time: 20080501T01:01:01
400- web_time_utc: 20080501T00:01:01
401+ web_time: 2008-05-01 01:01:01
402+ web_time_utc: 2008-05-01 00:01:01
403
404
405 Getting bugs from the server
406@@ -105,11 +105,11 @@
407 alias:
408 assigned_to: test@canonical.com
409 component: GPPSystems
410- creation_time: 20080610T16:19:53
411+ creation_time: 2008-06-10 16:19:53
412 id: 1
413 internals:...
414 is_open: True
415- last_change_time: 20080610T16:19:53
416+ last_change_time: 2008-06-10 16:19:53
417 priority: P1
418 product: Marvin
419 resolution: FIXED
420@@ -135,16 +135,7 @@
421 date / time.
422
423 >>> from datetime import datetime
424- >>> from xmlrpclib import DateTime
425 >>> last_change_time = datetime(2008, 6, 11, 9, 0, 0)
426-
427- # XXX 2009-08-21 gmb (bug 254999):
428- # We can remove this once we upgrade to python 2.5. We encode
429- # last_change_time into an XML-RPC DateTime manually. This is
430- # because xmlrpclib can't handle DateTime encoding within a
431- # dict.
432- >>> last_change_time = DateTime(last_change_time.timetuple())
433-
434 >>> return_value = server.Bug.search({
435 ... 'last_change_time': last_change_time,
436 ... })
437@@ -158,11 +149,11 @@
438 alias: bug-two
439 assigned_to: marvin@heartofgold.ship
440 component: Crew
441- creation_time: 20080611T09:23:12
442+ creation_time: 2008-06-11 09:23:12
443 id: 2
444 internals:...
445 is_open: True
446- last_change_time: 20080611T09:24:29
447+ last_change_time: 2008-06-11 09:24:29
448 priority: P1
449 product: HeartOfGold
450 resolution:
451@@ -175,7 +166,6 @@
452 results to those IDs.
453
454 >>> last_change_time = datetime(2007, 6, 10, 1, 1, 1)
455- >>> last_change_time = DateTime(last_change_time.timetuple())
456 >>> return_value = server.Bug.search({
457 ... 'id': [1],
458 ... 'last_change_time': last_change_time,
459@@ -188,11 +178,11 @@
460 alias:
461 assigned_to: test@canonical.com
462 component: GPPSystems
463- creation_time: 20080610T16:19:53
464+ creation_time: 2008-06-10 16:19:53
465 id: 1
466 internals:...
467 is_open: True
468- last_change_time: 20080610T16:19:53
469+ last_change_time: 2008-06-10 16:19:53
470 priority: P1
471 product: Marvin
472 resolution: FIXED
473@@ -206,11 +196,6 @@
474
475 >>> from datetime import timedelta
476 >>> last_change_time = datetime.now() + timedelta(days=42)
477-
478- >>> # XXX 2008-08-05 gmb (bug 254999):
479- >>> # We can remove this once we upgrade to python 2.5.
480- >>> last_change_time = DateTime(last_change_time.timetuple())
481-
482 >>> return_value = server.Bug.search({
483 ... 'last_change_time': last_change_time,
484 ... })
485@@ -232,11 +217,11 @@
486 alias: bug-two
487 assigned_to: marvin@heartofgold.ship
488 component: Crew
489- creation_time: 20080611T09:23:12
490+ creation_time: 2008-06-11 09:23:12
491 id: 2
492 internals:...
493 is_open: True
494- last_change_time: 20080611T09:24:29
495+ last_change_time: 2008-06-11 09:24:29
496 priority: P1
497 product: HeartOfGold
498 resolution:
499@@ -257,11 +242,11 @@
500 alias:
501 assigned_to: test@canonical.com
502 component: GPPSystems
503- creation_time: 20080610T16:19:53
504+ creation_time: 2008-06-10 16:19:53
505 id: 1
506 internals:...
507 is_open: True
508- last_change_time: 20080610T16:19:53
509+ last_change_time: 2008-06-10 16:19:53
510 priority: P1
511 product: Marvin
512 resolution: FIXED
513@@ -272,11 +257,11 @@
514 alias: bug-two
515 assigned_to: marvin@heartofgold.ship
516 component: Crew
517- creation_time: 20080611T09:23:12
518+ creation_time: 2008-06-11 09:23:12
519 id: 2
520 internals:...
521 is_open: True
522- last_change_time: 20080611T09:24:29
523+ last_change_time: 2008-06-11 09:24:29
524 priority: P1
525 product: HeartOfGold
526 resolution:
527@@ -321,14 +306,14 @@
528 id: 1
529 is_private: False
530 text: I'd really appreciate it if Marvin would enjoy life a bit.
531- time: 20080616T12:44:29
532+ time: 2008-06-16 12:44:29
533 <BLANKLINE>
534 author: marvin
535 bug_id: 1
536 id: 3
537 is_private: False
538 text: Life? Don't talk to me about life.
539- time: 20080616T13:22:29
540+ time: 2008-06-16 13:22:29
541 <BLANKLINE>
542 <BLANKLINE>
543 Bug 2:
544@@ -337,14 +322,14 @@
545 id: 2
546 is_private: False
547 text: Bring the passengers to the bridge please Marvin.
548- time: 20080616T13:08:08
549+ time: 2008-06-16 13:08:08
550 <BLANKLINE>
551 author: Ford Prefect <ford.prefect@h2g2.com>
552 bug_id: 2
553 id: 4
554 is_private: False
555 text: I appear to have become a perfectly safe penguin.
556- time: 20080617T20:28:40
557+ time: 2008-06-17 20:28:40
558 <BLANKLINE>
559 <BLANKLINE>
560
561@@ -366,14 +351,14 @@
562 id: 1
563 is_private: False
564 text: I'd really appreciate it if Marvin would enjoy life a bit.
565- time: 20080616T12:44:29
566+ time: 2008-06-16 12:44:29
567 Comment 4:
568 author: Ford Prefect <ford.prefect@h2g2.com>
569 bug_id: 2
570 id: 4
571 is_private: False
572 text: I appear to have become a perfectly safe penguin.
573- time: 20080617T20:28:40
574+ time: 2008-06-17 20:28:40
575 <BLANKLINE>
576
577 Note that only comments have been returned when only 'comment_ids' have
578@@ -499,11 +484,11 @@
579 alias:
580 assigned_to: test@canonical.com
581 component: GPPSystems
582- creation_time: 20080610T16:19:53
583+ creation_time: 2008-06-10 16:19:53
584 id: 1
585 internals:...
586 is_open: True
587- last_change_time: 20080610T16:19:53
588+ last_change_time: 2008-06-10 16:19:53
589 priority: P1
590 product: Marvin
591 resolution: FIXED
592
593=== modified file 'lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt'
594--- lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt 2009-12-11 16:05:52 +0000
595+++ lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt 2009-12-23 12:17:18 +0000
596@@ -105,9 +105,9 @@
597 >>> time_dict = server.Launchpad.time()
598 >>> for key in sorted(time_dict):
599 ... print "%s: %s" % (key, time_dict[key])
600- local_time: 20080501T01:01:01
601+ local_time: 2008-05-01 01:01:01
602 tz_name: UTC
603- utc_time: 20080501T01:01:01
604+ utc_time: 2008-05-01 01:01:01
605
606 We can set the local time value on the remote server to make testing
607 more useful.
608@@ -122,9 +122,9 @@
609 >>> time_dict = server.Launchpad.time()
610 >>> for key in sorted(time_dict):
611 ... print "%s: %s" % (key, time_dict[key])
612- local_time: 20080515T16:19:53
613+ local_time: 2008-05-15 16:19:53
614 tz_name: US/Central
615- utc_time: 20080515T22:19:53
616+ utc_time: 2008-05-15 22:19:53
617
618
619 Launchpad.get_bugs()
620@@ -144,11 +144,11 @@
621 alias:
622 assigned_to: test@canonical.com
623 component: GPPSystems
624- creation_time: 20080610T16:19:53
625+ creation_time: 2008-06-10 16:19:53
626 id: 1
627 internals:...
628 is_open: True
629- last_change_time: 20080610T16:19:53
630+ last_change_time: 2008-06-10 16:19:53
631 priority: P1
632 product: Marvin
633 resolution: FIXED
634@@ -170,11 +170,11 @@
635 alias:
636 assigned_to: test@canonical.com
637 component: GPPSystems
638- creation_time: 20080610T16:19:53
639+ creation_time: 2008-06-10 16:19:53
640 id: 1
641 internals:...
642 is_open: True
643- last_change_time: 20080610T16:19:53
644+ last_change_time: 2008-06-10 16:19:53
645 priority: P1
646 product: Marvin
647 resolution: FIXED
648@@ -186,11 +186,11 @@
649 alias: bug-two
650 assigned_to: marvin@heartofgold.ship
651 component: Crew
652- creation_time: 20080611T09:23:12
653+ creation_time: 2008-06-11 09:23:12
654 id: 2
655 internals:...
656 is_open: True
657- last_change_time: 20080611T09:24:29
658+ last_change_time: 2008-06-11 09:24:29
659 priority: P1
660 product: HeartOfGold
661 resolution:
662@@ -209,11 +209,11 @@
663 alias: bug-two
664 assigned_to: marvin@heartofgold.ship
665 component: Crew
666- creation_time: 20080611T09:23:12
667+ creation_time: 2008-06-11 09:23:12
668 id: 2
669 internals:...
670 is_open: True
671- last_change_time: 20080611T09:24:29
672+ last_change_time: 2008-06-11 09:24:29
673 priority: P1
674 product: HeartOfGold
675 resolution:
676@@ -228,17 +228,8 @@
677 allowing Launchpad to get only the recently-updated subset of a given
678 set of remote bugs.
679
680- >>> from xmlrpclib import DateTime
681-
682 >>> changed_since = datetime(2008, 6, 11, 9, 0, 0)
683
684- >>> # We encode changed_since into an XML-RPC DateTime manually.
685- >>> # This is because xmlrpclib can't handle DateTime encoding
686- >>> # within a dict.
687- >>> # XXX 2008-08-05 gmb (bug 254999):
688- >>> # We can remove this once we upgrade to python 2.5.
689- >>> changed_since = DateTime(changed_since.timetuple())
690-
691 >>> return_value = server.Launchpad.get_bugs({
692 ... 'ids': [1, 2],
693 ... 'changed_since': changed_since,
694@@ -254,11 +245,11 @@
695 alias: bug-two
696 assigned_to: marvin@heartofgold.ship
697 component: Crew
698- creation_time: 20080611T09:23:12
699+ creation_time: 2008-06-11 09:23:12
700 id: 2
701 internals:...
702 is_open: True
703- last_change_time: 20080611T09:24:29
704+ last_change_time: 2008-06-11 09:24:29
705 priority: P1
706 product: HeartOfGold
707 resolution:
708@@ -273,10 +264,6 @@
709 >>> from datetime import timedelta
710 >>> changed_since = datetime.now() + timedelta(days=42)
711
712- >>> # XXX 2008-08-05 gmb (bug 254999):
713- >>> # We can remove this once we upgrade to python 2.5.
714- >>> changed_since = DateTime(changed_since.timetuple())
715-
716 >>> return_value = server.Launchpad.get_bugs({
717 ... 'ids': [1, 2],
718 ... 'changed_since': changed_since,
719@@ -304,11 +291,11 @@
720 alias: bug-two
721 assigned_to: marvin@heartofgold.ship
722 component: Crew
723- creation_time: 20080611T09:23:12
724+ creation_time: 2008-06-11 09:23:12
725 id: 2
726 internals:...
727 is_open: True
728- last_change_time: 20080611T09:24:29
729+ last_change_time: 2008-06-11 09:24:29
730 priority: P1
731 product: HeartOfGold
732 resolution:
733@@ -366,13 +353,13 @@
734 id: 1
735 number: 1
736 text: I'd really appreciate it if Marvin would enjoy life a bit.
737- time: 20080616T12:44:29
738+ time: 2008-06-16 12:44:29
739 <BLANKLINE>
740 author: marvin
741 id: 3
742 number: 2
743 text: Life? Don't talk to me about life.
744- time: 20080616T13:22:29
745+ time: 2008-06-16 13:22:29
746 <BLANKLINE>
747 <BLANKLINE>
748 Bug 2:
749@@ -380,13 +367,13 @@
750 id: 2
751 number: 1
752 text: Bring the passengers to the bridge please Marvin.
753- time: 20080616T13:08:08
754+ time: 2008-06-16 13:08:08
755 <BLANKLINE>
756 author: Ford Prefect <ford.prefect@h2g2.com>
757 id: 4
758 number: 2
759 text: I appear to have become a perfectly safe penguin.
760- time: 20080617T20:28:40
761+ time: 2008-06-17 20:28:40
762
763 If an ids parameter is specified along with bug_ids, only the comments
764 whose IDs are in the list of IDs passed will be returned.
765@@ -401,7 +388,7 @@
766 id: 1
767 number: 1
768 text: I'd really appreciate it if Marvin would enjoy life a bit.
769- time: 20080616T12:44:29
770+ time: 2008-06-16 12:44:29
771 <BLANKLINE>
772 <BLANKLINE>
773 Bug 2:
774@@ -409,7 +396,7 @@
775 id: 2
776 number: 1
777 text: Bring the passengers to the bridge please Marvin.
778- time: 20080616T13:08:08
779+ time: 2008-06-16 13:08:08
780
781 Passing an include_fields parameter allows us to limit which fields are
782 returned for each comment.
783
784=== modified file 'lib/lp/bugs/tests/externalbugtracker.py'
785--- lib/lp/bugs/tests/externalbugtracker.py 2009-11-30 10:21:23 +0000
786+++ lib/lp/bugs/tests/externalbugtracker.py 2009-12-23 12:17:18 +0000
787@@ -65,7 +65,7 @@
788 while bugtracker_set.getByName("%s-%d" % (name, index)) is not None:
789 index += 1
790 name += '-%d' % index
791- bugtracker = BugTracker(
792+ BugTracker(
793 name=name,
794 title='%s *TESTING*' % (bugtracker_type.title,),
795 bugtrackertype=bugtracker_type,
796@@ -282,7 +282,6 @@
797 buglist_xml = read_test_file(self.buglist_file)
798 bug_ids = str(form[self.bug_id_form_element]).split(',')
799 bug_li_items = []
800- status_tag = None
801 for bug_id in bug_ids:
802 bug_id = int(bug_id)
803 if bug_id not in self.bugzilla_bugs:
804@@ -527,17 +526,12 @@
805 if local_datetime is None:
806 local_datetime = datetime(2008, 5, 1, 1, 1, 1)
807
808- # We return xmlrpc dateTimes rather than doubles since that's
809- # what BugZilla will return.
810- local_time = xmlrpclib.DateTime(local_datetime.timetuple())
811-
812 utc_offset_delta = timedelta(seconds=self.utc_offset)
813 utc_date_time = local_datetime - utc_offset_delta
814
815- utc_time = xmlrpclib.DateTime(utc_date_time.timetuple())
816 return {
817- 'local_time': local_time,
818- 'utc_time': utc_time,
819+ 'local_time': local_datetime,
820+ 'utc_time': utc_date_time,
821 'tz_name': self.timezone,
822 }
823
824@@ -593,7 +587,6 @@
825 "One of ('ids', 'products') should be specified")
826
827 bugs_to_return = []
828- bugs = dict(self.bugs)
829
830 # We enforce permissiveness, since we'll always call this method
831 # with permissive=True in the Real World.
832@@ -601,14 +594,14 @@
833 assert permissive, "get_bugs() must be called with permissive=True"
834
835 # If a changed_since argument is specified, marshall it into a
836- # datetime so that we can use it for comparisons.
837- # XXX 2008-08-05 gmb (bug 254999):
838- # We can remove these lines once we upgrade to python 2.5.
839+ # datetime so that we can use it for comparisons. Even though
840+ # xmlrpclib in Python 2.5 groks datetime, by the time this
841+ # method is called xmlrpclib has already converted all
842+ # datetimes to xmlrpclib.DateTime.
843 changed_since = arguments.get('changed_since')
844 if changed_since is not None:
845- changed_since_timetuple = time.strptime(
846- str(changed_since), '%Y%m%dT%H:%M:%S')
847- changed_since = datetime(*changed_since_timetuple[:6])
848+ changed_since = datetime.strptime(
849+ changed_since.value, '%Y%m%dT%H:%M:%S')
850
851 # If we have some products but no bug_ids we just get all the
852 # bug IDs for those products and stuff them in the bug_ids list
853@@ -644,14 +637,6 @@
854 bug_dict['product'] not in products):
855 continue
856
857- # Update the DateTime fields of the bug dict so that they
858- # look like ones that would be sent over XML-RPC.
859- for time_field in ('creation_time', 'last_change_time'):
860- datetime_value = bug_dict[time_field]
861- timestamp = time.mktime(datetime_value.timetuple())
862- xmlrpc_datetime = xmlrpclib.DateTime(timestamp)
863- bug_dict[time_field] = xmlrpc_datetime
864-
865 bugs_to_return.append(bug_dict)
866
867 # "Why are you returning a list here?" I hear you cry. Well,
868@@ -662,15 +647,9 @@
869
870 def _copy_comment(self, comment, fields_to_return=None):
871 # Copy wanted fields.
872- comment = dict(
873+ return dict(
874 (key, value) for (key, value) in comment.iteritems()
875 if fields_to_return is None or key in fields_to_return)
876- # Replace the time field with an XML-RPC DateTime.
877- if 'time' in comment:
878- comment['time'] = xmlrpclib.DateTime(
879- comment['time'].timetuple())
880- return comment
881-
882
883 def comments(self, arguments):
884 """Return comments for a given set of bugs."""
885@@ -1617,8 +1596,7 @@
886 The response body is an XMLRPC response. In addition we set the
887 info of the response to contain a cookie.
888 """
889- assert (
890- isinstance(req, Request),
891+ assert isinstance(req, Request), (
892 'Expected a urllib2.Request, got %s' % req)
893
894 if 'testError' in req.data: