Skip to content

Commit 2221719

Browse files
author
Steve Canny
committed
add RelationshipCollection.xml
1 parent 058ae06 commit 2221719

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

opc/oxml.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,17 @@ def target_mode(self):
175175
return self.get('TargetMode', RTM.INTERNAL)
176176

177177

178+
class CT_Relationships(OxmlBaseElement):
179+
"""
180+
``<Relationships>`` element, the root element in a .rels file.
181+
"""
182+
@staticmethod
183+
def new():
184+
"""
185+
Return a new ``<Relationships>`` element.
186+
"""
187+
188+
178189
class CT_Types(OxmlBaseElement):
179190
"""
180191
``<Types>`` element, the container element for Default and Override

opc/package.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Provides an API for manipulating Open Packaging Convention (OPC) packages.
1212
"""
1313

14+
from opc.oxml import CT_Relationships
1415
from opc.packuri import PACKAGE_URI
1516
from opc.pkgreader import PackageReader
1617
from opc.pkgwriter import PackageWriter
@@ -243,6 +244,18 @@ def add_relationship(self, reltype, target, rId, external=False):
243244
self._rels.append(rel)
244245
return rel
245246

247+
@property
248+
def xml(self):
249+
"""
250+
Serialize this relationship collection into XML suitable for storage
251+
as a .rels file in an OPC package.
252+
"""
253+
rels_elm = CT_Relationships.new()
254+
for rel in self._rels:
255+
rels_elm.add_rel(rel.rId, rel.reltype, rel.target_ref,
256+
rel.is_external)
257+
return rels_elm.xml
258+
246259

247260
class Unmarshaller(object):
248261
"""

tests/test_package.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from mock import call, Mock, patch, PropertyMock
1515

16+
from opc.oxml import CT_Relationships
1617
from opc.package import (
1718
OpcPackage, Part, PartFactory, _Relationship, RelationshipCollection,
1819
Unmarshaller
@@ -235,6 +236,41 @@ class DescribeRelationshipCollection(object):
235236
def _Relationship_(self, request):
236237
return class_mock('opc.package._Relationship', request)
237238

239+
@pytest.fixture
240+
def rels(self):
241+
"""
242+
Populated RelationshipCollection instance that will exercise the
243+
rels.xml property.
244+
"""
245+
rels = RelationshipCollection('/baseURI')
246+
rels.add_relationship(
247+
reltype='http://rt-hyperlink', target='http://some/link',
248+
rId='rId1', external=True
249+
)
250+
part = Mock(name='part')
251+
part.partname.relative_ref.return_value = '../media/image1.png'
252+
rels.add_relationship(reltype='http://rt-image', target=part,
253+
rId='rId2')
254+
return rels
255+
256+
@pytest.fixture
257+
def rels_elm(self, request):
258+
"""
259+
Return a rels_elm mock that will be returned from
260+
CT_Relationships.new()
261+
"""
262+
# create rels_elm mock with a .xml property
263+
rels_elm = Mock(name='rels_elm')
264+
xml = PropertyMock(name='xml')
265+
type(rels_elm).xml = xml
266+
rels_elm.attach_mock(xml, 'xml')
267+
rels_elm.reset_mock() # to clear attach_mock call
268+
# patch CT_Relationships to return that rels_elm
269+
patch_ = patch.object(CT_Relationships, 'new', return_value=rels_elm)
270+
patch_.start()
271+
request.addfinalizer(patch_.stop)
272+
return rels_elm
273+
238274
def it_has_a_len(self):
239275
rels = RelationshipCollection(None)
240276
assert len(rels) == 0
@@ -273,6 +309,21 @@ def it_can_add_a_relationship(self, _Relationship_):
273309
assert rels[0] == rel
274310
assert rel == _Relationship_.return_value
275311

312+
def it_can_compose_rels_xml(self, rels, rels_elm):
313+
# exercise ---------------------
314+
rels.xml
315+
# trace ------------------------
316+
print('Actual calls:\n%s' % rels_elm.mock_calls)
317+
# verify -----------------------
318+
expected_rels_elm_calls = [
319+
call.add_rel('rId1', 'http://rt-hyperlink', 'http://some/link',
320+
True),
321+
call.add_rel('rId2', 'http://rt-image', '../media/image1.png',
322+
False),
323+
call.xml()
324+
]
325+
assert rels_elm.mock_calls == expected_rels_elm_calls
326+
276327

277328
class DescribeUnmarshaller(object):
278329

0 commit comments

Comments
 (0)