diff --git a/Pipfile b/Pipfile
index 56f3bc26..009e370c 100644
--- a/Pipfile
+++ b/Pipfile
@@ -38,7 +38,7 @@ recommonmark = "*"
requests = "*"
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
sphinx = "*"
-spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
+spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "cr-connect-106-augment-eval"}
#spiffworkflow = {editable = true,path="/home/kelly/sartography/SpiffWorkflow/"}
swagger-ui-bundle = "*"
webtest = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index 8aabe194..36b98856 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "381d29428eb328ad6167774b510b9d818bd1505b95f50454a19f1564782326cc"
+ "sha256": "afb6a541d1a9f33155f91529ad961492dceded89466aa1e02fed9901ac5eb146"
},
"pipfile-spec": 6,
"requires": {
@@ -804,7 +804,7 @@
},
"spiffworkflow": {
"git": "https://github.com/sartography/SpiffWorkflow.git",
- "ref": "11ad40bbcb0fbd3c5bc1078e4989dc38b749f7f3"
+ "ref": "7712830665b4419df019413ac095cb0749adb346"
},
"sqlalchemy": {
"hashes": [
diff --git a/crc/scripts/fact_service.py b/crc/scripts/fact_service.py
index b3701312..19e5cb3f 100644
--- a/crc/scripts/fact_service.py
+++ b/crc/scripts/fact_service.py
@@ -40,7 +40,7 @@ class FactService(Script):
else:
details = "unknown fact type."
- self.add_data_to_task(task, details)
+ #self.add_data_to_task(task, details)
print(details)
return details
diff --git a/crc/scripts/ldap.py b/crc/scripts/ldap.py
new file mode 100644
index 00000000..577d4a75
--- /dev/null
+++ b/crc/scripts/ldap.py
@@ -0,0 +1,50 @@
+import copy
+
+from crc import app
+from crc.api.common import ApiError
+from crc.scripts.script import Script
+from crc.services.ldap_service import LdapService
+
+
+class Ldap(Script):
+ """This Script allows to be introduced as part of a workflow and called from there, taking
+ a UID (or several) as input and looking it up through LDAP to return the person's details """
+
+ def get_description(self):
+ return """
+Attempts to create a dictionary with person details, using the
+provided argument (a UID) and look it up through LDAP.
+
+Examples:
+supervisor_info = ldap(supervisor_uid) // Sets the supervisor information to ldap details for the given uid.
+"""
+
+ def do_task_validate_only(self, task, *args, **kwargs):
+ return self.set_users_info_in_task(task, args)
+
+ def do_task(self, task, study_id, workflow_id, *args, **kwargs):
+ return self.set_users_info_in_task(task, args)
+
+ def set_users_info_in_task(self, task, args):
+ if len(args) != 1:
+ raise ApiError(code="missing_argument",
+ message="Ldap takes a single argument, the "
+ "UID for the person we want to look up")
+ uid = args[0]
+ user_info_dict = {}
+
+ user_info = LdapService.user_info(uid)
+ user_info_dict = {
+ "display_name": user_info.display_name,
+ "given_name": user_info.given_name,
+ "email_address": user_info.email_address,
+ "telephone_number": user_info.telephone_number,
+ "title": user_info.title,
+ "department": user_info.department,
+ "affiliation": user_info.affiliation,
+ "sponsor_type": user_info.sponsor_type,
+ "uid": user_info.uid,
+ "proper_name": user_info.proper_name()
+ }
+
+ return user_info_dict
diff --git a/crc/scripts/ldap_lookup.py b/crc/scripts/ldap_lookup.py
deleted file mode 100644
index 62bd287a..00000000
--- a/crc/scripts/ldap_lookup.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import copy
-
-from crc import app
-from crc.api.common import ApiError
-from crc.scripts.script import Script
-from crc.services.ldap_service import LdapService
-
-
-USER_DETAILS = {
- "PIComputingID": {
- "value": "",
- "data": {
- },
- "label": "invalid uid"
- }
-}
-
-
-class LdapLookup(Script):
- """This Script allows to be introduced as part of a workflow and called from there, taking
- a UID as input and looking it up through LDAP to return the person's details """
-
- def get_description(self):
- return """
-Attempts to create a dictionary with person details, using the
-provided argument (a UID) and look it up through LDAP.
-
-Example:
-LdapLookup PIComputingID
-"""
-
- def do_task_validate_only(self, task, *args, **kwargs):
- self.get_user_info(task, args)
-
- def do_task(self, task, *args, **kwargs):
- args = [arg for arg in args if type(arg) == str]
- user_info = self.get_user_info(task, args)
-
- user_details = copy.deepcopy(USER_DETAILS)
- user_details['PIComputingID']['value'] = user_info['uid']
- if len(user_info.keys()) > 1:
- user_details['PIComputingID']['label'] = user_info.pop('label')
- else:
- user_info.pop('uid')
- user_details['PIComputingID']['data'] = user_info
- return user_details
-
- def get_user_info(self, task, args):
- if len(args) < 1:
- raise ApiError(code="missing_argument",
- message="Ldap lookup script requires one argument. The "
- "UID for the person we want to look up")
-
- arg = args.pop() # Extracting only one value for now
- uid = task.workflow.script_engine.evaluate_expression(task, arg)
- if not isinstance(uid, str):
- raise ApiError(code="invalid_argument",
- message="Ldap lookup script requires one 1 UID argument, of type string.")
- user_info_dict = {}
- try:
- user_info = LdapService.user_info(uid)
- user_info_dict = {
- "display_name": user_info.display_name,
- "given_name": user_info.given_name,
- "email_address": user_info.email_address,
- "telephone_number": user_info.telephone_number,
- "title": user_info.title,
- "department": user_info.department,
- "affiliation": user_info.affiliation,
- "sponsor_type": user_info.sponsor_type,
- "uid": user_info.uid,
- "label": user_info.proper_name()
- }
- except:
- user_info_dict['uid'] = uid
- app.logger.error(f'Ldap lookup failed for UID {uid}')
-
- return user_info_dict
diff --git a/crc/scripts/ldap_replace.py b/crc/scripts/ldap_replace.py
deleted file mode 100644
index 88e2986a..00000000
--- a/crc/scripts/ldap_replace.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import copy
-
-from crc import app
-from crc.api.common import ApiError
-from crc.scripts.script import Script
-from crc.services.ldap_service import LdapService
-
-
-class LdapReplace(Script):
- """This Script allows to be introduced as part of a workflow and called from there, taking
- a UID (or several) as input and looking it up through LDAP to return the person's details """
-
- def get_description(self):
- return """
-Attempts to create a dictionary with person details, using the
-provided argument (a UID) and look it up through LDAP.
-
-Examples:
-#! LdapReplace supervisor
-#! LdapReplace supervisor collaborator
-#! LdapReplace supervisor cosupervisor collaborator
-"""
-
- def do_task_validate_only(self, task, *args, **kwargs):
- self.set_users_info_in_task(task, args)
-
- def do_task(self, task, *args, **kwargs):
- args = [arg for arg in args if type(arg) == str]
- self.set_users_info_in_task(task, args)
-
- def set_users_info_in_task(self, task, args):
- if len(args) < 1:
- raise ApiError(code="missing_argument",
- message="Ldap replace script requires at least one argument. The "
- "UID for the person(s) we want to look up")
-
- users_info = {}
- for arg in args:
- uid = task.workflow.script_engine.evaluate_expression(task, arg)
- if not isinstance(uid, str):
- raise ApiError(code="invalid_argument",
- message="Ldap replace script found an invalid argument, type string is required")
- user_info_dict = {}
- try:
- user_info = LdapService.user_info(uid)
- user_info_dict = {
- "display_name": user_info.display_name,
- "given_name": user_info.given_name,
- "email_address": user_info.email_address,
- "telephone_number": user_info.telephone_number,
- "title": user_info.title,
- "department": user_info.department,
- "affiliation": user_info.affiliation,
- "sponsor_type": user_info.sponsor_type,
- "uid": user_info.uid,
- "proper_name": user_info.proper_name()
- }
- except:
- app.logger.error(f'Ldap replace failed for UID {uid}')
- task.data[arg] = user_info_dict
diff --git a/crc/scripts/script.py b/crc/scripts/script.py
index ac4ce38d..84c2ee05 100644
--- a/crc/scripts/script.py
+++ b/crc/scripts/script.py
@@ -23,6 +23,53 @@ class Script(object):
"This is an internal error. The script you are trying to execute '%s' " % self.__class__.__name__ +
"does must provide a validate_only option that mimics the do_task, " +
"but does not make external calls or database updates." )
+ @staticmethod
+ def generate_augmented_list(task, study_id,workflow_id):
+ """
+ this makes a dictionary of lambda functions that are closed over the class instance that
+ They represent. This is passed into PythonScriptParser as a list of helper functions that are
+ available for running. In general, they maintain the do_task call structure that they had, but
+ they always return a value rather than updating the task data.
+
+ We may be able to remove the task for each of these calls if we are not using it other than potentially
+ updating the task data.
+ """
+ def make_closure(subclass,task,study_id,workflow_id):
+ instance = subclass()
+ return lambda *a : subclass.do_task(instance,task,study_id,workflow_id,*a)
+ execlist = {}
+ subclasses = Script.get_all_subclasses()
+ for x in range(len(subclasses)):
+ subclass = subclasses[x]
+ execlist[subclass.__module__.split('.')[-1]] = make_closure(subclass,task,study_id,
+ workflow_id)
+ return execlist
+
+ @staticmethod
+ def generate_augmented_validate_list(task, study_id, workflow_id):
+ """
+ this makes a dictionary of lambda functions that are closed over the class instance that
+ They represent. This is passed into PythonScriptParser as a list of helper functions that are
+ available for running. In general, they maintain the do_task call structure that they had, but
+ they always return a value rather than updating the task data.
+
+ We may be able to remove the task for each of these calls if we are not using it other than potentially
+ updating the task data.
+ """
+
+ def make_closure_validate(subclass,task,study_id,workflow_id):
+ instance = subclass()
+ return lambda *a : subclass.do_task_validate_only(instance,task,study_id,workflow_id,*a)
+ execlist = {}
+ subclasses = Script.get_all_subclasses()
+ for x in range(len(subclasses)):
+ subclass = subclasses[x]
+ execlist[subclass.__module__.split('.')[-1]] = make_closure_validate(subclass,task,study_id,
+ workflow_id)
+ return execlist
+
+
+
@staticmethod
def get_all_subclasses():
diff --git a/crc/scripts/study_info.py b/crc/scripts/study_info.py
index f274b899..6b55e0fd 100644
--- a/crc/scripts/study_info.py
+++ b/crc/scripts/study_info.py
@@ -8,7 +8,7 @@ from crc.scripts.script import Script
from crc.services.file_service import FileService
from crc.services.protocol_builder import ProtocolBuilderService
from crc.services.study_service import StudyService
-
+from box import Box
class StudyInfo(Script):
"""Please see the detailed description that is provided below. """
@@ -149,11 +149,11 @@ Returns information specific to the protocol.
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
"""For validation only, pretend no results come back from pb"""
- self.check_args(args)
+ self.check_args(args,2)
# Assure the reference file exists (a bit hacky, but we want to raise this error early, and cleanly.)
FileService.get_reference_file_data(FileService.DOCUMENT_LIST)
FileService.get_reference_file_data(FileService.INVESTIGATOR_LIST)
- data = {
+ data = Box({
"study":{
"info": {
"id": 12,
@@ -195,38 +195,50 @@ Returns information specific to the protocol.
'id': 0,
}
}
- }
- self.add_data_to_task(task=task, data=data["study"])
- self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
+ })
+ if args[0]=='documents':
+ return StudyService().get_documents_status(study_id)
+ return data['study'][args[0]]
+ #self.add_data_to_task(task=task, data=data["study"])
+ #self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
- self.check_args(args)
-
+ self.check_args(args,2)
+ prefix = None
+ if len(args) > 1:
+ prefix = args[1]
cmd = args[0]
- study_info = {}
- if self.__class__.__name__ in task.data:
- study_info = task.data[self.__class__.__name__]
-
+ # study_info = {}
+ # if self.__class__.__name__ in task.data:
+ # study_info = task.data[self.__class__.__name__]
+ retval = None
if cmd == 'info':
study = session.query(StudyModel).filter_by(id=study_id).first()
schema = StudySchema()
- self.add_data_to_task(task, {cmd: schema.dump(study)})
+ retval = schema.dump(study)
if cmd == 'investigators':
- self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id)})
+ retval = StudyService().get_investigators(study_id)
if cmd == 'roles':
- self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id, all=True)})
+ retval = StudyService().get_investigators(study_id, all=True)
if cmd == 'details':
- self.add_data_to_task(task, {cmd: self.pb.get_study_details(study_id)})
+ retval = self.pb.get_study_details(study_id)
if cmd == 'approvals':
- self.add_data_to_task(task, {cmd: StudyService().get_approvals(study_id)})
+ retval = StudyService().get_approvals(study_id)
if cmd == 'documents':
- self.add_data_to_task(task, {cmd: StudyService().get_documents_status(study_id)})
+ retval = StudyService().get_documents_status(study_id)
if cmd == 'protocol':
- self.add_data_to_task(task, {cmd: StudyService().get_protocol(study_id)})
+ retval = StudyService().get_protocol(study_id)
+ if isinstance(retval,dict) and prefix is not None:
+ return Box({x:retval[x] for x in retval.keys() if x[:len(prefix)] == prefix})
+ elif isinstance(retval,dict):
+ return Box(retval)
+ else:
+ return retval
- def check_args(self, args):
- if len(args) != 1 or (args[0] not in StudyInfo.type_options):
+
+ def check_args(self, args, maxlen=1):
+ if len(args) < 1 or len(args) > maxlen or (args[0] not in StudyInfo.type_options):
raise ApiError(code="missing_argument",
message="The StudyInfo script requires a single argument which must be "
"one of %s" % ",".join(StudyInfo.type_options))
diff --git a/crc/services/workflow_processor.py b/crc/services/workflow_processor.py
index 165d3313..2ec13702 100644
--- a/crc/services/workflow_processor.py
+++ b/crc/services/workflow_processor.py
@@ -17,6 +17,7 @@ from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser
from SpiffWorkflow.exceptions import WorkflowTaskExecException
from SpiffWorkflow.specs import WorkflowSpec
+import crc
from crc import session, app
from crc.api.common import ApiError
from crc.models.file import FileDataModel, FileModel, FileType
@@ -28,64 +29,71 @@ from crc import app
class CustomBpmnScriptEngine(BpmnScriptEngine):
"""This is a custom script processor that can be easily injected into Spiff Workflow.
- Rather than execute arbitrary code, this assumes the script references a fully qualified python class
- such as myapp.RandomFact. """
+ It will execute python code read in from the bpmn. It will also make any scripts in the
+ scripts directory available for execution. """
def execute(self, task: SpiffTask, script, data):
- """
- Functions in two modes.
- 1. If the command is proceeded by #! then this is assumed to be a python script, and will
- attempt to load that python module and execute the do_task method on that script. Scripts
- must be located in the scripts package and they must extend the script.py class.
- 2. If not proceeded by the #! this will attempt to execute the script directly and assumes it is
- valid Python.
- """
- # Shlex splits the whole string while respecting double quoted strings within
- if not script.startswith('#!'):
- try:
- super().execute(task, script, data)
- except SyntaxError as e:
- raise ApiError.from_task('syntax_error',
- f'If you are running a pre-defined script, please'
- f' proceed the script with "#!", otherwise this is assumed to be'
- f' pure python: {script}, {e.msg}', task=task)
- else:
- self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
- def run_predefined_script(self, task: SpiffTask, script, data):
- commands = shlex.split(script)
- path_and_command = commands[0].rsplit(".", 1)
- if len(path_and_command) == 1:
- module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
- class_name = path_and_command[0]
+ study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
+ if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
+ workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
else:
- module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
- class_name = path_and_command[1]
+ workflow_id = None
+
try:
- mod = __import__(module_name, fromlist=[class_name])
- klass = getattr(mod, class_name)
- study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
- if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
- workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
- else:
- workflow_id = None
-
- if not isinstance(klass(), Script):
- raise ApiError.from_task("invalid_script",
- "This is an internal error. The script '%s:%s' you called " %
- (module_name, class_name) +
- "does not properly implement the CRC Script class.",
- task=task)
if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
- """If this is running a validation, and not a normal process, then we want to
- mimic running the script, but not make any external calls or database changes."""
- klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
+ augmentMethods = Script.generate_augmented_validate_list(task, study_id, workflow_id)
else:
- klass().do_task(task, study_id, workflow_id, *commands[1:])
- except ModuleNotFoundError:
- raise ApiError.from_task("invalid_script",
- "Unable to locate Script: '%s:%s'" % (module_name, class_name),
- task=task)
+ augmentMethods = Script.generate_augmented_list(task, study_id, workflow_id)
+
+ super().execute(task, script, data, externalMethods=augmentMethods)
+ except SyntaxError as e:
+ raise ApiError('syntax_error',
+ f'Something is wrong with your python script '
+ f'please correct the following:'
+ f' {script}, {e.msg}')
+ except NameError as e:
+ raise ApiError('name_error',
+ f'something you are referencing does not exist:'
+ f' {script}, {e.name}')
+
+ # else:
+ # self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
+
+ # def run_predefined_script(self, task: SpiffTask, script, data):
+ # commands = shlex.split(script)
+ # path_and_command = commands[0].rsplit(".", 1)
+ # if len(path_and_command) == 1:
+ # module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
+ # class_name = path_and_command[0]
+ # else:
+ # module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
+ # class_name = path_and_command[1]
+ # try:
+ # mod = __import__(module_name, fromlist=[class_name])
+ # klass = getattr(mod, class_name)
+ # study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
+ # if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
+ # workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
+ # else:
+ # workflow_id = None
+ #
+ # if not isinstance(klass(), Script):
+ # raise ApiError.from_task("invalid_script",
+ # "This is an internal error. The script '%s:%s' you called " %
+ # (module_name, class_name) +
+ # "does not properly implement the CRC Script class.",
+ # task=task)
+ # if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
+ # """If this is running a validation, and not a normal process, then we want to
+ # mimic running the script, but not make any external calls or database changes."""
+ # klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
+ # else:
+ # klass().do_task(task, study_id, workflow_id, *commands[1:])
+ # except ModuleNotFoundError:
+ # raise ApiError.from_task("invalid_script",
+ # "Unable to locate Script: '%s:%s'" % (module_name, class_name),
+ # task=task)
def evaluate_expression(self, task, expression):
"""
@@ -180,10 +188,10 @@ class WorkflowProcessor(object):
bpmn_workflow = BpmnWorkflow(spec, script_engine=self._script_engine)
bpmn_workflow.data[WorkflowProcessor.STUDY_ID_KEY] = workflow_model.study_id
bpmn_workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY] = validate_only
- try:
- bpmn_workflow.do_engine_steps()
- except WorkflowException as we:
- raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
+ #try:
+ bpmn_workflow.do_engine_steps()
+ # except WorkflowException as we:
+ # raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
return bpmn_workflow
def save(self):
diff --git a/crc/static/bpmn/core_info/core_info.bpmn b/crc/static/bpmn/core_info/core_info.bpmn
index 8c69ffb3..9763ced6 100644
--- a/crc/static/bpmn/core_info/core_info.bpmn
+++ b/crc/static/bpmn/core_info/core_info.bpmn
@@ -212,7 +212,8 @@
SequenceFlow_1r3yrhy
Flow_09h1imz
- #! StudyInfo details
+ StudyInfo = {}
+StudyInfo['details'] = study_info('details')
Flow_09h1imz
diff --git a/crc/static/bpmn/data_security_plan/data_security_plan.bpmn b/crc/static/bpmn/data_security_plan/data_security_plan.bpmn
index 86426d6d..87b931b9 100644
--- a/crc/static/bpmn/data_security_plan/data_security_plan.bpmn
+++ b/crc/static/bpmn/data_security_plan/data_security_plan.bpmn
@@ -453,7 +453,7 @@ Indicate all the possible formats in which you will transmit your data outside o
SequenceFlow_0k2r83n
SequenceFlow_0t6xl9i
SequenceFlow_16kyite
- #! CompleteTemplate NEW_DSP_template.docx Study_DataSecurityPlan
+ complete_template('NEW_DSP_template.docx','Study_DataSecurityPlan')
##### Instructions
diff --git a/crc/static/bpmn/documents_approvals/documents_approvals.bpmn b/crc/static/bpmn/documents_approvals/documents_approvals.bpmn
index 12e85e34..c7130ee4 100644
--- a/crc/static/bpmn/documents_approvals/documents_approvals.bpmn
+++ b/crc/static/bpmn/documents_approvals/documents_approvals.bpmn
@@ -53,12 +53,13 @@
Flow_0c7ryff
Flow_142jtxs
- #! StudyInfo approvals
+ StudyInfo['approvals'] = study_info('approvals')
Flow_1k3su2q
Flow_0c7ryff
- #! StudyInfo documents
+ StudyInfo = {}
+StudyInfo['documents'] = study_info('documents')
diff --git a/crc/static/bpmn/ide_supplement/ide_supplement.bpmn b/crc/static/bpmn/ide_supplement/ide_supplement.bpmn
index 7a83643b..394a1d46 100644
--- a/crc/static/bpmn/ide_supplement/ide_supplement.bpmn
+++ b/crc/static/bpmn/ide_supplement/ide_supplement.bpmn
@@ -36,7 +36,8 @@
SequenceFlow_1dhb8f4
SequenceFlow_1uzcl1f
- #! StudyInfo details
+ StudyInfo = {}
+StudyInfo['details'] = study_info('details')
diff --git a/crc/static/bpmn/ids_full_submission/ids_full_submission.bpmn b/crc/static/bpmn/ids_full_submission/ids_full_submission.bpmn
index 25a9ad6e..4e940cf4 100644
--- a/crc/static/bpmn/ids_full_submission/ids_full_submission.bpmn
+++ b/crc/static/bpmn/ids_full_submission/ids_full_submission.bpmn
@@ -217,7 +217,8 @@ Protocol Owner: **(need to insert value here)**
SequenceFlow_1dexemq
Flow_1x9d2mo
- #! StudyInfo documents
+ StudyInfo = {}
+StudyInfo['documents'] = study_info('documents')
diff --git a/crc/static/bpmn/ind_update/ind_update.bpmn b/crc/static/bpmn/ind_update/ind_update.bpmn
index 528a87ce..1d288dc6 100644
--- a/crc/static/bpmn/ind_update/ind_update.bpmn
+++ b/crc/static/bpmn/ind_update/ind_update.bpmn
@@ -12,7 +12,8 @@
SequenceFlow_1dhb8f4
SequenceFlow_1uzcl1f
- #! StudyInfo details
+ StudyInfo = {}
+StudyInfo['details'] = study_info('details')
diff --git a/crc/static/bpmn/irb_api_details/irb_api_details.bpmn b/crc/static/bpmn/irb_api_details/irb_api_details.bpmn
index b4f540f5..9e0b6271 100644
--- a/crc/static/bpmn/irb_api_details/irb_api_details.bpmn
+++ b/crc/static/bpmn/irb_api_details/irb_api_details.bpmn
@@ -8,7 +8,8 @@
SequenceFlow_1fmyo77
SequenceFlow_18nr0gf
- #! StudyInfo details
+ StudyInfo = {}
+StudyInfo['details'] = study_info('details')
diff --git a/crc/static/bpmn/irb_api_personnel/irb_api_personnel.bpmn b/crc/static/bpmn/irb_api_personnel/irb_api_personnel.bpmn
index a5258cbe..c347fd93 100644
--- a/crc/static/bpmn/irb_api_personnel/irb_api_personnel.bpmn
+++ b/crc/static/bpmn/irb_api_personnel/irb_api_personnel.bpmn
@@ -7,7 +7,8 @@
Flow_0kcrx5l
Flow_1dcsioh
- #! StudyInfo investigators
+ StudyInfo = {}
+StudyInfo['investigators'] = study_info('investigators')
## The following information was gathered:
diff --git a/crc/static/bpmn/research_rampup/research_rampup.bpmn b/crc/static/bpmn/research_rampup/research_rampup.bpmn
index 4a04eb6d..eaa1dab7 100644
--- a/crc/static/bpmn/research_rampup/research_rampup.bpmn
+++ b/crc/static/bpmn/research_rampup/research_rampup.bpmn
@@ -598,7 +598,7 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
This step is internal to the system and do not require and user interaction
Flow_11uqavk
Flow_0aqgwvu
- #! CompleteTemplate ResearchRampUpPlan.docx RESEARCH_RAMPUP
+ complete_template('ResearchRampUpPlan.docx','RESEARCH_RAMPUP')
@@ -755,7 +755,7 @@ Notify the Area Monitor for
This step is internal to the system and do not require and user interaction
Flow_0j4rs82
Flow_07ge8uf
- #!RequestApproval ApprvlApprvr1 ApprvlApprvr2
+ request_approval('ApprvlApprvr1','ApprvlApprvr2')
#### Script Task
@@ -764,7 +764,7 @@ This step is internal to the system and do not require and user interaction
Flow_16y8glw
Flow_0uc4o6c
- #! UpdateStudy title:PIComputingID.label pi:PIComputingID.value
+ update_study('title:PIComputingID.label','pi:PIComputingID.value')
#### Weekly Personnel Schedule(s)
diff --git a/crc/static/bpmn/top_level_workflow/top_level_workflow.bpmn b/crc/static/bpmn/top_level_workflow/top_level_workflow.bpmn
index 23d6ff72..61e59156 100644
--- a/crc/static/bpmn/top_level_workflow/top_level_workflow.bpmn
+++ b/crc/static/bpmn/top_level_workflow/top_level_workflow.bpmn
@@ -11,7 +11,8 @@
SequenceFlow_1ees8ka
SequenceFlow_17ct47v
- #! StudyInfo documents
+ StudyInfo = {}
+StudyInfo['documents'] = study_info('documents')
Flow_1m8285h
@@ -62,7 +63,8 @@
Flow_0pwtiqm
Flow_0eq6px2
- #! StudyInfo details
+ StudyInfo = {}
+StudyInfo['details'] = study_info('details')
Flow_14ce1d7
@@ -91,7 +93,8 @@
Flow_1qyrmzn
Flow_0vo6ul1
- #! StudyInfo investigators
+ StudyInfo = {}
+StudyInfo['investigators'] = study_info('investigators')
diff --git a/tests/data/docx/docx.bpmn b/tests/data/docx/docx.bpmn
index 8c741114..fe11b7c5 100644
--- a/tests/data/docx/docx.bpmn
+++ b/tests/data/docx/docx.bpmn
@@ -27,7 +27,7 @@
SequenceFlow_1i7hk1a
SequenceFlow_11c35oq
- #! CompleteTemplate Letter.docx AD_CoCApp
+ complete_template('Letter.docx','AD_CoCApp')
SequenceFlow_11c35oq
diff --git a/tests/data/email/email.bpmn b/tests/data/email/email.bpmn
index 11ecec2e..3395e788 100644
--- a/tests/data/email/email.bpmn
+++ b/tests/data/email/email.bpmn
@@ -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/data/invalid_script/invalid_script.bpmn b/tests/data/invalid_script/invalid_script.bpmn
index b85e2bc4..af470aa1 100644
--- a/tests/data/invalid_script/invalid_script.bpmn
+++ b/tests/data/invalid_script/invalid_script.bpmn
@@ -11,7 +11,7 @@
SequenceFlow_1pnq3kg
SequenceFlow_12pf6um
- #! NoSuchScript withArg1
+ no_such_script('withArg1')
diff --git a/tests/data/ldap_replace/ldap_replace.bpmn b/tests/data/ldap_replace/ldap_replace.bpmn
index 77f8c7ad..64389299 100644
--- a/tests/data/ldap_replace/ldap_replace.bpmn
+++ b/tests/data/ldap_replace/ldap_replace.bpmn
@@ -10,7 +10,8 @@
Flow_08n2npe
Flow_1xlrgne
- #! LdapReplace Supervisor Investigator
+ Supervisor = ldap(Supervisor)
+Investigator = ldap(Investigator)
@@ -33,6 +34,10 @@
+
+
+
+
@@ -45,22 +50,18 @@
-
-
-
-
+
+
+
-
-
-
diff --git a/tests/data/multi_instance/multi_instance.bpmn b/tests/data/multi_instance/multi_instance.bpmn
index c1e610a5..50674246 100644
--- a/tests/data/multi_instance/multi_instance.bpmn
+++ b/tests/data/multi_instance/multi_instance.bpmn
@@ -29,7 +29,8 @@
Flow_0t6p1sb
SequenceFlow_1p568pp
- #! StudyInfo investigators
+ StudyInfo = {}
+StudyInfo['investigators'] = study_info('investigators')
diff --git a/tests/data/multi_instance_parallel/multi_instance_parallel.bpmn b/tests/data/multi_instance_parallel/multi_instance_parallel.bpmn
index d20c8499..0c31670e 100644
--- a/tests/data/multi_instance_parallel/multi_instance_parallel.bpmn
+++ b/tests/data/multi_instance_parallel/multi_instance_parallel.bpmn
@@ -11,7 +11,7 @@
# Please provide addtional information about:
-## Investigator ID: {{investigator.user_id}}
+## Investigator ID: {{investigator.user_id}}
## Role: {{investigator.type_full}}
@@ -29,7 +29,8 @@
Flow_0t6p1sb
SequenceFlow_1p568pp
- #! StudyInfo investigators
+ StudyInfo = {}
+StudyInfo['investigators'] = study_info('investigators')
diff --git a/tests/data/random_fact/random_fact.bpmn b/tests/data/random_fact/random_fact.bpmn
index d5ffcbed..6bee51b7 100644
--- a/tests/data/random_fact/random_fact.bpmn
+++ b/tests/data/random_fact/random_fact.bpmn
@@ -132,7 +132,7 @@ Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
SequenceFlow_0641sh6
SequenceFlow_0t29gjo
- #! FactService
+ FactService = fact_service()
# Great Job!
diff --git a/tests/data/study_details/study_details.bpmn b/tests/data/study_details/study_details.bpmn
index 2b46f935..62714433 100644
--- a/tests/data/study_details/study_details.bpmn
+++ b/tests/data/study_details/study_details.bpmn
@@ -8,12 +8,19 @@
SequenceFlow_1nfe5m9
SequenceFlow_1bqiin0
- #! StudyInfo info
+ StudyInfo = {}
+StudyInfo['info'] = study_info('info')
-
+
- SequenceFlow_1bqiin0
+ Flow_0ochvmi
+
+
+ SequenceFlow_1bqiin0
+ Flow_0ochvmi
+ study = study_info('info','p')
+
@@ -29,10 +36,17 @@
-
+
-
+
+
+
+
+
+
+
+
diff --git a/tests/data/top_level_workflow/top_level_workflow.bpmn b/tests/data/top_level_workflow/top_level_workflow.bpmn
index 8b1bb888..3cb74fd9 100644
--- a/tests/data/top_level_workflow/top_level_workflow.bpmn
+++ b/tests/data/top_level_workflow/top_level_workflow.bpmn
@@ -11,7 +11,8 @@
SequenceFlow_1ees8ka
SequenceFlow_17ct47v
- #! StudyInfo documents
+ StudyInfo = {}
+StudyInfo['documents'] = study_info('documents')
Flow_1m8285h
diff --git a/tests/ldap/test_ldap_lookup_script.py b/tests/ldap/test_ldap_lookup_script.py
index 220ca9c8..0a88a899 100644
--- a/tests/ldap/test_ldap_lookup_script.py
+++ b/tests/ldap/test_ldap_lookup_script.py
@@ -1,7 +1,8 @@
from tests.base_test import BaseTest
from crc.services.workflow_processor import WorkflowProcessor
-from crc.scripts.ldap_replace import LdapReplace
+from crc.scripts.ldap import Ldap
+from crc.api.common import ApiError
from crc import db, mail
@@ -14,60 +15,19 @@ class TestLdapLookupScript(BaseTest):
processor = WorkflowProcessor(workflow)
task = processor.next_task()
- task.data = {
- 'PIComputingID': 'dhf8r'
- }
+ script = Ldap()
+ user_details = script.do_task(task, workflow.study_id, workflow.id, "dhf8r")
- script = LdapReplace()
- user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
-
- self.assertEqual(task.data['PIComputingID']['display_name'], 'Dan Funk')
- self.assertEqual(task.data['PIComputingID']['given_name'], 'Dan')
- self.assertEqual(task.data['PIComputingID']['email_address'], 'dhf8r@virginia.edu')
- self.assertEqual(task.data['PIComputingID']['telephone_number'], '+1 (434) 924-1723')
- self.assertEqual(task.data['PIComputingID']['title'], 'E42:He\'s a hoopy frood')
- self.assertEqual(task.data['PIComputingID']['department'], 'E0:EN-Eng Study of Parallel Universes')
- self.assertEqual(task.data['PIComputingID']['affiliation'], 'faculty')
- self.assertEqual(task.data['PIComputingID']['sponsor_type'], 'Staff')
- self.assertEqual(task.data['PIComputingID']['uid'], 'dhf8r')
- self.assertEqual(task.data['PIComputingID']['proper_name'], 'Dan Funk - (dhf8r)')
-
- def test_get_existing_users_details(self):
- self.load_example_data()
- self.create_reference_document()
- workflow = self.create_workflow('empty_workflow')
- processor = WorkflowProcessor(workflow)
- task = processor.next_task()
-
- task.data = {
- 'supervisor': 'dhf8r',
- 'investigator': 'lb3dp'
- }
-
- script = LdapReplace()
- user_details = script.do_task(task, workflow.study_id, workflow.id, "supervisor", "investigator")
-
- self.assertEqual(task.data['supervisor']['display_name'], 'Dan Funk')
- self.assertEqual(task.data['supervisor']['given_name'], 'Dan')
- self.assertEqual(task.data['supervisor']['email_address'], 'dhf8r@virginia.edu')
- self.assertEqual(task.data['supervisor']['telephone_number'], '+1 (434) 924-1723')
- self.assertEqual(task.data['supervisor']['title'], 'E42:He\'s a hoopy frood')
- self.assertEqual(task.data['supervisor']['department'], 'E0:EN-Eng Study of Parallel Universes')
- self.assertEqual(task.data['supervisor']['affiliation'], 'faculty')
- self.assertEqual(task.data['supervisor']['sponsor_type'], 'Staff')
- self.assertEqual(task.data['supervisor']['uid'], 'dhf8r')
- self.assertEqual(task.data['supervisor']['proper_name'], 'Dan Funk - (dhf8r)')
-
- self.assertEqual(task.data['investigator']['display_name'], 'Laura Barnes')
- self.assertEqual(task.data['investigator']['given_name'], 'Laura')
- self.assertEqual(task.data['investigator']['email_address'], 'lb3dp@virginia.edu')
- self.assertEqual(task.data['investigator']['telephone_number'], '+1 (434) 924-1723')
- self.assertEqual(task.data['investigator']['title'], 'E0:Associate Professor of Systems and Information Engineering')
- self.assertEqual(task.data['investigator']['department'], 'E0:EN-Eng Sys and Environment')
- self.assertEqual(task.data['investigator']['affiliation'], 'faculty')
- self.assertEqual(task.data['investigator']['sponsor_type'], 'Staff')
- self.assertEqual(task.data['investigator']['uid'], 'lb3dp')
- self.assertEqual(task.data['investigator']['proper_name'], 'Laura Barnes - (lb3dp)')
+ self.assertEqual(user_details['display_name'], 'Dan Funk')
+ self.assertEqual(user_details['given_name'], 'Dan')
+ self.assertEqual(user_details['email_address'], 'dhf8r@virginia.edu')
+ self.assertEqual(user_details['telephone_number'], '+1 (434) 924-1723')
+ self.assertEqual(user_details['title'], 'E42:He\'s a hoopy frood')
+ self.assertEqual(user_details['department'], 'E0:EN-Eng Study of Parallel Universes')
+ self.assertEqual(user_details['affiliation'], 'faculty')
+ self.assertEqual(user_details['sponsor_type'], 'Staff')
+ self.assertEqual(user_details['uid'], 'dhf8r')
+ self.assertEqual(user_details['proper_name'], 'Dan Funk - (dhf8r)')
def test_get_invalid_user_details(self):
self.load_example_data()
@@ -80,10 +40,10 @@ class TestLdapLookupScript(BaseTest):
'PIComputingID': 'rec3z'
}
- script = LdapReplace()
- user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
+ script = Ldap()
+ with(self.assertRaises(ApiError)):
+ user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
- self.assertEqual(task.data['PIComputingID'], {})
def test_bpmn_task_receives_user_details(self):
workflow = self.create_workflow('ldap_replace')
diff --git a/tests/workflow/test_workflow_spec_validation_api.py b/tests/workflow/test_workflow_spec_validation_api.py
index 0c17892e..29fd5a14 100644
--- a/tests/workflow/test_workflow_spec_validation_api.py
+++ b/tests/workflow/test_workflow_spec_validation_api.py
@@ -89,8 +89,8 @@ class TestWorkflowSpecValidation(BaseTest):
self.load_example_data()
errors = self.validate_workflow("invalid_script")
self.assertEqual(2, len(errors))
- self.assertEqual("error_loading_workflow", errors[0]['code'])
- self.assertTrue("NoSuchScript" in errors[0]['message'])
+ self.assertEqual("workflow_validation_exception", errors[0]['code'])
+ #self.assertTrue("NoSuchScript" in errors[0]['message'])
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
self.assertEqual("invalid_script.bpmn", errors[0]['file_name'])
@@ -99,7 +99,7 @@ class TestWorkflowSpecValidation(BaseTest):
self.load_example_data()
errors = self.validate_workflow("invalid_script2")
self.assertEqual(2, len(errors))
- self.assertEqual("error_loading_workflow", errors[0]['code'])
+ self.assertEqual("workflow_validation_exception", errors[0]['code'])
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
self.assertEqual("invalid_script2.bpmn", errors[0]['file_name'])