From 340f67e538f27ac27bdeb3c1d831f0fbe2fca4af Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:02:02 -0400 Subject: [PATCH 01/20] refs #203: Made it possible to pass along dotted string path to tag. This will prevent quite a few circular imports. --- pydocx/models.py | 17 ++++++++++++++++- pydocx/openxml/wordprocessing/deleted_run.py | 3 +-- pydocx/openxml/wordprocessing/inserted_run.py | 3 +-- pydocx/openxml/wordprocessing/smart_tag_run.py | 3 +-- pydocx/openxml/wordprocessing/table.py | 5 ----- pydocx/openxml/wordprocessing/table_cell.py | 2 +- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/pydocx/models.py b/pydocx/models.py index e8e70545..f75e26bd 100644 --- a/pydocx/models.py +++ b/pydocx/models.py @@ -5,6 +5,7 @@ unicode_literals, ) +import importlib import inspect from collections import defaultdict @@ -120,9 +121,23 @@ class ParkingLot(XmlModel): def __init__(self, *types, **kwargs): default = kwargs.pop('default', []) super(XmlCollection, self).__init__(self, default=default) - self.types = set(types) + self._types = types self._name_to_type_map = None + @property + def types(self): + return set(self._set_types(*self._types)) + + def _set_types(self, *types): + base_path = 'pydocx.openxml.{}' + for _type in types: + if isinstance(_type, basestring): + path, klass, = _type.rsplit('.', 1) + module = importlib.import_module(base_path.format(path)) + yield getattr(module, klass) + else: + yield _type + @property def name_to_type_map(self): if self._name_to_type_map is None: diff --git a/pydocx/openxml/wordprocessing/deleted_run.py b/pydocx/openxml/wordprocessing/deleted_run.py index dedf6917..3d55ff69 100644 --- a/pydocx/openxml/wordprocessing/deleted_run.py +++ b/pydocx/openxml/wordprocessing/deleted_run.py @@ -16,7 +16,6 @@ class DeletedRun(XmlModel): children = XmlCollection( Run, SmartTagRun, + 'wordprocessing.DeletedRun', # TODO Needs InsertedRun ) - -DeletedRun.children.types.add(DeletedRun) diff --git a/pydocx/openxml/wordprocessing/inserted_run.py b/pydocx/openxml/wordprocessing/inserted_run.py index cc19ec72..7fc0255c 100644 --- a/pydocx/openxml/wordprocessing/inserted_run.py +++ b/pydocx/openxml/wordprocessing/inserted_run.py @@ -16,7 +16,6 @@ class InsertedRun(XmlModel): children = XmlCollection( Run, SmartTagRun, + 'wordprocessing.InsertedRun', # TODO Needs DeletedRun ) - -InsertedRun.children.types.add(InsertedRun) diff --git a/pydocx/openxml/wordprocessing/smart_tag_run.py b/pydocx/openxml/wordprocessing/smart_tag_run.py index e56fd0fe..dfa906f9 100644 --- a/pydocx/openxml/wordprocessing/smart_tag_run.py +++ b/pydocx/openxml/wordprocessing/smart_tag_run.py @@ -14,6 +14,5 @@ class SmartTagRun(XmlModel): children = XmlCollection( Run, + 'wordprocessing.SmartTagRun', ) - -SmartTagRun.children.types.add(SmartTagRun) diff --git a/pydocx/openxml/wordprocessing/table.py b/pydocx/openxml/wordprocessing/table.py index 2fc85907..61314b29 100644 --- a/pydocx/openxml/wordprocessing/table.py +++ b/pydocx/openxml/wordprocessing/table.py @@ -8,7 +8,6 @@ from collections import defaultdict from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.table_cell import TableCell from pydocx.openxml.wordprocessing.table_row import TableRow @@ -46,7 +45,3 @@ def calculate_table_cell_spans(self): if active_rowspan_for_column: cell_to_rowspan_count[active_rowspan_for_column] += 1 # noqa return dict(cell_to_rowspan_count) - - -# Python makes defining nested class hierarchies at the global level difficult -TableCell.children.types.add(Table) diff --git a/pydocx/openxml/wordprocessing/table_cell.py b/pydocx/openxml/wordprocessing/table_cell.py index 7df2dc31..8a538e86 100644 --- a/pydocx/openxml/wordprocessing/table_cell.py +++ b/pydocx/openxml/wordprocessing/table_cell.py @@ -17,5 +17,5 @@ class TableCell(XmlModel): children = XmlCollection( Paragraph, - # Table is added in wordprocessing.table + 'wordprocessing.Table', ) From d0b2cb62ce7a621db4711d9e0ad8445beafb5204 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:03:37 -0400 Subject: [PATCH 02/20] refs #203: Added new test files. --- tests/fixtures/textbox.docx | Bin 0 -> 4710 bytes tests/fixtures/textbox.html | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 tests/fixtures/textbox.docx create mode 100644 tests/fixtures/textbox.html diff --git a/tests/fixtures/textbox.docx b/tests/fixtures/textbox.docx new file mode 100644 index 0000000000000000000000000000000000000000..5ad956b2345ccc5c584ff4a406ae364ab2c4fc43 GIT binary patch literal 4710 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 a&+vb;4ho?py&C|4nsh0WXv^|*$^QdHSLKcX literal 0 HcmV?d00001 diff --git a/tests/fixtures/textbox.html b/tests/fixtures/textbox.html new file mode 100644 index 00000000..e834424b --- /dev/null +++ b/tests/fixtures/textbox.html @@ -0,0 +1,4 @@ +

AAA

+

BBB

+

CCC

+

DDD

