diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index add17fd..0e5c50a 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,2 +1,5 @@ eclipse.preferences.version=1 encoding//docxtpl/__init__.py=utf-8 +encoding//tests/cellbg.py=utf-8 +encoding//tests/order.py=utf-8 +encoding//tests/subdoc.py=utf-8 diff --git a/CHANGES.rst b/CHANGES.rst index d45a604..2a9364e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,8 @@ -0.1.2 (2015-03-13) +0.1.3 (2015-03-13) +------------------ +- add subdoc support +- add some exemples in tests/ + +0.1.2 (2015-03-12) ------------------ - First running version \ No newline at end of file diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index a315e1f..55f50f6 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -21,9 +21,17 @@ class DocxTemplate(object): def __getattr__(self, name): return getattr(self.docx, name) - def build_xml(self,context): - src_xml = etree.tostring(self.docx._element.body, pretty_print=True) - + def get_docx(self): + return self.docx + + def get_xml(self): + return etree.tostring(self.docx._element.body, pretty_print=True) + + def write_xml(self,filename): + with open(filename,'w') as fh: + fh.write(self.get_xml()) + + def patch_xml(self,src_xml): # strip all xml tags inside {% %} and {{ }} # that Microsoft word can insert into xml code for this part of the document def striptags(m): @@ -34,22 +42,28 @@ class DocxTemplate(object): def cellbg(m): cell_xml = m.group(1) + m.group(3) cell_xml = re.sub(r'](?:(?!]).)*.*?','',cell_xml,flags=re.DOTALL) - return re.sub(r'()',r'\1{{ %s}}\2' % m.group(2), cell_xml) + cell_xml = re.sub(r'','', cell_xml, count=1) + return re.sub(r'(]*>)',r'\1' % m.group(2), cell_xml) src_xml = re.sub(r'(](?:(?!]).)*){%\s*cellbg\s+([^%]*)\s*%}(.*?)',cellbg,src_xml,flags=re.DOTALL) - # replace xml code corresponding to the paragraph containing {{{ xxx }}} by {{ xxx }} - src_xml = re.sub(r'](?:(?!]).)*{{{([^}]*)}}}.*?',r'{{\1}}',src_xml,flags=re.DOTALL) - - # replace xml code corresponding to the row containing {% tr-xxx template tag by {% xxx template tag itself - src_xml = re.sub(r'](?:(?!]).)*{%\s*tr-([^%]*%}).*?',r'{% \1',src_xml,flags=re.DOTALL) - - # replace xml code corresponding to the paragraph containing {% p-xxx template tag by {% xxx template tag itself - src_xml = re.sub(r'](?:(?!]).)*{%\s*p-([^%]*%}).*?',r'{% \1',src_xml,flags=re.DOTALL) + for y in ['tr', 'p', 'r']: + # replace into xml code the row containing {%y xxx %} or {{y xxx}} template tag + # by {% xxx %} or {{ xx }} without any surronding xml tags. + pat = r'](?:(?!]).)*({%%|{{)%(y)s ([^}%%]*(?:%%}|}})).*?' % {'y':y} + src_xml = re.sub(pat, r'\1 \2',src_xml,flags=re.DOTALL) + return src_xml + + def render_xml(self,src_xml,context): template = Template(src_xml) - dst_xml = template.render(context) - + dst_xml = template.render(context) return dst_xml + + def build_xml(self,context): + xml = self.get_xml() + xml = self.patch_xml(xml) + xml = self.render_xml(xml, context) + return xml def map_xml(self,xml): root = self.docx._element @@ -59,10 +73,28 @@ class DocxTemplate(object): def render(self,context): xml = self.build_xml(context) self.map_xml(xml) + + def new_subdoc(self): + return Subdoc(self) class Subdoc(object): """ Class for subdocumentation insertion into master document """ - pass + def __init__(self, tpl): + self.tpl = tpl + self.docx = tpl.get_docx() + self.subdocx = Document() + self.subdocx._part = self.docx._part + + def __getattr__(self, name): + return getattr(self.subdocx, name) + + def __unicode__(self): + xml = '' + for p in self.paragraphs: + xml += '\n' + re.sub(r'^.*\n', '', etree.tostring(p._element,pretty_print=True)) + return xml + + class Tpldoc(object): """ class to build documenation to be passed into template variables """ diff --git a/setup.py b/setup.py index e3f6b9c..ac23556 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ News """ % read('README', 'CHANGES') setup(name='docxtpl', - version='0.1.2', + version='0.1.3', description='Python docx template engine', long_description=long_description, classifiers=[ diff --git a/tests/cellbg.py b/tests/cellbg.py new file mode 100644 index 0000000..d42ffc9 --- /dev/null +++ b/tests/cellbg.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +''' +Created : 2015-03-12 + +@author: Eric Lapouyade +''' + +from docxtpl import DocxTemplate + +tpl=DocxTemplate('test_files/cellbg_tpl.docx') + +context = { + 'alerts' : [ + {'date' : '2015-03-10', 'desc' : 'Very critical alert', 'type' : 'CRITICAL', 'bg': 'FF0000' }, + {'date' : '2015-03-11', 'desc' : 'Just a warning', 'type' : 'WARNING', 'bg': 'FFDD00' }, + {'date' : '2015-03-12', 'desc' : 'Information', 'type' : 'INFO', 'bg': '8888FF' }, + {'date' : '2015-03-13', 'desc' : 'Debug trace', 'type' : 'DEBUG', 'bg': 'FF00FF' }, + ], +} + +tpl.render(context) +tpl.save('test_files/cellbg.docx') diff --git a/tests/order.py b/tests/order.py index a7d90ee..db3077d 100644 --- a/tests/order.py +++ b/tests/order.py @@ -1,3 +1,10 @@ +# -*- coding: utf-8 -*- +''' +Created : 2015-03-12 + +@author: Eric Lapouyade +''' + from docxtpl import DocxTemplate tpl=DocxTemplate('test_files/order_tpl.docx') diff --git a/tests/subdoc.py b/tests/subdoc.py new file mode 100644 index 0000000..bb9afcf --- /dev/null +++ b/tests/subdoc.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +''' +Created : 2015-03-12 + +@author: Eric Lapouyade +''' + +from docxtpl import DocxTemplate + +tpl=DocxTemplate('test_files/subdoc_tpl.docx') + +sd = tpl.new_subdoc() +p = sd.add_paragraph('This is a sub-document inserted into a bigger one') +p = sd.add_paragraph('It has been ') +p.add_run('dynamically').style = 'dynamic' +p.add_run(' generated with python by using ') +p.add_run('python-docx').italic = True +p.add_run(' library') + +context = { + 'mysubdoc' : sd, +} + +tpl.render(context) +tpl.save('test_files/subdoc.docx') diff --git a/tests/test_files/cellbg.docx b/tests/test_files/cellbg.docx new file mode 100644 index 0000000..478ab71 Binary files /dev/null and b/tests/test_files/cellbg.docx differ diff --git a/tests/test_files/cellbg_tpl.docx b/tests/test_files/cellbg_tpl.docx new file mode 100644 index 0000000..1b63f8c Binary files /dev/null and b/tests/test_files/cellbg_tpl.docx differ diff --git a/tests/test_files/order.docx b/tests/test_files/order.docx index a4874bc..30b4e10 100644 Binary files a/tests/test_files/order.docx and b/tests/test_files/order.docx differ diff --git a/tests/test_files/order_tpl.docx b/tests/test_files/order_tpl.docx index 04e3fa3..5dd7343 100644 Binary files a/tests/test_files/order_tpl.docx and b/tests/test_files/order_tpl.docx differ diff --git a/tests/test_files/subdoc.docx b/tests/test_files/subdoc.docx new file mode 100644 index 0000000..67d7563 Binary files /dev/null and b/tests/test_files/subdoc.docx differ diff --git a/tests/test_files/subdoc_tpl.docx b/tests/test_files/subdoc_tpl.docx new file mode 100644 index 0000000..2965a55 Binary files /dev/null and b/tests/test_files/subdoc_tpl.docx differ