Repository URL to install this package:
|
Version:
0.8.10 ▾
|
# encoding: utf-8
"""Unit test suite for docx.image.jpeg module"""
from __future__ import absolute_import, print_function
import pytest
from docx.compat import BytesIO
from docx.image.constants import JPEG_MARKER_CODE, MIME_TYPE
from docx.image.helpers import BIG_ENDIAN, StreamReader
from docx.image.jpeg import (
_App0Marker,
_App1Marker,
Exif,
Jfif,
_JfifMarkers,
Jpeg,
_Marker,
_MarkerFactory,
_MarkerFinder,
_MarkerParser,
_SofMarker,
)
from docx.image.tiff import Tiff
from ..unitutil.mock import (
ANY,
call,
class_mock,
initializer_mock,
instance_mock,
method_mock,
)
class DescribeJpeg(object):
def it_knows_its_content_type(self):
jpeg = Jpeg(None, None, None, None)
assert jpeg.content_type == MIME_TYPE.JPEG
def it_knows_its_default_ext(self):
jpeg = Jpeg(None, None, None, None)
assert jpeg.default_ext == 'jpg'
class DescribeExif(object):
def it_can_construct_from_an_exif_stream(self, from_exif_fixture):
# fixture ----------------------
stream_, _JfifMarkers_, cx, cy, horz_dpi, vert_dpi = (
from_exif_fixture
)
# exercise ---------------------
exif = Exif.from_stream(stream_)
# verify -----------------------
_JfifMarkers_.from_stream.assert_called_once_with(stream_)
assert isinstance(exif, Exif)
assert exif.px_width == cx
assert exif.px_height == cy
assert exif.horz_dpi == horz_dpi
assert exif.vert_dpi == vert_dpi
class DescribeJfif(object):
def it_can_construct_from_a_jfif_stream(self, from_jfif_fixture):
stream_, _JfifMarkers_, cx, cy, horz_dpi, vert_dpi = (
from_jfif_fixture
)
jfif = Jfif.from_stream(stream_)
_JfifMarkers_.from_stream.assert_called_once_with(stream_)
assert isinstance(jfif, Jfif)
assert jfif.px_width == cx
assert jfif.px_height == cy
assert jfif.horz_dpi == horz_dpi
assert jfif.vert_dpi == vert_dpi
# fixtures -------------------------------------------------------
@pytest.fixture
def from_exif_fixture(self, stream_, _JfifMarkers_, jfif_markers_):
px_width, px_height = 111, 222
horz_dpi, vert_dpi = 333, 444
jfif_markers_.sof.px_width = px_width
jfif_markers_.sof.px_height = px_height
jfif_markers_.app1.horz_dpi = horz_dpi
jfif_markers_.app1.vert_dpi = vert_dpi
return (
stream_, _JfifMarkers_, px_width, px_height, horz_dpi, vert_dpi
)
@pytest.fixture
def from_jfif_fixture(self, stream_, _JfifMarkers_, jfif_markers_):
px_width, px_height = 111, 222
horz_dpi, vert_dpi = 333, 444
jfif_markers_.sof.px_width = px_width
jfif_markers_.sof.px_height = px_height
jfif_markers_.app0.horz_dpi = horz_dpi
jfif_markers_.app0.vert_dpi = vert_dpi
return (
stream_, _JfifMarkers_, px_width, px_height, horz_dpi, vert_dpi
)
@pytest.fixture
def _JfifMarkers_(self, request, jfif_markers_):
_JfifMarkers_ = class_mock(request, 'docx.image.jpeg._JfifMarkers')
_JfifMarkers_.from_stream.return_value = jfif_markers_
return _JfifMarkers_
@pytest.fixture
def jfif_markers_(self, request):
return instance_mock(request, _JfifMarkers)
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_JfifMarkers(object):
def it_can_construct_from_a_jfif_stream(
self, stream_, _MarkerParser_, _JfifMarkers__init_, soi_, app0_, sof_, sos_
):
marker_lst = [soi_, app0_, sof_, sos_]
jfif_markers = _JfifMarkers.from_stream(stream_)
_MarkerParser_.from_stream.assert_called_once_with(stream_)
_JfifMarkers__init_.assert_called_once_with(ANY, marker_lst)
assert isinstance(jfif_markers, _JfifMarkers)
def it_can_find_the_APP0_marker(self, app0_fixture):
jfif_markers, app0_ = app0_fixture
app0 = jfif_markers.app0
assert app0 is app0_
def it_can_find_the_APP1_marker(self, app1_fixture):
jfif_markers, app1_ = app1_fixture
app1 = jfif_markers.app1
assert app1 is app1_
def it_raises_if_it_cant_find_the_APP0_marker(self, no_app0_fixture):
jfif_markers = no_app0_fixture
with pytest.raises(KeyError):
jfif_markers.app0
def it_raises_if_it_cant_find_the_APP1_marker(self, no_app1_fixture):
jfif_markers = no_app1_fixture
with pytest.raises(KeyError):
jfif_markers.app1
def it_can_find_the_SOF_marker(self, sof_fixture):
jfif_markers, sof_ = sof_fixture
sof = jfif_markers.sof
assert sof is sof_
def it_raises_if_it_cant_find_the_SOF_marker(self, no_sof_fixture):
jfif_markers = no_sof_fixture
with pytest.raises(KeyError):
jfif_markers.sof
# fixtures -------------------------------------------------------
@pytest.fixture
def app0_(self, request):
return instance_mock(
request, _App0Marker, marker_code=JPEG_MARKER_CODE.APP0
)
@pytest.fixture
def app1_(self, request):
return instance_mock(
request, _App1Marker, marker_code=JPEG_MARKER_CODE.APP1
)
@pytest.fixture
def app0_fixture(self, soi_, app0_, eoi_):
markers = (soi_, app0_, eoi_)
jfif_markers = _JfifMarkers(markers)
return jfif_markers, app0_
@pytest.fixture
def app1_fixture(self, soi_, app1_, eoi_):
markers = (soi_, app1_, eoi_)
jfif_markers = _JfifMarkers(markers)
return jfif_markers, app1_
@pytest.fixture
def eoi_(self, request):
return instance_mock(
request, _SofMarker, marker_code=JPEG_MARKER_CODE.EOI
)
@pytest.fixture
def _JfifMarkers__init_(self, request):
return initializer_mock(request, _JfifMarkers)
@pytest.fixture
def marker_parser_(self, request, markers_all_):
marker_parser_ = instance_mock(request, _MarkerParser)
marker_parser_.iter_markers.return_value = markers_all_
return marker_parser_
@pytest.fixture
def _MarkerParser_(self, request, marker_parser_):
_MarkerParser_ = class_mock(request, 'docx.image.jpeg._MarkerParser')
_MarkerParser_.from_stream.return_value = marker_parser_
return _MarkerParser_
@pytest.fixture
def markers_all_(self, request, soi_, app0_, sof_, sos_, eoi_):
return [soi_, app0_, sof_, sos_, eoi_]
@pytest.fixture
def no_app0_fixture(self, soi_, eoi_):
markers = (soi_, eoi_)
return _JfifMarkers(markers)
@pytest.fixture
def no_app1_fixture(self, soi_, eoi_):
markers = (soi_, eoi_)
return _JfifMarkers(markers)
@pytest.fixture
def no_sof_fixture(self, soi_, eoi_):
markers = (soi_, eoi_)
return _JfifMarkers(markers)
@pytest.fixture
def sof_(self, request):
return instance_mock(
request, _SofMarker, marker_code=JPEG_MARKER_CODE.SOF0
)
@pytest.fixture
def sof_fixture(self, soi_, sof_, eoi_):
markers = (soi_, sof_, eoi_)
jfif_markers = _JfifMarkers(markers)
return jfif_markers, sof_
@pytest.fixture
def soi_(self, request):
return instance_mock(
request, _Marker, marker_code=JPEG_MARKER_CODE.SOI
)
@pytest.fixture
def sos_(self, request):
return instance_mock(
request, _Marker, marker_code=JPEG_MARKER_CODE.SOS
)
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_Marker(object):
def it_can_construct_from_a_stream_and_offset(self, from_stream_fixture):
stream, marker_code, offset, _Marker__init_, length = from_stream_fixture
marker = _Marker.from_stream(stream, marker_code, offset)
_Marker__init_.assert_called_once_with(ANY, marker_code, offset, length)
assert isinstance(marker, _Marker)
# fixtures -------------------------------------------------------
@pytest.fixture(params=[
(JPEG_MARKER_CODE.SOI, 2, 0),
(JPEG_MARKER_CODE.APP0, 4, 16),
])
def from_stream_fixture(self, request, _Marker__init_):
marker_code, offset, length = request.param
bytes_ = b'\xFF\xD8\xFF\xE0\x00\x10'
stream_reader = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
return stream_reader, marker_code, offset, _Marker__init_, length
@pytest.fixture
def _Marker__init_(self, request):
return initializer_mock(request, _Marker)
class Describe_App0Marker(object):
def it_can_construct_from_a_stream_and_offset(self, _App0Marker__init_):
bytes_ = b'\x00\x10JFIF\x00\x01\x01\x01\x00\x2A\x00\x18'
marker_code, offset, length = JPEG_MARKER_CODE.APP0, 0, 16
density_units, x_density, y_density = 1, 42, 24
stream = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
app0_marker = _App0Marker.from_stream(stream, marker_code, offset)
_App0Marker__init_.assert_called_once_with(
ANY, marker_code, offset, length, density_units, x_density, y_density
)
assert isinstance(app0_marker, _App0Marker)
def it_knows_the_image_dpi(self, dpi_fixture):
density_units, x_density, y_density, horz_dpi, vert_dpi = dpi_fixture
app0 = _App0Marker(
None, None, None, density_units, x_density, y_density
)
assert app0.horz_dpi == horz_dpi
assert app0.vert_dpi == vert_dpi
# fixtures -------------------------------------------------------
@pytest.fixture
def _App0Marker__init_(self, request):
return initializer_mock(request, _App0Marker)
@pytest.fixture(params=[
(0, 100, 200, 72, 72),
(1, 100, 200, 100, 200),
(2, 100, 200, 254, 508),
])
def dpi_fixture(self, request):
density_units, x_density, y_density, horz_dpi, vert_dpi = (
request.param
)
return density_units, x_density, y_density, horz_dpi, vert_dpi
class Describe_App1Marker(object):
def it_can_construct_from_a_stream_and_offset(
self, _App1Marker__init_, _tiff_from_exif_segment_
):
bytes_ = b'\x00\x42Exif\x00\x00'
marker_code, offset, length = JPEG_MARKER_CODE.APP1, 0, 66
horz_dpi, vert_dpi = 42, 24
stream = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
app1_marker = _App1Marker.from_stream(stream, marker_code, offset)
_tiff_from_exif_segment_.assert_called_once_with(stream, offset, length)
_App1Marker__init_.assert_called_once_with(
ANY, marker_code, offset, length, horz_dpi, vert_dpi
)
assert isinstance(app1_marker, _App1Marker)
def it_can_construct_from_non_Exif_APP1_segment(self, _App1Marker__init_):
bytes_ = b'\x00\x42Foobar'
marker_code, offset, length = JPEG_MARKER_CODE.APP1, 0, 66
stream = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
app1_marker = _App1Marker.from_stream(stream, marker_code, offset)
_App1Marker__init_.assert_called_once_with(
ANY, marker_code, offset, length, 72, 72
)
assert isinstance(app1_marker, _App1Marker)
def it_gets_a_tiff_from_its_Exif_segment_to_help_construct(
self, get_tiff_fixture):
stream, offset, length = get_tiff_fixture[:3]
BytesIO_, segment_bytes, substream_ = get_tiff_fixture[3:6]
Tiff_, tiff_ = get_tiff_fixture[6:]
tiff = _App1Marker._tiff_from_exif_segment(stream, offset, length)
BytesIO_.assert_called_once_with(segment_bytes)
Tiff_.from_stream.assert_called_once_with(substream_)
assert tiff is tiff_
def it_knows_the_image_dpi(self):
horz_dpi, vert_dpi = 42, 24
app1 = _App1Marker(None, None, None, horz_dpi, vert_dpi)
assert app1.horz_dpi == horz_dpi
assert app1.vert_dpi == vert_dpi
# fixtures -------------------------------------------------------
@pytest.fixture
def _App1Marker__init_(self, request):
return initializer_mock(request, _App1Marker)
@pytest.fixture
def BytesIO_(self, request, substream_):
return class_mock(
request, 'docx.image.jpeg.BytesIO', return_value=substream_
)
@pytest.fixture
def get_tiff_fixture(self, request, BytesIO_, substream_, Tiff_, tiff_):
bytes_ = b'xfillerxMM\x00*\x00\x00\x00\x42'
stream_reader = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
offset, segment_length, segment_bytes = 0, 16, bytes_[8:]
return (
stream_reader, offset, segment_length, BytesIO_, segment_bytes,
substream_, Tiff_, tiff_
)
@pytest.fixture
def substream_(self, request):
return instance_mock(request, BytesIO)
@pytest.fixture
def Tiff_(self, request, tiff_):
Tiff_ = class_mock(request, 'docx.image.jpeg.Tiff')
Tiff_.from_stream.return_value = tiff_
return Tiff_
@pytest.fixture
def tiff_(self, request):
return instance_mock(request, Tiff, horz_dpi=42, vert_dpi=24)
@pytest.fixture
def _tiff_from_exif_segment_(self, request, tiff_):
return method_mock(
request, _App1Marker, '_tiff_from_exif_segment', autospec=False,
return_value=tiff_
)
class Describe_SofMarker(object):
def it_can_construct_from_a_stream_and_offset(self, request, _SofMarker__init_):
bytes_ = b'\x00\x11\x00\x00\x2A\x00\x18'
marker_code, offset, length = JPEG_MARKER_CODE.SOF0, 0, 17
px_width, px_height = 24, 42
stream = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
sof_marker = _SofMarker.from_stream(stream, marker_code, offset)
_SofMarker__init_.assert_called_once_with(
ANY, marker_code, offset, length, px_width, px_height
)
assert isinstance(sof_marker, _SofMarker)
def it_knows_the_image_width_and_height(self):
sof = _SofMarker(None, None, None, 42, 24)
assert sof.px_width == 42
assert sof.px_height == 24
# fixtures -------------------------------------------------------
@pytest.fixture
def _SofMarker__init_(self, request):
return initializer_mock(request, _SofMarker)
class Describe_MarkerFactory(object):
def it_constructs_the_appropriate_marker_object(self, call_fixture):
marker_code, stream_, offset_, marker_cls_ = call_fixture
marker = _MarkerFactory(marker_code, stream_, offset_)
marker_cls_.from_stream.assert_called_once_with(
stream_, marker_code, offset_
)
assert marker is marker_cls_.from_stream.return_value
# fixtures -------------------------------------------------------
@pytest.fixture(params=[
JPEG_MARKER_CODE.APP0,
JPEG_MARKER_CODE.APP1,
JPEG_MARKER_CODE.SOF0,
JPEG_MARKER_CODE.SOF7,
JPEG_MARKER_CODE.SOS,
])
def call_fixture(
self, request, stream_, offset_, _App0Marker_, _App1Marker_,
_SofMarker_, _Marker_):
marker_code = request.param
if marker_code == JPEG_MARKER_CODE.APP0:
marker_cls_ = _App0Marker_
elif marker_code == JPEG_MARKER_CODE.APP1:
marker_cls_ = _App1Marker_
elif marker_code in JPEG_MARKER_CODE.SOF_MARKER_CODES:
marker_cls_ = _SofMarker_
else:
marker_cls_ = _Marker_
return marker_code, stream_, offset_, marker_cls_
@pytest.fixture
def _App0Marker_(self, request):
return class_mock(request, 'docx.image.jpeg._App0Marker')
@pytest.fixture
def _App1Marker_(self, request):
return class_mock(request, 'docx.image.jpeg._App1Marker')
@pytest.fixture
def _Marker_(self, request):
return class_mock(request, 'docx.image.jpeg._Marker')
@pytest.fixture
def offset_(self, request):
return instance_mock(request, int)
@pytest.fixture
def _SofMarker_(self, request):
return class_mock(request, 'docx.image.jpeg._SofMarker')
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_MarkerFinder(object):
def it_can_construct_from_a_stream(self, stream_, _MarkerFinder__init_):
marker_finder = _MarkerFinder.from_stream(stream_)
_MarkerFinder__init_.assert_called_once_with(ANY, stream_)
assert isinstance(marker_finder, _MarkerFinder)
def it_can_find_the_next_marker_after_a_given_offset(self, next_fixture):
marker_finder, start, expected_code_and_offset = next_fixture
marker_code, segment_offset = marker_finder.next(start)
assert (marker_code, segment_offset) == expected_code_and_offset
# fixtures -------------------------------------------------------
@pytest.fixture
def _MarkerFinder__init_(self, request):
return initializer_mock(request, _MarkerFinder)
@pytest.fixture(params=[
(0, JPEG_MARKER_CODE.SOI, 2),
(1, JPEG_MARKER_CODE.APP0, 4),
(2, JPEG_MARKER_CODE.APP0, 4),
(3, JPEG_MARKER_CODE.EOI, 12),
(4, JPEG_MARKER_CODE.EOI, 12),
(6, JPEG_MARKER_CODE.EOI, 12),
(8, JPEG_MARKER_CODE.EOI, 12),
])
def next_fixture(self, request):
start, marker_code, segment_offset = request.param
bytes_ = b'\xFF\xD8\xFF\xE0\x00\x01\xFF\x00\xFF\xFF\xFF\xD9'
stream_reader = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
marker_finder = _MarkerFinder(stream_reader)
expected_code_and_offset = (marker_code, segment_offset)
return marker_finder, start, expected_code_and_offset
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
class Describe_MarkerParser(object):
def it_can_construct_from_a_jfif_stream(
self, stream_, StreamReader_, _MarkerParser__init_, stream_reader_
):
marker_parser = _MarkerParser.from_stream(stream_)
StreamReader_.assert_called_once_with(stream_, BIG_ENDIAN)
_MarkerParser__init_.assert_called_once_with(ANY, stream_reader_)
assert isinstance(marker_parser, _MarkerParser)
def it_can_iterate_over_the_jfif_markers_in_its_stream(
self, iter_markers_fixture):
(marker_parser, stream_, _MarkerFinder_, marker_finder_,
_MarkerFactory_, marker_codes, offsets,
marker_lst) = iter_markers_fixture
markers = [marker for marker in marker_parser.iter_markers()]
_MarkerFinder_.from_stream.assert_called_once_with(stream_)
assert marker_finder_.next.call_args_list == [
call(0), call(2), call(20)
]
assert _MarkerFactory_.call_args_list == [
call(marker_codes[0], stream_, offsets[0]),
call(marker_codes[1], stream_, offsets[1]),
call(marker_codes[2], stream_, offsets[2]),
]
assert markers == marker_lst
# fixtures -------------------------------------------------------
@pytest.fixture
def app0_(self, request):
return instance_mock(request, _App0Marker, segment_length=16)
@pytest.fixture
def eoi_(self, request):
return instance_mock(request, _Marker, segment_length=0)
@pytest.fixture
def iter_markers_fixture(
self, stream_reader_, _MarkerFinder_, marker_finder_,
_MarkerFactory_, soi_, app0_, eoi_):
marker_parser = _MarkerParser(stream_reader_)
offsets = [2, 4, 22]
marker_lst = [soi_, app0_, eoi_]
marker_finder_.next.side_effect = [
(JPEG_MARKER_CODE.SOI, offsets[0]),
(JPEG_MARKER_CODE.APP0, offsets[1]),
(JPEG_MARKER_CODE.EOI, offsets[2]),
]
marker_codes = [
JPEG_MARKER_CODE.SOI, JPEG_MARKER_CODE.APP0, JPEG_MARKER_CODE.EOI
]
return (
marker_parser, stream_reader_, _MarkerFinder_, marker_finder_,
_MarkerFactory_, marker_codes, offsets, marker_lst
)
@pytest.fixture
def _MarkerFactory_(self, request, soi_, app0_, eoi_):
return class_mock(
request, 'docx.image.jpeg._MarkerFactory',
side_effect=[soi_, app0_, eoi_]
)
@pytest.fixture
def _MarkerFinder_(self, request, marker_finder_):
_MarkerFinder_ = class_mock(request, 'docx.image.jpeg._MarkerFinder')
_MarkerFinder_.from_stream.return_value = marker_finder_
return _MarkerFinder_
@pytest.fixture
def marker_finder_(self, request):
return instance_mock(request, _MarkerFinder)
@pytest.fixture
def _MarkerParser__init_(self, request):
return initializer_mock(request, _MarkerParser)
@pytest.fixture
def soi_(self, request):
return instance_mock(request, _Marker, segment_length=0)
@pytest.fixture
def stream_(self, request):
return instance_mock(request, BytesIO)
@pytest.fixture
def StreamReader_(self, request, stream_reader_):
return class_mock(
request, 'docx.image.jpeg.StreamReader',
return_value=stream_reader_
)
@pytest.fixture
def stream_reader_(self, request):
return instance_mock(request, StreamReader)