/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
0.4.14 by Martin Pool
Update xmlrpc api
18
from getpass import getpass
0.4.17 by Martin Pool
Allow xmlrpc service url to be overridden by $BZR_LP_XMLRPC_URL
19
import os
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
20
from urlparse import urlsplit, urlunsplit
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
21
import urllib
0.4.4 by Martin Pool
Start forming xmlrpc requests
22
import xmlrpclib
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
23
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
24
from bzrlib import (
25
    config,
26
    errors,
2900.2.22 by Vincent Ladeuil
Polishing.
27
    __version__ as _bzrlib_version,
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
28
    )
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
29
30
# for testing, do
31
'''
32
export BZR_LP_XMLRPC_URL=http://xmlrpc.staging.launchpad.net/bazaar/
33
'''
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
34
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.
35
class LaunchpadService(object):
0.4.27 by Martin Pool
doc
36
    """A service to talk to Launchpad via XMLRPC.
37
    
38
    See http://bazaar-vcs.org/Specs/LaunchpadRpc for the methods we can call.
39
    """
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
40
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
41
    # NB: this 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.
42
    # '/RPC2'
3200.2.2 by Robert Collins
* The launchpad plugin now uses the ``edge`` xmlrpc server to avoid
43
    # We use edge because:
44
    # Beta users get redirected to it
45
    # All users can use it
46
    # There is a bug in the launchpad side where redirection causes an OOPS.
47
    DEFAULT_SERVICE_URL = 'https://xmlrpc.edge.launchpad.net/bazaar/'
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
48
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.
49
    transport = None
50
    registrant_email = None
51
    registrant_password = None
52
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
53
54
    def __init__(self, transport=None):
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
55
        """Construct a new service talking to the launchpad rpc server"""
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
56
        if transport is None:
57
            uri_type = urllib.splittype(self.service_url)[0]
58
            if uri_type == 'https':
59
                transport = xmlrpclib.SafeTransport()
60
            else:
61
                transport = xmlrpclib.Transport()
62
            transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \
2900.2.22 by Vincent Ladeuil
Polishing.
63
                    % (_bzrlib_version, xmlrpclib.__version__)
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
64
        self.transport = transport
65
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
66
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.
67
    @property
68
    def service_url(self):
69
        """Return the http or https url for the xmlrpc server.
70
71
        This does not include the username/password credentials.
72
        """
73
        key = 'BZR_LP_XMLRPC_URL'
74
        if key in os.environ:
75
            return os.environ[key]
76
        else:
77
            return self.DEFAULT_SERVICE_URL
78
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
79
    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.
80
        """Return the proxy for XMLRPC requests."""
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
81
        if authenticated:
82
            # auth info must be in url
83
            # TODO: if there's no registrant email perhaps we should
84
            # just connect anonymously?
85
            scheme, hostinfo, path = urlsplit(self.service_url)[:3]
86
            assert '@' not in hostinfo
87
            assert self.registrant_email is not None
88
            assert self.registrant_password is not None
89
            # TODO: perhaps fully quote the password to make it very slightly
90
            # obscured
91
            # TODO: can we perhaps add extra Authorization headers
92
            # directly to the request, rather than putting this into
93
            # the url?  perhaps a bit more secure against accidentally
94
            # revealing it.  std66 s3.2.1 discourages putting the
95
            # password in the url.
96
            hostinfo = '%s:%s@%s' % (urllib.quote(self.registrant_email),
97
                                     urllib.quote(self.registrant_password),
98
                                     hostinfo)
99
            url = urlunsplit((scheme, hostinfo, path, '', ''))
100
        else:
101
            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.
102
        return xmlrpclib.ServerProxy(url, transport=self.transport)
103
104
    def gather_user_credentials(self):
105
        """Get the password from the user."""
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
106
        the_config = config.GlobalConfig()
107
        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.
108
        if self.registrant_password is None:
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
109
            auth = config.AuthenticationConfig()
110
            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.
111
            prompt = 'launchpad.net password for %s: ' % \
112
                    self.registrant_email
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
113
            # We will reuse http[s] credentials if we can, prompt user
114
            # otherwise
115
            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.
116
                                                         self.registrant_email,
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
117
                                                         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.
118
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
119
    def send_request(self, method_name, method_params, authenticated):
120
        proxy = self.get_proxy(authenticated)
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
121
        assert method_name
122
        method = getattr(proxy, method_name)
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
123
        try:
124
            result = method(*method_params)
125
        except xmlrpclib.ProtocolError, e:
126
            if e.errcode == 301:
127
                # TODO: This can give a ProtocolError representing a 301 error, whose
