commit
26a8b633d1
2
Pipfile
2
Pipfile
|
@ -24,7 +24,7 @@ pyjwt = "*"
|
|||
requests = "*"
|
||||
xlsxwriter = "*"
|
||||
webtest = "*"
|
||||
spiffworkflow = {editable = true,git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
|
||||
spiffworkflow = {editable = true,git = "https://github.com/sartography/SpiffWorkflow.git",ref = "bug/the_horror"}
|
||||
alembic = "*"
|
||||
coverage = "*"
|
||||
sphinx = "*"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "26d23456010d3e5a559386d412cef3beacd92d5a4e474f2afdb0737ea0f20f04"
|
||||
"sha256": "bd289126c41b0f5f2761f0415d85e1110a584256460374a9ce4cda07c0033ddd"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -83,11 +83,11 @@
|
|||
},
|
||||
"beautifulsoup4": {
|
||||
"hashes": [
|
||||
"sha256:594ca51a10d2b3443cbac41214e12dbb2a1cd57e1a7344659849e2e20ba6a8d8",
|
||||
"sha256:a4bbe77fd30670455c5296242967a123ec28c37e9702a8a81bd2f20a4baf0368",
|
||||
"sha256:d4e96ac9b0c3a6d3f0caae2e4124e6055c5dcafde8e2f831ff194c104f0775a0"
|
||||
"sha256:73cc4d115b96f79c7d77c1c7f7a0a8d4c57860d1041df407dd1aae7f07a77fd7",
|
||||
"sha256:a6237df3c32ccfaee4fd201c8f5f9d9df619b93121d01353a64a73ce8c6ef9a8",
|
||||
"sha256:e718f2342e2e099b640a34ab782407b7b676f47ee272d6739e60b8ea23829f2c"
|
||||
],
|
||||
"version": "==4.9.0"
|
||||
"version": "==4.9.1"
|
||||
},
|
||||
"billiard": {
|
||||
"hashes": [
|
||||
|
@ -725,10 +725,10 @@
|
|||
},
|
||||
"soupsieve": {
|
||||
"hashes": [
|
||||
"sha256:e914534802d7ffd233242b785229d5ba0766a7f487385e3f714446a07bf540ae",
|
||||
"sha256:fcd71e08c0aee99aca1b73f45478549ee7e7fc006d51b37bec9e9def7dc22b69"
|
||||
"sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55",
|
||||
"sha256:a59dc181727e95d25f781f0eb4fd1825ff45590ec8ff49eadfd7f1a537cc0232"
|
||||
],
|
||||
"version": "==2.0"
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"sphinx": {
|
||||
"hashes": [
|
||||
|
@ -783,7 +783,7 @@
|
|||
"spiffworkflow": {
|
||||
"editable": true,
|
||||
"git": "https://github.com/sartography/SpiffWorkflow.git",
|
||||
"ref": "29afbcd69d7bb266c7b08962b5f0b36fdbc4636b"
|
||||
"ref": "c810e219765abe2d39322a984b074a5949559112"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
|
|
|
@ -149,7 +149,9 @@ def set_current_task(workflow_id, task_id):
|
|||
raise ApiError("invalid_state", "You may not move the token to a task who's state is not "
|
||||
"currently set to COMPLETE or READY.")
|
||||
|
||||
task.reset_token(reset_data=False) # we could optionally clear the previous data.
|
||||
# Only reset the token if the task doesn't already have it.
|
||||
if task.state == task.COMPLETED:
|
||||
task.reset_token(reset_data=False) # we could optionally clear the previous data.
|
||||
processor.save()
|
||||
WorkflowService.log_task_action(processor, task, WorkflowService.TASK_ACTION_TOKEN_RESET)
|
||||
workflow_api_model = __get_workflow_api_model(processor, task)
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
from io import StringIO, BytesIO
|
||||
import copy
|
||||
from io import BytesIO
|
||||
|
||||
from jinja2 import UndefinedError
|
||||
import jinja2
|
||||
from docxtpl import DocxTemplate, Listing
|
||||
|
||||
from crc import session
|
||||
from crc.api.common import ApiError
|
||||
from crc.models.file import FileModel, FileDataModel, CONTENT_TYPES
|
||||
from crc.models.workflow import WorkflowSpecModel, WorkflowModel
|
||||
from docxtpl import DocxTemplate
|
||||
import jinja2
|
||||
|
||||
from crc.models.file import CONTENT_TYPES
|
||||
from crc.models.workflow import WorkflowModel
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
@ -66,11 +65,30 @@ Takes two arguments:
|
|||
|
||||
def make_template(self, binary_stream, context):
|
||||
doc = DocxTemplate(binary_stream)
|
||||
doc_context = copy.deepcopy(context)
|
||||
doc_context = self.rich_text_update(doc_context)
|
||||
jinja_env = jinja2.Environment(autoescape=True)
|
||||
doc.render(context, jinja_env)
|
||||
doc.render(doc_context, jinja_env)
|
||||
target_stream = BytesIO()
|
||||
doc.save(target_stream)
|
||||
target_stream.seek(0) # move to the beginning of the stream.
|
||||
return target_stream
|
||||
|
||||
|
||||
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
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
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
|
||||
|
||||
|
||||
class TestCompleteTemplate(unittest.TestCase):
|
||||
|
||||
def test_rich_text_update(self):
|
||||
script = CompleteTemplate()
|
||||
data = {"name": "Dan"}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
self.assertEquals(data, data_copy)
|
||||
|
||||
def test_rich_text_update_new_line(self):
|
||||
script = CompleteTemplate()
|
||||
data = {"name": "Dan\n Funk"}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
self.assertNotEqual(data, data_copy)
|
||||
self.assertIsInstance(data_copy["name"], Listing)
|
||||
|
||||
def test_rich_text_nested_new_line(self):
|
||||
script = CompleteTemplate()
|
||||
data = {"names": [{"name": "Dan\n Funk"}]}
|
||||
data_copy = copy.deepcopy(data)
|
||||
script.rich_text_update(data_copy)
|
||||
self.assertNotEqual(data, data_copy)
|
||||
self.assertIsInstance(data_copy["names"][0]["name"], Listing)
|
Loading…
Reference in New Issue