flake8 and mypy fixes w/ burnettk

This commit is contained in:
jasquat 2023-04-20 13:01:05 -04:00
parent 48ff72b00b
commit f082f0966c
10 changed files with 55 additions and 50 deletions

View File

@ -1,9 +1,11 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional from typing import Optional
from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
@dataclass @dataclass
@ -12,7 +14,7 @@ class ProcessInstanceErrorDetailModel(SpiffworkflowBaseDBModel):
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
process_instance_event_id: int = db.Column(ForeignKey("process_instance_event.id"), nullable=False, index=True) process_instance_event_id: int = db.Column(ForeignKey("process_instance_event.id"), nullable=False, index=True)
process_instance_event = relationship('ProcessInstanceEventModel') # type: ignore process_instance_event = relationship("ProcessInstanceEventModel") # type: ignore
message: str = db.Column(db.String(1024), nullable=False) message: str = db.Column(db.String(1024), nullable=False)

View File

@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
from sqlalchemy.orm import relationship
from typing import Any from typing import Any
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.orm import validates from sqlalchemy.orm import validates
from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum

View File

@ -1,11 +1,11 @@
from typing import Optional from typing import Optional
from spiffworkflow_backend.exceptions.api_error import ApiError
import flask.wrappers import flask.wrappers
from flask import jsonify from flask import jsonify
from flask import make_response from flask import make_response
from sqlalchemy import and_ from sqlalchemy import and_
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel

View File

