/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'
1668.1.11 by Martin Pool
(launchpad) default xmlrpc service url should be https
43
    DEFAULT_SERVICE_URL = 'https://xmlrpc.launchpad.net/bazaar/'
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
44
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.
45
    transport = None
46
    registrant_email = None
47
    registrant_password = None
48
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
49
50
    def __init__(self, transport=None):
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
51
        """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
52
        if transport is None:
53
            uri_type = urllib.splittype(self.service_url)[0]
54
            if uri_type == 'https':
55
                transport = xmlrpclib.SafeTransport()
56
            else:
57
                transport = xmlrpclib.Transport()
58
            transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \
2900.2.22 by Vincent Ladeuil
Polishing.
59
                    % (_bzrlib_version, xmlrpclib.__version__)
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
60
        self.transport = transport
61
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
62
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.
63
    @property
64
    def service_url(self):
65
        """Return the http or https url for the xmlrpc server.
66
67
        This does not include the username/password credentials.
68
        """
69
        key = 'BZR_LP_XMLRPC_URL'
70
        if key in os.environ:
71
            return os.environ[key]
72
        else:
73
            return self.DEFAULT_SERVICE_URL
74
75
    def get_proxy(self):
76
        """Return the proxy for XMLRPC requests."""
77
        # auth info must be in url
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
78
        # TODO: if there's no registrant email perhaps we should just connect
79
        # anonymously?
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
        scheme, hostinfo, path = urlsplit(self.service_url)[:3]
81
        assert '@' not in hostinfo
82
        assert self.registrant_email is not None
83
        assert self.registrant_password is not None
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
84
        # TODO: perhaps fully quote the password to make it very slightly
85
        # obscured
86
        # TODO: can we perhaps add extra Authorization headers directly to the 
87
        # request, rather than putting this into the url?  perhaps a bit more 
88
        # secure against accidentally revealing it.  std66 s3.2.1 discourages putting
89
        # the password in the url.
0.4.29 by Martin Pool
(register-branch) override xmlrpc user-agent; move Transport construction
90
        hostinfo = '%s:%s@%s' % (urllib.quote(self.registrant_email),
91
                                 urllib.quote(self.registrant_password),
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.
92
                                 hostinfo)
93
        url = urlunsplit((scheme, hostinfo, path, '', ''))
94
        return xmlrpclib.ServerProxy(url, transport=self.transport)
95
96
    def gather_user_credentials(self):
97
        """Get the password from the user."""
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
98
        config = config.GlobalConfig()
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.
99
        self.registrant_email = config.user_email()
100
        if self.registrant_password is None:
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
101
            auth = config.AuthenticationConfig()
102
            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.
103
            prompt = 'launchpad.net password for %s: ' % \
104
                    self.registrant_email
2900.2.21 by Vincent Ladeuil
Make lp_registration aware of authentication config.
105
            # We will reuse http[s] credentials if we can, prompt user
106
            # otherwise
107
            self.registrant_password = auth.get_password(scheme, hostinfo,
108
                                                         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.
109
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
110
    def send_request(self, method_name, method_params):
111
        proxy = self.get_proxy()
112
        assert method_name
113
        method = getattr(proxy, method_name)
1668.1.9 by Martin Pool
(launchpad plugin) Better reporting of errors from xmlrpc
114
        try:
115
            result = method(*method_params)
116
        except xmlrpclib.ProtocolError, e:
117
            if e.errcode == 301:
118
                # TODO: This can give a ProtocolError representing a 301 error, whose
119
                # e.headers['location'] tells where to go and e.errcode==301; should
120
                # probably log something and retry on the new url.
121
                raise NotImplementedError("should resend request to %s, but this isn't implemented"
122
                        % e.headers.get('Location', 'NO-LOCATION-PRESENT'))
123
            else:
124
                # we don't want to print the original message because its
125
                # str representation includes the plaintext password.
126
                # TODO: print more headers to help in tracking down failures
127
                raise errors.BzrError("xmlrpc protocol error connecting to %s: %s %s"
128
                        % (self.service_url, e.errcode, e.errmsg))
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
129
        return result
130
131
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.
132
class BaseRequest(object):
133
    """Base request for talking to a XMLRPC server."""
134
135
    # Set this to the XMLRPC method name.
136
    _methodname = None
137
138
    def _request_params(self):
139
        """Return the arguments to pass to the method"""
140
        raise NotImplementedError(self._request_params)
141
142
    def submit(self, service):
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
143
        """Submit request to Launchpad XMLRPC server.
