Repository URL to install this package:
|
Version:
0.8.10 ▾
|
# encoding: utf-8
"""Unit test suite for docx.image.tiff module"""
from __future__ import absolute_import, print_function
import pytest
from docx.compat import BytesIO
from docx.image.constants import MIME_TYPE, TIFF_TAG
from docx.image.helpers import BIG_ENDIAN, LITTLE_ENDIAN, StreamReader
from docx.image.tiff import (
_AsciiIfdEntry,
_IfdEntries,
_IfdEntry,
_IfdEntryFactory,
_IfdParser,
_LongIfdEntry,
_RationalIfdEntry,
_ShortIfdEntry,
Tiff,
_TiffParser,
)
from ..unitutil.mock import (
ANY,
call,
class_mock,
function_mock,
initializer_mock,
instance_mock,
loose_mock,
method_mock,
)
class DescribeTiff(object):
def it_can_construct_from_a_tiff_stream(
self, stream_, _TiffParser_, tiff_parser_, Tiff__init_
):
px_width, px_height = 111, 222
horz_dpi, vert_dpi = 333, 444
tiff_parser_.px_width = px_width
tiff_parser_.px_height = px_height
tiff_parser_.horz_dpi = horz_dpi
tiff_parser_.vert_dpi = vert_dpi
tiff = Tiff.from_stream(stream_)
_TiffParser_.parse.assert_called_once_with(stream_)
Tiff__init_.assert_called_once_with(
ANY, px_width, px_height, horz_dpi, vert_dpi
)
assert isinstance(tiff, Tiff)
def it_knows_its_content_type(self):
tiff = Tiff(None, None, None, None)
assert tiff.content_type == MIME_TYPE.TIFF
def it_knows_its_default_ext(self):
tiff = Tiff(None, None, None, None)
assert tiff.default_ext == 'tiff'
# fixtures -------------------------------------------------------
@pytest.fixture
def Tiff__init_(self, request):
return initializer_mock(request, Tiff)
@pytest.fixture
def _TiffParser_(self, request, tiff_parser_):
_TiffParser_ = class_mock(request, 'docx.image.tiff._TiffParser')
_TiffParser_.parse.return_value = tiff_parser_
return _TiffParser_
@pytest.fixture
def tiff_parser_(self, request):
return instance_mock(request, _TiffParser)
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_TiffParser(object):
def it_can_parse_the_properties_from_a_tiff_stream(
self,
stream_,
_make_stream_reader_,
_IfdEntries_,
ifd0_offset_,
stream_rdr_,
_TiffParser__init_,
ifd_entries_,
):
tiff_parser = _TiffParser.parse(stream_)
_make_stream_reader_.assert_called_once_with(stream_)
_IfdEntries_.from_stream.assert_called_once_with(
stream_rdr_, ifd0_offset_
)
_TiffParser__init_.assert_called_once_with(ANY, ifd_entries_)
assert isinstance(tiff_parser, _TiffParser)
def it_makes_a_stream_reader_to_help_parse(self, mk_stream_rdr_fixture):
stream, StreamReader_, endian, stream_rdr_ = mk_stream_rdr_fixture
stream_rdr = _TiffParser._make_stream_reader(stream)
StreamReader_.assert_called_once_with(stream, endian)
assert stream_rdr is stream_rdr_
def it_knows_image_width_and_height_after_parsing(self):
px_width, px_height = 42, 24
entries = {
TIFF_TAG.IMAGE_WIDTH: px_width,
TIFF_TAG.IMAGE_LENGTH: px_height,
}
ifd_entries = _IfdEntries(entries)
tiff_parser = _TiffParser(ifd_entries)
assert tiff_parser.px_width == px_width
assert tiff_parser.px_height == px_height
def it_knows_the_horz_and_vert_dpi_after_parsing(self, dpi_fixture):
tiff_parser, expected_horz_dpi, expected_vert_dpi = dpi_fixture
assert tiff_parser.horz_dpi == expected_horz_dpi
assert tiff_parser.vert_dpi == expected_vert_dpi
# fixtures -------------------------------------------------------
@pytest.fixture(params=[
(1, 150, 240, 72, 72),
(2, 42, 24, 42, 24),
(3, 100, 200, 254, 508),
(2, None, None, 72, 72),
(None, 96, 100, 96, 100),
])
def dpi_fixture(self, request):
resolution_unit, x_resolution, y_resolution = request.param[:3]
expected_horz_dpi, expected_vert_dpi = request.param[3:]
entries = {}
if resolution_unit is not None:
entries[TIFF_TAG.RESOLUTION_UNIT] = resolution_unit
if x_resolution is not None:
entries[TIFF_TAG.X_RESOLUTION] = x_resolution
if y_resolution is not None:
entries[TIFF_TAG.Y_RESOLUTION] = y_resolution
tiff_parser = _TiffParser(entries)
return tiff_parser, expected_horz_dpi, expected_vert_dpi
@pytest.fixture
def _IfdEntries_(self, request, ifd_entries_):
_IfdEntries_ = class_mock(request, 'docx.image.tiff._IfdEntries')
_IfdEntries_.from_stream.return_value = ifd_entries_
return _IfdEntries_
@pytest.fixture
def ifd_entries_(self, request):
return instance_mock(request, _IfdEntries)
@pytest.fixture
def ifd0_offset_(self, request):
return instance_mock(request, int)
@pytest.fixture
def _make_stream_reader_(self, request, stream_rdr_):
return method_mock(
request,
_TiffParser,
'_make_stream_reader',
autospec=False,
return_value=stream_rdr_
)
@pytest.fixture(params=[
(b'MM\x00*', BIG_ENDIAN),
(b'II*\x00', LITTLE_ENDIAN),
])
def mk_stream_rdr_fixture(self, request, StreamReader_, stream_rdr_):
bytes_, endian = request.param
stream = BytesIO(bytes_)
return stream, StreamReader_, endian, stream_rdr_
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
@pytest.fixture
def StreamReader_(self, request, stream_rdr_):
return class_mock(
request, 'docx.image.tiff.StreamReader', return_value=stream_rdr_
)
@pytest.fixture
def stream_rdr_(self, request, ifd0_offset_):
stream_rdr_ = instance_mock(request, StreamReader)
stream_rdr_.read_long.return_value = ifd0_offset_
return stream_rdr_
@pytest.fixture
def _TiffParser__init_(self, request):
return initializer_mock(request, _TiffParser)
class Describe_IfdEntries(object):
def it_can_construct_from_a_stream_and_offset(
self,
stream_,
offset_,
_IfdParser_,
ifd_parser_,
_IfdEntries__init_,
ifd_entry_,
ifd_entry_2_,
):
ifd_parser_.iter_entries.return_value = [ifd_entry_, ifd_entry_2_]
entries_ = {1: 42, 2: 24}
ifd_entries = _IfdEntries.from_stream(stream_, offset_)
_IfdParser_.assert_called_once_with(stream_, offset_)
_IfdEntries__init_.assert_called_once_with(ANY, entries_)
assert isinstance(ifd_entries, _IfdEntries)
def it_has_basic_mapping_semantics(self):
key, value = 1, 'foobar'
entries = {key: value}
ifd_entries = _IfdEntries(entries)
assert key in ifd_entries
assert ifd_entries[key] == value
# fixtures -------------------------------------------------------
@pytest.fixture
def ifd_entry_(self, request):
return instance_mock(request, _IfdEntry, tag=1, value=42)
@pytest.fixture
def ifd_entry_2_(self, request):
return instance_mock(request, _IfdEntry, tag=2, value=24)
@pytest.fixture
def _IfdEntries__init_(self, request):
return initializer_mock(request, _IfdEntries)
@pytest.fixture
def _IfdParser_(self, request, ifd_parser_):
return class_mock(
request, 'docx.image.tiff._IfdParser', return_value=ifd_parser_
)
@pytest.fixture
def ifd_parser_(self, request):
return instance_mock(request, _IfdParser)
@pytest.fixture
def offset_(self, request):
return instance_mock(request, int)
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_IfdParser(object):
def it_can_iterate_through_the_directory_entries_in_an_IFD(
self, iter_fixture):
(ifd_parser, _IfdEntryFactory_, stream_rdr, offsets,
expected_entries) = iter_fixture
entries = [e for e in ifd_parser.iter_entries()]
assert _IfdEntryFactory_.call_args_list == [
call(stream_rdr, offsets[0]),
call(stream_rdr, offsets[1]),
]
assert entries == expected_entries
# fixtures -------------------------------------------------------
@pytest.fixture
def ifd_entry_(self, request):
return instance_mock(request, _IfdEntry, tag=1, value=42)
@pytest.fixture
def ifd_entry_2_(self, request):
return instance_mock(request, _IfdEntry, tag=2, value=24)
@pytest.fixture
def _IfdEntryFactory_(self, request, ifd_entry_, ifd_entry_2_):
return function_mock(
request, 'docx.image.tiff._IfdEntryFactory',
side_effect=[ifd_entry_, ifd_entry_2_]
)
@pytest.fixture
def iter_fixture(self, _IfdEntryFactory_, ifd_entry_, ifd_entry_2_):
stream_rdr = StreamReader(BytesIO(b'\x00\x02'), BIG_ENDIAN)
offsets = [2, 14]
ifd_parser = _IfdParser(stream_rdr, offset=0)
expected_entries = [ifd_entry_, ifd_entry_2_]
return (
ifd_parser, _IfdEntryFactory_, stream_rdr, offsets,
expected_entries
)
class Describe_IfdEntryFactory(object):
def it_constructs_the_right_class_for_a_given_ifd_entry(self, fixture):
stream_rdr, offset, entry_cls_, ifd_entry_ = fixture
ifd_entry = _IfdEntryFactory(stream_rdr, offset)
entry_cls_.from_stream.assert_called_once_with(stream_rdr, offset)
assert ifd_entry is ifd_entry_
# fixtures -------------------------------------------------------
@pytest.fixture(params=[
(b'\x66\x66\x00\x01', 'BYTE'),
(b'\x66\x66\x00\x02', 'ASCII'),
(b'\x66\x66\x00\x03', 'SHORT'),
(b'\x66\x66\x00\x04', 'LONG'),
(b'\x66\x66\x00\x05', 'RATIONAL'),
(b'\x66\x66\x00\x06', 'CUSTOM'),
])
def fixture(
self, request, ifd_entry_, _IfdEntry_, _AsciiIfdEntry_,
_ShortIfdEntry_, _LongIfdEntry_, _RationalIfdEntry_):
bytes_, entry_type = request.param
entry_cls_ = {
'BYTE': _IfdEntry_,
'ASCII': _AsciiIfdEntry_,
'SHORT': _ShortIfdEntry_,
'LONG': _LongIfdEntry_,
'RATIONAL': _RationalIfdEntry_,
'CUSTOM': _IfdEntry_,
}[entry_type]
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
offset = 0
return stream_rdr, offset, entry_cls_, ifd_entry_
@pytest.fixture
def ifd_entry_(self, request):
return instance_mock(request, _IfdEntry)
@pytest.fixture
def _IfdEntry_(self, request, ifd_entry_):
_IfdEntry_ = class_mock(request, 'docx.image.tiff._IfdEntry')
_IfdEntry_.from_stream.return_value = ifd_entry_
return _IfdEntry_
@pytest.fixture
def _AsciiIfdEntry_(self, request, ifd_entry_):
_AsciiIfdEntry_ = class_mock(
request, 'docx.image.tiff._AsciiIfdEntry')
_AsciiIfdEntry_.from_stream.return_value = ifd_entry_
return _AsciiIfdEntry_
@pytest.fixture
def _ShortIfdEntry_(self, request, ifd_entry_):
_ShortIfdEntry_ = class_mock(
request, 'docx.image.tiff._ShortIfdEntry')
_ShortIfdEntry_.from_stream.return_value = ifd_entry_
return _ShortIfdEntry_
@pytest.fixture
def _LongIfdEntry_(self, request, ifd_entry_):
_LongIfdEntry_ = class_mock(
request, 'docx.image.tiff._LongIfdEntry')
_LongIfdEntry_.from_stream.return_value = ifd_entry_
return _LongIfdEntry_
@pytest.fixture
def _RationalIfdEntry_(self, request, ifd_entry_):
_RationalIfdEntry_ = class_mock(
request, 'docx.image.tiff._RationalIfdEntry')
_RationalIfdEntry_.from_stream.return_value = ifd_entry_
return _RationalIfdEntry_
@pytest.fixture
def offset_(self, request):
return instance_mock(request, int)
class Describe_IfdEntry(object):
def it_can_construct_from_a_stream_and_offset(
self, _parse_value_, _IfdEntry__init_, value_
):
bytes_ = b'\x00\x01\x66\x66\x00\x00\x00\x02\x00\x00\x00\x03'
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
offset, tag_code, value_count, value_offset = 0, 1, 2, 3
_parse_value_.return_value = value_
ifd_entry = _IfdEntry.from_stream(stream_rdr, offset)
_parse_value_.assert_called_once_with(
stream_rdr, offset, value_count, value_offset
)
_IfdEntry__init_.assert_called_once_with(ANY, tag_code, value_)
assert isinstance(ifd_entry, _IfdEntry)
def it_provides_read_only_access_to_the_directory_entry(self):
tag_code, value = 1, 2
ifd_entry = _IfdEntry(tag_code, value)
assert (ifd_entry.tag, ifd_entry.value) == (tag_code, value)
# fixtures -------------------------------------------------------
@pytest.fixture
def _IfdEntry__init_(self, request):
return initializer_mock(request, _IfdEntry)
@pytest.fixture
def _parse_value_(self, request):
return method_mock(request, _IfdEntry, '_parse_value', autospec=False)
@pytest.fixture
def value_(self, request):
return loose_mock(request)
class Describe_AsciiIfdEntry(object):
def it_can_parse_an_ascii_string_IFD_entry(self):
bytes_ = b'foobar\x00'
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
val = _AsciiIfdEntry._parse_value(stream_rdr, None, 7, 0)
assert val == 'foobar'
class Describe_ShortIfdEntry(object):
def it_can_parse_a_short_int_IFD_entry(self):
bytes_ = b'foobaroo\x00\x2A'
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
val = _ShortIfdEntry._parse_value(stream_rdr, 0, 1, None)
assert val == 42
class Describe_LongIfdEntry(object):
def it_can_parse_a_long_int_IFD_entry(self):
bytes_ = b'foobaroo\x00\x00\x00\x2A'
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
val = _LongIfdEntry._parse_value(stream_rdr, 0, 1, None)
assert val == 42
class Describe_RationalIfdEntry(object):
def it_can_parse_a_rational_IFD_entry(self):
bytes_ = b'\x00\x00\x00\x2A\x00\x00\x00\x54'
stream_rdr = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
val = _RationalIfdEntry._parse_value(stream_rdr, None, 1, 0)
assert val == 0.5