~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/_urllib2_wrappers.py

  • Committer: Vincent Ladeuil
  • Date: 2009-02-05 10:20:51 UTC
  • mfrom: (3945.1.8 pb-http)
  • mto: This revision was merged to the branch mainline in revision 3983.
  • Revision ID: v.ladeuil+lp@free.fr-20090205102051-gyivrlud1hk1c12g
Progress bar at socket level for http

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
    )
68
68
 
69
69
 
70
 
class _BufferedMakefileSocket(object):
71
 
 
72
 
    def __init__(self, sock):
 
70
class _ReportingFileSocket(object):
 
71
 
 
72
    def __init__(self, filesock, report_activity=None):
 
73
        self.filesock = filesock
 
74
        self._report_activity = report_activity
 
75
 
 
76
 
 
77
    def read(self, size=1):
 
78
        s = self.filesock.read(size)
 
79
        self._report_activity(len(s), 'read')
 
80
        return s
 
81
 
 
82
    def readline(self, size=-1):
 
83
        s = self.filesock.readline(size)
 
84
        self._report_activity(len(s), 'read')
 
85
        return s
 
86
 
 
87
    def __getattr__(self, name):
 
88
        return getattr(self.filesock, name)
 
89
 
 
90
 
 
91
class _ReportingSocket(object):
 
92
 
 
93
    def __init__(self, sock, report_activity=None):
73
94
        self.sock = sock
 
95
        self._report_activity = report_activity
 
96
 
 
97
    def send(self, s, *args):
 
98
        self.sock.send(s, *args)
 
99
        self._report_activity(len(s), 'write')
 
100
 
 
101
    def sendall(self, s, *args):
 
102
        self.sock.send(s, *args)
 
103
        self._report_activity(len(s), 'write')
 
104
 
 
105
    def recv(self, *args):
 
106
        s = self.sock.recv(*args)
 
107
        self._report_activity(len(s), 'read')
 
108
        return s
74
109
 
75
110
    def makefile(self, mode='r', bufsize=-1):
76
 
        return self.sock.makefile(mode, 65536)
 
111
        # httplib creates a fileobject that doesn't do buffering, which
 
112
        # makes fp.readline() very expensive because it only reads one byte
 
113
        # at a time.  So we wrap the socket in an object that forces
 
114
        # sock.makefile to make a buffered file.
 
115
        fsock = self.sock.makefile(mode, 65536)
 
116
        # And wrap that into a reporting kind of fileobject
 
117
        return _ReportingFileSocket(fsock, self._report_activity)
77
118
 
78
119
    def __getattr__(self, name):
79
120
        return getattr(self.sock, name)
96
137
    # 8k chunks should be fine.
97
138
    _discarded_buf_size = 8192
98
139
 
99
 
    def __init__(self, sock, *args, **kwargs):
100
 
        # httplib creates a fileobject that doesn't do buffering, which
101
 
        # makes fp.readline() very expensive because it only reads one byte
102
 
        # at a time.  So we wrap the socket in an object that forces
103
 
        # sock.makefile to make a buffered file.
104
 
        sock = _BufferedMakefileSocket(sock)
105
 
        httplib.HTTPResponse.__init__(self, sock, *args, **kwargs)
106
 
 
107
140
    def begin(self):
