Skip to content

Commit ba56ea4

Browse files
author
Steve Canny
committed
add OpcPackage.save()
1 parent 6e60dbc commit ba56ea4

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

opc/package.py

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

1414
from opc.packuri import PACKAGE_URI
1515
from opc.pkgreader import PackageReader
16+
from opc.pkgwriter import PackageWriter
1617

1718

1819
class OpcPackage(object):
@@ -52,6 +53,15 @@ def rels(self):
5253
"""
5354
return self._rels
5455

56+
def save(self, pkg_file):
57+
"""
58+
Save this package to *pkg_file*, where *file* can be either a path to
59+
a file (a string) or a file-like object.
60+
"""
61+
for part in self.parts:
62+
part._before_marshal()
63+
PackageWriter.write(pkg_file, self._rels, self.parts)
64+
5565
def _add_relationship(self, reltype, target, rId, external=False):
5666
"""
5767
Return newly added |_Relationship| instance of *reltype* between this

opc/pkgwriter.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# pkgwriter.py
4+
#
5+
# Copyright (C) 2013 Steve Canny scanny@cisco.com
6+
#
7+
# This module is part of python-opc and is released under the MIT License:
8+
# http://www.opensource.org/licenses/mit-license.php
9+
10+
"""
11+
Provides a low-level, write-only API to a serialized Open Packaging
12+
Convention (OPC) package, essentially an implementation of OpcPackage.save()
13+
"""
14+
15+
16+
class PackageWriter(object):
17+
"""
18+
Writes a zip-format OPC package to *pkg_file*, where *pkg_file* can be
19+
either a path to a zip file (a string) or a file-like object. Its single
20+
API method, :meth:`write`, is static, so this class is not intended to
21+
be instantiated.
22+
"""
23+
@staticmethod
24+
def write(pkg_file, pkg_rels, parts):
25+
"""
26+
Write a physical package (.pptx file) to *pkg_file* containing
27+
*pkg_rels* and *parts* and a content types stream based on the
28+
content types of the parts.
29+
"""

tests/test_package.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import pytest
1313

14-
from mock import call, Mock, patch
14+
from mock import call, Mock, patch, PropertyMock
1515

1616
from opc.package import (
1717
OpcPackage, Part, PartFactory, _Relationship, RelationshipCollection,
@@ -33,10 +33,24 @@ class DescribeOpcPackage(object):
3333
def PackageReader_(self, request):
3434
return class_mock('opc.package.PackageReader', request)
3535

36+
@pytest.fixture
37+
def PackageWriter_(self, request):
38+
return class_mock('opc.package.PackageWriter', request)
39+
3640
@pytest.fixture
3741
def PartFactory_(self, request):
3842
return class_mock('opc.package.PartFactory', request)
3943

44+
@pytest.fixture
45+
def parts(self, request):
46+
"""
47+
Return a mock patching property OpcPackage.parts, reversing the
48+
patch after each use.
49+
"""
50+
_patch = patch.object(OpcPackage, 'parts', new_callable=PropertyMock)
51+
request.addfinalizer(_patch.stop)
52+
return _patch.start()
53+
4054
@pytest.fixture
4155
def Unmarshaller_(self, request):
4256
return class_mock('opc.package.Unmarshaller', request)
@@ -102,6 +116,19 @@ def it_can_iterate_over_parts_by_walking_rels_graph(self):
102116
# verify -----------------------
103117
assert generated_parts == [part1, part2]
104118

119+
def it_can_save_to_a_pkg_file(self, PackageWriter_, parts):
120+
# mockery ----------------------
121+
pkg_file = Mock(name='pkg_file')
122+
pkg = OpcPackage()
123+
parts.return_value = parts = [Mock(name='part1'), Mock(name='part2')]
124+
# exercise ---------------------
125+
pkg.save(pkg_file)
126+
# verify -----------------------
127+
for part in parts:
128+
part._before_marshal.assert_called_once_with()
129+
PackageWriter_.write.assert_called_once_with(pkg_file, pkg._rels,
130+
parts)
131+
105132

106133
class DescribePart(object):
107134

0 commit comments

Comments
 (0)