From 368e957aa9ca60c388162b973e73d054ee99823b Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:04:13 -0400 Subject: [PATCH 03/20] refs #203: Alphabetize all the things. --- tests/export/test_docx.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/export/test_docx.py b/tests/export/test_docx.py index a1a96895..9afc1a4a 100644 --- a/tests/export/test_docx.py +++ b/tests/export/test_docx.py @@ -24,16 +24,15 @@ def convert(path, *args, **kwargs): class ConvertDocxToHtmlTestCase(DocXFixtureTestCaseFactory): cases = ( - 'read_same_image_multiple_times', 'all_configured_styles', + 'export_from_googledocs', + 'external_image', + 'has_missing_image', + 'has_missing_image', 'has_title', 'inline_tags', - 'has_missing_image', 'justification', 'list_in_table', - 'external_image', - 'export_from_googledocs', - 'has_missing_image', 'lists_with_styles', 'missing_numbering', 'missing_style', @@ -41,6 +40,8 @@ class ConvertDocxToHtmlTestCase(DocXFixtureTestCaseFactory): 'nested_table_rowspan', 'nested_tables', 'no_break_hyphen', + 'read_same_image_multiple_times', + 'rotate_image', 'shift_enter', 'simple', 'simple_lists', @@ -48,10 +49,9 @@ class ConvertDocxToHtmlTestCase(DocXFixtureTestCaseFactory): 'special_chars', 'styled_bolding', 'table_col_row_span', + 'table_with_multi_rowspan', 'tables_in_lists', 'track_changes_on', - 'table_with_multi_rowspan', - 'rotate_image' ) @raises(MalformedDocxException) From 60156807ca12f22a6744ab39f4d56477b0f9918e Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:04:32 -0400 Subject: [PATCH 04/20] refs #203: Added the new test to the runner. --- tests/export/test_docx.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/export/test_docx.py b/tests/export/test_docx.py index 9afc1a4a..977a6e82 100644 --- a/tests/export/test_docx.py +++ b/tests/export/test_docx.py @@ -51,6 +51,7 @@ class ConvertDocxToHtmlTestCase(DocXFixtureTestCaseFactory): 'table_col_row_span', 'table_with_multi_rowspan', 'tables_in_lists', + 'textbox', 'track_changes_on', ) From 47b0a2e4451acbddd173f27846f6e8e19b5fab90 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:05:19 -0400 Subject: [PATCH 05/20] refs #203: Added the new tags needed to deal with textboxes --- .../openxml/markup_compatibility/__init__.py | 7 ++++++ .../markup_compatibility/alternate_content.py | 14 +++++++++++ .../openxml/markup_compatibility/fallback.py | 14 +++++++++++ pydocx/openxml/vml/shape.py | 3 ++- pydocx/openxml/wordprocessing/__init__.py | 2 ++ pydocx/openxml/wordprocessing/run.py | 2 ++ pydocx/openxml/wordprocessing/textbox.py | 24 +++++++++++++++++++ 7 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 pydocx/openxml/markup_compatibility/__init__.py create mode 100644 pydocx/openxml/markup_compatibility/alternate_content.py create mode 100644 pydocx/openxml/markup_compatibility/fallback.py create mode 100644 pydocx/openxml/wordprocessing/textbox.py diff --git a/pydocx/openxml/markup_compatibility/__init__.py b/pydocx/openxml/markup_compatibility/__init__.py new file mode 100644 index 00000000..14f8fbbe --- /dev/null +++ b/pydocx/openxml/markup_compatibility/__init__.py @@ -0,0 +1,7 @@ +from pydocx.openxml.markup_compatibility.alternate_content import AlternateContent +from pydocx.openxml.markup_compatibility.fallback import Fallback + +__all__ = [ + 'AlternateContent', + 'Fallback', +] diff --git a/pydocx/openxml/markup_compatibility/alternate_content.py b/pydocx/openxml/markup_compatibility/alternate_content.py new file mode 100644 index 00000000..78fb8b4e --- /dev/null +++ b/pydocx/openxml/markup_compatibility/alternate_content.py @@ -0,0 +1,14 @@ +# coding: utf-8 +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.markup_compatibility.fallback import Fallback + + +class AlternateContent(XmlModel): + XML_TAG = 'AlternateContent' + children = XmlCollection(Fallback) diff --git a/pydocx/openxml/markup_compatibility/fallback.py b/pydocx/openxml/markup_compatibility/fallback.py new file mode 100644 index 00000000..b281576a --- /dev/null +++ b/pydocx/openxml/markup_compatibility/fallback.py @@ -0,0 +1,14 @@ +# coding: utf-8 +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.picture import Picture + + +class Fallback(XmlModel): + XML_TAG = 'Fallback' + children = XmlCollection(Picture) diff --git a/pydocx/openxml/vml/shape.py b/pydocx/openxml/vml/shape.py index 457b6c67..8fdd83f6 100644 --- a/pydocx/openxml/vml/shape.py +++ b/pydocx/openxml/vml/shape.py @@ -7,13 +7,14 @@ from pydocx.models import XmlModel, XmlCollection, XmlAttribute from pydocx.openxml.vml.image_data import ImageData +from pydocx.openxml.wordprocessing.textbox import Textbox class Shape(XmlModel): XML_TAG = 'shape' style = XmlAttribute() - children = XmlCollection(ImageData) + children = XmlCollection(ImageData, Textbox) # TODO perhaps we could have a prepare_style, or clean_style convention? diff --git a/pydocx/openxml/wordprocessing/__init__.py b/pydocx/openxml/wordprocessing/__init__.py index 916f2cf8..bab1673d 100644 --- a/pydocx/openxml/wordprocessing/__init__.py +++ b/pydocx/openxml/wordprocessing/__init__.py @@ -40,6 +40,7 @@ from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa from pydocx.openxml.wordprocessing.table_row import TableRow from pydocx.openxml.wordprocessing.text import Text +from pydocx.openxml.wordprocessing.textbox import Textbox __all__ = [ 'AbstractNum', @@ -79,6 +80,7 @@ 'Styles', 'TabChar', 'Table', + 'Textbox', 'TableCell', 'TableRow', 'Text', diff --git a/pydocx/openxml/wordprocessing/run.py b/pydocx/openxml/wordprocessing/run.py index fcd9f6f0..2acdb944 100644 --- a/pydocx/openxml/wordprocessing/run.py +++ b/pydocx/openxml/wordprocessing/run.py @@ -20,6 +20,7 @@ from pydocx.openxml.wordprocessing.footnote_reference import FootnoteReference from pydocx.openxml.wordprocessing.footnote_reference_mark import FootnoteReferenceMark from pydocx.openxml.wordprocessing.embedded_object import EmbeddedObject +from pydocx.openxml.markup_compatibility import AlternateContent from pydocx.util.memoize import memoized @@ -41,6 +42,7 @@ class Run(XmlModel): FootnoteReferenceMark, FieldChar, FieldCode, + AlternateContent, ) def get_style_chain_stack(self): diff --git a/pydocx/openxml/wordprocessing/textbox.py b/pydocx/openxml/wordprocessing/textbox.py new file mode 100644 index 00000000..c959e103 --- /dev/null +++ b/pydocx/openxml/wordprocessing/textbox.py @@ -0,0 +1,24 @@ +# coding: utf-8 +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.models import XmlModel, XmlCollection +# from pydocx.openxml.wordprocessing import Paragraph + + +class TxBxContent(XmlModel): + XML_TAG = 'txbxContent' + children = XmlCollection( + 'wordprocessing.Paragraph', + ) + + +class Textbox(XmlModel): + XML_TAG = 'textbox' + + children = XmlCollection( + TxBxContent, + ) From d2b373cd6d720c8e65cf35bb2f5ef083ee99889e Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:20:07 -0400 Subject: [PATCH 06/20] refs #203: "Fixed" the test. I am getting nested paragraphs, so I'll need to figure that out. --- pydocx/export/base.py | 19 ++++++++++++++++++- pydocx/openxml/wordprocessing/__init__.py | 5 +++-- pydocx/openxml/wordprocessing/textbox.py | 1 - tests/fixtures/textbox.html | 5 +++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pydocx/export/base.py b/pydocx/export/base.py index 7d364c70..b0456153 100644 --- a/pydocx/export/base.py +++ b/pydocx/export/base.py @@ -15,7 +15,7 @@ NumberingSpan, NumberingSpanBuilder, ) -from pydocx.openxml import wordprocessing, vml +from pydocx.openxml import wordprocessing, vml, markup_compatibility from pydocx.openxml.packaging import WordprocessingDocument @@ -67,6 +67,10 @@ def __init__(self, path): wordprocessing.EmbeddedObject: self.export_embedded_object, NumberingSpan: self.export_numbering_span, NumberingItem: self.export_numbering_item, + markup_compatibility.AlternateContent: self.export_alternate_content, + markup_compatibility.Fallback: self.export_fallback, + wordprocessing.Textbox: self.export_textbox, + wordprocessing.TxBxContent: self.export_textbox_content, } self.field_type_to_export_func_map = { 'HYPERLINK': getattr(self, 'export_field_hyperlink', None), @@ -531,3 +535,16 @@ def export_field_char(self, field_char): def export_field_code(self, field_code): pass + + def export_textbox(self, textbox): + return self.yield_nested(textbox.children, self.export_node) + + def export_textbox_content(self, textbox_content): + return self.yield_nested(textbox_content.children, self.export_node) + + # Markup Compatibility exporters + def export_alternate_content(self, alternate_content): + return self.yield_nested(alternate_content.children, self.export_node) + + def export_fallback(self, fallback): + return self.yield_nested(fallback.children, self.export_node) diff --git a/pydocx/openxml/wordprocessing/__init__.py b/pydocx/openxml/wordprocessing/__init__.py index bab1673d..be7d7f85 100644 --- a/pydocx/openxml/wordprocessing/__init__.py +++ b/pydocx/openxml/wordprocessing/__init__.py @@ -40,7 +40,7 @@ from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa from pydocx.openxml.wordprocessing.table_row import TableRow from pydocx.openxml.wordprocessing.text import Text -from pydocx.openxml.wordprocessing.textbox import Textbox +from pydocx.openxml.wordprocessing.textbox import Textbox, TxBxContent __all__ = [ 'AbstractNum', @@ -80,8 +80,9 @@ 'Styles', 'TabChar', 'Table', - 'Textbox', 'TableCell', 'TableRow', 'Text', + 'Textbox', + 'TxBxContent', ] diff --git a/pydocx/openxml/wordprocessing/textbox.py b/pydocx/openxml/wordprocessing/textbox.py index c959e103..f759200b 100644 --- a/pydocx/openxml/wordprocessing/textbox.py +++ b/pydocx/openxml/wordprocessing/textbox.py @@ -6,7 +6,6 @@ ) from pydocx.models import XmlModel, XmlCollection -# from pydocx.openxml.wordprocessing import Paragraph class TxBxContent(XmlModel): diff --git a/tests/fixtures/textbox.html b/tests/fixtures/textbox.html index e834424b..2640dda2 100644 --- a/tests/fixtures/textbox.html +++ b/tests/fixtures/textbox.html @@ -1,4 +1,5 @@ +