144
145
        :param service: LaunchpadService indicating where to send
146
            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.
147
        """
0.4.21 by Martin Pool
Refactor BaseRequest.submit so details of submission are in the LaunchpadService
148
        return service.send_request(self._methodname, self._request_params())
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.
149
150
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
151
class DryRunLaunchpadService(LaunchpadService):
152
    """Service that just absorbs requests without sending to server.
153
    
154
    The dummy service does not need authentication.
155
    """
156
157
    def send_request(self, method_name, method_params):
158
        pass
159
160
    def gather_user_credentials(self):
161
        pass
162
163
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.
164
class BranchRegistrationRequest(BaseRequest):
165
    """Request to tell Launchpad about a bzr branch."""
166
167
    _methodname = 'register_branch'
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
168
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
169
    def __init__(self, branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
170
                 branch_name='',
171
                 branch_title='',
172
                 branch_description='',
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
173
                 author_email='',
0.4.15 by Martin Pool
(register-branch) Add command-line options
174
                 product_name='',
175
                 ):
0.4.14 by Martin Pool
Update xmlrpc api
176
        assert branch_url
0.4.4 by Martin Pool
Start forming xmlrpc requests
177
        self.branch_url = branch_url
0.4.15 by Martin Pool
(register-branch) Add command-line options
178
        if branch_name:
179
            self.branch_name = branch_name
0.4.14 by Martin Pool
Update xmlrpc api
180
        else:
0.4.15 by Martin Pool
(register-branch) Add command-line options
181
            self.branch_name = self._find_default_branch_name(self.branch_url)
182
        self.branch_title = branch_title
183
        self.branch_description = branch_description
184
        self.author_email = author_email
185
        self.product_name = product_name
0.4.4 by Martin Pool
Start forming xmlrpc requests
186
187
    def _request_params(self):
188
        """Return xmlrpc request parameters"""
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
189
        # This must match the parameter tuple expected by Launchpad for this
190
        # method
0.4.4 by Martin Pool
Start forming xmlrpc requests
191
        return (self.branch_url,
0.4.15 by Martin Pool
(register-branch) Add command-line options
192
                self.branch_name,
0.4.14 by Martin Pool
Update xmlrpc api
193
                self.branch_title,
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
194
                self.branch_description,
0.4.14 by Martin Pool
Update xmlrpc api
195
                self.author_email,
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
196
                self.product_name,
0.4.4 by Martin Pool
Start forming xmlrpc requests
197
               )
198
0.4.15 by Martin Pool
(register-branch) Add command-line options
199
    def _find_default_branch_name(self, branch_url):
0.4.14 by Martin Pool
Update xmlrpc api
200
        i = branch_url.rfind('/')
201
        return branch_url[i+1:]
202
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.
203
204
class BranchBugLinkRequest(BaseRequest):
205
    """Request to link a bzr branch in Launchpad to a bug."""
206
207
    _methodname = 'link_branch_to_bug'
208
209
    def __init__(self, branch_url, bug_id):
210
        assert branch_url
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
211
        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.
212
        self.branch_url = branch_url
213
214
    def _request_params(self):
215
        """Return xmlrpc request parameters"""
216
        # This must match the parameter tuple expected by Launchpad for this
217
        # method
218
        return (self.branch_url, self.bug_id, '')