summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@proxience.com>2015-04-21 17:57:59 +0200
committerÉtienne Loks <etienne.loks@proxience.com>2015-04-21 17:57:59 +0200
commit21d4c81976bd4d6807cfcdbdd160513b73c1f3f9 (patch)
tree8acdc9d1fd6f1f46e8e3a07dc9d2c71cf28d2cb8
parentbd74e8bee0f94ae82e11d5047ae8d5abfbf12f44 (diff)
downloadIshtar-21d4c81976bd4d6807cfcdbdd160513b73c1f3f9.tar.bz2
Ishtar-21d4c81976bd4d6807cfcdbdd160513b73c1f3f9.zip
Restore temporary old ooo_replace
-rw-r--r--ishtar_common/models.py5
-rw-r--r--ishtar_common/ooo_replace.py186
2 files changed, 189 insertions, 2 deletions
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index eb643ff1c..6c153fb9c 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -48,7 +48,7 @@ from django.contrib import admin
from simple_history.models import HistoricalRecords as BaseHistoricalRecords
-from oook_replace.oook_replace import oook_replace
+from ishtar_common.ooo_replace import ooo_replace
from ishtar_common.model_merging import merge_model_objects
from ishtar_common.utils import get_cache
@@ -861,7 +861,8 @@ class DocumentTemplate(models.Model):
slugify(self.name.replace(' ', '_').lower()) + u'-' +\
datetime.date.today().strftime('%Y-%m-%d') +\
u"." + self.template.name.split('.')[-1]
- missing = oook_replace(self.template, output_name, c_object.get_values())
+ values = c_object.get_values()
+ missing = ooo_replace(self.template, output_name, values)
return output_name
class Department(models.Model):
diff --git a/ishtar_common/ooo_replace.py b/ishtar_common/ooo_replace.py
new file mode 100644
index 000000000..4c487dd17
--- /dev/null
+++ b/ishtar_common/ooo_replace.py
@@ -0,0 +1,186 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import locale, re
+from zipfile import ZipFile, ZIP_DEFLATED
+from cStringIO import StringIO
+from xml.etree.cElementTree import ElementTree, fromstring
+
+from django.conf import settings
+
+OOO_NS = "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}"
+
+def _set_value_from_formula(value, context, default_value):
+ value = value.strip()
+ if value.startswith("ooow:") and len(value) >= 5:
+ value = value[5:]
+ if value.startswith('"') and value.endswith('"') and len(value) > 1:
+ value = value[1:-1]
+ elif value in context:
+ value = _format_value(context[value], default_value)
+ else:
+ value = None
+ return value
+
+def _parse_condition(condition, context, default_value):
+ # parse only == and != operator
+ operator = ""
+ if "!=" in condition:
+ operator = "!="
+ elif "==" in condition:
+ operator = "=="
+ else:
+ return
+ var1, var2 = condition.split(operator)
+ var1 = _set_value_from_formula(var1, context, default_value)
+ var2 = _set_value_from_formula(var2, context, default_value)
+ res = var1 == var2
+ if operator == '!=':
+ res = not res
+ return res
+
+def _format_value(value, default_value):
+ if hasattr(value, 'strftime'):
+ c_locale = settings.LANGUAGE_CODE.split('-')
+ if len(c_locale) == 2:
+ c_locale[1] = c_locale[1].upper()
+ c_locale = "_".join(c_locale)
+ if locale.getlocale()[0] != c_locale:
+ for loc in (c_locale, c_locale+'.utf8'):
+ try:
+ locale.setlocale(locale.LC_ALL, loc)
+ break
+ except:
+ pass
+ try:
+ if settings.DATE_FORMAT:
+ value = value.strftime(settings.DATE_FORMAT).lower()
+ else:
+ value = value.strftime('%x')
+ except ValueError:
+ value = unicode(value)
+ if locale.getlocale()[1]:
+ value = value.decode(locale.getlocale()[1])
+ value = unicode(value) if value else default_value
+ return value
+
+VAR_EXPR = u"###%sVAR %s###"
+WHOLE_KEY_FILTER = u"((?:(?: )*(?:<[^#>]*>)*(?: )*(?:[-a-zA-Z0-9_])*(?: )*)*)"
+WHOLE_KEY_FILTER = u"([^#]*)"
+RE_VAR = re.compile(VAR_EXPR % (WHOLE_KEY_FILTER, WHOLE_KEY_FILTER))
+IF_EXPR = u"###%sIF %s###(.*)###ENDIF###"
+RE_IF = re.compile(IF_EXPR % (WHOLE_KEY_FILTER, WHOLE_KEY_FILTER))
+TAG_FILTER = re.compile(u"(<[^<^>]*>)")
+KEY_FILTER = re.compile(u"([-a-zA-Z0-9_]*)")
+
+def _filter_key(base_key):
+ # return (key, extra_marker)
+ # manage strange key such as:
+ # test_<text:span text:style-name="T1">date</text:span>
+ key = base_key[:]
+ key = key.strip()
+ tags, new_key = '', key[:]
+ for tag in TAG_FILTER.findall(key):
+ tags += tag
+ new_key = new_key.replace(tag, '')
+ full_key = ''
+ for k in KEY_FILTER.findall(new_key):
+ if not k:
+ continue
+ full_key += k
+ return full_key, tags
+
+def _custom_parsing(context, value, default_value=''):
+ """
+ ###VAR nom_var### for displaying a variable name
+ ###IF nom_var### ###ENDIF### for conditionnal display
+ Be carreful nested condition are not yet managed!
+ """
+ for regexp, sub_exp, if_cond in ((RE_IF, IF_EXPR, True),
+ (RE_VAR, VAR_EXPR, False)):
+ for base_key in regexp.findall(value[:]):
+ v, val = "", None
+ if if_cond: # the value inside the if is parsed
+ pre_tag, base_key, val = base_key
+ else:
+ pre_tag, base_key = base_key
+ key, extra_markers = _filter_key(base_key)
+ v = ''
+ if pre_tag:
+ v = pre_tag
+ if key in context and context[key]:
+ if if_cond:
+ v += _custom_parsing(context, val, default_value)
+ else:
+ v += _format_value(context[key], default_value)
+ # to preserve a consistent OOO file put extra_markers
+ if extra_markers:
+ v += extra_markers
+ value = re.sub(sub_exp % (pre_tag, base_key), v, value)
+ return value
+
+def ooo_replace(infile, outfile, context, default_value=''):
+ inzip = ZipFile(infile, 'r', ZIP_DEFLATED)
+ outzip = ZipFile(outfile, 'w', ZIP_DEFLATED)
+
+ # regular ooo parsing
+ content = ElementTree(fromstring(inzip.read('content.xml')))
+ missing_keys = set()
+ for xp in ('variable-set', 'variable-get'):
+ for p in content.findall(".//"+OOO_NS+xp):
+ name = p.get(OOO_NS+"name")
+ if name in context:
+ value = context[name]
+ p.text = _format_value(value, default_value)
+ else:
+ if default_value != None:
+ p.text = default_value
+ missing_keys.add(name)
+ for p in content.findall(".//"+OOO_NS+"conditional-text"):
+ condition = p.get(OOO_NS+"condition")
+ res = 'true' if _parse_condition(condition, context, default_value) \
+ else 'false'
+ value = p.get(OOO_NS+'string-value-if-' + res)
+ value = _format_value(value, default_value)
+ if value.strip() in context:
+ value = context[value.strip()]
+ p.text = value
+
+ # raw content parsing
+ str_io = StringIO()
+ content.write(str_io)
+ value = str_io.getvalue()
+ value = _custom_parsing(context, value, default_value).encode('utf-8')
+
+ for f in inzip.infolist():
+ if f.filename == 'content.xml':
+ outzip.writestr('content.xml', value)
+ else:
+ outzip.writestr(f, inzip.read(f.filename))
+ inzip.close()
+ outzip.close()
+ return missing_keys
+
+if __name__ == '__main__':
+ infile = "../archaeological_files/tests/AR_dossier_DRAC_modele_ishtar_1-MOD.odt"
+ outfile = "../archaeological_files/tests/AR_dossier_DRAC_modele_ishtar-test.odt"
+ rep = {"file_incharge_surname":u"Yann",
+ "file_incharge_name":u"Le Jeune",
+ "fileact_ref":u"ref"}
+ ooo_replace(infile, outfile, rep, default_value="")