~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/launchpad/lp_registration.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-02 19:56:24 UTC
  • mto: This revision was merged to the branch mainline in revision 4469.
  • Revision ID: john@arbash-meinel.com-20090602195624-utljsyz0qgmq63lg
Add a chunks_to_gzip function.
This allows the _record_to_data code to build up a list of chunks,
rather than requiring a single string.
It should be ~ the same performance when using a single string, since
we are only adding a for() loop over the chunks and an if check.
We could possibly just remove the if check and not worry about adding
some empty strings in there.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
 
18
from getpass import getpass
18
19
import os
19
 
import socket
20
20
from urlparse import urlsplit, urlunsplit
21
21
import urllib
22
22
import xmlrpclib
23
23
 
 
24
from bzrlib.lazy_import import lazy_import
 
25
lazy_import(globals(), """
 
26
from bzrlib import urlutils
 
27
""")
 
28
 
24
29
from bzrlib import (
25
30
    config,
26
31
    errors,
27
 
    urlutils,
28
32
    __version__ as _bzrlib_version,
29
33
    )
30
 
from bzrlib.transport.http import _urllib2_wrappers
31
 
 
32
34
 
33
35
# for testing, do
34
36
'''
51
53
        errors.BzrError.__init__(self, url=url)
52
54
 
53
55
 
54
 
class XMLRPCTransport(xmlrpclib.Transport):
55
 
 
56
 
    def __init__(self, scheme):
57
 
        # In python2.4 xmlrpclib.Transport is a old-style class, and does not
58
 
        # define __init__, so we check first
59
 
        init = getattr(xmlrpclib.Transport, '__init__', None)
60
 
        if init is not None:
61
 
            init(self)
62
 
        self._scheme = scheme
63
 
        self._opener = _urllib2_wrappers.Opener()
64
 
        self.verbose = 0
65
 
 
66
 
    def request(self, host, handler, request_body, verbose=0):
67
 
        self.verbose = verbose
68
 
        url = self._scheme + "://" + host + handler
69
 
        request = _urllib2_wrappers.Request("POST", url, request_body)
70
 
        # FIXME: _urllib2_wrappers will override user-agent with its own
71
 
        # request.add_header("User-Agent", self.user_agent)
72
 
        request.add_header("Content-Type", "text/xml")
73
 
 
74
 
        response = self._opener.open(request)
75
 
        if response.code != 200:
76
 
            raise xmlrpclib.ProtocolError(host + handler, response.code,
77
 
                                          response.msg, response.info())
78
 
        return self.parse_response(response)
79
 
 
80
 
 
81
56
class LaunchpadService(object):
82
57
    """A service to talk to Launchpad via XMLRPC.
83
58
 
84
 
    See http://wiki.bazaar.canonical.com/Specs/LaunchpadRpc for the methods we can call.
 
59
    See http://bazaar-vcs.org/Specs/LaunchpadRpc for the methods we can call.
85
60
    """
86
61
 
87
62
    LAUNCHPAD_DOMAINS = {
88
63
        'production': 'launchpad.net',
 
64
        'edge': 'edge.launchpad.net',
89
65
        'staging': 'staging.launchpad.net',
90
 
        'qastaging': 'qastaging.launchpad.net',
91
66
        'demo': 'demo.launchpad.net',
92
67
        'dev': 'launchpad.dev',
93
68
        }
98
73
    for instance, domain in LAUNCHPAD_DOMAINS.iteritems():
99
74
        LAUNCHPAD_INSTANCE[instance] = 'https://xmlrpc.%s/bazaar/' % domain
100
75
 
101
 
    # We use production as the default because edge has been deprecated circa
102
 
    # 2010-11 (see bug https://bugs.launchpad.net/bzr/+bug/583667)
103
 
    DEFAULT_INSTANCE = 'production'
 
76
    # We use edge as the default because:
 
77
    # Beta users get redirected to it
 
78
    # All users can use it
 
79
    # There is a bug in the launchpad side where redirection causes an OOPS.
 
80
    DEFAULT_INSTANCE = 'edge'
104
81
    DEFAULT_SERVICE_URL = LAUNCHPAD_INSTANCE[DEFAULT_INSTANCE]
105
82
 
106
83
    transport = None
113
90
        self._lp_instance = lp_instance
114
91
        if transport is None:
115
92
            uri_type = urllib.splittype(self.service_url)[0]
116
 
            transport = XMLRPCTransport(uri_type)
 
93
            if uri_type == 'https':
 
94
                transport = xmlrpclib.SafeTransport()
 
95
            else:
 
96
                transport = xmlrpclib.Transport()
117
97
            transport.user_agent = 'bzr/%s (xmlrpclib/%s)' \
118
98
                    % (_bzrlib_version, xmlrpclib.__version__)
119
99
        self.transport = transport
120
100
 
 
101
 
121
102
    @property
122
103
    def service_url(self):
123
104
        """Return the http or https url for the xmlrpc server.
135
116
        else:
136
117
            return self.DEFAULT_SERVICE_URL
137
118
 
138
 
    @classmethod
139
 
    def for_url(cls, url, **kwargs):
140
 
        """Return the Launchpad service corresponding to the given URL."""
141
 
        result = urlsplit(url)
142
 
        lp_instance = result[1]
143
 
        if lp_instance == '':
144
 
            lp_instance = None
145
 
        elif lp_instance not in cls.LAUNCHPAD_INSTANCE:
146
 
            raise errors.InvalidURL(path=url)
147
 
        return cls(lp_instance=lp_instance, **kwargs)
148
 
 
149
119
    def get_proxy(self, authenticated):
150
120
        """Return the proxy for XMLRPC requests."""
151
121
        if authenticated:
207
177
                # TODO: print more headers to help in tracking down failures
208
178
                raise errors.BzrError("xmlrpc protocol error connecting to %s: %s %s"
209
179
                        % (self.service_url, e.errcode, e.errmsg))
210
 
        except socket.gaierror, e:
211
 
            raise errors.ConnectionError(
212
 
                "Could not resolve '%s'" % self.domain,
213
 
                orig_error=e)
214
180
        return result
215
181
 
216
182
    @property
221
187
            instance = self._lp_instance
222
188
        return self.LAUNCHPAD_DOMAINS[instance]
223
189
 
224
 
    def _guess_branch_path(self, branch_url, _request_factory=None):
 
190
    def get_web_url_from_branch_url(self, branch_url, _request_factory=None):
 
191
        """Get the Launchpad web URL for the given branch URL.
 
192
 
 
193
        :raise errors.InvalidURL: if 'branch_url' cannot be identified as a
 
194
            Launchpad branch URL.
 
195
        :return: The URL of the branch on Launchpad.
 
196
        """
225
197
        scheme, hostinfo, path = urlsplit(branch_url)[:3]
226
198
        if _request_factory is None:
227
199
            _request_factory = ResolveLaunchpadPathRequest
239
211
                for domain in self.LAUNCHPAD_DOMAINS.itervalues())
240
212
            if hostinfo not in domains:
241
213
                raise NotLaunchpadBranch(branch_url)
242
 
        return path.lstrip('/')
243
 
 
244
 
    def get_web_url_from_branch_url(self, branch_url, _request_factory=None):
245
 
        """Get the Launchpad web URL for the given branch URL.
246
 
 
247
 
        :raise errors.InvalidURL: if 'branch_url' cannot be identified as a
248
 
            Launchpad branch URL.
249
 
        :return: The URL of the branch on Launchpad.
250
 
        """
251
 
        path = self._guess_branch_path(branch_url, _request_factory)
252
214
        return urlutils.join('https://code.%s' % self.domain, path)
253
215
 
254
216
 
352
314
    def __init__(self, path):
353
315
        if not path:
354
316
            raise errors.InvalidURL(path=path,
355
 
                                    extra="You must specify a project.")
 
317
                                    extra="You must specify a product.")
356
318
        self.path = path
357
319
 
358
320
    def _request_params(self):