From d62c17349419f448e5a6ecc21ca13807f6ed2694 Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Sun, 17 May 2020 11:57:04 -0400 Subject: [PATCH 1/5] Updating with new changes to the spiffworkflow navigation. --- Pipfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index d95c9014..70dce08a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -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": "d972448cb5772c35175119e5d0e0f12e1dff9c1b" }, "sqlalchemy": { "hashes": [ From fc080ce7a8ba1844e19c8f3bbfc0d00d4d2c256c Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Sun, 17 May 2020 13:29:36 -0400 Subject: [PATCH 2/5] Don't reset the token to something that already has a token. Terrible things happen and we hit a recursion. --- crc/api/workflow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crc/api/workflow.py b/crc/api/workflow.py index 368560d3..5d5b2af5 100644 --- a/crc/api/workflow.py +++ b/crc/api/workflow.py @@ -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) From 7ce460fffc0a425581e456fbb5d9c1f52177cfae Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Sun, 17 May 2020 17:06:00 -0400 Subject: [PATCH 3/5] using a branch of spiffworkflow that fixes a deep recursion issue - this isn't perfect, but it's miles better than it was. --- Pipfile | 2 +- Pipfile.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Pipfile b/Pipfile index 6c9960d2..6f374722 100644 --- a/Pipfile +++ b/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 = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 70dce08a..f67a9025 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -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": [ @@ -783,7 +783,7 @@ "spiffworkflow": { "editable": true, "git": "https://github.com/sartography/SpiffWorkflow.git", - "ref": "d972448cb5772c35175119e5d0e0f12e1dff9c1b" + "ref": "7be29f4bf8b3b5302dfeedaa8d1eff55e126e5ec" }, "sqlalchemy": { "hashes": [ From 5f2331f081ea7c98ab46101ba63a4a6bbb4b60f7 Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Mon, 18 May 2020 06:56:29 -0400 Subject: [PATCH 4/5] Bumping w/ fixes in spiffworkflow for reset token. --- Pipfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile.lock b/Pipfile.lock index f67a9025..54178d09 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -783,7 +783,7 @@ "spiffworkflow": { "editable": true, "git": "https://github.com/sartography/SpiffWorkflow.git", - "ref": "7be29f4bf8b3b5302dfeedaa8d1eff55e126e5ec" + "ref": "c810e219765abe2d39322a984b074a5949559112" }, "sqlalchemy": { "hashes": [ From 5c5c2a7312d047f586a2997967ea96683accfd5a Mon Sep 17 00:00:00 2001 From: Dan Funk Date: Mon, 18 May 2020 11:55:10 -0400 Subject: [PATCH 5/5] Assure that new lines entered in text-fields are correctly added to the final word document. --- crc/scripts/complete_template.py | 36 +++++++++++++++++++------- tests/test_complete_template_script.py | 36 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 tests/test_complete_template_script.py diff --git a/crc/scripts/complete_template.py b/crc/scripts/complete_template.py index 81de06b8..4fc7eb16 100644 --- a/crc/scripts/complete_template.py +++ b/crc/scripts/complete_template.py @@ -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 diff --git a/tests/test_complete_template_script.py b/tests/test_complete_template_script.py new file mode 100644 index 00000000..dfac20c6 --- /dev/null +++ b/tests/test_complete_template_script.py @@ -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)