From 750a202e99d55326088bf162c4518b43dd1d2769 Mon Sep 17 00:00:00 2001 From: Sartography Date: Sun, 6 Dec 2020 10:22:32 -0500 Subject: [PATCH 1/6] Test and BPMN files for testing email script --- tests/data/email_script/email_script.bpmn | 71 +++++++++++++++++++++++ tests/test_email_script.py | 20 +++++++ 2 files changed, 91 insertions(+) create mode 100644 tests/data/email_script/email_script.bpmn create mode 100644 tests/test_email_script.py diff --git a/tests/data/email_script/email_script.bpmn b/tests/data/email_script/email_script.bpmn new file mode 100644 index 00000000..7719e696 --- /dev/null +++ b/tests/data/email_script/email_script.bpmn @@ -0,0 +1,71 @@ + + + + + Flow_0scd96e + + + + + + + + + + + + + Flow_0scd96e + Flow_0c60gne + + + + Flow_19fqvhc + + + + Dear Person, + + +Thank you for using this email example. +I hope this makes sense. + + +Yours faithfully, + + +Dan + Flow_0c60gne + Flow_19fqvhc + email("My Email Subject", email_address) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_email_script.py b/tests/test_email_script.py new file mode 100644 index 00000000..5ec05ca8 --- /dev/null +++ b/tests/test_email_script.py @@ -0,0 +1,20 @@ +from tests.base_test import BaseTest + + +class TestEmailScript(BaseTest): + + def test_email_script(self): + + workflow = self.create_workflow('email_script') + + # Start the workflow. + first_task = self.get_workflow_api(workflow).next_task + # self.assertEqual('Activity_GetData', first_task.name) + workflow = self.get_workflow_api(workflow) + # self.complete_form(workflow, first_task, {'email_address': 'mike@sartography.com'}) + # self.complete_form(workflow, first_task, {'email_address': 'kcm4zc'}, user_uid='kcm4zc') + result = self.complete_form(workflow, first_task, {'email_address': "'kcm4zc'"}) + print(result) + task = self.get_workflow_api(workflow).next_task + self.assertEqual(task.name, 'string') + # self.assertEqual('Activity_HowMany', workflow.next_task.name) From 730d0ca18fef399331a4b131f6704041a009f475 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Mon, 7 Dec 2020 16:23:41 -0500 Subject: [PATCH 2/6] Email script now uses an email address instead of a UVA LDAP user_id. --- crc/scripts/email.py | 42 +++++++++++++++++++++++++++++++++++++- tests/test_email_script.py | 36 +++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/crc/scripts/email.py b/crc/scripts/email.py index 855ec8a4..8854a342 100644 --- a/crc/scripts/email.py +++ b/crc/scripts/email.py @@ -7,6 +7,8 @@ from crc.scripts.script import Script from crc.services.ldap_service import LdapService from crc.services.mails import send_mail +from email_validator import validate_email, EmailNotValidError + class Email(Script): """This Script allows to be introduced as part of a workflow and called from there, specifying @@ -30,7 +32,8 @@ Email Subject ApprvlApprvr1 PIComputingID def do_task(self, task, *args, **kwargs): args = [arg for arg in args if type(arg) == str] subject = self.get_subject(task, args) - recipients = self.get_users_info(task, args) + # recipients = self.get_users_info(task, args) + recipients = self.get_email_recipients(task, args) content, content_html = self.get_content(task) if recipients: send_mail( @@ -41,6 +44,43 @@ Email Subject ApprvlApprvr1 PIComputingID content_html=content_html ) + def get_email_recipients(self, task, args): + emails = [] + + if len(args[1]) < 1: + raise ApiError(code="missing_argument", + message="Email script requires at least one argument, " + "an email address to process. " + "Multiple email addresses are accepted.") + if isinstance(args[1], str): + try: + valid = validate_email(args[1]) + except EmailNotValidError as e: + # email is not valid, exception message is human-readable + raise ApiError(code="invalid_argument", + message="Email script requires a valid email address. " + "%s " % e) + print(str(e)) + else: + emails.append(valid.email) + + elif isinstance(args[1], list): + for arg in args[1]: + if isinstance(arg, str): + # TODO: need to validate + try: + valid = validate_email(args[1]) + except EmailNotValidError as e: + # email is not valid, exception message is human-readable + raise ApiError(code="invalid_argument", + message="Email script requires a valid email address." + "Multiple address are allowed.") + print(str(e)) + else: + emails.append(valid.email) + + return emails + def get_users_info(self, task, args): if len(args) < 1: raise ApiError(code="missing_argument", diff --git a/tests/test_email_script.py b/tests/test_email_script.py index 5ec05ca8..3bca598e 100644 --- a/tests/test_email_script.py +++ b/tests/test_email_script.py @@ -1,20 +1,32 @@ from tests.base_test import BaseTest +from crc import mail + + +# class TestEmailDirectly(BaseTest): +# +# def test_email_directly(self): +# recipients = ['michaelc@cullerton.com'] +# sender = 'michaelc@cullerton.com' +# with mail.record_messages() as outbox: +# mail.send_message(subject='testing', +# body='test', +# recipients=recipients, +# sender=sender) +# assert len(outbox) == 1 +# assert outbox[0].subject == "testing" class TestEmailScript(BaseTest): def test_email_script(self): + with mail.record_messages() as outbox: - workflow = self.create_workflow('email_script') + workflow = self.create_workflow('email_script') - # Start the workflow. - first_task = self.get_workflow_api(workflow).next_task - # self.assertEqual('Activity_GetData', first_task.name) - workflow = self.get_workflow_api(workflow) - # self.complete_form(workflow, first_task, {'email_address': 'mike@sartography.com'}) - # self.complete_form(workflow, first_task, {'email_address': 'kcm4zc'}, user_uid='kcm4zc') - result = self.complete_form(workflow, first_task, {'email_address': "'kcm4zc'"}) - print(result) - task = self.get_workflow_api(workflow).next_task - self.assertEqual(task.name, 'string') - # self.assertEqual('Activity_HowMany', workflow.next_task.name) + first_task = self.get_workflow_api(workflow).next_task + # self.assertEqual('Activity_GetData', first_task.name) + workflow = self.get_workflow_api(workflow) + self.complete_form(workflow, first_task, {'email_address': 'michaelc@cullerton.com'}) + + self.assertEqual(1, len(outbox)) + self.assertEqual("My Email Subject", outbox[0].subject) From 32c5060a310dc099047d5675c23e973e0d633061 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Wed, 9 Dec 2020 12:11:46 -0500 Subject: [PATCH 3/6] No longer use eval on the email address. It is already parsed. Tests for single and multiple emails, and email error checking. Still need to figure out how to implement multiple emails. --- crc/scripts/email.py | 138 +++++++++++----------- tests/data/email_script/email_script.bpmn | 47 ++++---- tests/test_email_script.py | 40 ++++++- 3 files changed, 133 insertions(+), 92 deletions(-) diff --git a/crc/scripts/email.py b/crc/scripts/email.py index 8854a342..62b6aebc 100644 --- a/crc/scripts/email.py +++ b/crc/scripts/email.py @@ -1,3 +1,5 @@ +import re + import markdown from jinja2 import Template @@ -7,8 +9,6 @@ from crc.scripts.script import Script from crc.services.ldap_service import LdapService from crc.services.mails import send_mail -from email_validator import validate_email, EmailNotValidError - class Email(Script): """This Script allows to be introduced as part of a workflow and called from there, specifying @@ -26,14 +26,18 @@ Email Subject ApprvlApprvr1 PIComputingID def do_task_validate_only(self, task, *args, **kwargs): self.get_subject(task, args) - self.get_users_info(task, args) + self.get_email_recipients(task, args) self.get_content(task) def do_task(self, task, *args, **kwargs): - args = [arg for arg in args if type(arg) == str] - subject = self.get_subject(task, args) - # recipients = self.get_users_info(task, args) - recipients = self.get_email_recipients(task, args) + args = [arg for arg in args if type(arg) == str or type(arg) == list] + + subject = args[0] + recipients = None + try: + recipients = self.get_email_recipients(task, args) + except ApiError: + raise content, content_html = self.get_content(task) if recipients: send_mail( @@ -44,81 +48,81 @@ Email Subject ApprvlApprvr1 PIComputingID content_html=content_html ) + def check_valid_email(self, email): + # regex from https://emailregex.com/ + regex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" + if (re.search(regex, email)): + return True + else: + return False + def get_email_recipients(self, task, args): emails = [] if len(args[1]) < 1: raise ApiError(code="missing_argument", - message="Email script requires at least one argument, " - "an email address to process. " + message="Email script requires at least one email address as an argument. " "Multiple email addresses are accepted.") + if isinstance(args[1], str): - try: - valid = validate_email(args[1]) - except EmailNotValidError as e: - # email is not valid, exception message is human-readable - raise ApiError(code="invalid_argument", - message="Email script requires a valid email address. " - "%s " % e) - print(str(e)) + if self.check_valid_email(args[1]): + emails.append(args[1]) else: - emails.append(valid.email) - - elif isinstance(args[1], list): - for arg in args[1]: - if isinstance(arg, str): - # TODO: need to validate - try: - valid = validate_email(args[1]) - except EmailNotValidError as e: - # email is not valid, exception message is human-readable - raise ApiError(code="invalid_argument", - message="Email script requires a valid email address." - "Multiple address are allowed.") - print(str(e)) - else: - emails.append(valid.email) - - return emails - - def get_users_info(self, task, args): - if len(args) < 1: - raise ApiError(code="missing_argument", - message="Email script requires at least one argument. The " - "name of the variable in the task data that contains user" - "id to process. Multiple arguments are accepted.") - emails = [] - for arg in args: - try: - uid = task.workflow.script_engine.evaluate_expression(task, arg) - except Exception as e: - app.logger.error(f'Workflow engines could not parse {arg}', exc_info=True) - continue - user_info = LdapService.user_info(uid) - email = user_info.email_address - emails.append(user_info.email_address) - if not isinstance(email, str): raise ApiError(code="invalid_argument", - message="The Email script requires at least 1 UID argument. The " - "name of the variable in the task data that contains subject and" - " user ids to process. This must point to an array or a string, but " - "it currently points to a %s " % emails.__class__.__name__) + message="The email address you provided could not be parsed. " + "The value you provided is '%s" % args[1]) - return emails + if isinstance(args[1], list): + for address in args[1]: + if self.check_valid_email(address): + emails.append(address) + else: + raise ApiError(code="invalid_argument", + message="The email address you provided could not be parsed. " + "The value you provided is '%s" % address) + + if len(emails) > 0: + return emails + else: + raise ApiError(code="invalid_argument", + message="Email script requires a valid email address.") + + # def get_users_info(self, task, args): + # if len(args) < 1: + # raise ApiError(code="missing_argument", + # message="Email script requires at least one argument. The " + # "name of the variable in the task data that contains user" + # "id to process. Multiple arguments are accepted.") + # emails = [] + # for arg in args: + # try: + # uid = task.workflow.script_engine.evaluate_expression(task, arg) + # except Exception as e: + # app.logger.error(f'Workflow engines could not parse {arg}', exc_info=True) + # continue + # user_info = LdapService.user_info(uid) + # email = user_info.email_address + # emails.append(user_info.email_address) + # if not isinstance(email, str): + # raise ApiError(code="invalid_argument", + # message="The Email script requires at least 1 UID argument. The " + # "name of the variable in the task data that contains subject and" + # " user ids to process. This must point to an array or a string, but " + # "it currently points to a %s " % emails.__class__.__name__) + # + # return emails def get_subject(self, task, args): - if len(args) < 1: + # subject = '' + if len(args[0]) < 1: raise ApiError(code="missing_argument", - message="Email script requires at least one subject argument. The " - "name of the variable in the task data that contains subject" - " to process. Multiple arguments are accepted.") + message="No subject was provided for the email message.") + subject = args[0] - if not isinstance(subject, str): + if not subject or not isinstance(subject, str): raise ApiError(code="invalid_argument", - message="The Email script requires 1 argument. The " - "the name of the variable in the task data that contains user" - "ids to process. This must point to an array or a string, but " - "it currently points to a %s " % subject.__class__.__name__) + message="The subject you provided could not be parsed. " + "The value is \"%s\" " % subject) return subject diff --git a/tests/data/email_script/email_script.bpmn b/tests/data/email_script/email_script.bpmn index 7719e696..201b70a1 100644 --- a/tests/data/email_script/email_script.bpmn +++ b/tests/data/email_script/email_script.bpmn @@ -1,11 +1,11 @@ - + Flow_0scd96e - - + + @@ -18,12 +18,12 @@ Flow_0scd96e Flow_0c60gne - - + + Flow_19fqvhc - - + + Dear Person, @@ -37,34 +37,35 @@ Yours faithfully, Dan Flow_0c60gne Flow_19fqvhc - email("My Email Subject", email_address) + subject = 'My Email Subject' +email(subject, email_address) - - - + + + - - + + - - - + + + - + - - + + - - + + - - + + diff --git a/tests/test_email_script.py b/tests/test_email_script.py index 3bca598e..42257d4b 100644 --- a/tests/test_email_script.py +++ b/tests/test_email_script.py @@ -24,9 +24,45 @@ class TestEmailScript(BaseTest): workflow = self.create_workflow('email_script') first_task = self.get_workflow_api(workflow).next_task - # self.assertEqual('Activity_GetData', first_task.name) + workflow = self.get_workflow_api(workflow) - self.complete_form(workflow, first_task, {'email_address': 'michaelc@cullerton.com'}) + self.complete_form(workflow, first_task, {'email_address': 'test@example.com'}) + + self.assertEqual(1, len(outbox)) + self.assertEqual('My Email Subject', outbox[0].subject) + self.assertEqual(['test@example.com'], outbox[0].recipients) + + def test_email_script_multiple(self): + with mail.record_messages() as outbox: + + workflow = self.create_workflow('email_script') + + first_task = self.get_workflow_api(workflow).next_task + + workflow = self.get_workflow_api(workflow) + self.complete_form(workflow, first_task, {'email_address': ['test@example.com', 'test2@example.com']}) self.assertEqual(1, len(outbox)) self.assertEqual("My Email Subject", outbox[0].subject) + self.assertEqual(2, len(outbox[0].recipients)) + self.assertEqual('test@example.com', outbox[0].recipients[0]) + self.assertEqual('test2@example.com', outbox[0].recipients[1]) + + def test_bad_email_address_1(self): + workflow = self.create_workflow('email_script') + + first_task = self.get_workflow_api(workflow).next_task + + workflow = self.get_workflow_api(workflow) + with self.assertRaises(AssertionError): + self.complete_form(workflow, first_task, {'email_address': 'test@example'}) + + + def test_bad_email_address_2(self): + workflow = self.create_workflow('email_script') + + first_task = self.get_workflow_api(workflow).next_task + + workflow = self.get_workflow_api(workflow) + with self.assertRaises(AssertionError): + self.complete_form(workflow, first_task, {'email_address': 'test'}) From 38a6fa782d935bdf5e9ec8f29fdd49b60e71fdce Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 14 Dec 2020 10:29:53 -0500 Subject: [PATCH 4/6] Fixing the email script test. --- tests/data/email/email.bpmn | 4 ++-- tests/emails/test_email_script.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/data/email/email.bpmn b/tests/data/email/email.bpmn index 3395e788..7ba69843 100644 --- a/tests/data/email/email.bpmn +++ b/tests/data/email/email.bpmn @@ -1,5 +1,5 @@ - + Flow_1synsig @@ -20,7 +20,7 @@ Email content to be delivered to {{ ApprvlApprvr1 }} --- Flow_08n2npe Flow_1xlrgne - email("Camunda Email Subject",'ApprvlApprvr1','PIComputingID') + email("Camunda Email Subject",ApprvlApprvr1,PIComputingID) diff --git a/tests/emails/test_email_script.py b/tests/emails/test_email_script.py index 1385609b..1a6c6860 100644 --- a/tests/emails/test_email_script.py +++ b/tests/emails/test_email_script.py @@ -1,6 +1,6 @@ +from tests.base_test import BaseTest from crc import mail from crc.models.email import EmailModel -from tests.base_test import BaseTest class TestEmailScript(BaseTest): @@ -9,8 +9,8 @@ class TestEmailScript(BaseTest): workflow = self.create_workflow('email') task_data = { - 'PIComputingID': 'dhf8r', - 'ApprvlApprvr1': 'lb3dp' + 'PIComputingID': 'dhf8r@virginia.edu', + 'ApprvlApprvr1': 'lb3dp@virginia.edu' } task = self.get_workflow_api(workflow).next_task From fd4b881416b671c5930fc5f57c110e9fb230c408 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 14 Dec 2020 10:30:10 -0500 Subject: [PATCH 5/6] upgrading the pip libraries. --- Pipfile.lock | 133 +++++++++++++++++------------------ crc/services/file_service.py | 3 +- 2 files changed, 65 insertions(+), 71 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index ed6931eb..b64e68b3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -33,10 +33,10 @@ }, "aniso8601": { "hashes": [ - "sha256:529dcb1f5f26ee0df6c0a1ee84b7b27197c3c50fc3a6321d66c544689237d072", - "sha256:c033f63d028b9a58e3ab0c2c7d0532ab4bfa7452bfc788fbfe3ddabd327b181a" + "sha256:246bf8d3611527030889e6df970878969d3a2f760ba3eb694fa1fb10e6ce53f9", + "sha256:51047d4fb51d7b8afd522b70f2d21a1b2487cbb7f7bd84ea852e9aa7808e7704" ], - "version": "==8.0.0" + "version": "==8.1.0" }, "attrs": { "hashes": [ @@ -80,10 +80,10 @@ }, "certifi": { "hashes": [ - "sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd", - "sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4" + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" ], - "version": "==2020.11.8" + "version": "==2020.12.5" }, "cffi": { "hashes": [ @@ -108,12 +108,14 @@ "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", @@ -548,40 +550,40 @@ }, "packaging": { "hashes": [ - "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", - "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858", + "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093" ], - "version": "==20.4" + "version": "==20.8" }, "pandas": { "hashes": [ - "sha256:09e0503758ad61afe81c9069505f8cb8c1e36ea8cc1e6826a95823ef5b327daf", - "sha256:0a11a6290ef3667575cbd4785a1b62d658c25a2fd70a5adedba32e156a8f1773", - "sha256:0d9a38a59242a2f6298fff45d09768b78b6eb0c52af5919ea9e45965d7ba56d9", - "sha256:112c5ba0f9ea0f60b2cc38c25f87ca1d5ca10f71efbee8e0f1bee9cf584ed5d5", - "sha256:185cf8c8f38b169dbf7001e1a88c511f653fbb9dfa3e048f5e19c38049e991dc", - "sha256:3aa8e10768c730cc1b610aca688f588831fa70b65a26cb549fbb9f35049a05e0", - "sha256:41746d520f2b50409dffdba29a15c42caa7babae15616bcf80800d8cfcae3d3e", - "sha256:43cea38cbcadb900829858884f49745eb1f42f92609d368cabcc674b03e90efc", - "sha256:5378f58172bd63d8c16dd5d008d7dcdd55bf803fcdbe7da2dcb65dbbf322f05b", - "sha256:54404abb1cd3f89d01f1fb5350607815326790efb4789be60508f458cdd5ccbf", - "sha256:5dac3aeaac5feb1016e94bde851eb2012d1733a222b8afa788202b836c97dad5", - "sha256:5fdb2a61e477ce58d3f1fdf2470ee142d9f0dde4969032edaf0b8f1a9dafeaa2", - "sha256:6613c7815ee0b20222178ad32ec144061cb07e6a746970c9160af1ebe3ad43b4", - "sha256:6d2b5b58e7df46b2c010ec78d7fb9ab20abf1d306d0614d3432e7478993fbdb0", - "sha256:8a5d7e57b9df2c0a9a202840b2881bb1f7a648eba12dd2d919ac07a33a36a97f", - "sha256:8b4c2055ebd6e497e5ecc06efa5b8aa76f59d15233356eb10dad22a03b757805", - "sha256:a15653480e5b92ee376f8458197a58cca89a6e95d12cccb4c2d933df5cecc63f", - "sha256:a7d2547b601ecc9a53fd41561de49a43d2231728ad65c7713d6b616cd02ddbed", - "sha256:a979d0404b135c63954dea79e6246c45dd45371a88631cdbb4877d844e6de3b6", - "sha256:b1f8111635700de7ac350b639e7e452b06fc541a328cf6193cf8fc638804bab8", - "sha256:c5a3597880a7a29a31ebd39b73b2c824316ae63a05c3c8a5ce2aea3fc68afe35", - "sha256:c681e8fcc47a767bf868341d8f0d76923733cbdcabd6ec3a3560695c69f14a1e", - "sha256:cf135a08f306ebbcfea6da8bf775217613917be23e5074c69215b91e180caab4", - "sha256:e2b8557fe6d0a18db4d61c028c6af61bfed44ef90e419ed6fadbdc079eba141e" + "sha256:0a643bae4283a37732ddfcecab3f62dd082996021b980f580903f4e8e01b3c5b", + "sha256:0de3ddb414d30798cbf56e642d82cac30a80223ad6fe484d66c0ce01a84d6f2f", + "sha256:19a2148a1d02791352e9fa637899a78e371a3516ac6da5c4edc718f60cbae648", + "sha256:21b5a2b033380adbdd36b3116faaf9a4663e375325831dac1b519a44f9e439bb", + "sha256:24c7f8d4aee71bfa6401faeba367dd654f696a77151a8a28bc2013f7ced4af98", + "sha256:26fa92d3ac743a149a31b21d6f4337b0594b6302ea5575b37af9ca9611e8981a", + "sha256:2860a97cbb25444ffc0088b457da0a79dc79f9c601238a3e0644312fcc14bf11", + "sha256:2b1c6cd28a0dfda75c7b5957363333f01d370936e4c6276b7b8e696dd500582a", + "sha256:2c2f7c670ea4e60318e4b7e474d56447cf0c7d83b3c2a5405a0dbb2600b9c48e", + "sha256:3be7a7a0ca71a2640e81d9276f526bca63505850add10206d0da2e8a0a325dae", + "sha256:4c62e94d5d49db116bef1bd5c2486723a292d79409fc9abd51adf9e05329101d", + "sha256:5008374ebb990dad9ed48b0f5d0038124c73748f5384cc8c46904dace27082d9", + "sha256:5447ea7af4005b0daf695a316a423b96374c9c73ffbd4533209c5ddc369e644b", + "sha256:573fba5b05bf2c69271a32e52399c8de599e4a15ab7cec47d3b9c904125ab788", + "sha256:5a780260afc88268a9d3ac3511d8f494fdcf637eece62fb9eb656a63d53eb7ca", + "sha256:70865f96bb38fec46f7ebd66d4b5cfd0aa6b842073f298d621385ae3898d28b5", + "sha256:731568be71fba1e13cae212c362f3d2ca8932e83cb1b85e3f1b4dd77d019254a", + "sha256:b61080750d19a0122469ab59b087380721d6b72a4e7d962e4d7e63e0c4504814", + "sha256:bf23a3b54d128b50f4f9d4675b3c1857a688cc6731a32f931837d72effb2698d", + "sha256:c16d59c15d946111d2716856dd5479221c9e4f2f5c7bc2d617f39d870031e086", + "sha256:c61c043aafb69329d0f961b19faa30b1dab709dd34c9388143fc55680059e55a", + "sha256:c94ff2780a1fd89f190390130d6d36173ca59fcfb3fe0ff596f9a56518191ccb", + "sha256:edda9bacc3843dfbeebaf7a701763e68e741b08fccb889c003b0a52f0ee95782", + "sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b" ], "index": "pypi", - "version": "==1.1.4" + "version": "==1.1.5" }, "psycopg2-binary": { "hashes": [ @@ -640,18 +642,18 @@ }, "pygithub": { "hashes": [ - "sha256:776befaddab9d8fddd525d52a6ca1ac228cf62b5b1e271836d766f4925e1452e", - "sha256:8ad656bf79958e775ec59f7f5a3dbcbadac12147ae3dc42708b951064096af15" + "sha256:053f1b8d553a344ebd3ca3972765d923ee7e8ecc3ea55bd203683f164348fa1a", + "sha256:14c96d55e3c0e295598e52fbbbf2a7862a293723482ae9000cb9c816faab4fb4" ], "index": "pypi", - "version": "==1.53" + "version": "==1.54" }, "pygments": { "hashes": [ - "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0", - "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773" + "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716", + "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08" ], - "version": "==2.7.2" + "version": "==2.7.3" }, "pyjwt": { "hashes": [ @@ -746,11 +748,11 @@ }, "requests": { "hashes": [ - "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8", - "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998" + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" ], "index": "pypi", - "version": "==2.25.0" + "version": "==2.24.0" }, "sentry-sdk": { "extras": [ @@ -779,11 +781,11 @@ }, "soupsieve": { "hashes": [ - "sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55", - "sha256:a59dc181727e95d25f781f0eb4fd1825ff45590ec8ff49eadfd7f1a537cc0232" + "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851", + "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e" ], "markers": "python_version >= '3.0'", - "version": "==2.0.1" + "version": "==2.1" }, "sphinx": { "hashes": [ @@ -837,7 +839,7 @@ }, "spiffworkflow": { "git": "https://github.com/sartography/SpiffWorkflow.git", - "ref": "6b2ed24bb340ebd31049312bd321f66ebf7b6b26" + "ref": "aec8e8e21ec8efe09b3c9ff24465824886890ad8" }, "sqlalchemy": { "hashes": [ @@ -892,10 +894,10 @@ }, "urllib3": { "hashes": [ - "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08", - "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473" + "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", + "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" ], - "version": "==1.26.2" + "version": "==1.25.11" }, "waitress": { "hashes": [ @@ -942,11 +944,11 @@ }, "xlrd": { "hashes": [ - "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2", - "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde" + "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd", + "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88" ], "index": "pypi", - "version": "==1.2.0" + "version": "==2.0.1" }, "xlsxwriter": { "hashes": [ @@ -1014,10 +1016,10 @@ }, "packaging": { "hashes": [ - "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", - "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858", + "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093" ], - "version": "==20.4" + "version": "==20.8" }, "pbr": { "hashes": [ @@ -1036,10 +1038,10 @@ }, "py": { "hashes": [ - "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", - "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342" + "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", + "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" ], - "version": "==1.9.0" + "version": "==1.10.0" }, "pyparsing": { "hashes": [ @@ -1050,18 +1052,11 @@ }, "pytest": { "hashes": [ - "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe", - "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e" + "sha256:b12e09409c5bdedc28d308469e156127004a436b41e9b44f9bff6446cbab9152", + "sha256:d69e1a80b34fe4d596c9142f35d9e523d98a2838976f1a68419a8f051b24cec6" ], "index": "pypi", - "version": "==6.1.2" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "version": "==1.15.0" + "version": "==6.2.0" }, "toml": { "hashes": [ diff --git a/crc/services/file_service.py b/crc/services/file_service.py index 2c55058c..a3882f26 100644 --- a/crc/services/file_service.py +++ b/crc/services/file_service.py @@ -6,7 +6,6 @@ from github import Github, GithubObject, UnknownObjectException from uuid import UUID from lxml import etree -import flask from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException from pandas import ExcelFile from sqlalchemy import desc @@ -82,7 +81,7 @@ class FileService(object): you get '1.0' rather than '1' fixme: This is stupid stupid slow. Place it in the database and just check if it is up to date.""" data_model = FileService.get_reference_file_data(reference_file_name) - xls = ExcelFile(data_model.data) + xls = ExcelFile(data_model.data, engine='openpyxl') df = xls.parse(xls.sheet_names[0]) for c in int_columns: df[c] = df[c].fillna(0) From 082dee46e04b851dde907b3b1dd51bb092551cd4 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 14 Dec 2020 10:37:35 -0500 Subject: [PATCH 6/6] fixing some failing tests. --- tests/test_tasks_api.py | 6 +++--- tests/test_user_roles.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_tasks_api.py b/tests/test_tasks_api.py index a6ffa710..92106201 100644 --- a/tests/test_tasks_api.py +++ b/tests/test_tasks_api.py @@ -113,14 +113,14 @@ class TestTasksApi(BaseTest): self.assertIsNotNone(workflow_api.navigation) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(6, len(nav)) self.assertEqual("Do You Have Bananas", nav[0]['title']) self.assertEqual("Bananas?", nav[1]['title']) self.assertEqual("FUTURE", nav[1]['state']) self.assertEqual("yes", nav[2]['title']) self.assertEqual("NOOP", nav[2]['state']) - self.assertEqual("no", nav[3]['title']) - self.assertEqual("NOOP", nav[3]['state']) + self.assertEqual("no", nav[4]['title']) + self.assertEqual("NOOP", nav[4]['state']) def test_navigation_with_exclusive_gateway(self): workflow = self.create_workflow('exclusive_gateway_2') diff --git a/tests/test_user_roles.py b/tests/test_user_roles.py index 3dea94e7..8f00332b 100644 --- a/tests/test_user_roles.py +++ b/tests/test_user_roles.py @@ -62,7 +62,7 @@ class TestTasksApi(BaseTest): workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual("supervisor", nav[1]['lane']) def test_get_outstanding_tasks_awaiting_current_user(self): @@ -121,7 +121,7 @@ class TestTasksApi(BaseTest): # Navigation as Submitter with ready task. workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual('READY', nav[0]['state']) # First item is ready, no progress yet. self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user. self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway, and belongs to no one, and is locked. @@ -149,7 +149,7 @@ class TestTasksApi(BaseTest): # Navigation as Supervisor workflow_api = self.get_workflow_api(workflow, user_uid=supervisor.uid) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual('LOCKED', nav[0]['state']) # First item belongs to the submitter, and is locked. self.assertEqual('READY', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user. self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway, and belongs to no one, and is locked. @@ -161,7 +161,7 @@ class TestTasksApi(BaseTest): # Navigation as Supervisor, after completing task. nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual('LOCKED', nav[0]['state']) # First item belongs to the submitter, and is locked. self.assertEqual('COMPLETED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user. self.assertEqual('COMPLETED', nav[2]['state']) # third item is a gateway, and is now complete. @@ -170,7 +170,7 @@ class TestTasksApi(BaseTest): # Navigation as Submitter, coming back in to a rejected workflow to view the rejection message. workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual('COMPLETED', nav[0]['state']) # First item belongs to the submitter, and is locked. self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user. self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway belonging to the supervisor, and is locked. @@ -179,7 +179,7 @@ class TestTasksApi(BaseTest): # Navigation as Submitter, re-completing the original request a second time, and sending it for review. workflow_api = self.complete_form(workflow, workflow_api.next_task, data, user_uid=submitter.uid) nav = workflow_api.navigation - self.assertEqual(5, len(nav)) + self.assertEqual(7, len(nav)) self.assertEqual('READY', nav[0]['state']) # When you loop back the task is again in the ready state. self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user. self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway belonging to the supervisor, and is locked.