~bzr-pqm/bzr/bzr.dev

5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
1
# Copyright (C) 2006-2011 Canonical Ltd
0.4.4 by Martin Pool
Start forming xmlrpc requests
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
0.4.4 by Martin Pool
Start forming xmlrpc requests
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.4.4 by Martin Pool
Start forming xmlrpc requests
16
6379.6.3 by Jelmer Vernooij
Use absolute_import.
17
from __future__ import absolute_import
18
0.4.4 by Martin Pool
Start forming xmlrpc requests
19
0.4.17 by Martin Pool
Allow xmlrpc service url to be overridden by $BZR_LP_XMLRPC_URL
20
import os
4505.4.1 by Jonathan Lange
Trap gaierror and reraise appropriate ConnectionError.
21
import socket
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
22
from urlparse import urlsplit, urlunsplit
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
23
import urllib
0.4.4 by Martin Pool
Start forming xmlrpc requests
24
import xmlrpclib
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
25
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
26
from bzrlib import (
27
    config,
28
    errors,
4505.6.3 by Jonathan Lange
Don't bother lazy importing.
29
    urlutils,
2900.2.22 by Vincent Ladeuil
Polishing.
30
    __version__ as _bzrlib_version,
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
31
    )
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
32
from bzrlib.transport.http import _urllib2_wrappers
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
33
4505.6.5 by Jonathan Lange
Factor out some code that guesses a branch's URL.
34
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
35
# for testing, do
36
'''
37
export BZR_LP_XMLRPC_URL=http://xmlrpc.staging.launchpad.net/bazaar/
38
'''
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
39
3193.5.2 by Tim Penhey
Updated the tests to handle unknown launchpad instances.
40
class InvalidLaunchpadInstance(errors.BzrError):
41
42
    _fmt = "%(lp_instance)s is not a valid Launchpad instance."
43
44
    def __init__(self, lp_instance):
45
        errors.BzrError.__init__(self, lp_instance=lp_instance)
46
47
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
48
class NotLaunchpadBranch(errors.BzrError):
49
4031.2.8 by Jonathan Lange
Say "registered on", not "hosted on".
50
    _fmt = "%(url)s is not registered on Launchpad."
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
51
52
    def __init__(self, url):
53
        errors.BzrError.__init__(self, url=url)
54
55
4776.2.6 by Vincent Ladeuil
Fixed as per review comments.
56
class XMLRPCTransport(xmlrpclib.Transport):
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
57
4776.3.1 by Vincent Ladeuil
Fix python2.4 compatibility with xmlrpclib.
58
    def __init__(self, scheme):
6238.2.24 by Vincent Ladeuil
Fix the last test failure by providing the test ca certs via the config option framework.
59
        xmlrpclib.Transport.__init__(self)
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
60
        self._scheme = scheme
61
        self._opener = _urllib2_wrappers.Opener()
62
        self.verbose = 0
63
64
    def request(self, host, handler, request_body, verbose=0):
65
        self.verbose = verbose
66
        url = self._scheme + "://" + host + handler
67
        request = _urllib2_wrappers.Request("POST", url, request_body)
4776.2.4 by Vincent Ladeuil
Note that User-Agent is lost (we use the bzrlib one though).
68
        # FIXME: _urllib2_wrappers will override user-agent with its own
69
        # request.add_header("User-Agent", self.user_agent)
4776.2.2 by Vincent Ladeuil
Start testing the XMLRPC transport re-implemented on top of _urllib2_wrappers.
70
        request.add_header("Content-Type", "text/xml")
71
72
        response = self._opener.open(request)
73
        if response.code != 200:
74
            raise xmlrpclib.ProtocolError(host + handler, response.code,
75
                                          response.msg, response.info())
76
        return self.parse_response(response)
77
78
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
79
class LaunchpadService(object):
0.4.27 by Martin Pool
doc
80
    """A service to talk to Launchpad via XMLRPC.
3193.5.2 by Tim Penhey
Updated the tests to handle unknown launchpad instances.
81
4988.4.2 by Martin Pool
Change url to canonical.com or wiki, plus some doc improvements in passing
82
    See http://wiki.bazaar.canonical.com/Specs/LaunchpadRpc for the methods we can call.
0.4.27 by Martin Pool
doc
83
    """
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
84
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
85
    LAUNCHPAD_DOMAINS = {
86
        'production': 'launchpad.net',
87
        'staging': 'staging.launchpad.net',
5615.2.1 by Jelmer Vernooij
Support the 'qastaging' instance of Launchpad.
88
        'qastaging': 'qastaging.launchpad.net',
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
89
        'demo': 'demo.launchpad.net',
90
        'dev': 'launchpad.dev',
91
        }