@ -1,11 +1,6 @@
from typing import Union
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.services.task_service import TaskService
from flask import current_app from flask import current_app
from flask import g from flask import g
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
@ -35,7 +30,9 @@ class ErrorHandlingService:
current_app.logger.error(e) current_app.logger.error(e)
@classmethod @classmethod
def _update_process_instance_in_database(cls, process_instance: ProcessInstanceModel, fault_or_suspend_on_exception: str) -> None: def _update_process_instance_in_database(
cls, process_instance: ProcessInstanceModel, fault_or_suspend_on_exception: str
) -> None:
# First, suspend or fault the instance # First, suspend or fault the instance
if fault_or_suspend_on_exception == "suspend": if fault_or_suspend_on_exception == "suspend":
cls._set_instance_status( cls._set_instance_status(

View File

@ -1,10 +1,7 @@
"""Process_instance_processor.""" """Process_instance_processor."""
# TODO: clean up this service for a clear distinction between it and the process_instance_service # TODO: clean up this service for a clear distinction between it and the process_instance_service
# where this points to the pi service # where this points to the pi service
import traceback
import _strptime # type: ignore import _strptime # type: ignore
from spiffworkflow_backend.models.process_instance_error_detail import ProcessInstanceErrorDetailModel
import copy import copy
import decimal import decimal
import json import json
@ -29,7 +26,6 @@ from uuid import UUID
import dateparser import dateparser
import pytz import pytz
from flask import current_app from flask import current_app
from flask import g
from lxml import etree # type: ignore from lxml import etree # type: ignore
from lxml.etree import XMLSyntaxError # type: ignore from lxml.etree import XMLSyntaxError # type: ignore
from RestrictedPython import safe_globals # type: ignore from RestrictedPython import safe_globals # type: ignore
@ -80,7 +76,6 @@ from spiffworkflow_backend.models.message_instance_correlation import (
) )
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.models.process_instance_metadata import ( from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel, ProcessInstanceMetadataModel,
@ -107,10 +102,8 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
from spiffworkflow_backend.services.task_service import JsonDataDict from spiffworkflow_backend.services.task_service import JsonDataDict
from spiffworkflow_backend.services.task_service import TaskService from spiffworkflow_backend.services.task_service import TaskService
from spiffworkflow_backend.services.user_service import UserService from spiffworkflow_backend.services.user_service import UserService
from spiffworkflow_backend.services.workflow_execution_service import ( from spiffworkflow_backend.services.workflow_execution_service import execution_strategy_named
ExecutionStrategyNotConfiguredError, from spiffworkflow_backend.services.workflow_execution_service import ExecutionStrategyNotConfiguredError
execution_strategy_named,
)
from spiffworkflow_backend.services.workflow_execution_service import ( from spiffworkflow_backend.services.workflow_execution_service import (
TaskModelSavingDelegate, TaskModelSavingDelegate,
) )
@ -228,6 +221,7 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
self.state.update(context) self.state.update(context)
try: try:
exec(script, self.state) # noqa exec(script, self.state) # noqa
return True
finally: finally:
# since the task data is not directly mutated when the script executes, need to determine which keys # since the task data is not directly mutated when the script executes, need to determine which keys
# have been deleted from the environment and remove them from task data if present. # have been deleted from the environment and remove them from task data if present.
@ -241,7 +235,6 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
# the task data needs to be updated with the current state so data references can be resolved properly. # the task data needs to be updated with the current state so data references can be resolved properly.
# the state will be removed later once the task is completed. # the state will be removed later once the task is completed.
context.update(self.state) context.update(self.state)
return True
def user_defined_state(self, external_methods: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: def user_defined_state(self, external_methods: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
keys_to_filter = self.non_user_defined_keys keys_to_filter = self.non_user_defined_keys
@ -1682,7 +1675,9 @@ class ProcessInstanceProcessor:
if execution_strategy_name is None: if execution_strategy_name is None:
execution_strategy_name = current_app.config["SPIFFWORKFLOW_BACKEND_ENGINE_STEP_DEFAULT_STRATEGY_WEB"] execution_strategy_name = current_app.config["SPIFFWORKFLOW_BACKEND_ENGINE_STEP_DEFAULT_STRATEGY_WEB"]
if execution_strategy_name is None: if execution_strategy_name is None:
raise ExecutionStrategyNotConfiguredError("SPIFFWORKFLOW_BACKEND_ENGINE_STEP_DEFAULT_STRATEGY_WEB has not been set") raise ExecutionStrategyNotConfiguredError(
"SPIFFWORKFLOW_BACKEND_ENGINE_STEP_DEFAULT_STRATEGY_WEB has not been set"
)
execution_strategy = execution_strategy_named(execution_strategy_name, task_model_delegate) execution_strategy = execution_strategy_named(execution_strategy_name, task_model_delegate)
execution_service = WorkflowExecutionService( execution_service = WorkflowExecutionService(

View File

@ -1,8 +1,5 @@
import contextlib import contextlib
import time import time
from spiffworkflow_backend.services.workflow_execution_service import WorkflowExecutionServiceError
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.services.task_service import TaskService
from typing import Generator from typing import Generator
from typing import List from typing import List
from typing import Optional from typing import Optional
@ -10,12 +7,15 @@ from typing import Optional
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.models.process_instance_queue import ( from spiffworkflow_backend.models.process_instance_queue import (
ProcessInstanceQueueModel, ProcessInstanceQueueModel,
) )
from spiffworkflow_backend.services.process_instance_lock_service import ( from spiffworkflow_backend.services.process_instance_lock_service import (
ProcessInstanceLockService, ProcessInstanceLockService,
) )
from spiffworkflow_backend.services.task_service import TaskService
from spiffworkflow_backend.services.workflow_execution_service import WorkflowExecutionServiceError
class ProcessInstanceIsNotEnqueuedError(Exception): class ProcessInstanceIsNotEnqueuedError(Exception):
@ -103,7 +103,9 @@ class ProcessInstanceQueueService:
# these events are handled in the WorkflowExecutionService. # these events are handled in the WorkflowExecutionService.
# that is, we don't need to add error_detail records here, etc. # that is, we don't need to add error_detail records here, etc.
if not isinstance(ex, WorkflowExecutionServiceError): if not isinstance(ex, WorkflowExecutionServiceError):
TaskService.add_event_to_process_instance(process_instance, ProcessInstanceEventType.process_instance_error.value, exception=ex) TaskService.add_event_to_process_instance(
process_instance, ProcessInstanceEventType.process_instance_error.value, exception=ex
)
db.session.commit() db.session.commit()
raise ex raise ex
finally: finally:

View File

@ -127,7 +127,9 @@ class ProcessInstanceService:
current_app.logger.error(error_message) current_app.logger.error(error_message)
@classmethod @classmethod
def run_process_intance_with_processor(cls, process_instance: ProcessInstanceModel, status_value: Optional[str] = None) -> Optional[ProcessInstanceProcessor]: def run_process_intance_with_processor(
cls, process_instance: ProcessInstanceModel, status_value: Optional[str] = None
) -> Optional[ProcessInstanceProcessor]:
processor = None processor = None
with ProcessInstanceQueueService.dequeued(process_instance): with ProcessInstanceQueueService.dequeued(process_instance):
processor = ProcessInstanceProcessor(process_instance) processor = ProcessInstanceProcessor(process_instance)

View File

@ -1,12 +1,7 @@
import copy import copy
import json import json
from spiffworkflow_backend.exceptions.api_error import ApiError
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
from flask import g
from spiffworkflow_backend.models import process_instance_error_detail
from spiffworkflow_backend.models.process_instance_error_detail import ProcessInstanceErrorDetailModel
import traceback
import time import time
import traceback
from hashlib import sha256 from hashlib import sha256
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
@ -14,19 +9,23 @@ from typing import TypedDict
from uuid import UUID from uuid import UUID
from flask import current_app from flask import current_app
from flask import g
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflow # type: ignore from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflow # type: ignore
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from SpiffWorkflow.task import TaskState from SpiffWorkflow.task import TaskState
from SpiffWorkflow.task import TaskStateNames from SpiffWorkflow.task import TaskStateNames
from sqlalchemy.dialects.mysql import insert as mysql_insert from sqlalchemy.dialects.mysql import insert as mysql_insert
from sqlalchemy.dialects.postgresql import insert as postgres_insert from sqlalchemy.dialects.postgresql import insert as postgres_insert
from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel
from spiffworkflow_backend.models.bpmn_process import BpmnProcessNotFoundError from spiffworkflow_backend.models.bpmn_process import BpmnProcessNotFoundError
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401 from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance_error_detail import ProcessInstanceErrorDetailModel
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.models.task import TaskModel # noqa: F401 from spiffworkflow_backend.models.task import TaskModel # noqa: F401
@ -162,7 +161,13 @@ class TaskService:
if task_model.state == "COMPLETED": if task_model.state == "COMPLETED":
event_type = ProcessInstanceEventType.task_completed.value event_type = ProcessInstanceEventType.task_completed.value
timestamp = task_model.end_in_seconds or task_model.start_in_seconds or time.time() timestamp = task_model.end_in_seconds or task_model.start_in_seconds or time.time()
process_instance_event, _process_instance_error_detail = TaskService.add_event_to_process_instance(self.process_instance, event_type, task_guid=task_model.guid, timestamp=timestamp, add_to_db_session=False) process_instance_event, _process_instance_error_detail = TaskService.add_event_to_process_instance(
self.process_instance,
event_type,
task_guid=task_model.guid,
timestamp=timestamp,
add_to_db_session=False,
)
self.process_instance_events[task_model.guid] = process_instance_event self.process_instance_events[task_model.guid] = process_instance_event
self.update_bpmn_process(spiff_task.workflow, bpmn_process) self.update_bpmn_process(spiff_task.workflow, bpmn_process)
@ -625,7 +630,9 @@ class TaskService:
task_line_contents = None task_line_contents = None
task_trace = None task_trace = None
task_offset = None task_offset = None
if isinstance(exception, WorkflowTaskException) or (isinstance(exception, ApiError) and exception.error_code == 'task_error'): if isinstance(exception, WorkflowTaskException) or (
isinstance(exception, ApiError) and exception.error_code == "task_error"
):
task_line_number = exception.line_number task_line_number = exception.line_number
task_line_contents = exception.error_line task_line_contents = exception.error_line
task_trace = exception.task_trace task_trace = exception.task_trace

View File

@ -1,18 +1,15 @@
from __future__ import annotations from __future__ import annotations
import copy import copy
import time import time
from abc import abstractmethod from abc import abstractmethod
from typing import Type, TypeVar
from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from typing import Callable from typing import Callable
from typing import Optional
from typing import Set
from uuid import UUID from uuid import UUID
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer # type: ignore from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer # type: ignore
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore
from SpiffWorkflow.exceptions import SpiffWorkflowException # type: ignore from SpiffWorkflow.exceptions import SpiffWorkflowException # type: ignore
from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from SpiffWorkflow.task import TaskState from SpiffWorkflow.task import TaskState
@ -23,7 +20,7 @@ from spiffworkflow_backend.models.message_instance_correlation import (
MessageInstanceCorrelationRuleModel, MessageInstanceCorrelationRuleModel,
) )
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.task_definition import TaskDefinitionModel # noqa: F401 from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
from spiffworkflow_backend.services.assertion_service import safe_assertion from spiffworkflow_backend.services.assertion_service import safe_assertion
from spiffworkflow_backend.services.process_instance_lock_service import ( from spiffworkflow_backend.services.process_instance_lock_service import (
ProcessInstanceLockService, ProcessInstanceLockService,
@ -32,8 +29,6 @@ from spiffworkflow_backend.services.task_service import StartAndEndTimes
from spiffworkflow_backend.services.task_service import TaskService from spiffworkflow_backend.services.task_service import TaskService
class WorkflowExecutionServiceError(WorkflowTaskException): # type: ignore class WorkflowExecutionServiceError(WorkflowTaskException): # type: ignore
@classmethod @classmethod
def from_workflow_task_exception( def from_workflow_task_exception(
@ -107,17 +102,17 @@ class TaskModelSavingDelegate(EngineStepDelegate):
serializer: BpmnWorkflowSerializer, serializer: BpmnWorkflowSerializer,
process_instance: ProcessInstanceModel, process_instance: ProcessInstanceModel,
bpmn_definition_to_task_definitions_mappings: dict, bpmn_definition_to_task_definitions_mappings: dict,
secondary_engine_step_delegate: Optional[EngineStepDelegate] = None, secondary_engine_step_delegate: EngineStepDelegate | None = None,
) -> None: ) -> None:
self.secondary_engine_step_delegate = secondary_engine_step_delegate self.secondary_engine_step_delegate = secondary_engine_step_delegate
self.process_instance = process_instance self.process_instance = process_instance
self.bpmn_definition_to_task_definitions_mappings = bpmn_definition_to_task_definitions_mappings self.bpmn_definition_to_task_definitions_mappings = bpmn_definition_to_task_definitions_mappings
self.serializer = serializer self.serializer = serializer
self.current_task_start_in_seconds: Optional[float] = None self.current_task_start_in_seconds: float | None = None
self.last_completed_spiff_task: Optional[SpiffTask] = None self.last_completed_spiff_task: SpiffTask | None = None
self.spiff_tasks_to_process: Set[UUID] = set() self.spiff_tasks_to_process: set[UUID] = set()
self.spiff_task_timestamps: dict[UUID, StartAndEndTimes] = {} self.spiff_task_timestamps: dict[UUID, StartAndEndTimes] = {}
self.task_service = TaskService( self.task_service = TaskService(
@ -364,9 +359,14 @@ class WorkflowExecutionService:
self.process_bpmn_messages() self.process_bpmn_messages()
self.queue_waiting_receive_messages() self.queue_waiting_receive_messages()
except WorkflowTaskException as wte: except WorkflowTaskException as wte:
TaskService.add_event_to_process_instance(self.process_instance_model, ProcessInstanceEventType.task_failed.value, exception=wte, task_guid=str(wte.task.id)) TaskService.add_event_to_process_instance(
self.process_instance_model,
ProcessInstanceEventType.task_failed.value,
exception=wte,
task_guid=str(wte.task.id),
)
self.execution_strategy.on_exception(self.bpmn_process_instance) self.execution_strategy.on_exception(self.bpmn_process_instance)
raise WorkflowExecutionServiceError.from_workflow_task_exception(wte) raise WorkflowExecutionServiceError.from_workflow_task_exception(wte) from wte
except SpiffWorkflowException as swe: except SpiffWorkflowException as swe:
self.execution_strategy.on_exception(self.bpmn_process_instance) self.execution_strategy.on_exception(self.bpmn_process_instance)
raise ApiError.from_workflow_exception("task_error", str(swe), swe) from swe raise ApiError.from_workflow_exception("task_error", str(swe), swe) from swe

View File

@ -36,7 +36,7 @@ class TestErrorHandlingService(BaseTest):
pip = ProcessInstanceProcessor(process_instance) pip = ProcessInstanceProcessor(process_instance)
with pytest.raises(ApiError) as e: with pytest.raises(ApiError) as e:
pip.do_engine_steps(save=True) pip.do_engine_steps(save=True)
ErrorHandlingService().handle_error(pip, e.value) ErrorHandlingService().handle_error(process_instance, e.value)
return process_instance return process_instance
def test_handle_error_suspends_or_faults_process( def test_handle_error_suspends_or_faults_process(