annotate upmana/mercurial/keepalive.py @ 39:ed322725b928 ornery-orc tip

Traipse 'OpenRPG' {110114-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Closed) New Features: New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order New to Server GUI, can now clear log New Earthdawn Dieroller New IronClaw roller, sheet, and image New ShapeShifter PC Sheet Updates: Update to Warhammer PC Sheet. Rollers set as macros. Should work with little maintanence. Update to Browser Server window. Display rooms with ' " & cleaner Update to Server. Handles ' " & cleaner Update to Dieroller. Cleaner, more effecient expression system Update to Hidden Die plugin, allows for non standard dice rolls Update to location.py, allows for more portable references when starting Traipse Update to the Features node Fixes: Fix to InterParse that was causing an Infernal Loop with Namespace Internal Fix to XML data, removed old Minidom and switched to Element Tree Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread Fix to Server, removing wxPython dependencies where not needed Fix to metaservers.xml file not being created Fix to Single and Double quotes in Whiteboard text Fix to Background images not showing when using the Image Server Fix to Duplicate chat names appearing Fix to Server GUI's logging output Fix to FNB.COLORFUL_TABS bug Fix to Gametree for XSLT Sheets Fix to Gametree for locating gametree files Fix to Send to Chat from Gametree Fix to Gametree, renaming and remapping operates correctly Fix to aliaslib, prevents error caused when SafeHTML is sent None
author sirebral
date Fri, 14 Jan 2011 05:24:52 -0600
parents ff154cf3350c
children
rev   line source
28
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1 # This library is free software; you can redistribute it and/or
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
2 # modify it under the terms of the GNU Lesser General Public
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
3 # License as published by the Free Software Foundation; either
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
4 # version 2.1 of the License, or (at your option) any later version.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
5 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
6 # This library is distributed in the hope that it will be useful,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
9 # Lesser General Public License for more details.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
10 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
11 # You should have received a copy of the GNU Lesser General Public
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
12 # License along with this library; if not, write to the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
13 # Free Software Foundation, Inc.,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
14 # 59 Temple Place, Suite 330,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
15 # Boston, MA 02111-1307 USA
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
16
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
17 # This file is part of urlgrabber, a high-level cross-protocol url-grabber
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
18 # Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
19
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
20 # Modified by Benoit Boissinot:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
21 # - fix for digest auth (inspired from urllib2.py @ Python v2.4)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
22 # Modified by Dirkjan Ochtman:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
23 # - import md5 function from a local util module
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
24 # Modified by Martin Geisler:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
25 # - moved md5 function from local util module to this module
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
26
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
27 """An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
28
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
29 >>> import urllib2
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
30 >>> from keepalive import HTTPHandler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
31 >>> keepalive_handler = HTTPHandler()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
32 >>> opener = urllib2.build_opener(keepalive_handler)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
33 >>> urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
34 >>>
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
35 >>> fo = urllib2.urlopen('http://www.python.org')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
36
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
37 If a connection to a given host is requested, and all of the existing
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
38 connections are still in use, another connection will be opened. If
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
39 the handler tries to use an existing connection but it fails in some
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
40 way, it will be closed and removed from the pool.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
41
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
42 To remove the handler, simply re-run build_opener with no arguments, and
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
43 install that opener.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
44
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
45 You can explicitly close connections by using the close_connection()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
46 method of the returned file-like object (described below) or you can
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
47 use the handler methods:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
48
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
49 close_connection(host)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
50 close_all()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
51 open_connections()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
52
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
53 NOTE: using the close_connection and close_all methods of the handler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
54 should be done with care when using multiple threads.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
55 * there is nothing that prevents another thread from creating new
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
56 connections immediately after connections are closed
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
57 * no checks are done to prevent in-use connections from being closed
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
58
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
59 >>> keepalive_handler.close_all()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
60
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
61 EXTRA ATTRIBUTES AND METHODS
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
62
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
63 Upon a status of 200, the object returned has a few additional
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
64 attributes and methods, which should not be used if you want to
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
65 remain consistent with the normal urllib2-returned objects:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
66
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
67 close_connection() - close the connection to the host
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
68 readlines() - you know, readlines()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
69 status - the return status (ie 404)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
70 reason - english translation of status (ie 'File not found')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
71
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
72 If you want the best of both worlds, use this inside an
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
73 AttributeError-catching try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
74
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
75 >>> try: status = fo.status
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
76 >>> except AttributeError: status = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
77
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
78 Unfortunately, these are ONLY there if status == 200, so it's not
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
79 easy to distinguish between non-200 responses. The reason is that
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
80 urllib2 tries to do clever things with error codes 301, 302, 401,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
81 and 407, and it wraps the object upon return.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
82
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
83 For python versions earlier than 2.4, you can avoid this fancy error
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
84 handling by setting the module-level global HANDLE_ERRORS to zero.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
85 You see, prior to 2.4, it's the HTTP Handler's job to determine what
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
86 to handle specially, and what to just pass up. HANDLE_ERRORS == 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
87 means "pass everything up". In python 2.4, however, this job no
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
88 longer belongs to the HTTP Handler and is now done by a NEW handler,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
89 HTTPErrorProcessor. Here's the bottom line:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
90
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
91 python version < 2.4
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
92 HANDLE_ERRORS == 1 (default) pass up 200, treat the rest as
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
93 errors
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
94 HANDLE_ERRORS == 0 pass everything up, error processing is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
95 left to the calling code
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
96 python version >= 2.4
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
97 HANDLE_ERRORS == 1 pass up 200, treat the rest as errors
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
98 HANDLE_ERRORS == 0 (default) pass everything up, let the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
99 other handlers (specifically,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
100 HTTPErrorProcessor) decide what to do
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
101
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
102 In practice, setting the variable either way makes little difference
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
103 in python 2.4, so for the most consistent behavior across versions,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
104 you probably just want to use the defaults, which will give you
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
105 exceptions on errors.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
106
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
107 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
108
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
109 # $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
110
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
111 import urllib2
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
112 import httplib
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
113 import socket
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
114 import thread
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
115
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
116 DEBUG = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
117
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
118 import sys
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
119 if sys.version_info < (2, 4): HANDLE_ERRORS = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
120 else: HANDLE_ERRORS = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
121
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
122 class ConnectionManager:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
123 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
124 The connection manager must be able to:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
125 * keep track of all existing
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
126 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
127 def __init__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
128 self._lock = thread.allocate_lock()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
129 self._hostmap = {} # map hosts to a list of connections
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
130 self._connmap = {} # map connections to host
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
131 self._readymap = {} # map connection to ready state
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
132
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
133 def add(self, host, connection, ready):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
134 self._lock.acquire()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
135 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
136 if not host in self._hostmap: self._hostmap[host] = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
137 self._hostmap[host].append(connection)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
138 self._connmap[connection] = host
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
139 self._readymap[connection] = ready
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
140 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
141 self._lock.release()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
142
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
143 def remove(self, connection):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
144 self._lock.acquire()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
145 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
146 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
147 host = self._connmap[connection]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
148 except KeyError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
149 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
150 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
151 del self._connmap[connection]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
152 del self._readymap[connection]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
153 self._hostmap[host].remove(connection)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
154 if not self._hostmap[host]: del self._hostmap[host]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
155 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
156 self._lock.release()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
157
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
158 def set_ready(self, connection, ready):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
159 try: self._readymap[connection] = ready
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
160 except KeyError: pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
161
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
162 def get_ready_conn(self, host):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
163 conn = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
164 self._lock.acquire()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
165 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
166 if host in self._hostmap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
167 for c in self._hostmap[host]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
168 if self._readymap[c]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
169 self._readymap[c] = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
170 conn = c
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
171 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
172 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
173 self._lock.release()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
174 return conn
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
175
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
176 def get_all(self, host=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
177 if host:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
178 return list(self._hostmap.get(host, []))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
179 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
180 return dict(self._hostmap)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
181
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
182 class KeepAliveHandler:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
183 def __init__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
184 self._cm = ConnectionManager()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
185
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
186 #### Connection Management
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
187 def open_connections(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
188 """return a list of connected hosts and the number of connections
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
189 to each. [('foo.com:80', 2), ('bar.org', 1)]"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
190 return [(host, len(li)) for (host, li) in self._cm.get_all().items()]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
191
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
192 def close_connection(self, host):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
193 """close connection(s) to <host>
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
194 host is the host:port spec, as in 'www.cnn.com:8080' as passed in.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
195 no error occurs if there is no connection to that host."""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
196 for h in self._cm.get_all(host):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
197 self._cm.remove(h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
198 h.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
199
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
200 def close_all(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
201 """close all open connections"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
202 for host, conns in self._cm.get_all().iteritems():
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
203 for h in conns:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
204 self._cm.remove(h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
205 h.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
206
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
207 def _request_closed(self, request, host, connection):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
208 """tells us that this request is now closed and the the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
209 connection is ready for another request"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
210 self._cm.set_ready(connection, 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
211
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
212 def _remove_connection(self, host, connection, close=0):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
213 if close: connection.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
214 self._cm.remove(connection)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
215
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
216 #### Transaction Execution
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
217 def http_open(self, req):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
218 return self.do_open(HTTPConnection, req)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
219
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
220 def do_open(self, http_class, req):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
221 host = req.get_host()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
222 if not host:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
223 raise urllib2.URLError('no host given')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
224
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
225 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
226 h = self._cm.get_ready_conn(host)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
227 while h:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
228 r = self._reuse_connection(h, req, host)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
229
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
230 # if this response is non-None, then it worked and we're
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
231 # done. Break out, skipping the else block.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
232 if r: break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
233
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
234 # connection is bad - possibly closed by server
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
235 # discard it and ask for the next free connection
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
236 h.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
237 self._cm.remove(h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
238 h = self._cm.get_ready_conn(host)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
239 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
240 # no (working) free connections were found. Create a new one.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
241 h = http_class(host)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
242 if DEBUG: DEBUG.info("creating new connection to %s (%d)",
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
243 host, id(h))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
244 self._cm.add(host, h, 0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
245 self._start_transaction(h, req)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
246 r = h.getresponse()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
247 except (socket.error, httplib.HTTPException), err:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
248 raise urllib2.URLError(err)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
249
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
250 # if not a persistent connection, don't try to reuse it
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
251 if r.will_close: self._cm.remove(h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
252
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
253 if DEBUG: DEBUG.info("STATUS: %s, %s", r.status, r.reason)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
254 r._handler = self
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
255 r._host = host
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
256 r._url = req.get_full_url()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
257 r._connection = h
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
258 r.code = r.status
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
259 r.headers = r.msg
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
260 r.msg = r.reason
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
261
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
262 if r.status == 200 or not HANDLE_ERRORS:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
263 return r
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
264 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
265 return self.parent.error('http', req, r,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
266 r.status, r.msg, r.headers)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
267
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
268 def _reuse_connection(self, h, req, host):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
269 """start the transaction with a re-used connection
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
270 return a response object (r) upon success or None on failure.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
271 This DOES not close or remove bad connections in cases where
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
272 it returns. However, if an unexpected exception occurs, it
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
273 will close and remove the connection before re-raising.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
274 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
275 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
276 self._start_transaction(h, req)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
277 r = h.getresponse()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
278 # note: just because we got something back doesn't mean it
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
279 # worked. We'll check the version below, too.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
280 except (socket.error, httplib.HTTPException):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
281 r = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
282 except:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
283 # adding this block just in case we've missed
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
284 # something we will still raise the exception, but
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
285 # lets try and close the connection and remove it
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
286 # first. We previously got into a nasty loop
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
287 # where an exception was uncaught, and so the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
288 # connection stayed open. On the next try, the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
289 # same exception was raised, etc. The tradeoff is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
290 # that it's now possible this call will raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
291 # a DIFFERENT exception
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
292 if DEBUG: DEBUG.error("unexpected exception - closing " + \
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
293 "connection to %s (%d)", host, id(h))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
294 self._cm.remove(h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
295 h.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
296 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
297
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
298 if r is None or r.version == 9:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
299 # httplib falls back to assuming HTTP 0.9 if it gets a
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
300 # bad header back. This is most likely to happen if
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
301 # the socket has been closed by the server since we
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
302 # last used the connection.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
303 if DEBUG: DEBUG.info("failed to re-use connection to %s (%d)",
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
304 host, id(h))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
305 r = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
306 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
307 if DEBUG: DEBUG.info("re-using connection to %s (%d)", host, id(h))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
308
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
309 return r
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
310
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
311 def _start_transaction(self, h, req):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
312 # What follows mostly reimplements HTTPConnection.request()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
313 # except it adds self.parent.addheaders in the mix.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
314 headers = req.headers.copy()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
315 if sys.version_info >= (2, 4):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
316 headers.update(req.unredirected_hdrs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
317 headers.update(self.parent.addheaders)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
318 headers = dict((n.lower(), v) for n,v in headers.items())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
319 skipheaders = {}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
320 for n in ('host', 'accept-encoding'):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
321 if n in headers:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
322 skipheaders['skip_' + n.replace('-', '_')] = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
323 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
324 if req.has_data():
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
325 data = req.get_data()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
326 h.putrequest('POST', req.get_selector(), **skipheaders)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
327 if 'content-type' not in headers:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
328 h.putheader('Content-type',
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
329 'application/x-www-form-urlencoded')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
330 if 'content-length' not in headers:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
331 h.putheader('Content-length', '%d' % len(data))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
332 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
333 h.putrequest('GET', req.get_selector(), **skipheaders)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
334 except (socket.error), err:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
335 raise urllib2.URLError(err)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
336 for k, v in headers.items():
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
337 h.putheader(k, v)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
338 h.endheaders()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
339 if req.has_data():
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
340 h.send(data)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
341
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
342 class HTTPHandler(KeepAliveHandler, urllib2.HTTPHandler):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
343 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
344
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
345 class HTTPResponse(httplib.HTTPResponse):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
346 # we need to subclass HTTPResponse in order to
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
347 # 1) add readline() and readlines() methods
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
348 # 2) add close_connection() methods
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
349 # 3) add info() and geturl() methods
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
350
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
351 # in order to add readline(), read must be modified to deal with a
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
352 # buffer. example: readline must read a buffer and then spit back
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
353 # one line at a time. The only real alternative is to read one
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
354 # BYTE at a time (ick). Once something has been read, it can't be
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
355 # put back (ok, maybe it can, but that's even uglier than this),
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
356 # so if you THEN do a normal read, you must first take stuff from
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
357 # the buffer.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
358
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
359 # the read method wraps the original to accomodate buffering,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
360 # although read() never adds to the buffer.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
361 # Both readline and readlines have been stolen with almost no
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
362 # modification from socket.py
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
363
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
364
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
365 def __init__(self, sock, debuglevel=0, strict=0, method=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
366 if method: # the httplib in python 2.3 uses the method arg
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
367 httplib.HTTPResponse.__init__(self, sock, debuglevel, method)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
368 else: # 2.2 doesn't
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
369 httplib.HTTPResponse.__init__(self, sock, debuglevel)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
370 self.fileno = sock.fileno
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
371 self.code = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
372 self._rbuf = ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
373 self._rbufsize = 8096
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
374 self._handler = None # inserted by the handler later
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
375 self._host = None # (same)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
376 self._url = None # (same)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
377 self._connection = None # (same)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
378
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
379 _raw_read = httplib.HTTPResponse.read
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
380
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
381 def close(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
382 if self.fp:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
383 self.fp.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
384 self.fp = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
385 if self._handler:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
386 self._handler._request_closed(self, self._host,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
387 self._connection)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
388
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
389 def close_connection(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
390 self._handler._remove_connection(self._host, self._connection, close=1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
391 self.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
392
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
393 def info(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
394 return self.headers
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
395
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
396 def geturl(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
397 return self._url
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
398
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
399 def read(self, amt=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
400 # the _rbuf test is only in this first if for speed. It's not
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
401 # logically necessary
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
402 if self._rbuf and not amt is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
403 L = len(self._rbuf)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
404 if amt > L:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
405 amt -= L
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
406 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
407 s = self._rbuf[:amt]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
408 self._rbuf = self._rbuf[amt:]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
409 return s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
410
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
411 s = self._rbuf + self._raw_read(amt)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
412 self._rbuf = ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
413 return s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
414
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
415 # stolen from Python SVN #68532 to fix issue1088
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
416 def _read_chunked(self, amt):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
417 chunk_left = self.chunk_left
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
418 value = ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
419
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
420 # XXX This accumulates chunks by repeated string concatenation,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
421 # which is not efficient as the number or size of chunks gets big.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
422 while True:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
423 if chunk_left is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
424 line = self.fp.readline()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
425 i = line.find(';')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
426 if i >= 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
427 line = line[:i] # strip chunk-extensions
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
428 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
429 chunk_left = int(line, 16)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
430 except ValueError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
431 # close the connection as protocol synchronisation is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
432 # probably lost
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
433 self.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
434 raise httplib.IncompleteRead(value)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
435 if chunk_left == 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
436 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
437 if amt is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
438 value += self._safe_read(chunk_left)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
439 elif amt < chunk_left:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
440 value += self._safe_read(amt)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
441 self.chunk_left = chunk_left - amt
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
442 return value
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
443 elif amt == chunk_left:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
444 value += self._safe_read(amt)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
445 self._safe_read(2) # toss the CRLF at the end of the chunk
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
446 self.chunk_left = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
447 return value
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
448 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
449 value += self._safe_read(chunk_left)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
450 amt -= chunk_left
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
451
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
452 # we read the whole chunk, get another
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
453 self._safe_read(2) # toss the CRLF at the end of the chunk
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
454 chunk_left = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
455
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
456 # read and discard trailer up to the CRLF terminator
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
457 ### note: we shouldn't have any trailers!
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
458 while True:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
459 line = self.fp.readline()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
460 if not line:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
461 # a vanishingly small number of sites EOF without
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
462 # sending the trailer
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
463 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
464 if line == '\r\n':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
465 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
466
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
467 # we read everything; close the "file"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
468 self.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
469
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
470 return value
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
471
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
472 def readline(self, limit=-1):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
473 i = self._rbuf.find('\n')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
474 while i < 0 and not (0 < limit <= len(self._rbuf)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
475 new = self._raw_read(self._rbufsize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
476 if not new: break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
477 i = new.find('\n')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
478 if i >= 0: i = i + len(self._rbuf)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
479 self._rbuf = self._rbuf + new
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
480 if i < 0: i = len(self._rbuf)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
481 else: i = i+1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
482 if 0 <= limit < len(self._rbuf): i = limit
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
483 data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
484 return data
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
485
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
486 def readlines(self, sizehint = 0):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
487 total = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
488 list = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
489 while 1:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
490 line = self.readline()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
491 if not line: break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
492 list.append(line)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
493 total += len(line)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
494 if sizehint and total >= sizehint:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
495 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
496 return list
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
497
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
498
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
499 class HTTPConnection(httplib.HTTPConnection):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
500 # use the modified response class
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
501 response_class = HTTPResponse
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
502
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
503 #########################################################################
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
504 ##### TEST FUNCTIONS
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
505 #########################################################################
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
506
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
507 def error_handler(url):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
508 global HANDLE_ERRORS
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
509 orig = HANDLE_ERRORS
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
510 keepalive_handler = HTTPHandler()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
511 opener = urllib2.build_opener(keepalive_handler)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
512 urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
513 pos = {0: 'off', 1: 'on'}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
514 for i in (0, 1):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
515 print " fancy error handling %s (HANDLE_ERRORS = %i)" % (pos[i], i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
516 HANDLE_ERRORS = i
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
517 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
518 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
519 fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
520 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
521 try: status, reason = fo.status, fo.reason
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
522 except AttributeError: status, reason = None, None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
523 except IOError, e:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
524 print " EXCEPTION: %s" % e
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
525 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
526 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
527 print " status = %s, reason = %s" % (status, reason)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
528 HANDLE_ERRORS = orig
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
529 hosts = keepalive_handler.open_connections()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
530 print "open connections:", hosts
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
531 keepalive_handler.close_all()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
532
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
533 def md5(s):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
534 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
535 from hashlib import md5 as _md5
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
536 except ImportError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
537 from md5 import md5 as _md5
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
538 global md5
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
539 md5 = _md5
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
540 return _md5(s)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
541
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
542 def continuity(url):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
543 format = '%25s: %s'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
544
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
545 # first fetch the file with the normal http handler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
546 opener = urllib2.build_opener()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
547 urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
548 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
549 foo = fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
550 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
551 m = md5.new(foo)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
552 print format % ('normal urllib', m.hexdigest())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
553
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
554 # now install the keepalive handler and try again
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
555 opener = urllib2.build_opener(HTTPHandler())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
556 urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
557
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
558 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
559 foo = fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
560 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
561 m = md5.new(foo)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
562 print format % ('keepalive read', m.hexdigest())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
563
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
564 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
565 foo = ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
566 while 1:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
567 f = fo.readline()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
568 if f: foo = foo + f
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
569 else: break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
570 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
571 m = md5.new(foo)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
572 print format % ('keepalive readline', m.hexdigest())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
573
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
574 def comp(N, url):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
575 print ' making %i connections to:\n %s' % (N, url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
576
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
577 sys.stdout.write(' first using the normal urllib handlers')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
578 # first use normal opener
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
579 opener = urllib2.build_opener()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
580 urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
581 t1 = fetch(N, url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
582 print ' TIME: %.3f s' % t1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
583
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
584 sys.stdout.write(' now using the keepalive handler ')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
585 # now install the keepalive handler and try again
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
586 opener = urllib2.build_opener(HTTPHandler())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
587 urllib2.install_opener(opener)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
588 t2 = fetch(N, url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
589 print ' TIME: %.3f s' % t2
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
590 print ' improvement factor: %.2f' % (t1/t2, )
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
591
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
592 def fetch(N, url, delay=0):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
593 import time
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
594 lens = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
595 starttime = time.time()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
596 for i in range(N):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
597 if delay and i > 0: time.sleep(delay)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
598 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
599 foo = fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
600 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
601 lens.append(len(foo))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
602 diff = time.time() - starttime
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
603
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
604 j = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
605 for i in lens[1:]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
606 j = j + 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
607 if not i == lens[0]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
608 print "WARNING: inconsistent length on read %i: %i" % (j, i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
609
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
610 return diff
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
611
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
612 def test_timeout(url):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
613 global DEBUG
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
614 dbbackup = DEBUG
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
615 class FakeLogger:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
616 def debug(self, msg, *args): print msg % args
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
617 info = warning = error = debug
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
618 DEBUG = FakeLogger()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
619 print " fetching the file to establish a connection"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
620 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
621 data1 = fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
622 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
623
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
624 i = 20
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
625 print " waiting %i seconds for the server to close the connection" % i
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
626 while i > 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
627 sys.stdout.write('\r %2i' % i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
628 sys.stdout.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
629 time.sleep(1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
630 i -= 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
631 sys.stderr.write('\r')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
632
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
633 print " fetching the file a second time"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
634 fo = urllib2.urlopen(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
635 data2 = fo.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
636 fo.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
637
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
638 if data1 == data2:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
639 print ' data are identical'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
640 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
641 print ' ERROR: DATA DIFFER'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
642
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
643 DEBUG = dbbackup
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
644
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
645
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
646 def test(url, N=10):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
647 print "checking error hander (do this on a non-200)"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
648 try: error_handler(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
649 except IOError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
650 print "exiting - exception will prevent further tests"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
651 sys.exit()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
652 print
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
653 print "performing continuity test (making sure stuff isn't corrupted)"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
654 continuity(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
655 print
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
656 print "performing speed comparison"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
657 comp(N, url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
658 print
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
659 print "performing dropped-connection check"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
660 test_timeout(url)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
661
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
662 if __name__ == '__main__':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
663 import time
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
664 import sys
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
665 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
666 N = int(sys.argv[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
667 url = sys.argv[2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
668 except:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
669 print "%s <integer> <url>" % sys.argv[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
670 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
671 test(url, N)