run_pyl had various recommendations that I find a bit of a pain in the butt, but that I did anyway.
This commit is contained in:
parent
a38ecc2e60
commit
b2fb0dd79f
|
@ -10,15 +10,15 @@ from typing import Union
|
|||
|
||||
import flask.wrappers
|
||||
import jinja2
|
||||
from SpiffWorkflow.exceptions import WorkflowTaskException
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import jsonify
|
||||
from flask import make_response
|
||||
from flask.wrappers import Response
|
||||
from jinja2 import TemplateSyntaxError
|
||||
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
|
||||
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
|
||||
from SpiffWorkflow.task import TaskState
|
||||
from jinja2 import TemplateSyntaxError
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy import asc
|
||||
from sqlalchemy import desc
|
||||
|
@ -293,9 +293,11 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
|
|||
task.properties["instructionsForEndUser"] = _render_jinja_template(
|
||||
task.properties["instructionsForEndUser"], spiff_task
|
||||
)
|
||||
except WorkflowTaskException as wfe:
|
||||
except WorkflowTaskException as wfe:
|
||||
wfe.add_note("Failed to render instructions for end user.")
|
||||
raise ApiError.from_workflow_exception("instructions_error", str(wfe), exp=wfe)
|
||||
raise ApiError.from_workflow_exception(
|
||||
"instructions_error", str(wfe), exp=wfe
|
||||
) from wfe
|
||||
return make_response(jsonify(task), 200)
|
||||
|
||||
|
||||
|
@ -518,10 +520,13 @@ def _prepare_form_data(
|
|||
return _render_jinja_template(file_contents, spiff_task)
|
||||
except WorkflowTaskException as wfe:
|
||||
wfe.add_note(f"Error in Json Form File '{form_file}'")
|
||||
api_error = ApiError.from_workflow_exception("instructions_error", str(wfe), exp=wfe)
|
||||
api_error = ApiError.from_workflow_exception(
|
||||
"instructions_error", str(wfe), exp=wfe
|
||||
)
|
||||
api_error.file_name = form_file
|
||||
raise api_error
|
||||
|
||||
|
||||
def _render_jinja_template(unprocessed_template: str, spiff_task: SpiffTask) -> str:
|
||||
"""Render_jinja_template."""
|
||||
jinja_environment = jinja2.Environment(
|
||||
|
@ -531,11 +536,17 @@ def _render_jinja_template(unprocessed_template: str, spiff_task: SpiffTask) ->
|
|||
template = jinja_environment.from_string(unprocessed_template)
|
||||
return template.render(**spiff_task.data)
|
||||
except jinja2.exceptions.TemplateError as template_error:
|
||||
wfe = WorkflowTaskException(str(template_error), task=spiff_task, exception=template_error)
|
||||
wfe = WorkflowTaskException(
|
||||
str(template_error), task=spiff_task, exception=template_error
|
||||
)
|
||||
if isinstance(template_error, TemplateSyntaxError):
|
||||
wfe.line_number = template_error.lineno
|
||||
wfe.error_line = template_error.source.split('\n')[template_error.lineno - 1]
|
||||
wfe.add_note("Jinja2 template errors can happen when trying to displaying task data")
|
||||
wfe.error_line = template_error.source.split("\n")[
|
||||
template_error.lineno - 1
|
||||
]
|
||||
wfe.add_note(
|
||||
"Jinja2 template errors can happen when trying to displaying task data"
|
||||
)
|
||||
raise wfe from template_error
|
||||
|
||||
|
||||
|
@ -582,14 +593,19 @@ def _update_form_schema_with_task_data_as_needed(
|
|||
|
||||
if task_data_var not in task.data:
|
||||
wte = WorkflowTaskException(
|
||||
f"Error building form. Attempting to create a selection list"
|
||||
f" with options from variable '{task_data_var}' but it doesn't"
|
||||
f" exist in the Task Data.", task=task)
|
||||
(
|
||||
"Error building form. Attempting to create a"
|
||||
" selection list with options from variable"
|
||||
f" '{task_data_var}' but it doesn't exist in"
|
||||
" the Task Data."
|
||||
),
|
||||
task=task,
|
||||
)
|
||||
raise (
|
||||
ApiError.from_workflow_exception(
|
||||
error_code="missing_task_data_var",
|
||||
message=str(wte),
|
||||
exp=wte
|
||||
exp=wte,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -873,7 +873,10 @@ class ProcessInstanceProcessor:
|
|||
f"Event of type {event_definition.event_type} sent to process instance"
|
||||
f" {self.process_instance_model.id}"
|
||||
)
|
||||
self.bpmn_process_instance.catch(event_definition)
|
||||
try:
|
||||
self.bpmn_process_instance.catch(event_definition)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.do_engine_steps(save=True)
|
||||
|
||||
def add_step(self, step: Union[dict, None] = None) -> None:
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
"""Test_various_bpmn_constructs."""
|
||||
from typing import Any
|
||||
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend import db
|
||||
from spiffworkflow_backend.models.human_task import HumanTaskModel
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
|
||||
class TestForGoodErrors(BaseTest):
|
||||
"""Assure when certain errors happen when rendering a jinaj2 error that it makes
|
||||
some sense."""
|
||||
"""Assure when certain errors happen when rendering a jinaj2 error that it makes some sense."""
|
||||
|
||||
def get_next_user_task(self, process_instance_id: int,
|
||||
client: FlaskClient,
|
||||
with_super_admin_user: UserModel,
|
||||
):
|
||||
def get_next_user_task(
|
||||
self,
|
||||
process_instance_id: int,
|
||||
client: FlaskClient,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> Any:
|
||||
"""Returns the next available user task for a given process instance, if possible."""
|
||||
human_tasks = (
|
||||
db.session.query(HumanTaskModel)
|
||||
.filter(HumanTaskModel.process_instance_id == process_instance_id)
|
||||
.all()
|
||||
.filter(HumanTaskModel.process_instance_id == process_instance_id)
|
||||
.all()
|
||||
)
|
||||
assert len(human_tasks) > 0, "No human tasks found for process."
|
||||
human_task = human_tasks[0]
|
||||
|
@ -30,12 +35,13 @@ class TestForGoodErrors(BaseTest):
|
|||
return response
|
||||
|
||||
def test_invalid_form(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""React json form schema with bad jinja syntax provides good error."""
|
||||
process_model = load_test_spec(
|
||||
process_model_id="group/simple_form_with_error",
|
||||
process_model_source_directory="simple_form_with_error",
|
||||
|
@ -53,13 +59,15 @@ class TestForGoodErrors(BaseTest):
|
|||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
response = self.get_next_user_task(process_instance_id, client, with_super_admin_user)
|
||||
response = self.get_next_user_task(
|
||||
process_instance_id, client, with_super_admin_user
|
||||
)
|
||||
assert response.json is not None
|
||||
assert response.json['error_type'] == 'TemplateSyntaxError'
|
||||
assert response.json['line_number'] == 3
|
||||
assert response.json['file_name'] == 'simple_form.json'
|
||||
assert response.json["error_type"] == "TemplateSyntaxError"
|
||||
assert response.json["line_number"] == 3
|
||||
assert response.json["file_name"] == "simple_form.json"
|
||||
|
||||
def test_jinja2_error_message_for_end_user_instructions (
|
||||
def test_jinja2_error_message_for_end_user_instructions(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
|
@ -80,14 +88,16 @@ class TestForGoodErrors(BaseTest):
|
|||
f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model.id)}/{process_instance.id}/run",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
)
|
||||
response = self.get_next_user_task(process_instance.id, client, with_super_admin_user)
|
||||
response = self.get_next_user_task(
|
||||
process_instance.id, client, with_super_admin_user
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert response.json is not None
|
||||
assert response.json['error_type'] == 'TemplateSyntaxError'
|
||||
assert response.json['line_number'] == 3
|
||||
assert response.json['error_line'] == '{{ x +=- 1}}'
|
||||
assert response.json['file_name'] == 'instructions_error.bpmn'
|
||||
assert 'instructions for end user' in response.json['message']
|
||||
assert 'Jinja2' in response.json['message']
|
||||
assert 'unexpected \'=\'' in response.json['message']
|
||||
assert response.json["error_type"] == "TemplateSyntaxError"
|
||||
assert response.json["line_number"] == 3
|
||||
assert response.json["error_line"] == "{{ x +=- 1}}"
|
||||
assert response.json["file_name"] == "instructions_error.bpmn"
|
||||
assert "instructions for end user" in response.json["message"]
|
||||
assert "Jinja2" in response.json["message"]
|
||||
assert "unexpected '='" in response.json["message"]
|
||||
|
|
|
@ -2806,7 +2806,7 @@ class TestProcessApi(BaseTest):
|
|||
)
|
||||
|
||||
data = {
|
||||
"dateTime": "timedelta(hours=1)",
|
||||
"dateTime": "PT1H",
|
||||
"external": True,
|
||||
"internal": True,
|
||||
"label": "Event_0e4owa3",
|
||||
|
|
|
@ -59,11 +59,7 @@ export default function ErrorDisplay() {
|
|||
}
|
||||
|
||||
errorTag = (
|
||||
<Notification
|
||||
title={title}
|
||||
onClose={() => (removeError())}
|
||||
type="error"
|
||||
>
|
||||
<Notification title={title} onClose={() => removeError()} type="error">
|
||||
{message}
|
||||
<br />
|
||||
{sentryLinkTag}
|
||||
|
|
|
@ -115,11 +115,11 @@ export default function ProcessInstanceRun({
|
|||
};
|
||||
|
||||
const processInstanceCreateAndRun = () => {
|
||||
setErrorObject(null);
|
||||
removeError();
|
||||
HttpService.makeCallToBackend({
|
||||
path: processInstanceCreatePath,
|
||||
successCallback: processModelRun,
|
||||
failureCallback: setErrorObject,
|
||||
failureCallback: addError,
|
||||
httpMethod: 'POST',
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createContext, useState, useCallback } from 'react';
|
||||
import React, { createContext, useState } from 'react';
|
||||
import { ErrorForDisplay } from '../interfaces';
|
||||
|
||||
type ErrorContextType = {
|
||||
|
@ -28,7 +28,7 @@ export default function APIErrorProvider({ children }) {
|
|||
addError: (newError: ErrorForDisplay | null) => addError(newError),
|
||||
removeError: () => removeError(),
|
||||
}),
|
||||
[error, addError, removeError]
|
||||
[error]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,6 @@ import {
|
|||
DEFAULT_PER_PAGE,
|
||||
DEFAULT_PAGE,
|
||||
} from './components/PaginationForTable';
|
||||
import { ErrorForDisplay } from './interfaces';
|
||||
|
||||
// https://www.30secondsofcode.org/js/s/slugify
|
||||
export const slugifyString = (str: any) => {
|
||||
|
|
|
@ -26,7 +26,7 @@ export default function Configuration() {
|
|||
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Configuration remove error")
|
||||
console.log('Configuration remove error');
|
||||
removeError();
|
||||
let newSelectedTabIndex = 0;
|
||||
if (location.pathname.match(/^\/admin\/configuration\/authentications\b/)) {
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
|||
// @ts-ignore
|
||||
import { Tabs, TabList, Tab } from '@carbon/react';
|
||||
import TaskShow from './TaskShow';
|
||||
import useAPIError from '../hooks/UseApiError';
|
||||
import MyTasks from './MyTasks';
|
||||
import GroupedTasks from './GroupedTasks';
|
||||
import CompletedInstances from './CompletedInstances';
|
||||
|
@ -11,7 +10,6 @@ import CreateNewInstance from './CreateNewInstance';
|
|||
|
||||
export default function HomePageRoutes() {
|
||||
const location = useLocation();
|
||||
const { removeError } = useAPIError();
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
|
|
@ -717,7 +717,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
setSelectingEvent(false);
|
||||
initializeTaskDataToDisplay(taskToDisplay);
|
||||
setEventPayload('{}');
|
||||
console.log("cancel updating task")
|
||||
console.log('cancel updating task');
|
||||
removeError();
|
||||
};
|
||||
|
||||
|
@ -737,7 +737,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||
if (!taskToDisplay) {
|
||||
return;
|
||||
}
|
||||
console.log("saveTaskData")
|
||||
console.log('saveTaskData');
|
||||
removeError();
|
||||
|
||||
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
|
||||
|
|
Loading…
Reference in New Issue