128
                # e.headers['location'] tells where to go and e.errcode==301; should
129
                # probably log something and retry on the new url.
130
                raise NotImplementedError("should resend request to %s, but this isn't implemented"
131
                        % e.headers.get('Location', 'NO-LOCATION-PRESENT'))
132
            else:
133
                # we don't want to print the original message because its
134
                # str representation includes the plaintext password.
135
                # TODO: print more headers to help in tracking down failures
136
                raise errors.BzrError("xmlrpc protocol error connecting to %s: %s %s"
137
                        % (self.service_url, e.errcode, e.errmsg))
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
138
        return result
139
140
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.
141
class BaseRequest(object):
142
    """Base request for talking to a XMLRPC server."""
143
144
    # Set this to the XMLRPC method name.
145
    _methodname = None
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
146
    _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.
147
148
    def _request_params(self):
149
        """Return the arguments to pass to the method"""
150
        raise NotImplementedError(self._request_params)
151
152
    def submit(self, service):
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
153
        """Submit request to Launchpad XMLRPC server.
154
155
        :param service: LaunchpadService indicating where to send
156
            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.
157
        """
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
158
        return service.send_request(self._methodname, self._request_params(),
159
                                    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.
160
161
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
162
class DryRunLaunchpadService(LaunchpadService):
163
    """Service that just absorbs requests without sending to server.
164
    
165
    The dummy service does not need authentication.
166
    """
167
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
168
    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.
169
        pass
170
171
    def gather_user_credentials(self):
172
        pass
173
174
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.
175
class BranchRegistrationRequest(BaseRequest):
176
    """Request to tell Launchpad about a bzr branch."""
177
178
    _methodname = 'register_branch'
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
179
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
180
    def __init__(self, branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
181
                 branch_name='',
182
                 branch_title='',
183
                 branch_description='',
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
184
                 author_email='',
0.4.15 by Martin Pool
(register-branch) Add command-line options
185
                 product_name='',
186
                 ):
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
187
        assert branch_url, 'branch_url %r is invalid' % branch_url
0.4.4 by Martin Pool
Start forming xmlrpc requests
188
        self.branch_url = branch_url
0.4.15 by Martin Pool
(register-branch) Add command-line options
189
        if branch_name:
190
            self.branch_name = branch_name
0.4.14 by Martin Pool
Update xmlrpc api
191
        else:
0.4.15 by Martin Pool
(register-branch) Add command-line options
192
            self.branch_name = self._find_default_branch_name(self.branch_url)
193
        self.branch_title = branch_title
194
        self.branch_description = branch_description
195
        self.author_email = author_email
196
        self.product_name = product_name
0.4.4 by Martin Pool
Start forming xmlrpc requests
197
198
    def _request_params(self):
199
        """Return xmlrpc request parameters"""
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
200
        # This must match the parameter tuple expected by Launchpad for this
201
        # method
0.4.4 by Martin Pool
Start forming xmlrpc requests
202
        return (self.branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
203
                self.branch_name,
0.4.14 by Martin Pool
Update xmlrpc api
204
                self.branch_title,
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
205
                self.branch_description,
0.4.14 by Martin Pool
Update xmlrpc api
206
                self.author_email,
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
207
                self.product_name,
0.4.4 by Martin Pool
Start forming xmlrpc requests
208
               )
209
0.4.15 by Martin Pool
(register-branch) Add command-line options
210
    def _find_default_branch_name(self, branch_url):
0.4.14 by Martin Pool
Update xmlrpc api
211
        i = branch_url.rfind('/')
212
        return branch_url[i+1:]
213
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.
214
215
class BranchBugLinkRequest(BaseRequest):
216
    """Request to link a bzr branch in Launchpad to a bug."""
217
218
    _methodname = 'link_branch_to_bug'
219
220
    def __init__(self, branch_url, bug_id):
221
        assert branch_url
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
222
        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.
223
        self.branch_url = branch_url
224
225
    def _request_params(self):
226
        """Return xmlrpc request parameters"""
227
        # This must match the parameter tuple expected by Launchpad for this
228
        # method
229
        return (self.branch_url, self.bug_id, '')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
230
231
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
232
class ResolveLaunchpadPathRequest(BaseRequest):
233
    """Request to resolve the path component of an lp: URL."""
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
234
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
235
    _methodname = 'resolve_lp_path'
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
236
    _authenticated = False
237
238
    def __init__(self, path):
239
        assert path
240
        self.path = path
241
242
    def _request_params(self):
243
        """Return xmlrpc request parameters"""
244
        return (self.path,)