*** WIP ***
Migrating the complete_template script stuff to JinjaService. Having trouble with the tools stuff. Pulled back to spot where test pass using CompleteTemplate
This commit is contained in:
parent
da9b902c19
commit
0122029e30
|
@ -24,9 +24,7 @@ def render_markdown(data, template):
|
|||
data structure. Useful for folks that are building these markdown templates.
|
||||
"""
|
||||
try:
|
||||
# template = Template(template)
|
||||
data = json.loads(data)
|
||||
# return template.render(**data)
|
||||
return JinjaService.get_content(template, data)
|
||||
except UndefinedError as ue:
|
||||
raise ApiError(code="undefined_field", message=ue.message)
|
||||
|
@ -42,6 +40,12 @@ def render_docx():
|
|||
try:
|
||||
file = connexion.request.files['file']
|
||||
data = connexion.request.form['data']
|
||||
# TODO: This bypasses the Jinja service and uses complete_template script
|
||||
# content = JinjaService().get_word_document_content(file, json.loads(data), image_file_data=None)
|
||||
#
|
||||
# target_stream = io.BytesIO()
|
||||
# content.save(target_stream)
|
||||
# target_stream.seek(0) # move to the beginning of the stream.
|
||||
target_stream = CompleteTemplate().make_template(file, json.loads(data))
|
||||
return send_file(
|
||||
io.BytesIO(target_stream.read()),
|
||||
|
|
|
@ -12,6 +12,7 @@ from crc.models.file import CONTENT_TYPES, FileModel, FileDataModel
|
|||
from crc.models.workflow import WorkflowModel
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.jinja_service import JinjaService
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
||||
|
||||
|
@ -108,10 +109,10 @@ Takes two arguments:
|
|||
|
||||
return image_file_data
|
||||
|
||||
def make_template(self, binary_stream, context, image_file_data=None):
|
||||
def make_template(self, binary_stream, task_data, image_file_data=None):
|
||||
# TODO: Move this into the jinja_service?
|
||||
doc = DocxTemplate(binary_stream)
|
||||
doc_context = copy.deepcopy(context)
|
||||
doc_context = copy.deepcopy(task_data)
|
||||
doc_context = self.rich_text_update(doc_context)
|
||||
doc_context = self.append_images(doc, doc_context, image_file_data)
|
||||
jinja_env = jinja2.Environment(autoescape=True)
|
||||
|
@ -119,6 +120,15 @@ Takes two arguments:
|
|||
doc.render(doc_context, jinja_env)
|
||||
except Exception as e:
|
||||
print (e)
|
||||
# try:
|
||||
# doc = JinjaService.get_word_document_content(binary_stream, task_data, image_file_data)
|
||||
# except jinja2.exceptions.TemplateError as te:
|
||||
# # raise ApiError.from_task(code="bad_template",
|
||||
# # message="There was a problem compiling your template.",
|
||||
# # task=self.task)
|
||||
# print(te)
|
||||
# except TypeError as te:
|
||||
# print(te)
|
||||
target_stream = BytesIO()
|
||||
doc.save(target_stream)
|
||||
target_stream.seek(0) # move to the beginning of the stream.
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
from docxtpl import DocxTemplate, Listing, InlineImage
|
||||
from jinja2 import Environment, DictLoader
|
||||
|
||||
from docx.shared import Inches
|
||||
from io import BytesIO
|
||||
|
||||
import copy
|
||||
|
||||
|
||||
class JinjaService:
|
||||
"""Service for Jinja2 templates.
|
||||
|
@ -27,13 +33,52 @@ Cool Right?
|
|||
templates['main_template'] = input_template
|
||||
jinja2_env = Environment(loader=DictLoader(templates))
|
||||
|
||||
try:
|
||||
template = jinja2_env.get_template('main_template')
|
||||
# We just make a call here and let any errors percolate up to the calling method
|
||||
template = jinja2_env.get_template('main_template')
|
||||
return template.render(**data)
|
||||
|
||||
except Exception:
|
||||
# TODO: Should we deal w/ specific exceptions here?
|
||||
# i.e., the ones in workflow_service._process_documentation
|
||||
raise
|
||||
@staticmethod
|
||||
def get_word_document_content(binary_stream, task_data, image_file_data=None):
|
||||
doc = DocxTemplate(binary_stream)
|
||||
doc_context = copy.deepcopy(task_data)
|
||||
doc_context = JinjaService().rich_text_update(doc_context)
|
||||
# doc_context = JinjaService().append_images(doc, doc_context, image_file_data)
|
||||
jinja2_env = Environment(autoescape=True)
|
||||
return doc.render(doc_context, jinja2_env)
|
||||
|
||||
else:
|
||||
return template.render(**data)
|
||||
def rich_text_update(self, context):
|
||||
"""This is a bit of a hack. If we find that /n characters exist in the data, we want
|
||||
these to come out in the final document without requiring someone to predict it in the
|
||||
template. Ideally we would use the 'RichText' feature of the python-docx library, but
|
||||
that requires we both escape it here, and in the Docx template. There is a thing called
|
||||
a 'listing' in python-docx library that only requires we use it on the way in, and the
|
||||
template doesn't have to think about it. So running with that for now."""
|
||||
# loop through the content, identify anything that has a newline character in it, and
|
||||
# wrap that sucker in a 'listing' function.
|
||||
if isinstance(context, dict):
|
||||
for k, v in context.items():
|
||||
context[k] = self.rich_text_update(v)
|
||||
elif isinstance(context, list):
|
||||
for i in range(len(context)):
|
||||
context[i] = self.rich_text_update(context[i])
|
||||
elif isinstance(context, str) and '\n' in context:
|
||||
return Listing(context)
|
||||
return context
|
||||
|
||||
def append_images(self, template, context, image_file_data):
|
||||
context['images'] = {}
|
||||
if image_file_data is not None:
|
||||
for file_data_model in image_file_data:
|
||||
fm = file_data_model.file_model
|
||||
if fm is not None:
|
||||
context['images'][fm.id] = {
|
||||
'name': fm.name,
|
||||
'url': '/v1.0/file/%s/data' % fm.id,
|
||||
'image': self.make_image(file_data_model, template)
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
def make_image(file_data_model, template):
|
||||
return InlineImage(template, BytesIO(file_data_model.data), width=Inches(6.5))
|
||||
|
|
|
@ -16,9 +16,16 @@
|
|||
<camunda:formData>
|
||||
<camunda:formField id="subject" label="Subject" type="string" />
|
||||
<camunda:formField id="recipients" label="Recipients" type="string" />
|
||||
<camunda:formField id="include_me" label="Included Template" type="string" />
|
||||
<camunda:formField id="include_me" label="Included Template" type="string">
|
||||
<camunda:properties>
|
||||
<camunda:property id="Property_01o03tf" value="'My Value'" />
|
||||
</camunda:properties>
|
||||
</camunda:formField>
|
||||
<camunda:formField id="name" label="Name" type="string" />
|
||||
</camunda:formData>
|
||||
<camunda:properties>
|
||||
<camunda:property name="my_extension" value="'My Value'" />
|
||||
</camunda:properties>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_0yh2coe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0ovknlg</bpmn:outgoing>
|
||||
|
@ -33,38 +40,35 @@ Thank you for supporting the cause!
|
|||
{% include 'include_me' %}
|
||||
|
||||
|
||||
Did we include the other template?
|
||||
|
||||
</bpmn:documentation>
|
||||
Did we include the other template?</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0ovknlg</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_103ct5a</bpmn:outgoing>
|
||||
<bpmn:script>email_model = email(subject=subject, recipients=recipients)</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:manualTask id="Activity_0170t0m" name="Display Email">
|
||||
<bpmn:documentation># Email Model
|
||||
{{ email_model }}
|
||||
</bpmn:documentation>
|
||||
{{ email_model }}</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_103ct5a</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1nd1ian</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_098hnjo">
|
||||
<bpmndi:BPMNEdge id="Flow_0yh2coe_di" bpmnElement="Flow_0yh2coe">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0ovknlg_di" bpmnElement="Flow_0ovknlg">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
<bpmndi:BPMNEdge id="Flow_1nd1ian_di" bpmnElement="Flow_1nd1ian">
|
||||
<di:waypoint x="690" y="117" />
|
||||
<di:waypoint x="752" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_103ct5a_di" bpmnElement="Flow_103ct5a">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="590" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1nd1ian_di" bpmnElement="Flow_1nd1ian">
|
||||
<di:waypoint x="690" y="117" />
|
||||
<di:waypoint x="752" y="117" />
|
||||
<bpmndi:BPMNEdge id="Flow_0ovknlg_di" bpmnElement="Flow_0ovknlg">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0yh2coe_di" bpmnElement="Flow_0yh2coe">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
import unittest
|
||||
from tests.base_test import BaseTest
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
import copy
|
||||
|
||||
from docxtpl import Listing
|
||||
|
||||
from crc import app
|
||||
from crc.scripts.complete_template import CompleteTemplate
|
||||
from tests.base_test import BaseTest
|
||||
from crc.services.jinja_service import JinjaService
|
||||
|
||||
|
||||
class TestCompleteTemplate(unittest.TestCase):
|
||||
|
||||
def test_rich_text_update(self):
|
||||
script = CompleteTemplate()
|
||||
script = JinjaService()
|
||||
data = {"name": "Dan"}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
self.assertEqual(data, data_copy)
|
||||
|
||||
def test_rich_text_update_new_line(self):
|
||||
script = CompleteTemplate()
|
||||
script = JinjaService()
|
||||
data = {"name": "Dan\n Funk"}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
|
@ -28,7 +29,7 @@ class TestCompleteTemplate(unittest.TestCase):
|
|||
self.assertIsInstance(data_copy["name"], Listing)
|
||||
|
||||
def test_rich_text_nested_new_line(self):
|
||||
script = CompleteTemplate()
|
||||
script = JinjaService()
|
||||
data = {"names": [{"name": "Dan\n Funk"}]}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
|
|
|
@ -4,6 +4,8 @@ from crc.services.workflow_service import WorkflowService
|
|||
|
||||
from crc import mail
|
||||
|
||||
import json
|
||||
|
||||
|
||||
class TestJinjaService(BaseTest):
|
||||
|
||||
|
@ -38,7 +40,13 @@ class TestJinjaService(BaseTest):
|
|||
print(f'test_jinja_service_email: {workflow_api.next_task.data}')
|
||||
|
||||
def test_jinja_service_tools(self):
|
||||
pass
|
||||
template = "This is my template. {% include 'include_me' %} Was something included?"
|
||||
data = {"name": "World",
|
||||
"include_me": "Hello {{name}}!"}
|
||||
rv = self.app.get('/v1.0/render_markdown?template=%s&data=%s' %
|
||||
(template, json.dumps(data)))
|
||||
self.assert_success(rv)
|
||||
self.assertIn("Hello World", rv.get_data(as_text=True))
|
||||
|
||||
def test_jinja_service_documents(self):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue