OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # |
| 3 # Copyright 2015 Google Inc. |
| 4 # |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 # you may not use this file except in compliance with the License. |
| 7 # You may obtain a copy of the License at |
| 8 # |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 # |
| 11 # Unless required by applicable law or agreed to in writing, software |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 # See the License for the specific language governing permissions and |
| 15 # limitations under the License. |
| 16 |
| 17 """Small helper class to provide a small slice of a stream. |
| 18 |
| 19 This class reads ahead to detect if we are at the end of the stream. |
| 20 """ |
| 21 |
| 22 from apitools.base.py import exceptions |
| 23 |
| 24 |
| 25 # TODO(user): Consider replacing this with a StringIO. |
| 26 class BufferedStream(object): |
| 27 |
| 28 """Buffers a stream, reading ahead to determine if we're at the end.""" |
| 29 |
| 30 def __init__(self, stream, start, size): |
| 31 self.__stream = stream |
| 32 self.__start_pos = start |
| 33 self.__buffer_pos = 0 |
| 34 self.__buffered_data = self.__stream.read(size) |
| 35 self.__stream_at_end = len(self.__buffered_data) < size |
| 36 self.__end_pos = self.__start_pos + len(self.__buffered_data) |
| 37 |
| 38 def __str__(self): |
| 39 return ('Buffered stream %s from position %s-%s with %s ' |
| 40 'bytes remaining' % (self.__stream, self.__start_pos, |
| 41 self.__end_pos, self._bytes_remaining)) |
| 42 |
| 43 def __len__(self): |
| 44 return len(self.__buffered_data) |
| 45 |
| 46 @property |
| 47 def stream_exhausted(self): |
| 48 return self.__stream_at_end |
| 49 |
| 50 @property |
| 51 def stream_end_position(self): |
| 52 return self.__end_pos |
| 53 |
| 54 @property |
| 55 def _bytes_remaining(self): |
| 56 return len(self.__buffered_data) - self.__buffer_pos |
| 57 |
| 58 def read(self, size=None): # pylint: disable=invalid-name |
| 59 """Reads from the buffer.""" |
| 60 if size is None or size < 0: |
| 61 raise exceptions.NotYetImplementedError( |
| 62 'Illegal read of size %s requested on BufferedStream. ' |
| 63 'Wrapped stream %s is at position %s-%s, ' |
| 64 '%s bytes remaining.' % |
| 65 (size, self.__stream, self.__start_pos, self.__end_pos, |
| 66 self._bytes_remaining)) |
| 67 |
| 68 data = '' |
| 69 if self._bytes_remaining: |
| 70 size = min(size, self._bytes_remaining) |
| 71 data = self.__buffered_data[ |
| 72 self.__buffer_pos:self.__buffer_pos + size] |
| 73 self.__buffer_pos += size |
| 74 return data |
OLD | NEW |