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
|
import io
import textwrap
import zipfile
from nose.tools import istest, assert_equal
from mammoth import docx, documents, zips
from ..testing import assert_raises, test_path
@istest
class ReadTests(object):
@istest
def can_read_document_with_single_paragraph_with_single_run_of_text(self):
with open(test_path("single-paragraph.docx"), "rb") as fileobj:
result = docx.read(fileobj=fileobj)
expected_document = documents.document([
documents.paragraph([
documents.run([
documents.text("Walking on imported air")
])
])
])
assert_equal(expected_document, result.value)
_relationship_namespaces = {
"r": "http://schemas.openxmlformats.org/package/2006/relationships",
}
@istest
def main_document_is_found_using_package_relationships():
fileobj = _create_zip({
"word/document2.xml": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8" ?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Hello.</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
"""),
"_rels/.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document2.xml" Id="rId1"/>
</Relationships>
"""),
})
result = docx.read(fileobj=fileobj)
expected_document = documents.document([
documents.paragraph([
documents.run([
documents.text("Hello.")
])
])
])
assert_equal(expected_document, result.value)
@istest
def error_is_raised_when_main_document_part_does_not_exist():
fileobj = _create_zip({
"_rels/.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document2.xml" Id="rId1"/>
</Relationships>
"""),
})
error = assert_raises(IOError, lambda: docx.read(fileobj=fileobj))
assert_equal(
"Could not find main document part. Are you sure this is a valid .docx file?",
str(error),
)
class TestPartPaths(object):
@istest
def main_document_part_is_found_using_package_relationships(self):
fileobj = _create_zip({
"word/document2.xml": " ",
"_rels/.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document2.xml" Id="rId1"/>
</Relationships>
"""),
})
part_paths = self._find_part_paths(fileobj)
assert_equal("word/document2.xml", part_paths.main_document)
@istest
def when_relationship_for_main_document_cannot_be_found_then_fallback_is_used(self):
fileobj = _create_zip({
"word/document.xml": " ",
})
part_paths = self._find_part_paths(fileobj)
assert_equal("word/document.xml", part_paths.main_document)
@istest
def comments_part_is_found_using_main_document_relationships(self):
fileobj = _create_zip({
"_rels/.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document.xml" Id="rId1"/>
</Relationships>
"""),
"word/document.xml": " ",
"word/_rels/document.xml.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" Target="target-path.xml" Id="rId2"/>
</Relationships>
"""),
"word/target-path.xml": " "
})
part_paths = self._find_part_paths(fileobj)
assert_equal("word/target-path.xml", part_paths.comments)
@istest
def when_relationship_for_comments_cannot_be_found_then_fallback_is_used(self):
fileobj = _create_zip({
"_rels/.rels": textwrap.dedent("""\
<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="/word/document.xml" Id="rId1"/>
</Relationships>
"""),
"word/document.xml": " ",
})
part_paths = self._find_part_paths(fileobj)
assert_equal("word/comments.xml", part_paths.comments)
def _find_part_paths(self, fileobj):
return docx._find_part_paths(zips.open_zip(fileobj, "r"))
def _create_zip(files):
fileobj = io.BytesIO()
zip_file = zipfile.ZipFile(fileobj, "w")
try:
for name, contents in files.items():
zip_file.writestr(name, contents)
finally:
zip_file.close()
fileobj.seek(0)
return fileobj
|