92
3211.1.1 by Ian Clatworthy
Extends the launchpad plugin's implementation of lp spec urls (Tim Penhey)
93
    # NB: these should always end in a slash to avoid xmlrpclib appending
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
94
    # '/RPC2'
3955.3.2 by Jonathan Lange
Tighten up the code a little, changing the dev service to use https,
95
    LAUNCHPAD_INSTANCE = {}
96
    for instance, domain in LAUNCHPAD_DOMAINS.iteritems():
97
        LAUNCHPAD_INSTANCE[instance] = 'https://xmlrpc.%s/bazaar/' % domain
98
4634.165.3 by Vincent Ladeuil
Delete all references to edge.launchpad.net in code and associated tests.
99
    # We use production as the default because edge has been deprecated circa
100
    # 2010-11 (see bug https://bugs.launchpad.net/bzr/+bug/583667)
5243.1.1 by Martin
Use the production server in the launchpad plugin rather than edge
101
    DEFAULT_INSTANCE = 'production'
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
102
    DEFAULT_SERVICE_URL = LAUNCHPAD_INSTANCE[DEFAULT_INSTANCE]
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
103
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
104
    transport = None
105
    registrant_email = None
106
    registrant_password = None
107
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
108
3193.5.1 by Tim Penhey
Mostly working, just need to update the tests for lp://dev
109
    def __init__(self, transport=None, lp_instance=None):
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
110
        """Construct a new service talking to the launchpad rpc server"""
3193.5.1 by Tim Penhey
Mostly working, just need to update the tests for lp://dev
111
        self._lp_instance = lp_instance
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
112
        if transport is None:
113
            uri_type = urllib.splittype(self.service_url)[0]
4776.2.6 by Vincent Ladeuil
Fixed as per review comments.
114
            transport = XMLRPCTransport(uri_type)
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
115
            transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \
2900.2.22 by Vincent Ladeuil
Polishing.
116
                    % (_bzrlib_version, xmlrpclib.__version__)
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
117
        self.transport = transport
118
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
119
    @property
120
    def service_url(self):
121
        """Return the http or https url for the xmlrpc server.
122
123
        This does not include the username/password credentials.
124
        """
125
        key = 'BZR_LP_XMLRPC_URL'
126
        if key in os.environ:
127
            return os.environ[key]
3193.5.1 by Tim Penhey
Mostly working, just need to update the tests for lp://dev
128
        elif self._lp_instance is not None:
3193.5.2 by Tim Penhey
Updated the tests to handle unknown launchpad instances.
129
            try:
130
                return self.LAUNCHPAD_INSTANCE[self._lp_instance]
131
            except KeyError:
132
                raise InvalidLaunchpadInstance(self._lp_instance)
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
133
        else:
134
            return self.DEFAULT_SERVICE_URL
135
4505.6.2 by Jonathan Lange
Extract a method that gets a service from a URL.
136
    @classmethod
137
    def for_url(cls, url, **kwargs):
138
        """Return the Launchpad service corresponding to the given URL."""
139
        result = urlsplit(url)
140
        lp_instance = result[1]
141
        if lp_instance == '':
142
            lp_instance = None
143
        elif lp_instance not in cls.LAUNCHPAD_INSTANCE:
144
            raise errors.InvalidURL(path=url)
145
        return cls(lp_instance=lp_instance, **kwargs)
146
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
147
    def get_proxy(self, authenticated):
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
148
        """Return the proxy for XMLRPC requests."""
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
149
        if authenticated:
150
            # auth info must be in url
151
            # TODO: if there's no registrant email perhaps we should
152
            # just connect anonymously?
153
            scheme, hostinfo, path = urlsplit(self.service_url)[:3]
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
154
            if '@' in hostinfo:
155
                raise AssertionError(hostinfo)
156
            if self.registrant_email is None:
157
                raise AssertionError()
158
            if self.registrant_password is None:
159
                raise AssertionError()
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
160
            # TODO: perhaps fully quote the password to make it very slightly
161
            # obscured
162
            # TODO: can we perhaps add extra Authorization headers
163
            # directly to the request, rather than putting this into
164
            # the url?  perhaps a bit more secure against accidentally
165
            # revealing it.  std66 s3.2.1 discourages putting the
166
            # password in the url.
6379.4.2 by Jelmer Vernooij
Add urlutils.quote / urlutils.unquote.
167
            hostinfo = '%s:%s@%s' % (urlutils.quote(self.registrant_email),
168
                                     urlutils.quote(self.registrant_password),
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
169
                                     hostinfo)
