Mercurial > hg
comparison hgext/bugzilla.py @ 15870:f4c859293ed4 stable
bugzilla: make XMLRPC interface support http and https access
Inadvertently support is currently only for https. For some reason I
thought xmlrpclib.SafeTransport did http and https, but it is https only.
So create http and https XMLRPC transports that retain cookies. Decide which
to use by inspecting the Bugzilla URL.
author | Jim Hague <jim.hague@acm.org> |
---|---|
date | Wed, 11 Jan 2012 16:54:29 +0000 |
parents | 29f55c0e39e7 |
children | b468cea3f29d |
comparison
equal
deleted
inserted
replaced
15848:012b285cf643 | 15870:f4c859293ed4 |
---|---|
253 ''' | 253 ''' |
254 | 254 |
255 from mercurial.i18n import _ | 255 from mercurial.i18n import _ |
256 from mercurial.node import short | 256 from mercurial.node import short |
257 from mercurial import cmdutil, mail, templater, util | 257 from mercurial import cmdutil, mail, templater, util |
258 import re, time, xmlrpclib | 258 import re, time, urlparse, xmlrpclib |
259 | 259 |
260 class bzaccess(object): | 260 class bzaccess(object): |
261 '''Base class for access to Bugzilla.''' | 261 '''Base class for access to Bugzilla.''' |
262 | 262 |
263 def __init__(self, ui): | 263 def __init__(self, ui): |
471 raise util.Abort(_('unknown database schema')) | 471 raise util.Abort(_('unknown database schema')) |
472 return ids[0][0] | 472 return ids[0][0] |
473 | 473 |
474 # Buzgilla via XMLRPC interface. | 474 # Buzgilla via XMLRPC interface. |
475 | 475 |
476 class CookieSafeTransport(xmlrpclib.SafeTransport): | 476 class cookietransportrequest(object): |
477 """A SafeTransport that retains cookies over its lifetime. | 477 """A Transport request method that retains cookies over its lifetime. |
478 | 478 |
479 The regular xmlrpclib transports ignore cookies. Which causes | 479 The regular xmlrpclib transports ignore cookies. Which causes |
480 a bit of a problem when you need a cookie-based login, as with | 480 a bit of a problem when you need a cookie-based login, as with |
481 the Bugzilla XMLRPC interface. | 481 the Bugzilla XMLRPC interface. |
482 | 482 |
483 So this is a SafeTransport which looks for cookies being set | 483 So this is a helper for defining a Transport which looks for |
484 in responses and saves them to add to all future requests. | 484 cookies being set in responses and saves them to add to all future |
485 It appears a SafeTransport can do both HTTP and HTTPS sessions, | 485 requests. |
486 which saves us having to do a CookieTransport too. | |
487 """ | 486 """ |
488 | 487 |
489 # Inspiration drawn from | 488 # Inspiration drawn from |
490 # http://blog.godson.in/2010/09/how-to-make-python-xmlrpclib-client.html | 489 # http://blog.godson.in/2010/09/how-to-make-python-xmlrpclib-client.html |
491 # http://www.itkovian.net/base/transport-class-for-pythons-xml-rpc-lib/ | 490 # http://www.itkovian.net/base/transport-class-for-pythons-xml-rpc-lib/ |
535 parser.feed(payload) | 534 parser.feed(payload) |
536 parser.close() | 535 parser.close() |
537 | 536 |
538 return unmarshaller.close() | 537 return unmarshaller.close() |
539 | 538 |
539 # The explicit calls to the underlying xmlrpclib __init__() methods are | |
540 # necessary. The xmlrpclib.Transport classes are old-style classes, and | |
541 # it turns out their __init__() doesn't get called when doing multiple | |
542 # inheritance with a new-style class. | |
543 class cookietransport(cookietransportrequest, xmlrpclib.Transport): | |
544 def __init__(self, use_datetime=0): | |
545 xmlrpclib.Transport.__init__(self, use_datetime) | |
546 | |
547 class cookiesafetransport(cookietransportrequest, xmlrpclib.SafeTransport): | |
548 def __init__(self, use_datetime=0): | |
549 xmlrpclib.SafeTransport.__init__(self, use_datetime) | |
550 | |
540 class bzxmlrpc(bzaccess): | 551 class bzxmlrpc(bzaccess): |
541 """Support for access to Bugzilla via the Bugzilla XMLRPC API. | 552 """Support for access to Bugzilla via the Bugzilla XMLRPC API. |
542 | 553 |
543 Requires a minimum Bugzilla version 3.4. | 554 Requires a minimum Bugzilla version 3.4. |
544 """ | 555 """ |
551 bzweb = bzweb.rstrip("/") + "/xmlrpc.cgi" | 562 bzweb = bzweb.rstrip("/") + "/xmlrpc.cgi" |
552 | 563 |
553 user = self.ui.config('bugzilla', 'user', 'bugs') | 564 user = self.ui.config('bugzilla', 'user', 'bugs') |
554 passwd = self.ui.config('bugzilla', 'password') | 565 passwd = self.ui.config('bugzilla', 'password') |
555 | 566 |
556 self.bzproxy = xmlrpclib.ServerProxy(bzweb, CookieSafeTransport()) | 567 self.bzproxy = xmlrpclib.ServerProxy(bzweb, self.transport(bzweb)) |
557 self.bzproxy.User.login(dict(login=user, password=passwd)) | 568 self.bzproxy.User.login(dict(login=user, password=passwd)) |
569 | |
570 def transport(self, uri): | |
571 if urlparse.urlparse(uri, "http")[0] == "https": | |
572 return cookiesafetransport() | |
573 else: | |
574 return cookietransport() | |
558 | 575 |
559 def get_bug_comments(self, id): | 576 def get_bug_comments(self, id): |
560 """Return a string with all comment text for a bug.""" | 577 """Return a string with all comment text for a bug.""" |
561 c = self.bzproxy.Bug.comments(dict(ids=[id])) | 578 c = self.bzproxy.Bug.comments(dict(ids=[id])) |
562 return ''.join([t['text'] for t in c['bugs'][str(id)]['comments']]) | 579 return ''.join([t['text'] for t in c['bugs'][str(id)]['comments']]) |