From c64b4ce78f553c40a7916e1857bbdd63ff7891ab Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev <40304587+dkropachev@users.noreply.github.com> Date: Tue, 29 Dec 2020 04:34:24 +0700 Subject: [PATCH] dvc/utils/stream: make IterStream seekable and peekable (#5084) fixes #5021 --- dvc/utils/stream.py | 15 +++++++++++++-- tests/test.p12 | Bin 0 -> 2479 bytes tests/unit/remote/test.p12 | Bin 0 -> 2479 bytes tests/unit/utils/test_http.py | 27 ++++++++++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/test.p12 create mode 100644 tests/unit/remote/test.p12 diff --git a/dvc/utils/stream.py b/dvc/utils/stream.py index cfa18d183..c2d3fe33e 100644 --- a/dvc/utils/stream.py +++ b/dvc/utils/stream.py @@ -6,11 +6,14 @@ class IterStream(io.RawIOBase): def __init__(self, iterator): # pylint: disable=super-init-not-called self.iterator = iterator - self.leftover = None + self.leftover = b"" def readable(self): return True + def writable(self) -> bool: + return False + # Python 3 requires only .readinto() method, it still uses other ones # under some circumstances and falls back if those are absent. Since # iterator already constructs byte strings for us, .readinto() is not the @@ -38,8 +41,16 @@ class IterStream(io.RawIOBase): # Return an arbitrary number or bytes if n <= 0: - self.leftover = None + self.leftover = b"" return chunk output, self.leftover = chunk[:n], chunk[n:] return output + + def peek(self, n): + while len(self.leftover) < n: + try: + self.leftover += next(self.iterator) + except StopIteration: + break + return self.leftover[:n] diff --git a/tests/test.p12 b/tests/test.p12 new file mode 100644 index 0000000000000000000000000000000000000000..6c391b054f9d0551b53682c190206c6e294fca25 GIT binary patch literal 2479 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