170
            url = urlunsplit((scheme, hostinfo, path, '', ''))
171
        else:
172
            url = self.service_url
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
173
        return xmlrpclib.ServerProxy(url, transport=self.transport)
174
175
    def gather_user_credentials(self):
176
        """Get the password from the user."""
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
177
        the_config = config.GlobalConfig()
178
        self.registrant_email = the_config.user_email()
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
179
        if self.registrant_password is None:
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
180
            auth = config.AuthenticationConfig()
181
            scheme, hostinfo = urlsplit(self.service_url)[:2]
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
182
            prompt = 'launchpad.net password for %s: ' % \
183
                    self.registrant_email
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
184
            # We will reuse http[s] credentials if we can, prompt user
185
            # otherwise
186
            self.registrant_password = auth.get_password(scheme, hostinfo,
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
187
                                                         self.registrant_email,
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
188
                                                         prompt=prompt)
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
189
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
190
    def send_request(self, method_name, method_params, authenticated):
191
        proxy = self.get_proxy(authenticated)
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
192
        method = getattr(proxy, method_name)
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
193
        try:
194
            result = method(*method_params)
195
        except xmlrpclib.ProtocolError, e:
196
            if e.errcode == 301:
197
                # TODO: This can give a ProtocolError representing a 301 error, whose
198
                # e.headers['location'] tells where to go and e.errcode==301; should
199
                # probably log something and retry on the new url.
200
                raise NotImplementedError("should resend request to %s, but this isn't implemented"
201
                        % e.headers.get('Location', 'NO-LOCATION-PRESENT'))
202
            else:
203
                # we don't want to print the original message because its
204
                # str representation includes the plaintext password.
205
                # TODO: print more headers to help in tracking down failures
206
                raise errors.BzrError("xmlrpc protocol error connecting to %s: %s %s"
207
                        % (self.service_url, e.errcode, e.errmsg))
4505.4.1 by Jonathan Lange
Trap gaierror and reraise appropriate ConnectionError.
208
        except socket.gaierror, e:
209
            raise errors.ConnectionError(
210
                "Could not resolve '%s'" % self.domain,
211
                orig_error=e)
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
212
        return result
213
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
214
    @property
215
    def domain(self):
216
        if self._lp_instance is None:
217
            instance = self.DEFAULT_INSTANCE
218
        else:
219
            instance = self._lp_instance
220
        return self.LAUNCHPAD_DOMAINS[instance]
221
4505.6.5 by Jonathan Lange
Factor out some code that guesses a branch's URL.
222
    def _guess_branch_path(self, branch_url, _request_factory=None):
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
223
        scheme, hostinfo, path = urlsplit(branch_url)[:3]
3955.3.8 by Jonathan Lange
Support lp URL shortcuts.
224
        if _request_factory is None:
225
            _request_factory = ResolveLaunchpadPathRequest
226
        if scheme == 'lp':
227
            resolve = _request_factory(path)
3955.3.9 by Jonathan Lange
Catch errors.
228
            try:
229
                result = resolve.submit(self)
230
            except xmlrpclib.Fault, fault:
231
                raise errors.InvalidURL(branch_url, str(fault))
3955.3.8 by Jonathan Lange
Support lp URL shortcuts.
232
            branch_url = result['urls'][0]
233
            path = urlsplit(branch_url)[2]
234
        else:
235
            domains = (
236
                'bazaar.%s' % domain
237
                for domain in self.LAUNCHPAD_DOMAINS.itervalues())
3955.3.5 by Jonathan Lange
Add an untested plugin, make the error handling a little nicer.
238
            if hostinfo not in domains:
239
                raise NotLaunchpadBranch(branch_url)
4505.6.5 by Jonathan Lange
Factor out some code that guesses a branch's URL.
240
        return path.lstrip('/')
241
242
    def get_web_url_from_branch_url(self, branch_url, _request_factory=None):
243
        """Get the Launchpad web URL for the given branch URL.
244
245
        :raise errors.InvalidURL: if 'branch_url' cannot be identified as a
246
            Launchpad branch URL.
247
        :return: The URL of the branch on Launchpad.
248
        """
249
        path = self._guess_branch_path(branch_url, _request_factory)
3955.3.7 by Jonathan Lange
Test the launchpad-open command. Fix up some minor bugs.
250
        return urlutils.join('https://code.%s' % self.domain, path)
3955.3.1 by Jonathan Lange
Start doing URL stuff, extracting the domain bit out of LaunchpadService,
251
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
252
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
253
class BaseRequest(object):
254
    """Base request for talking to a XMLRPC server."""
