Skip to content

Commit d7c283f

Browse files
committed
#70 - allow streaming iterables of strings
1 parent 1b9e524 commit d7c283f

3 files changed

Lines changed: 26 additions & 5 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
55

66
[project]
77
name = "json-stream"
8-
version = "2.4.0"
8+
version = "2.4.1"
99
authors = [
1010
{name = "Jamie Cockburn", email="jamie_cockburn@hotmail.co.uk"},
1111
]

src/json_stream/iterators.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@
44
class IterableStream(io.RawIOBase):
55
def __init__(self, iterable):
66
self.iterator = iter(iterable)
7-
self.remainder = None
7+
self.remainder = None # type: bytes | None
8+
9+
def _normalize_chunk(self, chunk):
10+
# Ensure chunk is bytes for writing into a binary buffer
11+
if isinstance(chunk, str):
12+
return chunk.encode()
13+
return chunk
814

915
def readinto(self, buffer):
1016
try:
11-
chunk = self.remainder or next(self.iterator)
12-
length = min(len(buffer), len(chunk))
13-
buffer[:length], self.remainder = chunk[:length], chunk[length:]
17+
# Wrap `buffer: WriteableBuffer` in memoryview to ensure len() and slicing
18+
mv = memoryview(buffer)
19+
chunk = self.remainder or self._normalize_chunk(next(self.iterator))
20+
length = min(len(mv), len(chunk))
21+
mv[:length], self.remainder = chunk[:length], chunk[length:]
1422
return length
1523
except StopIteration:
1624
return 0 # indicate EOF

src/json_stream/tests/test_iterators.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,16 @@ def test_read(self):
1515
# stream it and check the result
1616
stream = IterableStream(data)
1717
self.assertEqual(stream.read(), b"".join(data))
18+
19+
def test_read_str_chunks(self):
20+
# create some chunks of text data
21+
data_str = (
22+
"a" * io.DEFAULT_BUFFER_SIZE,
23+
"b" * (io.DEFAULT_BUFFER_SIZE + 1),
24+
"c" * (io.DEFAULT_BUFFER_SIZE - 1),
25+
)
26+
expected = ("".join(data_str)).encode()
27+
28+
# stream it and check the result
29+
stream = IterableStream(data_str)
30+
self.assertEqual(stream.read(), expected)

0 commit comments

Comments
 (0)