Merge pull request #155 from mx2048/master
Added compatibility with Python 2.7 as to the method `escape_values`.
This commit is contained in:
commit
01f4d16767
@ -18,13 +18,15 @@ try:
|
|||||||
from html import escape, unescape
|
from html import escape, unescape
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# cgi.escape is deprecated in python 3.7
|
# cgi.escape is deprecated in python 3.7
|
||||||
|
# import escape and unescape methods for Python 2.7
|
||||||
from cgi import escape
|
from cgi import escape
|
||||||
|
import HTMLParser
|
||||||
|
unescape = HTMLParser.HTMLParser().unescape
|
||||||
import re
|
import re
|
||||||
import six
|
import six
|
||||||
import binascii
|
import binascii
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
import sys
|
|
||||||
|
|
||||||
NEWLINE_XML = '</w:t><w:br/><w:t xml:space="preserve">'
|
NEWLINE_XML = '</w:t><w:br/><w:t xml:space="preserve">'
|
||||||
NEWPARAGRAPH_XML = '</w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">'
|
NEWPARAGRAPH_XML = '</w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">'
|
||||||
@ -175,40 +177,35 @@ class DocxTemplate(object):
|
|||||||
"""Escape strings for an XML Word document
|
"""Escape strings for an XML Word document
|
||||||
which may contain <, >, &, ', and ".
|
which may contain <, >, &, ', and ".
|
||||||
"""
|
"""
|
||||||
def escape_recursively(d):
|
def escape_recursively(d, identities):
|
||||||
"""Escape string values of the passed :dict: `d` in-place
|
"""Escape string values of the passed :dict: `d` in-place
|
||||||
including nested dictionaries.
|
including nested dictionaries of any depth.
|
||||||
"""
|
"""
|
||||||
nonlocal hash_values
|
for k, v in six.iteritems(d):
|
||||||
|
|
||||||
for k, v in d.items():
|
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
hash_value = id(v)
|
identity = id(v)
|
||||||
if hash_value not in hash_values:
|
if identity not in identities:
|
||||||
hash_values.add(hash_value)
|
identities.add(identity)
|
||||||
escape_recursively(v)
|
escape_recursively(v, identities)
|
||||||
else:
|
else:
|
||||||
# Avoid dict, Listing, InlineImage, RichText, etc. classes
|
# Avoid dict, Listing, InlineImage, RichText, etc. classes
|
||||||
# by comparing v to str. Do not use try-except.
|
# by comparing `v` to `str`. Do not use try-except.
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
# Unescape at first to avoid secondary escaping
|
# Unescape at first to avoid secondary escaping
|
||||||
d[k] = escape(unescape(v))
|
d[k] = escape(unescape(v))
|
||||||
|
|
||||||
# Avoid RecursionError (if back edges, i.e. cycles, exist)
|
# Avoid RecursionError (if back edges, i.e. cycles, exist)
|
||||||
# by using a set of hash values of iterated dictionaries.
|
# by using a set of unique identities of iterated dictionaries.
|
||||||
hash_values = {id(context), }
|
initial_identities = {id(context)}
|
||||||
|
|
||||||
escape_recursively(context)
|
escape_recursively(context, initial_identities)
|
||||||
|
|
||||||
def render(self, context, jinja_env=None, autoescape=False):
|
def render(self, context, jinja_env=None, autoescape=False):
|
||||||
if sys.version_info >= (3, 0) and autoescape:
|
if autoescape:
|
||||||
self.escape_values(context)
|
self.escape_values(context)
|
||||||
else:
|
|
||||||
# Sorry folk, use awesome Python3 such as 3.6
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Body
|
# Body
|
||||||
xml_src = self.build_xml(context,jinja_env)
|
xml_src = self.build_xml(context, jinja_env)
|
||||||
|
|
||||||
# fix tables if needed
|
# fix tables if needed
|
||||||
tree = self.fix_tables(xml_src)
|
tree = self.fix_tables(xml_src)
|
||||||
|
|||||||
@ -3,10 +3,10 @@ from docxtpl import *
|
|||||||
tpl = DocxTemplate("test_files/escape_tpl_auto.docx")
|
tpl = DocxTemplate("test_files/escape_tpl_auto.docx")
|
||||||
|
|
||||||
context = {'myvar': R('"less than" must be escaped : <, this can be done with RichText() or R()'),
|
context = {'myvar': R('"less than" must be escaped : <, this can be done with RichText() or R()'),
|
||||||
'myescvar':'It can be escaped with a "|e" jinja filter in the template too : < ',
|
'myescvar': 'It can be escaped with a "|e" jinja filter in the template too : < ',
|
||||||
'nlnp' : R('Here is a multiple\nlines\nstring\aand some\aother\aparagraphs\aNOTE: the current character styling is removed'),
|
'nlnp': R('Here is a multiple\nlines\nstring\aand some\aother\aparagraphs\aNOTE: the current character styling is removed'),
|
||||||
'mylisting': Listing('the listing\nwith\nsome\nlines\nand special chars : <>&'),
|
'mylisting': Listing('the listing\nwith\nsome\nlines\nand special chars : <>&'),
|
||||||
'autoescape': """These string should be auto escaped for an XML Word document which may contain <, >, &, ", and '."""
|
'autoescape': """<, >, &, ", and '."""
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl.render(context, autoescape=True)
|
tpl.render(context, autoescape=True)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user