Skip to content

Commit 10f1718

Browse files
author
Steve Canny
committed
shp: add InlineShapes.part
Added via parent protocol, implemented via docx.shared.Parented superclass
1 parent 6d46e86 commit 10f1718

3 files changed

Lines changed: 56 additions & 18 deletions

File tree

docx/parts/document.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from docx.opc.oxml import serialize_part_xml
99
from docx.opc.package import Part
1010
from docx.oxml.shared import nsmap, oxml_fromstring
11-
from docx.shared import lazyproperty
11+
from docx.shared import lazyproperty, Parented
1212
from docx.table import Table
1313
from docx.text import Paragraph
1414

@@ -50,7 +50,7 @@ def inline_shapes(self):
5050
The |InlineShapes| instance containing the inline shapes in the
5151
document.
5252
"""
53-
return InlineShapes(self._element.body)
53+
return InlineShapes(self._element.body, self)
5454

5555
@staticmethod
5656
def load(partname, content_type, blob, package):
@@ -67,6 +67,15 @@ def next_id(self):
6767
"""
6868
raise NotImplementedError
6969

70+
@property
71+
def part(self):
72+
"""
73+
Part of the parent protocol, "children" of the document will not know
74+
the part that contains them so must ask their parent object. That
75+
chain of delegation ends here for document child objects.
76+
"""
77+
return self
78+
7079

7180
class _Body(object):
7281
"""
@@ -160,13 +169,13 @@ def type(self):
160169
return WD_INLINE_SHAPE.NOT_IMPLEMENTED
161170

162171

163-
class InlineShapes(object):
172+
class InlineShapes(Parented):
164173
"""
165174
Sequence of |InlineShape| instances, supporting len(), iteration, and
166175
indexed access.
167176
"""
168-
def __init__(self, body_elm):
169-
super(InlineShapes, self).__init__()
177+
def __init__(self, body_elm, parent):
178+
super(InlineShapes, self).__init__(parent)
170179
self._body = body_elm
171180

172181
def __getitem__(self, idx):
@@ -198,15 +207,6 @@ def add_picture(self, image_descriptor):
198207
r = self._body.add_p().add_r()
199208
return InlineShape.new_picture(r, image, rId, shape_id)
200209

201-
@property
202-
def part(self):
203-
"""
204-
The package part containing this object, a |_Document| instance in
205-
this case.
206-
"""
207-
# return self._parent.part
208-
raise NotImplementedError
209-
210210
@property
211211
def _inline_lst(self):
212212
body = self._body

docx/shared.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,22 @@ def write_only_property(f):
3535
docstring = f.__doc__
3636

3737
return property(fset=f, doc=docstring)
38+
39+
40+
class Parented(object):
41+
"""
42+
Provides common services for document elements that occur below a part
43+
but may occasionally require an ancestor object to provide a service,
44+
such as add or drop a relationship. Provides ``self._parent`` attribute
45+
to subclasses.
46+
"""
47+
def __init__(self, parent):
48+
super(Parented, self).__init__()
49+
self._parent = parent
50+
51+
@property
52+
def part(self):
53+
"""
54+
The package part containing this object
55+
"""
56+
return self._parent.part

tests/parts/test_document.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
)
2929
from ..oxml.unitdata.text import a_p, a_sectPr, an_r
3030
from ..unitutil import (
31-
function_mock, class_mock, initializer_mock, instance_mock, property_mock
31+
function_mock, class_mock, initializer_mock, instance_mock, loose_mock,
32+
property_mock
3233
)
3334

3435

@@ -68,11 +69,18 @@ def it_provides_access_to_the_inline_shapes_in_the_document(
6869
self, inline_shapes_fixture):
6970
document, InlineShapes_, body_elm = inline_shapes_fixture
7071
inline_shapes = document.inline_shapes
71-
InlineShapes_.assert_called_once_with(body_elm)
72+
InlineShapes_.assert_called_once_with(body_elm, document)
7273
assert inline_shapes is InlineShapes_.return_value
7374

75+
def it_knows_it_is_the_part_its_child_objects_belong_to(self, document):
76+
assert document.part is document
77+
7478
# fixtures -------------------------------------------------------
7579

80+
@pytest.fixture
81+
def document(self):
82+
return _Document(None, None, None, None)
83+
7684
@pytest.fixture
7785
def document_blob_fixture(self, request, serialize_part_xml_):
7886
document_elm = instance_mock(request, CT_Document)
@@ -375,13 +383,18 @@ def it_can_add_an_inline_picture_to_the_document(
375383
)
376384
assert picture_shape is new_picture_shape_
377385

386+
def it_knows_the_part_it_belongs_to(self, inline_shapes_with_parent_):
387+
inline_shapes, parent_ = inline_shapes_with_parent_
388+
part = inline_shapes.part
389+
assert part is parent_.part
390+
378391
# fixtures -------------------------------------------------------
379392

380393
@pytest.fixture
381394
def add_picture_fixture(
382395
self, request, body_, document_, image_descriptor_, InlineShape_,
383396
r_, image_, rId_, shape_id_, new_picture_shape_):
384-
inline_shapes = InlineShapes(body_)
397+
inline_shapes = InlineShapes(body_, None)
385398
property_mock(request, InlineShapes, 'part', return_value=document_)
386399
return (
387400
inline_shapes, image_descriptor_, document_, InlineShape_, r_,
@@ -431,9 +444,15 @@ def inline_shapes_fixture(self):
431444
)
432445
)
433446
).element
434-
inline_shapes = InlineShapes(body)
447+
inline_shapes = InlineShapes(body, None)
435448
return inline_shapes, inline_shape_count
436449

450+
@pytest.fixture
451+
def inline_shapes_with_parent_(self, request):
452+
parent_ = loose_mock(request, name='parent_')
453+
inline_shapes = InlineShapes(None, parent_)
454+
return inline_shapes, parent_
455+
437456
@pytest.fixture
438457
def new_picture_shape_(self, request):
439458
return instance_mock(request, InlineShape)

0 commit comments

Comments
 (0)