Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67fab7e

Browse files
author
Steve Canny
committed
img: add _ChunkParser.iter_chunks()
1 parent 98b4ab2 commit 67fab7e

File tree

3 files changed

+98
-5
lines changed

3 files changed

+98
-5
lines changed

docx/image/constants.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ class MIME_TYPE(object):
104104
TIFF = 'image/tiff'
105105

106106

107+
class PNG_CHUNK_TYPE(object):
108+
"""
109+
PNG chunk type names
110+
"""
111+
IHDR = 'IHDR'
112+
pHYs = 'pHYs'
113+
IEND = 'IEND'
114+
115+
107116
class TAG(object):
108117
"""
109118
Identifiers for image attribute tags.

docx/image/png.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,29 @@ def iter_chunks(self):
243243
Generate a |_Chunk| subclass instance for each chunk in this parser's
244244
PNG stream, in the order encountered in the stream.
245245
"""
246+
for chunk_type, offset in self._iter_chunk_offsets():
247+
chunk = _ChunkFactory(chunk_type, self._stream_rdr, offset)
248+
yield chunk
249+
250+
def _iter_chunk_offsets(self):
251+
"""
252+
Generate a (chunk_type, chunk_offset) 2-tuple for each of the chunks
253+
in the PNG image stream. Iteration stops after the IEND chunk is
254+
returned.
255+
"""
246256
raise NotImplementedError
257+
258+
259+
def _ChunkFactory(chunk_type, stream_rdr, offset):
260+
"""
261+
Return a |_Chunk| subclass instance appropriate to *chunk_type* parsed
262+
from *stream_rdr* at *offset*.
263+
"""
264+
raise NotImplementedError
265+
266+
267+
class _Chunk(object):
268+
"""
269+
Base class for specific chunk types. Also serves as the default chunk
270+
type.
271+
"""

tests/image/test_png.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@
88

99
import pytest
1010

11+
from mock import call
12+
1113
from docx.compat import BytesIO
12-
from docx.image.constants import MIME_TYPE, TAG
14+
from docx.image.constants import MIME_TYPE, PNG_CHUNK_TYPE, TAG
1315
from docx.image.exceptions import InvalidImageStreamError
1416
from docx.image.helpers import BIG_ENDIAN, StreamReader
15-
from docx.image.png import _Chunks, _ChunkParser, Png, _PngParser
17+
from docx.image.png import _Chunk, _Chunks, _ChunkParser, Png, _PngParser
1618

1719
from ..unitutil import (
18-
initializer_mock, class_mock, instance_mock, method_mock, test_file
20+
function_mock, class_mock, initializer_mock, instance_mock, method_mock,
21+
test_file
1922
)
2023

2124

@@ -338,16 +341,72 @@ def it_can_construct_from_a_stream(self, from_stream_fixture):
338341
_ChunkParser__init_.assert_called_once_with(stream_rdr_)
339342
assert isinstance(chunk_parser, _ChunkParser)
340343

344+
def it_can_iterate_over_the_chunks_in_its_png_stream(self, iter_fixture):
345+
# fixture ----------------------
346+
chunk_parser, _iter_chunk_offsets_, _ChunkFactory_ = iter_fixture[:3]
347+
stream_rdr_, offsets, chunk_lst = iter_fixture[3:]
348+
# exercise ---------------------
349+
chunks = [chunk for chunk in chunk_parser.iter_chunks()]
350+
# verify -----------------------
351+
_iter_chunk_offsets_.assert_called_once_with()
352+
assert _ChunkFactory_.call_args_list == [
353+
call(PNG_CHUNK_TYPE.IHDR, stream_rdr_, offsets[0]),
354+
call(PNG_CHUNK_TYPE.pHYs, stream_rdr_, offsets[1]),
355+
]
356+
assert chunks == chunk_lst
357+
341358
# fixtures -------------------------------------------------------
342359

360+
@pytest.fixture
361+
def chunk_(self, request):
362+
return instance_mock(request, _Chunk)
363+
364+
@pytest.fixture
365+
def chunk_2_(self, request):
366+
return instance_mock(request, _Chunk)
367+
368+
@pytest.fixture
369+
def _ChunkFactory_(self, request, chunk_lst_):
370+
return function_mock(
371+
request, 'docx.image.png._ChunkFactory',
372+
side_effect=chunk_lst_
373+
)
374+
375+
@pytest.fixture
376+
def chunk_lst_(self, chunk_, chunk_2_):
377+
return [chunk_, chunk_2_]
378+
379+
@pytest.fixture
380+
def _ChunkParser__init_(self, request):
381+
return initializer_mock(request, _ChunkParser)
382+
343383
@pytest.fixture
344384
def from_stream_fixture(
345385
self, stream_, StreamReader_, stream_rdr_, _ChunkParser__init_):
346386
return stream_, StreamReader_, stream_rdr_, _ChunkParser__init_
347387

348388
@pytest.fixture
349-
def _ChunkParser__init_(self, request):
350-
return initializer_mock(request, _ChunkParser)
389+
def _iter_chunk_offsets_(self, request):
390+
chunk_offsets = (
391+
(PNG_CHUNK_TYPE.IHDR, 2),
392+
(PNG_CHUNK_TYPE.pHYs, 4),
393+
)
394+
return method_mock(
395+
request, _ChunkParser, '_iter_chunk_offsets',
396+
return_value=iter(chunk_offsets)
397+
)
398+
399+
@pytest.fixture
400+
def iter_fixture(
401+
self, _iter_chunk_offsets_, _ChunkFactory_, stream_rdr_, chunk_,
402+
chunk_2_):
403+
chunk_parser = _ChunkParser(stream_rdr_)
404+
offsets = [2, 4, 6]
405+
chunk_lst = [chunk_, chunk_2_]
406+
return (
407+
chunk_parser, _iter_chunk_offsets_, _ChunkFactory_, stream_rdr_,
408+
offsets, chunk_lst
409+
)
351410

352411
@pytest.fixture
353412
def StreamReader_(self, request, stream_rdr_):

0 commit comments

Comments
 (0)