AAA

BBB

-

CCC

-

DDD

+

CCCDDD

+

From 2937c06e54fc3e10c4d2c4ea9be27ce04125ffcb Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 15:30:54 -0400 Subject: [PATCH 07/20] refs #203: Get the rest of the tests to pass. --- pydocx/models.py | 9 +++++---- tox.ini | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pydocx/models.py b/pydocx/models.py index f75e26bd..e7cd1102 100644 --- a/pydocx/models.py +++ b/pydocx/models.py @@ -129,14 +129,15 @@ def types(self): return set(self._set_types(*self._types)) def _set_types(self, *types): - base_path = 'pydocx.openxml.{}' + base_path = 'pydocx.openxml.{0}' for _type in types: - if isinstance(_type, basestring): + try: path, klass, = _type.rsplit('.', 1) + except AttributeError: + yield _type + else: module = importlib.import_module(base_path.format(path)) yield getattr(module, klass) - else: - yield _type @property def name_to_type_map(self): diff --git a/tox.ini b/tox.ini index 8c79be6f..253c446f 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ commands = deps = -rrequirements/testing.txt defusedxml: defusedxml==0.4.1 + py26: importlib [testenv:docs] commands = From fed6498797a56f0008e18818b17f706e861a8f3e Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 16:22:07 -0400 Subject: [PATCH 08/20] refs #203: Update to the new hotness on the touched files. --- .../markup_compatibility/alternate_content.py | 3 +- .../openxml/markup_compatibility/fallback.py | 3 +- pydocx/openxml/vml/shape.py | 4 +- pydocx/openxml/wordprocessing/deleted_run.py | 6 +-- pydocx/openxml/wordprocessing/inserted_run.py | 6 +-- pydocx/openxml/wordprocessing/run.py | 39 +++++++------------ .../openxml/wordprocessing/smart_tag_run.py | 3 +- pydocx/openxml/wordprocessing/table.py | 3 +- pydocx/openxml/wordprocessing/table_cell.py | 3 +- 9 files changed, 23 insertions(+), 47 deletions(-) diff --git a/pydocx/openxml/markup_compatibility/alternate_content.py b/pydocx/openxml/markup_compatibility/alternate_content.py index 78fb8b4e..45bbb50a 100644 --- a/pydocx/openxml/markup_compatibility/alternate_content.py +++ b/pydocx/openxml/markup_compatibility/alternate_content.py @@ -6,9 +6,8 @@ ) from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.markup_compatibility.fallback import Fallback class AlternateContent(XmlModel): XML_TAG = 'AlternateContent' - children = XmlCollection(Fallback) + children = XmlCollection('markup_compatibility.Fallback') diff --git a/pydocx/openxml/markup_compatibility/fallback.py b/pydocx/openxml/markup_compatibility/fallback.py index b281576a..45cb9afe 100644 --- a/pydocx/openxml/markup_compatibility/fallback.py +++ b/pydocx/openxml/markup_compatibility/fallback.py @@ -6,9 +6,8 @@ ) from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.picture import Picture class Fallback(XmlModel): XML_TAG = 'Fallback' - children = XmlCollection(Picture) + children = XmlCollection('wordprocessing.Picture') diff --git a/pydocx/openxml/vml/shape.py b/pydocx/openxml/vml/shape.py index 8fdd83f6..b0d84f73 100644 --- a/pydocx/openxml/vml/shape.py +++ b/pydocx/openxml/vml/shape.py @@ -6,15 +6,13 @@ ) from pydocx.models import XmlModel, XmlCollection, XmlAttribute -from pydocx.openxml.vml.image_data import ImageData -from pydocx.openxml.wordprocessing.textbox import Textbox class Shape(XmlModel): XML_TAG = 'shape' style = XmlAttribute() - children = XmlCollection(ImageData, Textbox) + children = XmlCollection('vml.ImageData', 'wordprocessing.Textbox') # TODO perhaps we could have a prepare_style, or clean_style convention? diff --git a/pydocx/openxml/wordprocessing/deleted_run.py b/pydocx/openxml/wordprocessing/deleted_run.py index 3d55ff69..acce6951 100644 --- a/pydocx/openxml/wordprocessing/deleted_run.py +++ b/pydocx/openxml/wordprocessing/deleted_run.py @@ -6,16 +6,14 @@ ) from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.run import Run -from pydocx.openxml.wordprocessing.smart_tag_run import SmartTagRun class DeletedRun(XmlModel): XML_TAG = 'del' children = XmlCollection( - Run, - SmartTagRun, + 'wordprocessing.Run', + 'wordprocessing.SmartTagRun', 'wordprocessing.DeletedRun', # TODO Needs InsertedRun ) diff --git a/pydocx/openxml/wordprocessing/inserted_run.py b/pydocx/openxml/wordprocessing/inserted_run.py index 7fc0255c..8d0dd0cb 100644 --- a/pydocx/openxml/wordprocessing/inserted_run.py +++ b/pydocx/openxml/wordprocessing/inserted_run.py @@ -6,16 +6,14 @@ ) from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.run import Run -from pydocx.openxml.wordprocessing.smart_tag_run import SmartTagRun class InsertedRun(XmlModel): XML_TAG = 'ins' children = XmlCollection( - Run, - SmartTagRun, + 'wordprocessing.Run', + 'wordprocessing.SmartTagRun', 'wordprocessing.InsertedRun', # TODO Needs DeletedRun ) diff --git a/pydocx/openxml/wordprocessing/run.py b/pydocx/openxml/wordprocessing/run.py index 2acdb944..3766c98f 100644 --- a/pydocx/openxml/wordprocessing/run.py +++ b/pydocx/openxml/wordprocessing/run.py @@ -8,19 +8,6 @@ from pydocx.models import XmlModel, XmlCollection, XmlChild from pydocx.openxml.wordprocessing.run_properties import RunProperties -from pydocx.openxml.wordprocessing.br import Break -from pydocx.openxml.wordprocessing.drawing import Drawing -from pydocx.openxml.wordprocessing.field_char import FieldChar -from pydocx.openxml.wordprocessing.field_code import FieldCode -from pydocx.openxml.wordprocessing.picture import Picture -from pydocx.openxml.wordprocessing.no_break_hyphen import NoBreakHyphen -from pydocx.openxml.wordprocessing.text import Text -from pydocx.openxml.wordprocessing.tab_char import TabChar -from pydocx.openxml.wordprocessing.deleted_text import DeletedText -from pydocx.openxml.wordprocessing.footnote_reference import FootnoteReference -from pydocx.openxml.wordprocessing.footnote_reference_mark import FootnoteReferenceMark -from pydocx.openxml.wordprocessing.embedded_object import EmbeddedObject -from pydocx.openxml.markup_compatibility import AlternateContent from pydocx.util.memoize import memoized @@ -30,19 +17,19 @@ class Run(XmlModel): properties = XmlChild(type=RunProperties) children = XmlCollection( - EmbeddedObject, - TabChar, - Break, - NoBreakHyphen, - Text, - Drawing, - Picture, - DeletedText, - FootnoteReference, - FootnoteReferenceMark, - FieldChar, - FieldCode, - AlternateContent, + 'wordprocessing.EmbeddedObject', + 'wordprocessing.TabChar', + 'wordprocessing.Break', + 'wordprocessing.NoBreakHyphen', + 'wordprocessing.Text', + 'wordprocessing.Drawing', + 'wordprocessing.Picture', + 'wordprocessing.DeletedText', + 'wordprocessing.FootnoteReference', + 'wordprocessing.FootnoteReferenceMark', + 'wordprocessing.FieldChar', + 'wordprocessing.FieldCode', + 'markup_compatibility.AlternateContent', ) def get_style_chain_stack(self): diff --git a/pydocx/openxml/wordprocessing/smart_tag_run.py b/pydocx/openxml/wordprocessing/smart_tag_run.py index dfa906f9..1d8c0ee9 100644 --- a/pydocx/openxml/wordprocessing/smart_tag_run.py +++ b/pydocx/openxml/wordprocessing/smart_tag_run.py @@ -6,13 +6,12 @@ ) from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.run import Run class SmartTagRun(XmlModel): XML_TAG = 'smartTag' children = XmlCollection( - Run, + 'wordprocessing.Run', 'wordprocessing.SmartTagRun', ) diff --git a/pydocx/openxml/wordprocessing/table.py b/pydocx/openxml/wordprocessing/table.py index 61314b29..60c710b1 100644 --- a/pydocx/openxml/wordprocessing/table.py +++ b/pydocx/openxml/wordprocessing/table.py @@ -8,14 +8,13 @@ from collections import defaultdict from pydocx.models import XmlModel, XmlCollection -from pydocx.openxml.wordprocessing.table_row import TableRow class Table(XmlModel): XML_TAG = 'tbl' rows = XmlCollection( - TableRow, + 'wordprocessing.TableRow', ) def calculate_table_cell_spans(self): diff --git a/pydocx/openxml/wordprocessing/table_cell.py b/pydocx/openxml/wordprocessing/table_cell.py index 8a538e86..84320f29 100644 --- a/pydocx/openxml/wordprocessing/table_cell.py +++ b/pydocx/openxml/wordprocessing/table_cell.py @@ -6,7 +6,6 @@ ) from pydocx.models import XmlModel, XmlCollection, XmlChild -from pydocx.openxml.wordprocessing.paragraph import Paragraph from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa @@ -16,6 +15,6 @@ class TableCell(XmlModel): properties = XmlChild(type=TableCellProperties) children = XmlCollection( - Paragraph, + 'wordprocessing.Paragraph', 'wordprocessing.Table', ) From 563354c428686ee890aba70c3123d9524fe6437f Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 16:27:24 -0400 Subject: [PATCH 09/20] refs #203: Update note. --- CHANGELOG.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2cb69817..291ca6e2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,8 @@ +**dev** + +- Textboxes have been implemented. We no longer lose the content inside of + them. + **0.9.6** - Fixed issue in PyDocX CLI tool and added new test cases for the same From b80b0882b73023e38cac17cc4901aaf704138639 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 16:50:18 -0400 Subject: [PATCH 10/20] refs #203: Moved the definition of the textbox. --- pydocx/openxml/vml/__init__.py | 2 ++ pydocx/openxml/vml/textbox.py | 16 ++++++++++++++++ pydocx/openxml/wordprocessing/__init__.py | 3 +-- pydocx/openxml/wordprocessing/textbox.py | 8 -------- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 pydocx/openxml/vml/textbox.py diff --git a/pydocx/openxml/vml/__init__.py b/pydocx/openxml/vml/__init__.py index f44a969f..a2547821 100644 --- a/pydocx/openxml/vml/__init__.py +++ b/pydocx/openxml/vml/__init__.py @@ -1,8 +1,10 @@ # coding: utf-8 from pydocx.openxml.vml.image_data import ImageData from pydocx.openxml.vml.shape import Shape +from pydocx.openxml.vml.textbox import Textbox __all__ = [ 'ImageData', 'Shape', + 'Textbox', ] diff --git a/pydocx/openxml/vml/textbox.py b/pydocx/openxml/vml/textbox.py new file mode 100644 index 00000000..8cf196dd --- /dev/null +++ b/pydocx/openxml/vml/textbox.py @@ -0,0 +1,16 @@ +# coding: utf-8 +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.models import XmlModel, XmlCollection + + +class Textbox(XmlModel): + XML_TAG = 'textbox' + + children = XmlCollection( + 'wordprocessing.TxBxContent', + ) diff --git a/pydocx/openxml/wordprocessing/__init__.py b/pydocx/openxml/wordprocessing/__init__.py index be7d7f85..eacdec40 100644 --- a/pydocx/openxml/wordprocessing/__init__.py +++ b/pydocx/openxml/wordprocessing/__init__.py @@ -40,7 +40,7 @@ from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa from pydocx.openxml.wordprocessing.table_row import TableRow from pydocx.openxml.wordprocessing.text import Text -from pydocx.openxml.wordprocessing.textbox import Textbox, TxBxContent +from pydocx.openxml.wordprocessing.textbox import TxBxContent __all__ = [ 'AbstractNum', @@ -83,6 +83,5 @@ 'TableCell', 'TableRow', 'Text', - 'Textbox', 'TxBxContent', ] diff --git a/pydocx/openxml/wordprocessing/textbox.py b/pydocx/openxml/wordprocessing/textbox.py index f759200b..a6176804 100644 --- a/pydocx/openxml/wordprocessing/textbox.py +++ b/pydocx/openxml/wordprocessing/textbox.py @@ -13,11 +13,3 @@ class TxBxContent(XmlModel): children = XmlCollection( 'wordprocessing.Paragraph', ) - - -class Textbox(XmlModel): - XML_TAG = 'textbox' - - children = XmlCollection( - TxBxContent, - ) From afb093d2f9ec93d88ae981f0be74f7f9461be1b2 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 16:52:40 -0400 Subject: [PATCH 11/20] refs #203: Update the references to Textbox --- pydocx/export/base.py | 2 +- pydocx/openxml/vml/shape.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pydocx/export/base.py b/pydocx/export/base.py index b0456153..e88e8986 100644 --- a/pydocx/export/base.py +++ b/pydocx/export/base.py @@ -64,12 +64,12 @@ def __init__(self, path): wordprocessing.SimpleField: self.export_simple_field, vml.Shape: self.export_vml_shape, vml.ImageData: self.export_vml_image_data, + vml.Textbox: self.export_textbox, wordprocessing.EmbeddedObject: self.export_embedded_object, NumberingSpan: self.export_numbering_span, NumberingItem: self.export_numbering_item, markup_compatibility.AlternateContent: self.export_alternate_content, markup_compatibility.Fallback: self.export_fallback, - wordprocessing.Textbox: self.export_textbox, wordprocessing.TxBxContent: self.export_textbox_content, } self.field_type_to_export_func_map = { diff --git a/pydocx/openxml/vml/shape.py b/pydocx/openxml/vml/shape.py index b0d84f73..8fea39a1 100644 --- a/pydocx/openxml/vml/shape.py +++ b/pydocx/openxml/vml/shape.py @@ -12,7 +12,7 @@ class Shape(XmlModel): XML_TAG = 'shape' style = XmlAttribute() - children = XmlCollection('vml.ImageData', 'wordprocessing.Textbox') + children = XmlCollection('vml.ImageData', 'vml.Textbox') # TODO perhaps we could have a prepare_style, or clean_style convention? From f735783e268fff5315c0e61528aaf0fb17cfed84 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Wed, 11 May 2016 16:56:05 -0400 Subject: [PATCH 12/20] refs #203: Renamed the textbox content file. --- pydocx/openxml/wordprocessing/__init__.py | 2 +- .../openxml/wordprocessing/{textbox.py => textbox_content.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename pydocx/openxml/wordprocessing/{textbox.py => textbox_content.py} (100%) diff --git a/pydocx/openxml/wordprocessing/__init__.py b/pydocx/openxml/wordprocessing/__init__.py index eacdec40..2430064d 100644 --- a/pydocx/openxml/wordprocessing/__init__.py +++ b/pydocx/openxml/wordprocessing/__init__.py @@ -40,7 +40,7 @@ from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa from pydocx.openxml.wordprocessing.table_row import TableRow from pydocx.openxml.wordprocessing.text import Text -from pydocx.openxml.wordprocessing.textbox import TxBxContent +from pydocx.openxml.wordprocessing.textbox_content import TxBxContent __all__ = [ 'AbstractNum', diff --git a/pydocx/openxml/wordprocessing/textbox.py b/pydocx/openxml/wordprocessing/textbox_content.py similarity index 100% rename from pydocx/openxml/wordprocessing/textbox.py rename to pydocx/openxml/wordprocessing/textbox_content.py From 338a25b59fb721f3305d5e272ebda844a7d34c7e Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Thu, 12 May 2016 12:32:37 -0400 Subject: [PATCH 13/20] refs #203: Removed a comma. --- pydocx/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydocx/models.py b/pydocx/models.py index e7cd1102..960f3963 100644 --- a/pydocx/models.py +++ b/pydocx/models.py @@ -132,7 +132,7 @@ def _set_types(self, *types): base_path = 'pydocx.openxml.{0}' for _type in types: try: - path, klass, = _type.rsplit('.', 1) + path, klass = _type.rsplit('.', 1) except AttributeError: yield _type else: From 7e5fc4bf3da9305b27a8d57f5f828baf2ab0b5ed Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Thu, 12 May 2016 12:32:51 -0400 Subject: [PATCH 14/20] refs #203: Added XML based tests. --- .../export/html/test_markup_compatibility.py | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/export/html/test_markup_compatibility.py diff --git a/tests/export/html/test_markup_compatibility.py b/tests/export/html/test_markup_compatibility.py new file mode 100644 index 00000000..06d1cded --- /dev/null +++ b/tests/export/html/test_markup_compatibility.py @@ -0,0 +1,91 @@ +# coding: utf-8 + +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.test import DocumentGeneratorTestCase +from pydocx.test.utils import WordprocessingDocumentFactory +from pydocx.openxml.packaging import MainDocumentPart + + +class TableTestCase(DocumentGeneratorTestCase): + def test_textbox_with_content(self): + document_xml = ''' +

