Adding wip version for meego harmattan
[feedingit] / psa_harmattan / feedingit / deb_dist / feedingit-0.1.0 / pysrc / httpprogresshandler.py
1 #!/usr/bin/env python2.5
2
3 # Copyright (c) 2011 Neal H. Walfield <neal@walfield.org>
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 import urllib2 
19 import httplib
20 import time
21 import logging
22 logger = logging.getLogger(__name__)
23
24 class ProgressSocket(object):
25     """
26     Monitor what is being sent and received.
27     """
28     def __init__(self, socket, connection):
29         self.socket = socket
30         self.connection = connection
31
32     def __getattribute__(self, attr):
33         # logger.debug("%s.__getattribute__(%s)"
34         #              % (self.__class__.__name__, attr))
35
36         def send(data):
37             # 100k at a time.
38             bs = 100 * 1024
39             sent = 0
40             while sent < len (data):
41                 remaining = len (data) - sent
42                 if remaining < bs:
43                     amount = remaining
44                 else:
45                     amount = bs
46         
47                 self.socket.sendall(data[sent:sent+amount])
48                 sent += amount
49                 self.connection.stats['sent'] += amount
50                 self.connection.opener.stats['sent'] += amount
51         
52                 if self.connection.callback is not None:
53                     self.connection.callback ()
54         
55         def read(*args, **kwargs):
56             data = self.socket.read (*args, **kwargs)
57             # print "GOT: %s" % (data[0:240],)
58             self.connection.stats['received'] += len (data)
59             self.connection.opener.stats['received'] += len (data)
60             if self.connection.callback is not None:
61                 self.connection.callback ()
62             return data
63
64         if attr == 'send' or attr == 'sendall':
65             return send
66         if attr == 'read':
67             return read
68
69         try:
70             return super (ProgressSocket, self).__getattribute__(attr)
71         except AttributeError:
72             socket = super (ProgressSocket, self).__getattribute__('socket')
73             return socket.__getattribute__(attr)
74
75     def makefile(self, mode, bufsize):
76         return ProgressSocket (socket=self.socket.makefile(mode, bufsize),
77                                connection=self.connection)
78
79     def close(self):
80         return self.socket.close ()
81
82 def HTTPProgressConnectionBuilder(callback, opener):
83     class HTTPProgressConnection(httplib.HTTPConnection):
84         def __init__(self, *args, **kwargs):
85             self.method = None
86             self.url = None
87             return httplib.HTTPConnection.__init__ (self, *args, **kwargs)
88
89         def putrequest(self, method, url, *args, **kwargs):
90             self.method = method
91             self.url = url
92             return httplib.HTTPConnection.putrequest (
93                 self, method, url, *args, **kwargs)
94
95         def connect(self):
96             httplib.HTTPConnection.connect(self)
97             # Wrap the socket.
98             self.sock = ProgressSocket(socket=self.sock,
99                                        connection=self)
100
101     HTTPProgressConnection.callback = callback
102     HTTPProgressConnection.opener = opener
103     HTTPProgressConnection.stats \
104         = {'sent': 0, 'received': 0, 'started':time.time()}
105     return HTTPProgressConnection
106
107 class HTTPProgressHandler(urllib2.HTTPHandler):
108     def __init__(self, callback):
109         self.callback = callback
110         self.stats = {'sent': 0, 'received': 0, 'started':time.time()}
111         return urllib2.HTTPHandler.__init__(self)
112
113     def http_open(self, request):
114         return self.do_open(
115             HTTPProgressConnectionBuilder(self.callback, self),
116             request)
117
118 if __name__ == '__main__':
119     def callback(connection):
120         req = ""
121         if connection.method:
122             req += connection.method + " "
123         req += connection.host + ':' + str (connection.port)
124         if connection.url:
125             req += connection.url
126
127         cstats = connection.stats
128         ostats = connection.opener.stats
129
130         print(
131             ("%s: connection: %d sent, %d received: %d kb/s; "
132              + "opener: %d sent, %d received, %d kb/s")
133             % (req,
134                cstats['sent'], cstats['received'],
135                ((cstats['sent'] + cstats['received'])
136                 / (time.time() - cstats['started']) / 1024),
137                ostats['sent'], ostats['received'],
138                ((ostats['sent'] + ostats['received'])
139                 / (time.time() - ostats['started']) / 1024)))
140
141     opener = urllib2.build_opener(HTTPProgressHandler(callback))
142
143     data = opener.open ('http://google.com')
144     downloaded = 0
145     for d in data:
146         downloaded += len (d)
147     print "Document is %d bytes in size" % (downloaded,)