108
141
        """Begin to read the response from the server.
109
142
 
178
211
    # we want to warn. But not below a given thresold.
179
212
    _range_warning_thresold = 1024 * 1024
180
213
 
181
 
    def __init__(self):
 
214
    def __init__(self,
 
215
                 report_activity=None):
182
216
        self._response = None
 
217
        self._report_activity = report_activity
183
218
        self._ranges_received_whole_file = None
184
219
 
185
220
    def _mutter_connect(self):
216
251
        # Restore our preciousss
217
252
        self.sock = sock
218
253
 
 
254
    def _wrap_socket_for_reporting(self, sock):
 
255
        """Wrap the socket before anybody use it."""
 
256
        self.sock = _ReportingSocket(sock, self._report_activity)
 
257
 
219
258
 
220
259
class HTTPConnection(AbstractHTTPConnection, httplib.HTTPConnection):
221
260
 
222
261
    # XXX: Needs refactoring at the caller level.
223
 
    def __init__(self, host, port=None, proxied_host=None):
224
 
        AbstractHTTPConnection.__init__(self)
 
262
    def __init__(self, host, port=None, proxied_host=None,
 
263
                 report_activity=None):
 
264
        AbstractHTTPConnection.__init__(self, report_activity=report_activity)
225
265
        # Use strict=True since we don't support HTTP/0.9
226
266
        httplib.HTTPConnection.__init__(self, host, port, strict=True)
227
267
        self.proxied_host = proxied_host
230
270
        if 'http' in debug.debug_flags:
231
271
            self._mutter_connect()
232
272
        httplib.HTTPConnection.connect(self)
 
273
        self._wrap_socket_for_reporting(self.sock)
233
274
 
234
275
 
235
276
# Build the appropriate socket wrapper for ssl
248
289
class HTTPSConnection(AbstractHTTPConnection, httplib.HTTPSConnection):
249
290
 
250
291
    def __init__(self, host, port=None, key_file=None, cert_file=None,
251
 
                 proxied_host=None):
252
 
        AbstractHTTPConnection.__init__(self)
 
292
                 proxied_host=None,
 
293
                 report_activity=None):
 
294
        AbstractHTTPConnection.__init__(self, report_activity=report_activity)
253
295
        # Use strict=True since we don't support HTTP/0.9
254
296
        httplib.HTTPSConnection.__init__(self, host, port,
255
297
                                         key_file, cert_file, strict=True)
259
301
        if 'http' in debug.debug_flags:
260
302
            self._mutter_connect()
261
303
        httplib.HTTPConnection.connect(self)
 
304
        self._wrap_socket_for_reporting(self.sock)
262
305
        if self.proxied_host is None:
263
306
            self.connect_to_origin()
264
307
 
265
308
    def connect_to_origin(self):
266
 
        self.sock = _ssl_wrap_socket(self.sock, self.key_file, self.cert_file)
 
309
        ssl_sock = _ssl_wrap_socket(self.sock, self.key_file, self.cert_file)
 
310
        # Wrap the ssl socket before anybody use it
 
311
        self._wrap_socket_for_reporting(ssl_sock)
267
312
 
268
313
 
269
314
class Request(urllib2.Request):
355
400
 
356
401
    handler_order = 1000 # after all pre-processings
357
402
 
 
403
    def __init__(self, report_activity=None):
 
404
        self._report_activity = report_activity
 
405
 
358
406
    def create_connection(self, request, http_connection_class):
359
407
        host = request.get_host()
360
408
        if not host:
366
414
        # request is made)
367
415
        try:
368
416
            connection = http_connection_class(
369
 
                host, proxied_host=request.proxied_host)
 
417
                host, proxied_host=request.proxied_host,
 
418
                report_activity=self._report_activity)
370
419
        except httplib.InvalidURL, exception:
371
420
            # There is only one occurrence of InvalidURL in httplib
372
421
            raise errors.InvalidURL(request.get_full_url(),
1370
1419
    def __init__(self,
1371
1420
                 connection=ConnectionHandler,
1372
1421
                 redirect=HTTPRedirectHandler,
1373
 
                 error=HTTPErrorProcessor,):
1374
 
        self._opener = urllib2.build_opener( \
1375
 
            connection, redirect, error,
 
1422
                 error=HTTPErrorProcessor,
 
1423
                 report_activity=None):
 
1424
        self._opener = urllib2.build_opener(
 
1425
            connection(report_activity=report_activity),
 
1426
            redirect, error,
1376
1427
            ProxyHandler(),
1377
1428
            HTTPBasicAuthHandler(),
1378
1429
            HTTPDigestAuthHandler(),