1060
1060
response_marker = request_marker = MESSAGE_VERSION_THREE
1062
1062
def __init__(self, write_func):
1064
1064
self._real_write_func = write_func
1066
1066
def _write_func(self, bytes):
1067
self._buf.append(bytes)
1068
if len(self._buf) > 100:
1069
1071
def flush(self):
1071
self._real_write_func(self._buf)
1073
self._real_write_func(''.join(self._buf))
1074
1076
def _serialise_offsets(self, offsets):
1075
1077
"""Serialise a readv offset list."""
1158
1160
if response.body is not None:
1159
1161
self._write_prefixed_body(response.body)
1160
1162
elif response.body_stream is not None:
1161
for chunk in response.body_stream:
1162
self._write_prefixed_body(chunk)
1163
for exc_info, chunk in _iter_with_errors(response.body_stream):
1164
if exc_info is not None:
1165
self._write_error_status()
1166
error_struct = request._translate_error(exc_info[1])
1167
self._write_structure(error_struct)
1170
if isinstance(chunk, request.FailedSmartServerResponse):
1171
self._write_error_status()
1172
self._write_structure(chunk.args)
1174
self._write_prefixed_body(chunk)
1164
1175
self._write_end()
1178
def _iter_with_errors(iterable):
1179
"""Handle errors from iterable.next().
1183
for exc_info, value in _iter_with_errors(iterable):
1186
This is a safer alternative to::
1189
for value in iterable:
1194
Because the latter will catch errors from the for-loop body, not just
1197
If an error occurs, exc_info will be a exc_info tuple, and the generator
1198
will terminate. Otherwise exc_info will be None, and value will be the
1199
value from iterable.next(). Note that KeyboardInterrupt and SystemExit
1200
will not be itercepted.
1202
iterator = iter(iterable)
1205
yield None, iterator.next()
1206
except StopIteration:
1208
except (KeyboardInterrupt, SystemExit):
1211
yield sys.exc_info(), None
1167
1215
class ProtocolThreeRequester(_ProtocolThreeEncoder, Requester):
1169
1217
def __init__(self, medium_request):
1242
1290
# have finished sending the stream. We would notice at the end
1243
1291
# anyway, but if the medium can deliver it early then it's good
1244
1292
# to short-circuit the whole request...
1293
for exc_info, part in _iter_with_errors(stream):
1294
if exc_info is not None:
1295
# Iterating the stream failed. Cleanly abort the request.
1296
self._write_error_status()
1297
# Currently the client unconditionally sends ('error',) as the
1299
self._write_structure(('error',))
1301
self._medium_request.finished_writing()
1302
raise exc_info[0], exc_info[1], exc_info[2]
1247
1304
self._write_prefixed_body(part)
1250
exc_info = sys.exc_info()
1251
# Iterating the stream failed. Cleanly abort the request.
1252
self._write_error_status()
1253
# Currently the client unconditionally sends ('error',) as the
1255
self._write_structure(('error',))
1257
self._medium_request.finished_writing()
1258
raise exc_info[0], exc_info[1], exc_info[2]
1259
1306
self._write_end()
1260
1307
self._medium_request.finished_writing()