aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mammoth/docx/__init__.py96
-rw-r--r--mammoth/docx/comments_xml.py4
-rw-r--r--mammoth/docx/notes_xml.py8
-rw-r--r--tests/docx/comments_xml_tests.py18
-rw-r--r--tests/docx/notes_xml_tests.py10
5 files changed, 81 insertions, 55 deletions
diff --git a/mammoth/docx/__init__.py b/mammoth/docx/__init__.py
index b155cff..9d0cdc2 100644
--- a/mammoth/docx/__init__.py
+++ b/mammoth/docx/__init__.py
@@ -1,3 +1,4 @@
+from functools import partial
import os
from .. import results, lists
@@ -6,8 +7,8 @@ from .content_types_xml import empty_content_types, read_content_types_xml_eleme
from .relationships_xml import read_relationships_xml_element, Relationships
from .numbering_xml import read_numbering_xml_element, Numbering
from .styles_xml import read_styles_xml_element, Styles
-from .notes_xml import create_footnotes_reader, create_endnotes_reader
-from .comments_xml import create_comments_reader
+from .notes_xml import read_endnotes_xml_element, read_footnotes_xml_element
+from .comments_xml import read_comments_xml_element
from .files import Files
from . import body_xml, office_xml
from ..zips import open_zip
@@ -18,38 +19,40 @@ _empty_result = results.success([])
def read(fileobj):
zip_file = open_zip(fileobj, "r")
- body_readers = _body_readers(getattr(fileobj, "name", None), zip_file)
+ read_part_with_body = _part_with_body_reader(getattr(fileobj, "name", None), zip_file)
return results.combine([
- _read_notes(zip_file, body_readers),
- _read_comments(zip_file, body_readers),
+ _read_notes(zip_file, read_part_with_body),
+ _read_comments(zip_file, read_part_with_body),
]).bind(lambda referents:
- _read_document(zip_file, body_readers, notes=referents[0], comments=referents[1])
+ _read_document(zip_file, read_part_with_body, notes=referents[0], comments=referents[1])
)
-def _read_notes(zip_file, body_readers):
- read_footnotes_xml = create_footnotes_reader(body_readers("footnotes"))
- footnotes = _try_read_entry_or_default(
- zip_file, "word/footnotes.xml", read_footnotes_xml, default=_empty_result)
-
- read_endnotes_xml = create_endnotes_reader(body_readers("endnotes"))
- endnotes = _try_read_entry_or_default(
- zip_file, "word/endnotes.xml", read_endnotes_xml, default=_empty_result)
+def _read_notes(zip_file, read_part_with_body):
+ footnotes = read_part_with_body(
+ "word/footnotes.xml",
+ lambda root, body_reader: read_footnotes_xml_element(root, body_reader=body_reader),
+ default=_empty_result,
+ )
+ endnotes = read_part_with_body(
+ "word/endnotes.xml",
+ lambda root, body_reader: read_endnotes_xml_element(root, body_reader=body_reader),
+ default=_empty_result,
+ )
return results.combine([footnotes, endnotes]).map(lists.flatten)
-def _read_comments(zip_file, body_readers):
- return _try_read_entry_or_default(
- zip_file,
+def _read_comments(zip_file, read_part_with_body):
+ return read_part_with_body(
"word/comments.xml",
- create_comments_reader(body_readers("comments")),
+ lambda root, body_reader: read_comments_xml_element(root, body_reader=body_reader),
default=_empty_result,
)
-def _read_document(zip_file, body_readers, notes, comments):
+def _read_document(zip_file, read_part_with_body, notes, comments):
package_relationships = _try_read_entry_or_default(
zip_file,
"_rels/.rels",
@@ -59,14 +62,14 @@ def _read_document(zip_file, body_readers, notes, comments):
document_filename = _find_document_filename(zip_file, package_relationships)
- with zip_file.open(document_filename) as document_fileobj:
- document_xml = office_xml.read(document_fileobj)
- return read_document_xml_element(
- document_xml,
- body_reader=body_readers("document"),
+ return read_part_with_body(
+ document_filename,
+ partial(
+ read_document_xml_element,
notes=notes,
comments=comments,
- )
+ ),
+ )
def _find_document_filename(zip_file, relationships):
@@ -82,7 +85,7 @@ def _find_document_filename(zip_file, relationships):
return valid_targets[0]
-def _body_readers(document_path, zip_file):
+def _part_with_body_reader(document_path, zip_file):
content_types = _try_read_entry_or_default(
zip_file,
"[Content_Types].xml",
@@ -100,13 +103,10 @@ def _body_readers(document_path, zip_file):
Styles.EMPTY,
)
- def for_name(name):
- relationships_path = "word/_rels/{0}.xml.rels".format(name)
- relationships = _try_read_entry_or_default(
- zip_file, relationships_path, read_relationships_xml_element,
- default=Relationships.EMPTY)
+ def read_part(name, reader, default=_undefined):
+ relationships = _read_relationships(zip_file, _find_relationships_path_for(name))
- return body_xml.reader(
+ body_reader = body_xml.reader(
numbering=numbering,
content_types=content_types,
relationships=relationships,
@@ -114,13 +114,39 @@ def _body_readers(document_path, zip_file):
docx_file=zip_file,
files=Files(None if document_path is None else os.path.dirname(document_path)),
)
+
+ if default is _undefined:
+ return _read_entry(zip_file, name, partial(reader, body_reader=body_reader))
+ else:
+ return _try_read_entry_or_default(zip_file, name, partial(reader, body_reader=body_reader), default=default)
- return for_name
+ return read_part
+
+def _find_relationships_path_for(name):
+ parts = name.split("/")
+ return "/".join(parts[:-1] + ["_rels/" + parts[-1] + ".rels"])
+
+
+def _read_relationships(zip_file, name):
+ return _try_read_entry_or_default(
+ zip_file,
+ name,
+ read_relationships_xml_element,
+ default=Relationships.EMPTY,
+ )
+
def _try_read_entry_or_default(zip_file, name, reader, default):
if zip_file.exists(name):
- with zip_file.open(name) as fileobj:
- return reader(office_xml.read(fileobj))
+ return _read_entry(zip_file, name, reader)
else:
return default
+
+
+def _read_entry(zip_file, name, reader):
+ with zip_file.open(name) as fileobj:
+ return reader(office_xml.read(fileobj))
+
+
+_undefined = object()
diff --git a/mammoth/docx/comments_xml.py b/mammoth/docx/comments_xml.py
index 6d35c12..387432f 100644
--- a/mammoth/docx/comments_xml.py
+++ b/mammoth/docx/comments_xml.py
@@ -3,7 +3,7 @@ from .. import documents
from .. import results
-def create_comments_reader(body_reader):
+def read_comments_xml_element(element, body_reader):
def read_comments_xml_element(element):
comment_elements = element.find_children("w:comment")
return results.combine(lists.map(_read_comment_element, comment_elements))
@@ -21,4 +21,4 @@ def create_comments_reader(body_reader):
author_initials=read_optional_attribute("w:initials"),
))
- return read_comments_xml_element
+ return read_comments_xml_element(element)
diff --git a/mammoth/docx/notes_xml.py b/mammoth/docx/notes_xml.py
index f1072f9..5e4ea4e 100644
--- a/mammoth/docx/notes_xml.py
+++ b/mammoth/docx/notes_xml.py
@@ -5,7 +5,7 @@ from .. import documents
from .. import results
-def create_reader(note_type, body_reader):
+def _read_notes(note_type, element, body_reader):
def read_notes_xml_element(element):
note_elements = lists.filter(
_is_note_element,
@@ -26,7 +26,7 @@ def create_reader(note_type, body_reader):
body=body
))
- return read_notes_xml_element
+ return read_notes_xml_element(element)
-create_footnotes_reader = functools.partial(create_reader, "footnote")
-create_endnotes_reader = functools.partial(create_reader, "endnote")
+read_footnotes_xml_element = functools.partial(_read_notes, "footnote")
+read_endnotes_xml_element = functools.partial(_read_notes, "endnote")
diff --git a/tests/docx/comments_xml_tests.py b/tests/docx/comments_xml_tests.py
index eb52c21..1d5dd8d 100644
--- a/tests/docx/comments_xml_tests.py
+++ b/tests/docx/comments_xml_tests.py
@@ -2,16 +2,16 @@ from nose.tools import istest, assert_equal
from mammoth import documents
from mammoth.docx.xmlparser import element as xml_element
-from mammoth.docx.comments_xml import create_comments_reader
+from mammoth.docx.comments_xml import read_comments_xml_element
from mammoth.docx import body_xml
@istest
def id_and_body_of_comment_is_read():
body = [xml_element("w:p")]
- comments = create_comments_reader(body_xml.reader())(xml_element("w:comments", {}, [
+ comments = read_comments_xml_element(xml_element("w:comments", {}, [
xml_element("w:comment", {"w:id": "1"}, body),
- ]))
+ ]), body_reader=body_xml.reader())
assert_equal(1, len(comments.value))
assert_equal(comments.value[0].body, [documents.paragraph(children=[])])
assert_equal("1", comments.value[0].comment_id)
@@ -19,9 +19,9 @@ def id_and_body_of_comment_is_read():
@istest
def when_optional_attributes_of_comment_are_missing_then_they_are_read_as_none():
- comments = create_comments_reader(body_xml.reader())(xml_element("w:comments", {}, [
+ comments = read_comments_xml_element(xml_element("w:comments", {}, [
xml_element("w:comment", {"w:id": "1"}, []),
- ]))
+ ]), body_reader=body_xml.reader())
comment, = comments.value
assert_equal(None, comment.author_name)
assert_equal(None, comment.author_initials)
@@ -29,9 +29,9 @@ def when_optional_attributes_of_comment_are_missing_then_they_are_read_as_none()
@istest
def when_optional_attributes_of_comment_are_blank_then_they_are_read_as_none():
- comments = create_comments_reader(body_xml.reader())(xml_element("w:comments", {}, [
+ comments = read_comments_xml_element(xml_element("w:comments", {}, [
xml_element("w:comment", {"w:id": "1", "w:author": " ", "w:initials": " "}, []),
- ]))
+ ]), body_reader=body_xml.reader())
comment, = comments.value
assert_equal(None, comment.author_name)
assert_equal(None, comment.author_initials)
@@ -39,9 +39,9 @@ def when_optional_attributes_of_comment_are_blank_then_they_are_read_as_none():
@istest
def when_optional_attributes_of_comment_are_not_blank_then_they_are_read():
- comments = create_comments_reader(body_xml.reader())(xml_element("w:comments", {}, [
+ comments = read_comments_xml_element(xml_element("w:comments", {}, [
xml_element("w:comment", {"w:id": "1", "w:author": "The Piemaker", "w:initials": "TP"}, []),
- ]))
+ ]), body_reader=body_xml.reader())
comment, = comments.value
assert_equal("The Piemaker", comment.author_name)
assert_equal("TP", comment.author_initials)
diff --git a/tests/docx/notes_xml_tests.py b/tests/docx/notes_xml_tests.py
index b912991..56a7681 100644
--- a/tests/docx/notes_xml_tests.py
+++ b/tests/docx/notes_xml_tests.py
@@ -2,16 +2,16 @@ from nose.tools import istest, assert_equal
from mammoth import documents
from mammoth.docx.xmlparser import element as xml_element
-from mammoth.docx.notes_xml import create_footnotes_reader
+from mammoth.docx.notes_xml import read_footnotes_xml_element
from mammoth.docx import body_xml
@istest
def id_and_body_of_footnote_are_read():
footnote_body = [xml_element("w:p")]
- footnotes = create_footnotes_reader(body_xml.reader())(xml_element("w:footnotes", {}, [
+ footnotes = read_footnotes_xml_element(xml_element("w:footnotes", {}, [
xml_element("w:footnote", {"w:id": "1"}, footnote_body),
- ]))
+ ]), body_reader=body_xml.reader())
assert_equal(1, len(footnotes.value))
assert isinstance(footnotes.value[0].body[0], documents.Paragraph)
assert_equal("1", footnotes.value[0].note_id)
@@ -29,8 +29,8 @@ def separator_is_ignored():
def _assert_footnote_type_is_ignored(footnote_type):
footnote_body = [xml_element("w:p")]
- footnotes = create_footnotes_reader(None)(xml_element("w:footnotes", {}, [
+ footnotes = read_footnotes_xml_element(xml_element("w:footnotes", {}, [
xml_element("w:footnote", {"w:id": "1", "w:type": footnote_type}, footnote_body),
- ]))
+ ]), body_reader=None)
assert_equal(0, len(footnotes.value))