File: test_shape.py

package info (click to toggle)
python-docx 0.8.11%2Bdfsg1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,640 kB
  • sloc: xml: 25,311; python: 21,911; makefile: 168
file content (183 lines) | stat: -rw-r--r-- 6,591 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# encoding: utf-8

"""
Test suite for the docx.shape module
"""

from __future__ import absolute_import, print_function, unicode_literals

import pytest

from docx.enum.shape import WD_INLINE_SHAPE
from docx.oxml.ns import nsmap
from docx.shape import InlineShape, InlineShapes
from docx.shared import Length

from .oxml.unitdata.dml import (
    a_blip, a_blipFill, a_graphic, a_graphicData, a_pic, an_inline,
)
from .unitutil.cxml import element, xml
from .unitutil.mock import loose_mock


class DescribeInlineShapes(object):

    def it_knows_how_many_inline_shapes_it_contains(
            self, inline_shapes_fixture):
        inline_shapes, expected_count = inline_shapes_fixture
        assert len(inline_shapes) == expected_count

    def it_can_iterate_over_its_InlineShape_instances(
            self, inline_shapes_fixture):
        inline_shapes, inline_shape_count = inline_shapes_fixture
        actual_count = 0
        for inline_shape in inline_shapes:
            assert isinstance(inline_shape, InlineShape)
            actual_count += 1
        assert actual_count == inline_shape_count

    def it_provides_indexed_access_to_inline_shapes(
            self, inline_shapes_fixture):
        inline_shapes, inline_shape_count = inline_shapes_fixture
        for idx in range(-inline_shape_count, inline_shape_count):
            inline_shape = inline_shapes[idx]
            assert isinstance(inline_shape, InlineShape)

    def it_raises_on_indexed_access_out_of_range(
            self, inline_shapes_fixture):
        inline_shapes, inline_shape_count = inline_shapes_fixture
        with pytest.raises(IndexError):
            too_low = -1 - inline_shape_count
            inline_shapes[too_low]
        with pytest.raises(IndexError):
            too_high = inline_shape_count
            inline_shapes[too_high]

    def it_knows_the_part_it_belongs_to(self, inline_shapes_with_parent_):
        inline_shapes, parent_ = inline_shapes_with_parent_
        part = inline_shapes.part
        assert part is parent_.part

    # fixtures -------------------------------------------------------

    @pytest.fixture
    def inline_shapes_fixture(self):
        body = element(
            'w:body/w:p/(w:r/w:drawing/wp:inline, w:r/w:drawing/wp:inline)'
        )
        inline_shapes = InlineShapes(body, None)
        expected_count = 2
        return inline_shapes, expected_count

    # fixture components ---------------------------------------------

    @pytest.fixture
    def inline_shapes_with_parent_(self, request):
        parent_ = loose_mock(request, name='parent_')
        inline_shapes = InlineShapes(None, parent_)
        return inline_shapes, parent_


class DescribeInlineShape(object):

    def it_knows_what_type_of_shape_it_is(self, shape_type_fixture):
        inline_shape, inline_shape_type = shape_type_fixture
        assert inline_shape.type == inline_shape_type

    def it_knows_its_display_dimensions(self, dimensions_get_fixture):
        inline_shape, cx, cy = dimensions_get_fixture
        width = inline_shape.width
        height = inline_shape.height
        assert isinstance(width, Length)
        assert width == cx
        assert isinstance(height, Length)
        assert height == cy

    def it_can_change_its_display_dimensions(self, dimensions_set_fixture):
        inline_shape, cx, cy, expected_xml = dimensions_set_fixture
        inline_shape.width = cx
        inline_shape.height = cy
        assert inline_shape._inline.xml == expected_xml

    # fixtures -------------------------------------------------------

    @pytest.fixture
    def dimensions_get_fixture(self):
        inline_cxml, expected_cx, expected_cy = (
            'wp:inline/wp:extent{cx=333, cy=666}', 333, 666
        )
        inline_shape = InlineShape(element(inline_cxml))
        return inline_shape, expected_cx, expected_cy

    @pytest.fixture
    def dimensions_set_fixture(self):
        inline_cxml, new_cx, new_cy, expected_cxml = (
            'wp:inline/(wp:extent{cx=333,cy=666},a:graphic/a:graphicData/'
            'pic:pic/pic:spPr/a:xfrm/a:ext{cx=333,cy=666})',
            444, 888,
            'wp:inline/(wp:extent{cx=444,cy=888},a:graphic/a:graphicData/'
            'pic:pic/pic:spPr/a:xfrm/a:ext{cx=444,cy=888})'
        )
        inline_shape = InlineShape(element(inline_cxml))
        expected_xml = xml(expected_cxml)
        return inline_shape, new_cx, new_cy, expected_xml

    @pytest.fixture(params=[
        'embed pic', 'link pic', 'link+embed pic', 'chart', 'smart art',
        'not implemented'
    ])
    def shape_type_fixture(self, request):
        if request.param == 'embed pic':
            inline = self._inline_with_picture(embed=True)
            shape_type = WD_INLINE_SHAPE.PICTURE

        elif request.param == 'link pic':
            inline = self._inline_with_picture(link=True)
            shape_type = WD_INLINE_SHAPE.LINKED_PICTURE

        elif request.param == 'link+embed pic':
            inline = self._inline_with_picture(embed=True, link=True)
            shape_type = WD_INLINE_SHAPE.LINKED_PICTURE

        elif request.param == 'chart':
            inline = self._inline_with_uri(nsmap['c'])
            shape_type = WD_INLINE_SHAPE.CHART

        elif request.param == 'smart art':
            inline = self._inline_with_uri(nsmap['dgm'])
            shape_type = WD_INLINE_SHAPE.SMART_ART

        elif request.param == 'not implemented':
            inline = self._inline_with_uri('foobar')
            shape_type = WD_INLINE_SHAPE.NOT_IMPLEMENTED

        return InlineShape(inline), shape_type

    # fixture components ---------------------------------------------

    def _inline_with_picture(self, embed=False, link=False):
        picture_ns = nsmap['pic']

        blip_bldr = a_blip()
        if embed:
            blip_bldr.with_embed('rId1')
        if link:
            blip_bldr.with_link('rId2')

        inline = (
            an_inline().with_nsdecls('wp', 'r').with_child(
                a_graphic().with_nsdecls().with_child(
                    a_graphicData().with_uri(picture_ns).with_child(
                        a_pic().with_nsdecls().with_child(
                            a_blipFill().with_child(
                                blip_bldr)))))
        ).element
        return inline

    def _inline_with_uri(self, uri):
        inline = (
            an_inline().with_nsdecls('wp').with_child(
                a_graphic().with_nsdecls().with_child(
                    a_graphicData().with_uri(uri)))
        ).element
        return inline