+ + + + + + + +

+ + AAA + +

+ + + + + + + +

+ ''' + + document = WordprocessingDocumentFactory() + document.add(MainDocumentPart, document_xml) + + expected_html = ''' +

+

+ AAA +

+

+ ''' + self.assert_document_generates_html(document, expected_html) + + def test_textbox_with_content_outside_of_textbox(self): + document_xml = ''' +

+ AAA + + + + + + + +

+ + BBB + +

+ + + + + + + + CCC +

+ ''' + + document = WordprocessingDocumentFactory() + document.add(MainDocumentPart, document_xml) + + expected_html = ''' +

+ AAA +

+ BBB +

+ CCC +

+ ''' + self.assert_document_generates_html(document, expected_html) From 030b0d0590f877a17eb5156b69ce452288fc9bba Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Thu, 12 May 2016 14:51:23 -0400 Subject: [PATCH 15/20] refs #203: Update test. --- tests/export/html/test_markup_compatibility.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/export/html/test_markup_compatibility.py b/tests/export/html/test_markup_compatibility.py index 06d1cded..b98c2192 100644 --- a/tests/export/html/test_markup_compatibility.py +++ b/tests/export/html/test_markup_compatibility.py @@ -54,6 +54,7 @@ def test_textbox_with_content_outside_of_textbox(self):

AAA + BBB @@ -62,7 +63,7 @@ def test_textbox_with_content_outside_of_textbox(self):

- BBB + CCC

@@ -71,8 +72,9 @@ def test_textbox_with_content_outside_of_textbox(self): + DDD - CCC + EEE

''' @@ -81,11 +83,11 @@ def test_textbox_with_content_outside_of_textbox(self): expected_html = '''

- AAA + AAABBB

- BBB + CCC

- CCC + DDDEEE

''' self.assert_document_generates_html(document, expected_html) From 1ce2887742f83946365c4b3876b4f53226001e86 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Thu, 12 May 2016 15:45:40 -0400 Subject: [PATCH 16/20] refs #203: Added tests without markup compat. --- tests/export/html/test_textbox.py | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/export/html/test_textbox.py diff --git a/tests/export/html/test_textbox.py b/tests/export/html/test_textbox.py new file mode 100644 index 00000000..6d7cc5da --- /dev/null +++ b/tests/export/html/test_textbox.py @@ -0,0 +1,85 @@ +# coding: utf-8 + +from __future__ import ( + absolute_import, + print_function, + unicode_literals, +) + +from pydocx.test import DocumentGeneratorTestCase +from pydocx.test.utils import WordprocessingDocumentFactory +from pydocx.openxml.packaging import MainDocumentPart + + +class TableTestCase(DocumentGeneratorTestCase): + def test_textbox_with_content(self): + document_xml = ''' +

