From 0eedafc38f11d5e3ba0cca2a36876035a84235e5 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Tue, 23 Feb 2021 15:48:35 +0100 Subject: Fix label generation filter + tests --- ishtar_common/models.py | 134 ++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 66 deletions(-) (limited to 'ishtar_common/models.py') diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 55fb1566c..977b80ac6 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1580,46 +1580,18 @@ class DocumentTemplate(models.Model): def get_baselink_for_labels(self): return reverse('generate-labels', args=[self.slug]) - def publish(self, c_object): - tempdir = tempfile.mkdtemp("-ishtardocs") - output_name = tempdir + os.path.sep + \ - slugify(self.name.replace(' ', '_').lower()) + '-' + \ - datetime.date.today().strftime('%Y-%m-%d') + \ - "." + self.template.name.split('.')[-1] - item_re = r"([A-Za-z0-9_.]*)(\|[A-Za-z0-9_.-]*)*[|]*" - filtr = self.get_filter( - self.template, - [ - # {{ key1.key2 }} - r'{{ *' + item_re + ' *}}', - # {% for item in key1.key2 %} - r'{% *for +[A-Za-z0-9_]+ +in +' + item_re + r' *%}', - # {% if ** %} - r'{% (?:el)*if ([^}]*)%}', - ] - ) - # values = c_object.get_values(filtr=[]) - if "VALUES" in filtr: - filtr = [] - values = c_object.get_values(filtr=filtr) - if not filtr or 'VALUES' in filtr: - values['VALUES'] = json.dumps( - values, indent=4, sort_keys=True, - skipkeys=True, ensure_ascii=False, - separators=("", " : "), - ).replace(" " * 4, "\t") - engine = IshtarSecretaryRenderer() + def _exclude_filter(self, value): + """ + value is excluded from values to fetch? + """ + if not value or value in ("in", "not", "el") or value.startswith("|"): + return True try: - result = engine.render(self.template, **values) - except TemplateSyntaxError as e: - raise TemplateSyntaxError(str(e), e.lineno) - except UndefinedError as e: - raise TemplateSyntaxError(str(e), 0) - except Exception as e: - raise TemplateSyntaxError(str(e), 0) - with open(output_name, 'wb') as output: - output.write(result) - return output_name + int(value) + return True + except ValueError: # not a single int + pass + return False def get_filter(self, template, regexp_list=None): if not regexp_list: @@ -1637,30 +1609,21 @@ class DocumentTemplate(models.Model): if key not in filtr: filtr.append(key) new_filter = [] + OPERATORS = ["==", "not", "in", ">", "<", "!=", ">", "<", ">=", + "<=", "or", ">=", "<="] for fil in filtr: if not fil: continue new_filter += [f for f in fil.split(" ") - if f and f not in ( - "==", "not", "in", ">", "<", "!=", - ">", "<", ">=", "<=", "or", ">=", - "<=" - )] + if f and f not in OPERATORS] filtr = new_filter new_filter = [] for fil in filtr: - if not fil or fil in ("in", "not", "el") or fil.startswith("|"): - continue - try: - int(fil) - continue - except ValueError: # not a single int - pass - keys = fil.split("|")[0].split('.') - new_filter += keys + keys = fil.strip().split("|")[0].split('.') + new_filter += [k for k in keys if not self._exclude_filter(k)] prefix = "" for k in keys: - if not k: + if self._exclude_filter(k): continue if prefix: prefix += '_' @@ -1670,6 +1633,56 @@ class DocumentTemplate(models.Model): prefix += k return list(set(new_filter)) + ITEM_RE = r"([A-Za-z0-9_.]*)(?:[\[\]0-9-:])*(?:\|[^}]+)*" + BASE_RE = [ + # {{ key1.key2 }} + r'{{ *' + ITEM_RE + ' *}}', + # {% for item in key1.key2 %} + r'{% *for +[A-Za-z0-9_]+ +in +' + ITEM_RE + r' *%}', + # {% if ** %} + r'{% (?:el)*if ([^}]*)%}', + ] + + def publish(self, c_object): + tempdir = tempfile.mkdtemp("-ishtardocs") + output_name = tempdir + os.path.sep + \ + slugify(self.name.replace(' ', '_').lower()) + '-' + \ + datetime.date.today().strftime('%Y-%m-%d') + \ + "." + self.template.name.split('.')[-1] + filtr = self.get_filter(self.template, self.BASE_RE) + # values = c_object.get_values(filtr=[]) + if "VALUES" in filtr: + filtr = [] + values = c_object.get_values(filtr=filtr) + if not filtr or 'VALUES' in filtr: + values['VALUES'] = json.dumps( + values, indent=4, sort_keys=True, + skipkeys=True, ensure_ascii=False, + separators=("", " : "), + ).replace(" " * 4, "\t") + engine = IshtarSecretaryRenderer() + try: + result = engine.render(self.template, **values) + except TemplateSyntaxError as e: + raise TemplateSyntaxError(str(e), e.lineno) + except UndefinedError as e: + raise TemplateSyntaxError(str(e), 0) + except Exception as e: + raise TemplateSyntaxError(str(e), 0) + with open(output_name, 'wb') as output: + output.write(result) + return output_name + + LABEL_ITEM_RE = r"items\.\d\.([A-Za-z0-9_.]*)(?:[\[\]0-9-:])*(?:\|[^}]+)*" + LABEL_RE = [ + # {{items.4.key}} + r'{{ *' + LABEL_ITEM_RE + r' *}}', + # {% if ** %} + r'{% (?:el)*if ([^}]*)%}', + # {% for item in items.42.another_keys %} + r'{% *for +[A-Za-z0-9_]+ +in +' + LABEL_ITEM_RE + r' *%}', + ] + def publish_labels(self, objects): if not objects: return @@ -1681,18 +1694,7 @@ class DocumentTemplate(models.Model): len_objects = len(objects) names = [] - item_re = r"items\.\d\.([A-Za-z0-9_.]*)(?:\|[^}]+)*" - filtr = self.get_filter( - self.template, - [ - # {{items.4.key}} - r'{{ *' + item_re + r' *}}', - # {% if items.42.other_key %} - r'{% *(el)*if ' + item_re + r' *%}', - # {% for item in items.42.another_keys %} - r'{% *for +[A-Za-z0-9_]+ +in +' + item_re + r' *%}', - ] - ) + filtr = self.get_filter(self.template, self.LABEL_RE) for idx in range(int(len(objects) / self.label_per_page) + 1): if idx * self.label_per_page >= len_objects: break -- cgit v1.2.3