Skip to content

Commit 71c657d

Browse files
author
Steve Canny
committed
run: remove prior Run.add_picture() Implementation
In preparation for a complete rewrite.
1 parent 026009d commit 71c657d

File tree

8 files changed

+11
-276
lines changed

8 files changed

+11
-276
lines changed

docx/shape.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
)
1111

1212
from .enum.shape import WD_INLINE_SHAPE
13-
from .oxml.shape import CT_Inline, CT_Picture
1413
from .oxml.ns import nsmap
1514
from .shared import Parented
1615

@@ -41,19 +40,6 @@ def __iter__(self):
4140
def __len__(self):
4241
return len(self._inline_lst)
4342

44-
def add_picture(self, image_descriptor, run):
45-
"""
46-
Return an |InlineShape| instance containing the picture identified by
47-
*image_descriptor* and added to the end of *run*. The picture shape
48-
has the native size of the image. *image_descriptor* can be a path (a
49-
string) or a file-like object containing a binary image.
50-
"""
51-
image_part, rId = self.part.get_or_add_image_part(image_descriptor)
52-
shape_id = self.part.next_id
53-
r = run._r
54-
picture = InlineShape.new_picture(r, image_part, rId, shape_id)
55-
return picture
56-
5743
@property
5844
def _inline_lst(self):
5945
body = self._body
@@ -84,22 +70,6 @@ def height(self, cy):
8470
assert 0 < cy
8571
self._inline.extent.cy = cy
8672

87-
@classmethod
88-
def new_picture(cls, r, image_part, rId, shape_id):
89-
"""
90-
Return a new |InlineShape| instance containing an inline picture
91-
placement of *image_part* appended to run *r* and uniquely identified
92-
by *shape_id*.
93-
"""
94-
cx, cy, filename = (
95-
image_part.default_cx, image_part.default_cy, image_part.filename
96-
)
97-
pic_id = 0
98-
pic = CT_Picture.new(pic_id, filename, rId, cx, cy)
99-
inline = CT_Inline.new(cx, cy, shape_id, pic)
100-
r.add_drawing(inline)
101-
return cls(inline)
102-
10373
@property
10474
def type(self):
10575
"""

docx/text/run.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,7 @@ def add_picture(self, image_path_or_stream, width=None, height=None):
5757
(dpi) value specified in the image file, defaulting to 72 dpi if no
5858
value is specified, as is often the case.
5959
"""
60-
inline_shapes = self.part.inline_shapes
61-
picture = inline_shapes.add_picture(image_path_or_stream, self)
62-
63-
# scale picture dimensions if width and/or height provided
64-
if width is not None or height is not None:
65-
native_width, native_height = picture.width, picture.height
66-
if width is None:
67-
scaling_factor = float(height) / float(native_height)
68-
width = int(round(native_width * scaling_factor))
69-
elif height is None:
70-
scaling_factor = float(width) / float(native_width)
71-
height = int(round(native_height * scaling_factor))
72-
# set picture to scaled dimensions
73-
picture.width = width
74-
picture.height = height
75-
76-
return picture
60+
raise NotImplementedError
7761