+ + + + + +

+ + AAA + +

+ + + + + +

+ ''' + + document = WordprocessingDocumentFactory() + document.add(MainDocumentPart, document_xml) + + expected_html = ''' +

+

+ AAA +

+

+ ''' + self.assert_document_generates_html(document, expected_html) + + def test_textbox_with_content_outside_of_textbox(self): + document_xml = ''' +

+ AAA + + BBB + + + + +

+ + CCC + +

+ + + + + DDD + + EEE +

+ ''' + + document = WordprocessingDocumentFactory() + document.add(MainDocumentPart, document_xml) + + expected_html = ''' +

+ AAABBB +

+ CCC +

+ DDDEEE +

+ ''' + self.assert_document_generates_html(document, expected_html) From 6b738c118575de731a10c932da991e754354e7e5 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Fri, 13 May 2016 12:36:06 -0400 Subject: [PATCH 17/20] refs #203: name change. --- pydocx/export/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pydocx/export/base.py b/pydocx/export/base.py index 1b91a7fa..bee990bf 100644 --- a/pydocx/export/base.py +++ b/pydocx/export/base.py @@ -15,7 +15,7 @@ NumberingSpan, NumberingSpanBuilder, ) -from pydocx.openxml import wordprocessing, vml, markup_compatibility +from pydocx.openxml import markup_compatibility, vml, wordprocessing from pydocx.openxml.packaging import WordprocessingDocument @@ -68,8 +68,8 @@ def __init__(self, path): wordprocessing.EmbeddedObject: self.export_embedded_object, NumberingSpan: self.export_numbering_span, NumberingItem: self.export_numbering_item, - markup_compatibility.AlternateContent: self.export_alternate_content, - markup_compatibility.Fallback: self.export_fallback, + markup_compatibility.AlternateContent: self.export_markup_compatibility_alternate_content, # noqa + markup_compatibility.Fallback: self.export_markup_compatibility_fallback, wordprocessing.TxBxContent: self.export_textbox_content, } self.field_type_to_export_func_map = { @@ -547,8 +547,8 @@ def export_textbox_content(self, textbox_content): return self.yield_nested(textbox_content.children, self.export_node) # Markup Compatibility exporters - def export_alternate_content(self, alternate_content): + def export_markup_compatibility_alternate_content(self, alternate_content): return self.yield_nested(alternate_content.children, self.export_node) - def export_fallback(self, fallback): + def export_markup_compatibility_fallback(self, fallback): return self.yield_nested(fallback.children, self.export_node) From 5554636dc6f37e8aa23b6aa9a6841c691f3ee094 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Fri, 13 May 2016 12:37:36 -0400 Subject: [PATCH 18/20] Revert "refs #203: Update to the new hotness on the touched files." This reverts commit fed6498797a56f0008e18818b17f706e861a8f3e. --- .../markup_compatibility/alternate_content.py | 3 +- .../openxml/markup_compatibility/fallback.py | 3 +- pydocx/openxml/vml/shape.py | 4 +- pydocx/openxml/wordprocessing/deleted_run.py | 6 ++- pydocx/openxml/wordprocessing/inserted_run.py | 6 ++- pydocx/openxml/wordprocessing/run.py | 39 ++++++++++++------- .../openxml/wordprocessing/smart_tag_run.py | 3 +- pydocx/openxml/wordprocessing/table.py | 3 +- pydocx/openxml/wordprocessing/table_cell.py | 3 +- 9 files changed, 46 insertions(+), 24 deletions(-) diff --git a/pydocx/openxml/markup_compatibility/alternate_content.py b/pydocx/openxml/markup_compatibility/alternate_content.py index 45bbb50a..78fb8b4e 100644 --- a/pydocx/openxml/markup_compatibility/alternate_content.py +++ b/pydocx/openxml/markup_compatibility/alternate_content.py @@ -6,8 +6,9 @@ ) from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.markup_compatibility.fallback import Fallback class AlternateContent(XmlModel): XML_TAG = 'AlternateContent' - children = XmlCollection('markup_compatibility.Fallback') + children = XmlCollection(Fallback) diff --git a/pydocx/openxml/markup_compatibility/fallback.py b/pydocx/openxml/markup_compatibility/fallback.py index 45cb9afe..b281576a 100644 --- a/pydocx/openxml/markup_compatibility/fallback.py +++ b/pydocx/openxml/markup_compatibility/fallback.py @@ -6,8 +6,9 @@ ) from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.picture import Picture class Fallback(XmlModel): XML_TAG = 'Fallback' - children = XmlCollection('wordprocessing.Picture') + children = XmlCollection(Picture) diff --git a/pydocx/openxml/vml/shape.py b/pydocx/openxml/vml/shape.py index 8fea39a1..c73ceeaa 100644 --- a/pydocx/openxml/vml/shape.py +++ b/pydocx/openxml/vml/shape.py @@ -6,14 +6,14 @@ ) from pydocx.models import XmlModel, XmlCollection, XmlAttribute +from pydocx.openxml.vml.image_data import ImageData class Shape(XmlModel): XML_TAG = 'shape' style = XmlAttribute() - children = XmlCollection('vml.ImageData', 'vml.Textbox') - + children = XmlCollection(ImageData, 'vml.Textbox') # TODO perhaps we could have a prepare_style, or clean_style convention? def get_style(self): diff --git a/pydocx/openxml/wordprocessing/deleted_run.py b/pydocx/openxml/wordprocessing/deleted_run.py index acce6951..3d55ff69 100644 --- a/pydocx/openxml/wordprocessing/deleted_run.py +++ b/pydocx/openxml/wordprocessing/deleted_run.py @@ -6,14 +6,16 @@ ) from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.run import Run +from pydocx.openxml.wordprocessing.smart_tag_run import SmartTagRun class DeletedRun(XmlModel): XML_TAG = 'del' children = XmlCollection( - 'wordprocessing.Run', - 'wordprocessing.SmartTagRun', + Run, + SmartTagRun, 'wordprocessing.DeletedRun', # TODO Needs InsertedRun ) diff --git a/pydocx/openxml/wordprocessing/inserted_run.py b/pydocx/openxml/wordprocessing/inserted_run.py index 8d0dd0cb..7fc0255c 100644 --- a/pydocx/openxml/wordprocessing/inserted_run.py +++ b/pydocx/openxml/wordprocessing/inserted_run.py @@ -6,14 +6,16 @@ ) from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.run import Run +from pydocx.openxml.wordprocessing.smart_tag_run import SmartTagRun class InsertedRun(XmlModel): XML_TAG = 'ins' children = XmlCollection( - 'wordprocessing.Run', - 'wordprocessing.SmartTagRun', + Run, + SmartTagRun, 'wordprocessing.InsertedRun', # TODO Needs DeletedRun ) diff --git a/pydocx/openxml/wordprocessing/run.py b/pydocx/openxml/wordprocessing/run.py index 3766c98f..2acdb944 100644 --- a/pydocx/openxml/wordprocessing/run.py +++ b/pydocx/openxml/wordprocessing/run.py @@ -8,6 +8,19 @@ from pydocx.models import XmlModel, XmlCollection, XmlChild from pydocx.openxml.wordprocessing.run_properties import RunProperties +from pydocx.openxml.wordprocessing.br import Break +from pydocx.openxml.wordprocessing.drawing import Drawing +from pydocx.openxml.wordprocessing.field_char import FieldChar +from pydocx.openxml.wordprocessing.field_code import FieldCode +from pydocx.openxml.wordprocessing.picture import Picture +from pydocx.openxml.wordprocessing.no_break_hyphen import NoBreakHyphen +from pydocx.openxml.wordprocessing.text import Text +from pydocx.openxml.wordprocessing.tab_char import TabChar +from pydocx.openxml.wordprocessing.deleted_text import DeletedText +from pydocx.openxml.wordprocessing.footnote_reference import FootnoteReference +from pydocx.openxml.wordprocessing.footnote_reference_mark import FootnoteReferenceMark +from pydocx.openxml.wordprocessing.embedded_object import EmbeddedObject +from pydocx.openxml.markup_compatibility import AlternateContent from pydocx.util.memoize import memoized @@ -17,19 +30,19 @@ class Run(XmlModel): properties = XmlChild(type=RunProperties) children = XmlCollection( - 'wordprocessing.EmbeddedObject', - 'wordprocessing.TabChar', - 'wordprocessing.Break', - 'wordprocessing.NoBreakHyphen', - 'wordprocessing.Text', - 'wordprocessing.Drawing', - 'wordprocessing.Picture', - 'wordprocessing.DeletedText', - 'wordprocessing.FootnoteReference', - 'wordprocessing.FootnoteReferenceMark', - 'wordprocessing.FieldChar', - 'wordprocessing.FieldCode', - 'markup_compatibility.AlternateContent', + EmbeddedObject, + TabChar, + Break, + NoBreakHyphen, + Text, + Drawing, + Picture, + DeletedText, + FootnoteReference, + FootnoteReferenceMark, + FieldChar, + FieldCode, + AlternateContent, ) def get_style_chain_stack(self): diff --git a/pydocx/openxml/wordprocessing/smart_tag_run.py b/pydocx/openxml/wordprocessing/smart_tag_run.py index 1d8c0ee9..dfa906f9 100644 --- a/pydocx/openxml/wordprocessing/smart_tag_run.py +++ b/pydocx/openxml/wordprocessing/smart_tag_run.py @@ -6,12 +6,13 @@ ) from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.run import Run class SmartTagRun(XmlModel): XML_TAG = 'smartTag' children = XmlCollection( - 'wordprocessing.Run', + Run, 'wordprocessing.SmartTagRun', ) diff --git a/pydocx/openxml/wordprocessing/table.py b/pydocx/openxml/wordprocessing/table.py index 60c710b1..61314b29 100644 --- a/pydocx/openxml/wordprocessing/table.py +++ b/pydocx/openxml/wordprocessing/table.py @@ -8,13 +8,14 @@ from collections import defaultdict from pydocx.models import XmlModel, XmlCollection +from pydocx.openxml.wordprocessing.table_row import TableRow class Table(XmlModel): XML_TAG = 'tbl' rows = XmlCollection( - 'wordprocessing.TableRow', + TableRow, ) def calculate_table_cell_spans(self): diff --git a/pydocx/openxml/wordprocessing/table_cell.py b/pydocx/openxml/wordprocessing/table_cell.py index 84320f29..8a538e86 100644 --- a/pydocx/openxml/wordprocessing/table_cell.py +++ b/pydocx/openxml/wordprocessing/table_cell.py @@ -6,6 +6,7 @@ ) from pydocx.models import XmlModel, XmlCollection, XmlChild +from pydocx.openxml.wordprocessing.paragraph import Paragraph from pydocx.openxml.wordprocessing.table_cell_properties import TableCellProperties # noqa @@ -15,6 +16,6 @@ class TableCell(XmlModel): properties = XmlChild(type=TableCellProperties) children = XmlCollection( - 'wordprocessing.Paragraph', + Paragraph, 'wordprocessing.Table', ) From 4d12156fba236b113e97b40c7630ff4faf19bf0b Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Fri, 13 May 2016 12:38:51 -0400 Subject: [PATCH 19/20] refs #203: Added a comment. --- pydocx/openxml/markup_compatibility/fallback.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydocx/openxml/markup_compatibility/fallback.py b/pydocx/openxml/markup_compatibility/fallback.py index b281576a..397091e4 100644 --- a/pydocx/openxml/markup_compatibility/fallback.py +++ b/pydocx/openxml/markup_compatibility/fallback.py @@ -11,4 +11,5 @@ class Fallback(XmlModel): XML_TAG = 'Fallback' + # TODO #204: actually include all of the children defined in the spec. children = XmlCollection(Picture) From 7e20b60fc4c187a5e1ffe34a443c853337073178 Mon Sep 17 00:00:00 2001 From: Jason Ward Date: Fri, 13 May 2016 14:07:13 -0400 Subject: [PATCH 20/20] refs #203: Removed a dead comment. --- pydocx/export/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pydocx/export/base.py b/pydocx/export/base.py index bee990bf..baae919b 100644 --- a/pydocx/export/base.py +++ b/pydocx/export/base.py @@ -546,7 +546,6 @@ def export_textbox(self, textbox): def export_textbox_content(self, textbox_content): return self.yield_nested(textbox_content.children, self.export_node) - # Markup Compatibility exporters def export_markup_compatibility_alternate_content(self, alternate_content): return self.yield_nested(alternate_content.children, self.export_node)