255
256
    # Set this to the XMLRPC method name.
257
    _methodname = None
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
258
    _authenticated = True
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
259
260
    def _request_params(self):
261
        """Return the arguments to pass to the method"""
262
        raise NotImplementedError(self._request_params)
263
264
    def submit(self, service):
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
265
        """Submit request to Launchpad XMLRPC server.
266
267
        :param service: LaunchpadService indicating where to send
268
            the request and the authentication credentials.
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
269
        """
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
270
        return service.send_request(self._methodname, self._request_params(),
271
                                    self._authenticated)
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
272
273
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
274
class DryRunLaunchpadService(LaunchpadService):
275
    """Service that just absorbs requests without sending to server.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
276
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
277
    The dummy service does not need authentication.
278
    """
279
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
280
    def send_request(self, method_name, method_params, authenticated):
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
281
        pass
282
283
    def gather_user_credentials(self):
284
        pass
285
286
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
287
class BranchRegistrationRequest(BaseRequest):
288
    """Request to tell Launchpad about a bzr branch."""
289
290
    _methodname = 'register_branch'
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
291
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
292
    def __init__(self, branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
293
                 branch_name='',
294
                 branch_title='',
295
                 branch_description='',
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
296
                 author_email='',
0.4.15 by Martin Pool
(register-branch) Add command-line options
297
                 product_name='',
298
                 ):
3246.4.3 by Daniel Watkins
Replaced another assert.
299
        if not branch_url:
300
            raise errors.InvalidURL(branch_url, "You need to specify a non-empty branch URL.")
0.4.4 by Martin Pool
Start forming xmlrpc requests
301
        self.branch_url = branch_url
0.4.15 by Martin Pool
(register-branch) Add command-line options
302
        if branch_name:
303
            self.branch_name = branch_name
0.4.14 by Martin Pool
Update xmlrpc api
304
        else:
0.4.15 by Martin Pool
(register-branch) Add command-line options
305
            self.branch_name = self._find_default_branch_name(self.branch_url)
306
        self.branch_title = branch_title
307
        self.branch_description = branch_description
308
        self.author_email = author_email
309
        self.product_name = product_name
0.4.4 by Martin Pool
Start forming xmlrpc requests
310
311
    def _request_params(self):
312
        """Return xmlrpc request parameters"""
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
313
        # This must match the parameter tuple expected by Launchpad for this
314
        # method
0.4.4 by Martin Pool
Start forming xmlrpc requests
315
        return (self.branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
316
                self.branch_name,
0.4.14 by Martin Pool
Update xmlrpc api
317
                self.branch_title,
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
318
                self.branch_description,
0.4.14 by Martin Pool
Update xmlrpc api
319
                self.author_email,
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
320
                self.product_name,
0.4.4 by Martin Pool
Start forming xmlrpc requests
321
               )
322
0.4.15 by Martin Pool
(register-branch) Add command-line options
323
    def _find_default_branch_name(self, branch_url):
0.4.14 by Martin Pool
Update xmlrpc api
324
        i = branch_url.rfind('/')
325
        return branch_url[i+1:]
326
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
327
328
class BranchBugLinkRequest(BaseRequest):
329
    """Request to link a bzr branch in Launchpad to a bug."""
330
331
    _methodname = 'link_branch_to_bug'
332
333
    def __init__(self, branch_url, bug_id):
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
334
        self.bug_id = bug_id
0.4.19 by test at canonical
add possibility to link to a bug when registering a branch. factor out some common functionality from BranchRegistrationRequest.
335
        self.branch_url = branch_url
336
337
    def _request_params(self):
338
        """Return xmlrpc request parameters"""
339
        # This must match the parameter tuple expected by Launchpad for this
340
        # method
341
        return (self.branch_url, self.bug_id, '')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
342
343
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
344
class ResolveLaunchpadPathRequest(BaseRequest):
345
    """Request to resolve the path component of an lp: URL."""
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
346
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
347
    _methodname = 'resolve_lp_path'
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
348
    _authenticated = False
349
350
    def __init__(self, path):
3246.4.1 by Daniel Watkins
Replaced problematic assertion with exception call.
351
        if not path:
352
            raise errors.InvalidURL(path=path,
4416.7.1 by Neil Martinsen-Burrell
Fix 238764 refer to projects rather than products in launchpad plugin
353
                                    extra="You must specify a project.")
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
354
        self.path = path
355
356
    def _request_params(self):
357
        """Return xmlrpc request parameters"""
358
        return (self.path,)