@@ -63,11 +63,8 @@ def __init__ (self, conn=None):
6363 asyncore .dispatcher .__init__ (self , conn )
6464
6565 def set_terminator (self , term ):
66- "Set the input delimiter. Can be a fixed string of any length, or None"
67- if term is None :
68- self .terminator = ''
69- else :
70- self .terminator = term
66+ "Set the input delimiter. Can be a fixed string of any length, an integer, or None"
67+ self .terminator = term
7168
7269 def get_terminator (self ):
7370 return self .terminator
@@ -82,8 +79,7 @@ def handle_read (self):
8279 try :
8380 data = self .recv (self .ac_in_buffer_size )
8481 except socket .error , why :
85- import sys
86- self .handle_error (sys .exc_type , sys .exc_value , sys .exc_traceback )
82+ self .handle_error ()
8783 return
8884
8985 self .ac_in_buffer = self .ac_in_buffer + data
@@ -94,17 +90,33 @@ def handle_read (self):
9490 # combos with a single recv(1024).
9591
9692 while self .ac_in_buffer :
93+ lb = len (self .ac_in_buffer )
9794 terminator = self .get_terminator ()
98- terminator_len = len (terminator )
99- # 4 cases:
100- # 1) end of buffer matches terminator exactly:
101- # collect data, transition
102- # 2) end of buffer matches some prefix:
103- # collect data to the prefix
104- # 3) end of buffer does not match any prefix:
105- # collect data
106- # 4) no terminator, just collect the data
107- if terminator :
95+ if terminator is None :
96+ # no terminator, collect it all
97+ self .collect_incoming_data (self .ac_in_buffer )
98+ self .ac_in_buffer = ''
99+ elif type (terminator ) == type (0 ):
100+ # numeric terminator
101+ n = terminator
102+ if lb < n :
103+ self .collect_incoming_data (self .ac_in_buffer )
104+ self .ac_in_buffer = ''
105+ self .terminator = self .terminator - lb
106+ else :
107+ self .collect_incoming_data (self .ac_in_buffer [:n ])
108+ self .ac_in_buffer = self .ac_in_buffer [n :]
109+ self .terminator = 0
110+ self .found_terminator ()
111+ else :
112+ # 3 cases:
113+ # 1) end of buffer matches terminator exactly:
114+ # collect data, transition
115+ # 2) end of buffer matches some prefix:
116+ # collect data to the prefix
117+ # 3) end of buffer does not match any prefix:
118+ # collect data
119+ terminator_len = len (terminator )
108120 index = string .find (self .ac_in_buffer , terminator )
109121 if index != - 1 :
110122 # we found the terminator
@@ -116,18 +128,15 @@ def handle_read (self):
116128 # check for a prefix of the terminator
117129 index = find_prefix_at_end (self .ac_in_buffer , terminator )
118130 if index :
119- # we found a prefix, collect up to the prefix
120- self .collect_incoming_data (self .ac_in_buffer [:- index ])
121- self .ac_in_buffer = self .ac_in_buffer [- index :]
131+ if index != lb :
132+ # we found a prefix, collect up to the prefix
133+ self .collect_incoming_data (self .ac_in_buffer [:- index ])
134+ self .ac_in_buffer = self .ac_in_buffer [- index :]
122135 break
123136 else :
124137 # no prefix, collect it all
125138 self .collect_incoming_data (self .ac_in_buffer )
126139 self .ac_in_buffer = ''
127- else :
128- # no terminator, collect it all
129- self .collect_incoming_data (self .ac_in_buffer )
130- self .ac_in_buffer = ''
131140
132141 def handle_write (self ):
133142 self .initiate_send ()
@@ -144,17 +153,27 @@ def push_with_producer (self, producer):
144153 self .initiate_send ()
145154
146155 def readable (self ):
156+ "predicate for inclusion in the readable for select()"
147157 return (len (self .ac_in_buffer ) <= self .ac_in_buffer_size )
148158
149159 def writable (self ):
150- return len (self .ac_out_buffer ) or len (self .producer_fifo ) or (not self .connected )
160+ "predicate for inclusion in the writable for select()"
161+ # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected)
162+ # this is about twice as fast, though not as clear.
163+ return not (
164+ (self .ac_out_buffer is '' ) and
165+ self .producer_fifo .is_empty () and
166+ self .connected
167+ )
151168
152169 def close_when_done (self ):
170+ "automatically close this channel once the outgoing queue is empty"
153171 self .producer_fifo .push (None )
154172
155173 # refill the outgoing buffer by calling the more() method
156174 # of the first producer in the queue
157175 def refill_buffer (self ):
176+ _string_type = type ('' )
158177 while 1 :
159178 if len (self .producer_fifo ):
160179 p = self .producer_fifo .first ()
@@ -165,6 +184,10 @@ def refill_buffer (self):
165184 self .producer_fifo .pop ()
166185 self .close ()
167186 return
187+ elif type (p ) is _string_type :
188+ self .producer_fifo .pop ()
189+ self .ac_out_buffer = self .ac_out_buffer + p
190+ return
168191 data = p .more ()
169192 if data :
170193 self .ac_out_buffer = self .ac_out_buffer + data
@@ -177,14 +200,19 @@ def refill_buffer (self):
177200 def initiate_send (self ):
178201 obs = self .ac_out_buffer_size
179202 # try to refill the buffer
180- if (not self . _push_mode ) and ( len (self .ac_out_buffer ) < obs ):
203+ if (len (self .ac_out_buffer ) < obs ):
181204 self .refill_buffer ()
182205
183206 if self .ac_out_buffer and self .connected :
184207 # try to send the buffer
185- num_sent = self .send (self .ac_out_buffer [:obs ])
186- if num_sent :
187- self .ac_out_buffer = self .ac_out_buffer [num_sent :]
208+ try :
209+ num_sent = self .send (self .ac_out_buffer [:obs ])
210+ if num_sent :
211+ self .ac_out_buffer = self .ac_out_buffer [num_sent :]
212+
213+ except socket .error , why :
214+ self .handle_error ()
215+ return
188216
189217 def discard_buffers (self ):
190218 # Emergencies only!
@@ -193,17 +221,8 @@ def discard_buffers (self):
193221 while self .producer_fifo :
194222 self .producer_fifo .pop ()
195223
196- # ==================================================
197- # support for push mode.
198- # ==================================================
199- _push_mode = 0
200- def push_mode (self , boolean ):
201- self ._push_mode = boolean
202-
203- def writable_push (self ):
204- return self .connected and len (self .ac_out_buffer )
205-
206224class simple_producer :
225+
207226 def __init__ (self , data , buffer_size = 512 ):
208227 self .data = data
209228 self .buffer_size = buffer_size
@@ -228,6 +247,9 @@ def __init__ (self, list=None):
228247 def __len__ (self ):
229248 return len (self .list )
230249
250+ def is_empty (self ):
251+ return self .list == []
252+
231253 def first (self ):
232254 return self .list [0 ]
233255
0 commit comments