7862
def add_tab(self):
7963
"""

features/doc-add-picture.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,30 @@ Feature: Append an inline picture in its own paragraph
44
I need a way to add a picture in its own paragraph
55

66

7+
@wip
78
Scenario: Add a picture at native size
89
Given a blank document
910
When I add a picture specifying only the image file
1011
Then the document contains the inline picture
1112
And the picture has its native width and height
1213

1314

15+
@wip
1416
Scenario: Add a picture specifying both width and height
1517
Given a blank document
1618
When I add a picture specifying 1.75" width and 2.5" height
1719
Then picture.width is 1.75 inches
1820
And picture.height is 2.5 inches
1921

2022

23+
@wip
2124
Scenario: Add a picture specifying only width
2225
Given a blank document
2326
When I add a picture specifying a width of 1.5 inches
2427
Then picture.height is 2.14 inches
2528

2629

30+
@wip
2731
Scenario: Add a picture specifying only height
2832
Given a blank document
2933
When I add a picture specifying a height of 1.5 inches

features/run-add-picture.feature

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ Feature: Add picture to a run
33
As a developer using python-docx
44
I need a way to add a picture to a run
55

6+
7+
@wip
68
Scenario: Add a picture to a body paragraph run
79
Given a run
810
When I add a picture to the run
911
Then the picture appears at the end of the run
1012
And the document contains the inline picture
1113

1214

15+
@wip
1316
Scenario Outline: Add a picture to a run in a table cell
1417
Given a run inside a table cell retrieved from <cell-source>
1518
When I add a picture to the run

features/shp-add-inline-picture.feature

Lines changed: 0 additions & 16 deletions
This file was deleted.

features/steps/shape.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from docx.shape import InlineShape
1616
from docx.shared import Inches
1717

18-
from helpers import test_docx, test_file
18+
from helpers import test_docx
1919

2020

2121
# given ===================================================
@@ -49,23 +49,6 @@ def given_inline_shape_known_to_be_shape_of_type(context, shp_of_type):
4949

5050
# when =====================================================
5151

52-
@when('I add an inline picture from a file-like object')
53-
def when_add_inline_picture_from_file_like_object(context):
54-
document = context.document
55-
run = document.add_paragraph().add_run()
56-
with open(test_file('monty-truth.png'), 'rb') as f:
57-
context.inline_shape = document.inline_shapes.add_picture(f, run)
58-
59-
60-
@when('I add an inline picture to the document')
61-
def when_add_inline_picture_to_document(context):
62-
document = context.document
63-
run = document.add_paragraph().add_run()
64-
context.inline_shape = (document.inline_shapes.add_picture(
65-
test_file('monty-truth.png'), run
66-
))
67-
68-
6952
@when('I change the dimensions of the inline shape')
7053
def when_change_dimensions_of_inline_shape(context):
7154
inline_shape = context.inline_shape

tests/test_shape.py

Lines changed: 2 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,15 @@
99
import pytest
1010

1111
from docx.enum.shape import WD_INLINE_SHAPE
12-
from docx.oxml.document import CT_Body
1312
from docx.oxml.ns import nsmap
14-
from docx.oxml.text.run import CT_R
15-
from docx.parts.document import DocumentPart
16-
from docx.parts.image import ImagePart
1713
from docx.shape import InlineShape, InlineShapes
1814
from docx.shared import Length
19-
from docx.text.run import Run
2015

2116
from .oxml.unitdata.dml import (
22-
a_blip, a_blipFill, a_cNvGraphicFramePr, a_cNvPr, a_cNvPicPr, a_docPr,
23-
a_fillRect, a_graphic, a_graphicData, a_graphicFrameLocks, a_pic,
24-
a_prstGeom, a_stretch, an_ext, an_extent, an_inline, an_nvPicPr, an_off,
25-
an_spPr, an_xfrm
17+
a_blip, a_blipFill, a_graphic, a_graphicData, a_pic, an_inline,
2618
)
27-
from .oxml.unitdata.text import an_r
2819
from .unitutil.cxml import element, xml
29-
from .unitutil.mock import (
30-
class_mock, instance_mock, loose_mock, property_mock
31-
)
20+
from .unitutil.mock import loose_mock
3221

3322

3423
class DescribeInlineShapes(object):
@@ -64,42 +53,13 @@ def it_raises_on_indexed_access_out_of_range(
6453
too_high = inline_shape_count
6554
inline_shapes[too_high]
6655

67-
def it_can_add_an_inline_picture_to_the_document(
68-
self, add_picture_fixture):
69-
# fixture ----------------------
70-
(inline_shapes, image_descriptor_, document_, InlineShape_,
71-
run, r_, image_part_, rId_, shape_id_, new_picture_shape_
72-
) = add_picture_fixture
73-
# exercise ---------------------
74-
picture_shape = inline_shapes.add_picture(image_descriptor_, run)
75-
# verify -----------------------
76-
document_.get_or_add_image_part.assert_called_once_with(
77-
image_descriptor_
78-
)
79-
InlineShape_.new_picture.assert_called_once_with(
80-
r_, image_part_, rId_, shape_id_
81-
)
82-
assert picture_shape is new_picture_shape_
83-
8456
def it_knows_the_part_it_belongs_to(self, inline_shapes_with_parent_):
8557
inline_shapes, parent_ = inline_shapes_with_parent_
8658
part = inline_shapes.part
8759
assert part is parent_.part
8860

8961
# fixtures -------------------------------------------------------
9062

91-
@pytest.fixture
92-
def add_picture_fixture(
93-
self, request, body_, document_, image_descriptor_, InlineShape_,
94-
r_, image_part_, rId_, shape_id_, new_picture_shape_):
95-
inline_shapes = InlineShapes(body_, None)
96-
property_mock(request, InlineShapes, 'part', return_value=document_)
97-
run = Run(r_, None)
98-
return (
99-
inline_shapes, image_descriptor_, document_, InlineShape_, run,
100-
r_, image_part_, rId_, shape_id_, new_picture_shape_
101-
)
102-
10363
@pytest.fixture
10464
def inline_shapes_fixture(self):
10565
body = element(
@@ -111,71 +71,19 @@ def inline_shapes_fixture(self):
11171

11272
# fixture components ---------------------------------------------
11373

114-
@pytest.fixture
115-
def body_(self, request, r_):
116-
body_ = instance_mock(request, CT_Body)
117-
body_.add_p.return_value.add_r.return_value = r_
118-
return body_
119-
120-
@pytest.fixture
121-
def document_(self, request, rId_, image_part_, shape_id_):
122-
document_ = instance_mock(request, DocumentPart, name='document_')
123-
document_.get_or_add_image_part.return_value = image_part_, rId_
124-
document_.next_id = shape_id_
125-
return document_
126-
127-
@pytest.fixture
128-
def image_part_(self, request):
129-
return instance_mock(request, ImagePart)
130-
131-
@pytest.fixture
132-
def image_descriptor_(self, request):
133-
return instance_mock(request, str)
134-
135-
@pytest.fixture
136-
def InlineShape_(self, request, new_picture_shape_):
137-
InlineShape_ = class_mock(request, 'docx.shape.InlineShape')
138-
InlineShape_.new_picture.return_value = new_picture_shape_
139-
return InlineShape_
140-
14174
@pytest.fixture
14275
def inline_shapes_with_parent_(self, request):
14376
parent_ = loose_mock(request, name='parent_')
14477
inline_shapes = InlineShapes(None, parent_)
14578
return inline_shapes, parent_
14679

147-
@pytest.fixture
148-
def new_picture_shape_(self, request):
149-
return instance_mock(request, InlineShape)
150-
151-
@pytest.fixture
152-
def r_(self, request):
153-
return instance_mock(request, CT_R)
154-
155-
@pytest.fixture
156-
def rId_(self, request):
157-
return instance_mock(request, str)
158-
159-
@pytest.fixture
160-
def shape_id_(self, request):
161-
return instance_mock(request, int)
162-
16380

16481
class DescribeInlineShape(object):
16582

16683
def it_knows_what_type_of_shape_it_is(self, shape_type_fixture):
16784
inline_shape, inline_shape_type = shape_type_fixture
16885
assert inline_shape.type == inline_shape_type
16986

170-
def it_can_contruct_a_new_inline_picture_shape(
171-
self, new_picture_fixture):
172-
inline_shape, r, image_part_, rId, shape_id, expected_inline_xml = (
173-
new_picture_fixture
174-
)
175-
picture = inline_shape.new_picture(r, image_part_, rId, shape_id)
176-
assert picture._inline.xml == expected_inline_xml
177-
assert r[0][0] is picture._inline
178-
17987
def it_knows_its_display_dimensions(self, dimensions_get_fixture):
18088
inline_shape, cx, cy = dimensions_get_fixture
18189
width = inline_shape.width
@@ -211,29 +119,6 @@ def dimensions_set_fixture(self):
211119
expected_xml = xml(expected_cxml)
212120
return inline_shape, new_cx, new_cy, expected_xml
213121

214-
@pytest.fixture
215-
def new_picture_fixture(self, request, image_part_, image_params):
216-
filename, rId, cx, cy = image_params
217-
inline_shape = InlineShape(None)
218-
r = an_r().with_nsdecls().element
219-
shape_id = 7
220-
name = 'Picture %d' % shape_id
221-
uri = nsmap['pic']
222-
expected_inline = (
223-
an_inline().with_nsdecls('wp', 'a', 'pic', 'r', 'w').with_child(
224-
an_extent().with_cx(cx).with_cy(cy)).with_child(
225-
a_docPr().with_id(shape_id).with_name(name)).with_child(
226-
a_cNvGraphicFramePr().with_child(
227-
a_graphicFrameLocks().with_noChangeAspect(1))).with_child(
228-
a_graphic().with_child(
229-
a_graphicData().with_uri(uri).with_child(
230-
self._pic_bldr(filename, rId, cx, cy))))
231-
).element
232-
expected_inline_xml = expected_inline.xml
233-
return (
234-
inline_shape, r, image_part_, rId, shape_id, expected_inline_xml
235-
)
236-
237122
@pytest.fixture(params=[
238123
'embed pic', 'link pic', 'link+embed pic', 'chart', 'smart art',
239124
'not implemented'
@@ -267,22 +152,6 @@ def shape_type_fixture(self, request):
267152

268153
# fixture components ---------------------------------------------
269154

270-
@pytest.fixture
271-
def image_params(self):
272-
filename = 'foobar.garf'
273-
rId = 'rId42'
274-
cx, cy = 914422, 223344
275-
return filename, rId, cx, cy
276-
277-
@pytest.fixture
278-
def image_part_(self, request, image_params):
279-
filename, rId, cx, cy = image_params
280-
image_part_ = instance_mock(request, ImagePart)
281-
image_part_.default_cx = cx
282-
image_part_.default_cy = cy
283-
image_part_.filename = filename
284-
return image_part_
285-
286155
def _inline_with_picture(self, embed=False, link=False):
287156
picture_ns = nsmap['pic']
288157

@@ -309,20 +178,3 @@ def _inline_with_uri(self, uri):
309178
a_graphicData().with_uri(uri)))
310179
).element
311180
return inline
312-
313-
def _pic_bldr(self, name, rId, cx, cy):
314-
return (
315-
a_pic().with_child(
316-
an_nvPicPr().with_child(
317-
a_cNvPr().with_id(0).with_name(name)).with_child(
318-
a_cNvPicPr())).with_child(
319-
a_blipFill().with_child(
320-
a_blip().with_embed(rId)).with_child(
321-
a_stretch().with_child(
322-
a_fillRect()))).with_child(
323-
an_spPr().with_child(
324-
an_xfrm().with_child(
325-
an_off().with_x(0).with_y(0)).with_child(
326-
an_ext().with_cx(cx).with_cy(cy))).with_child(
327-
a_prstGeom().with_prst('rect')))
328-
)

0 commit comments

Comments
 (0)