3245.4.31
by Andrew Bennetts
Fix year in copyright statement of message.py |
1 |
# Copyright (C) 2008 Canonical Ltd
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
4183.7.1
by Sabin Iacob
update FSF mailing address |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
16 |
|
3195.3.24
by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler. |
17 |
import collections |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
18 |
from cStringIO import StringIO |
19 |
||
3245.4.24
by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions. |
20 |
from bzrlib import ( |
21 |
debug, |
|
22 |
errors, |
|
23 |
)
|
|
24 |
from bzrlib.trace import mutter |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
25 |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
26 |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
27 |
class MessageHandler(object): |
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
28 |
"""Base class for handling messages received via the smart protocol.
|
29 |
||
30 |
As parts of a message are received, the corresponding PART_received method
|
|
31 |
will be called.
|
|
32 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
33 |
|
34 |
def __init__(self): |
|
35 |
self.headers = None |
|
36 |
||
37 |
def headers_received(self, headers): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
38 |
"""Called when message headers are received.
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
39 |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
40 |
This default implementation just stores them in self.headers.
|
41 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
42 |
self.headers = headers |
43 |
||
44 |
def byte_part_received(self, byte): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
45 |
"""Called when a 'byte' part is received.
|
46 |
||
47 |
Note that a 'byte' part is a message part consisting of exactly one
|
|
48 |
byte.
|
|
49 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
50 |
raise NotImplementedError(self.byte_received) |
51 |
||
52 |
def bytes_part_received(self, bytes): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
53 |
"""Called when a 'bytes' part is received.
|
54 |
||
55 |
A 'bytes' message part can contain any number of bytes. It should not
|
|
56 |
be confused with a 'byte' part, which is always a single byte.
|
|
57 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
58 |
raise NotImplementedError(self.bytes_received) |
59 |
||
60 |
def structure_part_received(self, structure): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
61 |
"""Called when a 'structure' part is received.
|
62 |
||
63 |
:param structure: some structured data, which will be some combination
|
|
64 |
of list, dict, int, and str objects.
|
|
65 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
66 |
raise NotImplementedError(self.bytes_received) |
67 |
||
68 |
def protocol_error(self, exception): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
69 |
"""Called when there is a protocol decoding error.
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
70 |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
71 |
The default implementation just re-raises the exception.
|
72 |
"""
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
73 |
raise
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
74 |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
75 |
def end_received(self): |
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
76 |
"""Called when the end of the message is received."""
|
3245.4.27
by Andrew Bennetts
Tidy some XXXs in bzrlib/smart/message.py. |
77 |
# No-op by default.
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
78 |
pass
|
79 |
||
80 |
||
81 |
class ConventionalRequestHandler(MessageHandler): |
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
82 |
"""A message handler for "conventional" requests.
|
83 |
||
84 |
"Conventional" is used in the sense described in
|
|
85 |
doc/developers/network-protocol.txt: a simple message with arguments and an
|
|
86 |
optional body.
|
|
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
87 |
|
88 |
Possible states:
|
|
3842.3.19
by Andrew Bennetts
Tweaks suggested by review. |
89 |
* args: expecting args
|
90 |
* body: expecting body (terminated by receiving a post-body status)
|
|
91 |
* error: expecting post-body error
|
|
92 |
* end: expecting end of message
|
|
93 |
* nothing: finished
|
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
94 |
"""
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
95 |
|
96 |
def __init__(self, request_handler, responder): |
|
97 |
MessageHandler.__init__(self) |
|
98 |
self.request_handler = request_handler |
|
99 |
self.responder = responder |
|
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
100 |
self.expecting = 'args' |
101 |
self._should_finish_body = False |
|
102 |
self._response_sent = False |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
103 |
|
104 |
def protocol_error(self, exception): |
|
3245.4.50
by Andrew Bennetts
Clarify the code a little. |
105 |
if self.responder.response_sent: |
106 |
# We can only send one response to a request, no matter how many
|
|
107 |
# errors happen while processing it.
|
|
108 |
return
|
|
109 |
self.responder.send_error(exception) |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
110 |
|
111 |
def byte_part_received(self, byte): |
|
3923.5.1
by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts. |
112 |
if self.expecting == 'body': |
3923.5.4
by Andrew Bennetts
Allow a request's body part(s) to be followed by an error. |
113 |
if byte == 'S': |
114 |
# Success. Nothing more to come except the end of message.
|
|
115 |
self.expecting = 'end' |
|
116 |
elif byte == 'E': |
|
117 |
# Error. Expect an error structure.
|
|
118 |
self.expecting = 'error' |
|
119 |
else: |
|
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
120 |
raise errors.SmartProtocolError( |
121 |
'Non-success status byte in request body: %r' % (byte,)) |
|
122 |
else: |
|
123 |
raise errors.SmartProtocolError( |
|
124 |
'Unexpected message part: byte(%r)' % (byte,)) |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
125 |
|
126 |
def structure_part_received(self, structure): |
|
3923.5.4
by Andrew Bennetts
Allow a request's body part(s) to be followed by an error. |
127 |
if self.expecting == 'args': |
128 |
self._args_received(structure) |
|
129 |
elif self.expecting == 'error': |
|
130 |
self._error_received(structure) |
|
131 |
else: |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
132 |
raise errors.SmartProtocolError( |
133 |
'Unexpected message part: structure(%r)' % (structure,)) |
|
3923.5.4
by Andrew Bennetts
Allow a request's body part(s) to be followed by an error. |
134 |
|
135 |
def _args_received(self, args): |
|
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
136 |
self.expecting = 'body' |
4634.6.30
by Andrew Bennetts
Remove SmartServerRequest.dispatch_command, fix SmartServerRequest.args_received. |
137 |
self.request_handler.args_received(args) |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
138 |
if self.request_handler.finished_reading: |
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
139 |
self._response_sent = True |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
140 |
self.responder.send_response(self.request_handler.response) |
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
141 |
self.expecting = 'end' |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
142 |
|
3923.5.4
by Andrew Bennetts
Allow a request's body part(s) to be followed by an error. |
143 |
def _error_received(self, error_args): |
144 |
self.expecting = 'end' |
|
145 |
self.request_handler.post_body_error_received(error_args) |
|
146 |
||
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
147 |
def bytes_part_received(self, bytes): |
148 |
if self.expecting == 'body': |
|
149 |
self._should_finish_body = True |
|
150 |
self.request_handler.accept_body(bytes) |
|
151 |
else: |
|
152 |
raise errors.SmartProtocolError( |
|
153 |
'Unexpected message part: bytes(%r)' % (bytes,)) |
|
154 |
||
155 |
def end_received(self): |
|
3923.5.2
by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour. |
156 |
if self.expecting not in ['body', 'end']: |
3923.5.3
by Andrew Bennetts
Raise a better exception if a premature message end happens. |
157 |
raise errors.SmartProtocolError( |
158 |
'End of message received prematurely (while expecting %s)' |
|
3923.5.2
by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour. |
159 |
% (self.expecting,)) |
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
160 |
self.expecting = 'nothing' |
161 |
self.request_handler.end_received() |
|
3923.5.2
by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour. |
162 |
if not self.request_handler.finished_reading: |
163 |
raise errors.SmartProtocolError( |
|
164 |
"Complete conventional request was received, but request "
|
|
165 |
"handler has not finished reading.") |
|
3842.3.4
by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though. |
166 |
if not self._response_sent: |
167 |
self.responder.send_response(self.request_handler.response) |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
168 |
|
169 |
||
3245.4.26
by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers. |
170 |
class ResponseHandler(object): |
171 |
"""Abstract base class for an object that handles a smart response."""
|
|
172 |
||
173 |
def read_response_tuple(self, expect_body=False): |
|
174 |
"""Reads and returns the response tuple for the current request.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
175 |
|
3245.4.26
by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers. |
176 |
:keyword expect_body: a boolean indicating if a body is expected in the
|
177 |
response. Some protocol versions needs this information to know
|
|
178 |
when a response is finished. If False, read_body_bytes should
|
|
179 |
*not* be called afterwards. Defaults to False.
|
|
180 |
:returns: tuple of response arguments.
|
|
181 |
"""
|
|
182 |
raise NotImplementedError(self.read_response_tuple) |
|
183 |
||
184 |
def read_body_bytes(self, count=-1): |
|
185 |
"""Read and return some bytes from the body.
|
|
186 |
||
187 |
:param count: if specified, read up to this many bytes. By default,
|
|
188 |
reads the entire body.
|
|
189 |
:returns: str of bytes from the response body.
|
|
190 |
"""
|
|
191 |
raise NotImplementedError(self.read_body_bytes) |
|
192 |
||
193 |
def read_streamed_body(self): |
|
194 |
"""Returns an iterable that reads and returns a series of body chunks.
|
|
195 |
"""
|
|
196 |
raise NotImplementedError(self.read_streamed_body) |
|
197 |
||
198 |
def cancel_read_body(self): |
|
199 |
"""Stop expecting a body for this response.
|
|
200 |
||
201 |
If expect_body was passed to read_response_tuple, this cancels that
|
|
202 |
expectation (and thus finishes reading the response, allowing a new
|
|
203 |
request to be issued). This is useful if a response turns out to be an
|
|
204 |
error rather than a normal result with a body.
|
|
205 |
"""
|
|
206 |
raise NotImplementedError(self.cancel_read_body) |
|
207 |
||
208 |
||
209 |
class ConventionalResponseHandler(MessageHandler, ResponseHandler): |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
210 |
|
211 |
def __init__(self): |
|
212 |
MessageHandler.__init__(self) |
|
213 |
self.status = None |
|
214 |
self.args = None |
|
3195.3.24
by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler. |
215 |
self._bytes_parts = collections.deque() |
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
216 |
self._body_started = False |
217 |
self._body_stream_status = None |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
218 |
self._body = None |
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
219 |
self._body_error_args = None |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
220 |
self.finished_reading = False |
221 |
||
3245.4.26
by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers. |
222 |
def setProtoAndMediumRequest(self, protocol_decoder, medium_request): |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
223 |
self._protocol_decoder = protocol_decoder |
3245.4.26
by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers. |
224 |
self._medium_request = medium_request |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
225 |
|
226 |
def byte_part_received(self, byte): |
|
227 |
if byte not in ['E', 'S']: |
|
228 |
raise errors.SmartProtocolError( |
|
229 |
'Unknown response status: %r' % (byte,)) |
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
230 |
if self._body_started: |
231 |
if self._body_stream_status is not None: |
|
232 |
raise errors.SmartProtocolError( |
|
233 |
'Unexpected byte part received: %r' % (byte,)) |
|
234 |
self._body_stream_status = byte |
|
235 |
else: |
|
236 |
if self.status is not None: |
|
237 |
raise errors.SmartProtocolError( |
|
238 |
'Unexpected byte part received: %r' % (byte,)) |
|
239 |
self.status = byte |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
240 |
|
241 |
def bytes_part_received(self, bytes): |
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
242 |
self._body_started = True |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
243 |
self._bytes_parts.append(bytes) |
244 |
||
245 |
def structure_part_received(self, structure): |
|
3842.3.6
by Andrew Bennetts
Tweak bencode.py to decode sequences as tuples, not lists. |
246 |
if type(structure) is not tuple: |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
247 |
raise errors.SmartProtocolError( |
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
248 |
'Args structure is not a sequence: %r' % (structure,)) |
249 |
if not self._body_started: |
|
250 |
if self.args is not None: |
|
251 |
raise errors.SmartProtocolError( |
|
252 |
'Unexpected structure received: %r (already got %r)' |
|
253 |
% (structure, self.args)) |
|
254 |
self.args = structure |
|
255 |
else: |
|
256 |
if self._body_stream_status != 'E': |
|
257 |
raise errors.SmartProtocolError( |
|
258 |
'Unexpected structure received after body: %r' |
|
259 |
% (structure,)) |
|
260 |
self._body_error_args = structure |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
261 |
|
262 |
def _wait_for_response_args(self): |
|
263 |
while self.args is None and not self.finished_reading: |
|
264 |
self._read_more() |
|
265 |
||
266 |
def _wait_for_response_end(self): |
|
267 |
while not self.finished_reading: |
|
268 |
self._read_more() |
|
269 |
||
270 |
def _read_more(self): |
|
271 |
next_read_size = self._protocol_decoder.next_read_size() |
|
272 |
if next_read_size == 0: |
|
273 |
# a complete request has been read.
|
|
274 |
self.finished_reading = True |
|
3245.4.26
by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers. |
275 |
self._medium_request.finished_reading() |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
276 |
return
|
3750.1.2
by Vincent Ladeuil
Fixed as per Andrew's review. |
277 |
bytes = self._medium_request.read_bytes(next_read_size) |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
278 |
if bytes == '': |
279 |
# end of file encountered reading from server
|
|
3461.2.1
by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version. |
280 |
if 'hpss' in debug.debug_flags: |
281 |
mutter( |
|
282 |
'decoder state: buf[:10]=%r, state_accept=%s', |
|
3702.2.1
by Andrew Bennetts
Fix '_in_buffer' AttributeError when using the -Dhpss debug flag. |
283 |
self._protocol_decoder._get_in_buffer()[:10], |
3461.2.2
by Andrew Bennetts
Tweak suggested by John. |
284 |
self._protocol_decoder.state_accept.__name__) |
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
285 |
raise errors.ConnectionReset( |
4509.2.1
by Martin Pool
Tweak hpss connection-dropped error message |
286 |
"Unexpected end of message. "
|
287 |
"Please check connectivity and permissions, and report a bug "
|
|
288 |
"if problems persist.") |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
289 |
self._protocol_decoder.accept_bytes(bytes) |
290 |
||
3245.4.47
by Andrew Bennetts
Don't automatically send 'hello' requests from RemoteBzrDirFormat.probe_transport unless we have to (i.e. the transport is HTTP). |
291 |
def protocol_error(self, exception): |
292 |
# Whatever the error is, we're done with this request.
|
|
293 |
self.finished_reading = True |
|
294 |
self._medium_request.finished_reading() |
|
295 |
raise
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
296 |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
297 |
def read_response_tuple(self, expect_body=False): |
3245.4.24
by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions. |
298 |
"""Read a response tuple from the wire."""
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
299 |
self._wait_for_response_args() |
3195.3.18
by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though. |
300 |
if not expect_body: |
301 |
self._wait_for_response_end() |
|
3245.4.24
by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions. |
302 |
if 'hpss' in debug.debug_flags: |
303 |
mutter(' result: %r', self.args) |
|
304 |
if self.status == 'E': |
|
305 |
self._wait_for_response_end() |
|
306 |
_translate_error(self.args) |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
307 |
return tuple(self.args) |
308 |
||
309 |
def read_body_bytes(self, count=-1): |
|
310 |
"""Read bytes from the body, decoding into a byte stream.
|
|
3943.8.1
by Marius Kruger
remove all trailing whitespace from bzr source |
311 |
|
312 |
We read all bytes at once to ensure we've checked the trailer for
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
313 |
errors, and then feed the buffer back as read_body_bytes is called.
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
314 |
|
315 |
Like the builtin file.read in Python, a count of -1 (the default) means
|
|
316 |
read the entire body.
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
317 |
"""
|
3245.4.39
by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review. |
318 |
# TODO: we don't necessarily need to buffer the full request if count
|
319 |
# != -1. (2008/04/30, Andrew Bennetts)
|
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
320 |
if self._body is None: |
3195.3.18
by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though. |
321 |
self._wait_for_response_end() |
3245.4.25
by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols. |
322 |
body_bytes = ''.join(self._bytes_parts) |
323 |
if 'hpss' in debug.debug_flags: |
|
324 |
mutter(' %d body bytes read', len(body_bytes)) |
|
325 |
self._body = StringIO(body_bytes) |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
326 |
self._bytes_parts = None |
327 |
return self._body.read(count) |
|
328 |
||
3195.3.24
by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler. |
329 |
def read_streamed_body(self): |
330 |
while not self.finished_reading: |
|
331 |
while self._bytes_parts: |
|
3245.4.25
by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols. |
332 |
bytes_part = self._bytes_parts.popleft() |
4574.1.1
by Martin Pool
Move 'byte part read' messages to -Dhpssdetail |
333 |
if 'hpssdetail' in debug.debug_flags: |
4070.9.10
by Andrew Bennetts
Revert some cruft. |
334 |
mutter(' %d byte part read', len(bytes_part)) |
3245.4.25
by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols. |
335 |
yield bytes_part |
3195.3.24
by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler. |
336 |
self._read_more() |
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
337 |
if self._body_stream_status == 'E': |
338 |
_translate_error(self._body_error_args) |
|
3195.3.24
by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler. |
339 |
|
3195.3.17
by Andrew Bennetts
Some tests now passing using protocol 3. |
340 |
def cancel_read_body(self): |
341 |
self._wait_for_response_end() |
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
342 |
|
343 |
||
344 |
def _translate_error(error_tuple): |
|
3245.4.18
by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class. |
345 |
# Many exceptions need some state from the requestor to be properly
|
346 |
# translated (e.g. they need a branch object). So this only translates a
|
|
347 |
# few errors, and the rest are turned into a generic ErrorFromSmartServer.
|
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
348 |
error_name = error_tuple[0] |
349 |
error_args = error_tuple[1:] |
|
3245.4.35
by Andrew Bennetts
Remove some commented out cruft, test (and fix) handling of an 'UnknownMethod' response. |
350 |
if error_name == 'UnknownMethod': |
351 |
raise errors.UnknownSmartMethod(error_args[0]) |
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
352 |
if error_name == 'LockContention': |
353 |
raise errors.LockContention('(remote lock)') |
|
354 |
elif error_name == 'LockFailed': |
|
3245.4.24
by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions. |
355 |
raise errors.LockFailed(*error_args[:2]) |
4294.2.7
by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server. |
356 |
elif error_name == 'FileExists': |
357 |
raise errors.FileExists(error_args[0]) |
|
358 |
elif error_name == 'NoSuchFile': |
|
359 |
raise errors.NoSuchFile(error_args[0]) |
|
3245.4.5
by Andrew Bennetts
Implement interrupting body streams with an error. |
360 |
else: |
361 |
raise errors.ErrorFromSmartServer(error_tuple) |