~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/smart.py

  • Committer: John Arbash Meinel
  • Date: 2006-12-01 19:41:16 UTC
  • mfrom: (2158 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2159.
  • Revision ID: john@arbash-meinel.com-20061201194116-nvn5qhfxux5284jc
[merge] bzr.dev 2158

Show diffs side-by-side

added added

removed removed

Lines of Context:
233
233
        return None
234
234
    if req_line[-1] != '\n':
235
235
        raise errors.SmartProtocolError("request %r not terminated" % req_line)
236
 
    try:
237
 
        return tuple((a.decode('utf-8') for a in req_line[:-1].split('\x01')))
238
 
    except UnicodeDecodeError:
239
 
        raise errors.SmartProtocolError(
240
 
            "one or more arguments of request %r are not valid UTF-8"
241
 
            % req_line)
 
236
    return tuple(req_line[:-1].split('\x01'))
242
237
 
243
238
 
244
239
def _encode_tuple(args):
245
240
    """Encode the tuple args to a bytestream."""
246
 
    return '\x01'.join((a.encode('utf-8') for a in args)) + '\n'
 
241
    return '\x01'.join(args) + '\n'
247
242
 
248
243
 
249
244
class SmartProtocolBase(object):
269
264
    def __init__(self, backing_transport, write_func):
270
265
        self._backing_transport = backing_transport
271
266
        self.excess_buffer = ''
272
 
        self._finished_reading = False
 
267
        self._finished = False
273
268
        self.in_buffer = ''
274
269
        self.has_dispatched = False
275
270
        self.request = None
301
296
                    self.in_buffer = ''
302
297
                    self._send_response(self.request.response.args,
303
298
                        self.request.response.body)
304
 
                self.sync_with_request(self.request)
305
299
            except KeyboardInterrupt:
306
300
                raise
307
301
            except Exception, exception:
308
302
                # everything else: pass to client, flush, and quit
309
303
                self._send_response(('error', str(exception)))
310
 
                return None
 
304
                return
311
305
 
312
306
        if self.has_dispatched:
313
 
            if self._finished_reading:
 
307
            if self._finished:
314
308
                # nothing to do.XXX: this routine should be a single state 
315
309
                # machine too.
316
310
                self.excess_buffer += self.in_buffer
326
320
                self.request.end_of_body()
327
321
                assert self.request.finished_reading, \
328
322
                    "no more body, request not finished"
329
 
            self.sync_with_request(self.request)
330
323
            if self.request.response is not None:
331
324
                self._send_response(self.request.response.args,
332
325
                    self.request.response.body)
338
331
 
339
332
    def _send_response(self, args, body=None):
340
333
        """Send a smart server response down the output stream."""
 
334
        assert not self._finished, 'response already sent'
 
335
        self._finished = True
341
336
        self._write_func(_encode_tuple(args))
342
337
        if body is not None:
343
338
            assert isinstance(body, str), 'body must be a str'
344
339
            bytes = self._encode_bulk_data(body)
345
340
            self._write_func(bytes)
346
341
 
347
 
    def sync_with_request(self, request):
348
 
        self._finished_reading = request.finished_reading
349
 
        
350
342
    def next_read_size(self):
351
 
        if self._finished_reading:
 
343
        if self._finished:
352
344
            return 0
353
345
        if self._body_decoder is None:
354
346
            return 1
663
655
    def do_delete(self, relpath):
664
656
        self._backing_transport.delete(relpath)
665
657
 
666
 
    def do_iter_files_recursive(self, abspath):
667
 
        # XXX: the path handling needs some thought.
668
 
        #relpath = self._backing_transport.relpath(abspath)
669
 
        transport = self._backing_transport.clone(abspath)
 
658
    def do_iter_files_recursive(self, relpath):
 
659
        transport = self._backing_transport.clone(relpath)
670
660
        filenames = transport.iter_files_recursive()
671
661
        return SmartServerResponse(('names',) + tuple(filenames))
672
662
 
802
792
            # with a plain string
803
793
            str_or_unicode = e.object
804
794
            if isinstance(str_or_unicode, unicode):
805
 
                val = u'u:' + str_or_unicode
 
795
                # XXX: UTF-8 might have \x01 (our seperator byte) in it.  We
 
796
                # should escape it somehow.
 
797
                val = 'u:' + str_or_unicode.encode('utf-8')
806
798
            else:
807
 
                val = u's:' + str_or_unicode.encode('base64')
 
799
                val = 's:' + str_or_unicode.encode('base64')
808
800
            # This handles UnicodeEncodeError or UnicodeDecodeError
809
801
            return SmartServerResponse((e.__class__.__name__,
810
802
                    e.encoding, val, str(e.start), str(e.end), e.reason))
1221
1213
            end = int(resp[4])
1222
1214
            reason = str(resp[5]) # reason must always be a string
1223
1215
            if val.startswith('u:'):
1224
 
                val = val[2:]
 
1216
                val = val[2:].decode('utf-8')
1225
1217
            elif val.startswith('s:'):
1226
1218
                val = val[2:].decode('base64')
1227
1219
            if what == 'UnicodeDecodeError':