Index: tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/stream_slice.py |
diff --git a/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/stream_slice.py b/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/stream_slice.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..bd43daf9156477e4d90f04392d6a1f231f16cccd |
--- /dev/null |
+++ b/tools/telemetry/third_party/gsutilz/third_party/apitools/apitools/base/py/stream_slice.py |
@@ -0,0 +1,64 @@ |
+#!/usr/bin/env python |
+"""Small helper class to provide a small slice of a stream.""" |
+ |
+from apitools.base.py import exceptions |
+ |
+ |
+class StreamSlice(object): |
+ |
+ """Provides a slice-like object for streams.""" |
+ |
+ def __init__(self, stream, max_bytes): |
+ self.__stream = stream |
+ self.__remaining_bytes = max_bytes |
+ self.__max_bytes = max_bytes |
+ |
+ def __str__(self): |
+ return 'Slice of stream %s with %s/%s bytes not yet read' % ( |
+ self.__stream, self.__remaining_bytes, self.__max_bytes) |
+ |
+ def __len__(self): |
+ return self.__max_bytes |
+ |
+ def __nonzero__(self): |
+ # For 32-bit python2.x, len() cannot exceed a 32-bit number; avoid |
+ # accidental len() calls from httplib in the form of "if this_object:". |
+ return bool(self.__max_bytes) |
+ |
+ @property |
+ def length(self): |
+ # For 32-bit python2.x, len() cannot exceed a 32-bit number. |
+ return self.__max_bytes |
+ |
+ def read(self, size=None): # pylint: disable=missing-docstring |
+ """Read at most size bytes from this slice. |
+ |
+ Compared to other streams, there is one case where we may |
+ unexpectedly raise an exception on read: if the underlying stream |
+ is exhausted (i.e. returns no bytes on read), and the size of this |
+ slice indicates we should still be able to read more bytes, we |
+ raise exceptions.StreamExhausted. |
+ |
+ Args: |
+ size: If provided, read no more than size bytes from the stream. |
+ |
+ Returns: |
+ The bytes read from this slice. |
+ |
+ Raises: |
+ exceptions.StreamExhausted |
+ |
+ """ |
+ if size is not None: |
+ read_size = min(size, self.__remaining_bytes) |
+ else: |
+ read_size = self.__remaining_bytes |
+ data = self.__stream.read(read_size) |
+ if read_size > 0 and not data: |
+ raise exceptions.StreamExhausted( |
+ 'Not enough bytes in stream; expected %d, exhausted ' |
+ 'after %d' % ( |
+ self.__max_bytes, |
+ self.__max_bytes - self.__remaining_bytes)) |
+ self.__remaining_bytes -= len(data) |
+ return data |