diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py index 68feded2a..630e381ad 100644 --- a/spiffworkflow-backend/migrations/env.py +++ b/spiffworkflow-backend/migrations/env.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - import logging from logging.config import fileConfig diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 064b7e06a..dfea2ce81 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -375,7 +375,7 @@ paths: /processes: get: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_list - summary: Return a list of all processes (not just primary process of a process model) + summary: Return a list of all processes (not just primary process of a process model) useful for finding processes for call activites. tags: - Process Models diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py index 7075e417f..449c145d9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py @@ -63,8 +63,6 @@ CONTENT_TYPES = { } - - @dataclass(order=True) class File: """File.""" @@ -131,6 +129,3 @@ class FileSchema(Schema): references = marshmallow.fields.List( marshmallow.fields.Nested("SpecReferenceSchema") ) - - - diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py index 525641366..810cbc440 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py @@ -18,21 +18,21 @@ class SpecReference: """ identifier: str # The id of the process or decision. "Process_1234" - display_name: str # The name of the process or decision. "Invoice Submission" + display_name: str # The name of the process or decision. "Invoice Submission" process_model_id: str type: str # can be 'process' or 'decision' - file_name: str # The name of the file where this process or decision is defined. - relative_path: str # The path to the file. - has_lanes: bool # If this is a process, whether it has lanes or not. - is_executable: bool # Whether this process or decision is designated as executable. - is_primary: bool # Whether this is the primary process of a process model - messages: dict # Any messages defined in the same file where this process is defined. - correlations: dict # Any correlations defined in the same file with this process. - start_messages: list # The names of any messages that would start this process. + file_name: str # The name of the file where this process or decision is defined. + relative_path: str # The path to the file. + has_lanes: bool # If this is a process, whether it has lanes or not. + is_executable: bool # Whether this process or decision is designated as executable. + is_primary: bool # Whether this is the primary process of a process model + messages: dict # Any messages defined in the same file where this process is defined. + correlations: dict # Any correlations defined in the same file with this process. + start_messages: list # The names of any messages that would start this process. class SpecReferenceCache(SpiffworkflowBaseDBModel): - """A cache of information about all the Processes and Decisions defined in all files. """ + """A cache of information about all the Processes and Decisions defined in all files.""" __tablename__ = "spec_reference_cache" @@ -49,16 +49,18 @@ class SpecReferenceCache(SpiffworkflowBaseDBModel): @classmethod def from_spec_reference(cls, ref): + """From_spec_reference.""" return cls( - identifier=ref.identifier, - display_name=ref.display_name, - process_model_id=ref.process_model_id, - type=ref.type, - file_name=ref.file_name, - has_lanes=ref.has_lanes, - is_executable=ref.is_executable, - is_primary=ref.is_primary, - relative_path=ref.relative_path,) + identifier=ref.identifier, + display_name=ref.display_name, + process_model_id=ref.process_model_id, + type=ref.type, + file_name=ref.file_name, + has_lanes=ref.has_lanes, + is_executable=ref.is_executable, + is_primary=ref.is_primary, + relative_path=ref.relative_path, + ) class SpecReferenceSchema(Schema): @@ -68,8 +70,15 @@ class SpecReferenceSchema(Schema): """Meta.""" model = SpecReference - fields = ["identifier", "display_name", - "process_group_id", "process_model_id", - "type", "file_name", "has_lanes", - "is_executable", "is_primary"] - unknown = INCLUDE \ No newline at end of file + fields = [ + "identifier", + "display_name", + "process_group_id", + "process_model_id", + "type", + "file_name", + "has_lanes", + "is_executable", + "is_primary", + ] + unknown = INCLUDE diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index c2a7c1385..e61d00794 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -59,7 +59,8 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModelSchema -from spiffworkflow_backend.models.spec_reference import SpecReferenceCache, SpecReferenceSchema +from spiffworkflow_backend.models.spec_reference import SpecReferenceCache +from spiffworkflow_backend.models.spec_reference import SpecReferenceSchema from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.models.spiff_step_details import SpiffStepDetailsModel from spiffworkflow_backend.models.user import UserModel @@ -340,8 +341,8 @@ def process_model_list( def process_list() -> any: """Returns a list of all known processes - this includes processes that are not the - primary process - helpful for finding possible call activities. """ - references = SpecReferenceCache.query.filter_by(type = "process") + primary process - helpful for finding possible call activities.""" + references = SpecReferenceCache.query.filter_by(type="process") return SpecReferenceSchema(many=True).dump(references) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index 70ae93192..f13ab8d30 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -67,7 +67,6 @@ from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel -from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.group import GroupModel @@ -86,6 +85,7 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) +from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.spiff_step_details import SpiffStepDetailsModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModelSchema @@ -671,8 +671,9 @@ class ProcessInstanceProcessor: return parser @staticmethod - def backfill_missing_spec_reference_records(bpmn_process_identifier: str) -> Optional[str]: - + def backfill_missing_spec_reference_records( + bpmn_process_identifier: str, + ) -> Optional[str]: """Backfill_missing_spec_reference_records.""" process_models = ProcessModelService().get_process_models() for process_model in process_models: @@ -695,11 +696,15 @@ class ProcessInstanceProcessor: "bpmn_file_full_path_from_bpmn_process_identifier: bpmn_process_identifier is unexpectedly None" ) - spec_reference = SpecReferenceCache.query.filter_by(identifier=bpmn_process_identifier).first() + spec_reference = SpecReferenceCache.query.filter_by( + identifier=bpmn_process_identifier + ).first() bpmn_file_full_path = None if spec_reference is None: - bpmn_file_full_path = ProcessInstanceProcessor.backfill_missing_spec_reference_records( - bpmn_process_identifier + bpmn_file_full_path = ( + ProcessInstanceProcessor.backfill_missing_spec_reference_records( + bpmn_process_identifier + ) ) else: bpmn_file_full_path = os.path.join( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py index 24a05d128..e8e334f21 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -8,10 +8,9 @@ from typing import Optional from flask_bpmn.models.db import db from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore -from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.file import File -from spiffworkflow_backend.models.file import SpecReference from spiffworkflow_backend.models.file import FileType +from spiffworkflow_backend.models.file import SpecReference from spiffworkflow_backend.models.message_correlation_property import ( MessageCorrelationPropertyModel, ) @@ -20,6 +19,7 @@ from spiffworkflow_backend.models.message_triggerable_process_model import ( MessageTriggerableProcessModel, ) from spiffworkflow_backend.models.process_model import ProcessModelInfo +from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.services.custom_parser import MyCustomParser from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.process_model_service import ProcessModelService @@ -55,7 +55,7 @@ class SpecFileService(FileSystemService): @staticmethod def reference_map(references: list[SpecReference]) -> dict[str, SpecReference]: - """ Creates a dict with provided references organized by id. """ + """Creates a dict with provided references organized by id.""" ref_map = {} for ref in references: ref_map[ref.identifier] = ref @@ -63,13 +63,15 @@ class SpecFileService(FileSystemService): @staticmethod def get_references(process_models: List[ProcessModelInfo]) -> list[SpecReference]: - """Returns all references -- process_ids, and decision ids, across all process models provided""" + """Returns all references -- process_ids, and decision ids, across all process models provided.""" references = [] for process_model in process_models: references.extend(SpecFileService.get_references_for_process(process_model)) @staticmethod - def get_references_for_process(process_model_info: ProcessModelInfo) -> list[SpecReference]: + def get_references_for_process( + process_model_info: ProcessModelInfo, + ) -> list[SpecReference]: """Get_references_for_process.""" files = SpecFileService.get_files(process_model_info) references = [] @@ -80,7 +82,9 @@ class SpecFileService(FileSystemService): return references @staticmethod - def get_references_for_file(file: File, process_model_info: ProcessModelInfo) -> list[SpecReference]: + def get_references_for_file( + file: File, process_model_info: ProcessModelInfo + ) -> list[SpecReference]: """Uses spiffworkflow to parse BPMN and DMN files to determine how they can be externally referenced. Returns a list of Reference objects that contain the type of reference, the id, the name. @@ -116,9 +120,11 @@ class SpecFileService(FileSystemService): for sub_parser in sub_parsers: if parser_type == "process": has_lanes = sub_parser.has_lanes() - executable = sub_parser.process_executable + sub_parser.process_executable start_messages = sub_parser.start_messages() - is_primary = sub_parser.get_id() == process_model_info.primary_process_id + is_primary = ( + sub_parser.get_id() == process_model_info.primary_process_id + ) references.append( SpecReference( @@ -133,7 +139,7 @@ class SpecFileService(FileSystemService): messages=messages, is_primary=is_primary, correlations=correlations, - start_messages=start_messages + start_messages=start_messages, ) ) return references @@ -166,11 +172,12 @@ class SpecFileService(FileSystemService): if ref.is_primary: ProcessModelService().update_spec( - process_model_info, { + process_model_info, + { "primary_process_id": ref.identifier, "primary_file_name": file_name, "is_review": ref.has_lanes, - } + }, ) SpecFileService.update_process_cache(ref) SpecFileService.update_message_cache(ref) @@ -229,7 +236,10 @@ class SpecFileService(FileSystemService): @staticmethod def update_process_cache(ref: SpecReference) -> None: - process_id_lookup = SpecReferenceCache.query.filter_by(identifier=ref.identifier).first() + """Update_process_cache.""" + process_id_lookup = SpecReferenceCache.query.filter_by( + identifier=ref.identifier + ).first() if process_id_lookup is None: process_id_lookup = SpecReferenceCache.from_spec_reference(ref) db.session.add(process_id_lookup) @@ -246,9 +256,7 @@ class SpecFileService(FileSystemService): f"{process_id_lookup.relative_path}. It cannot be reused." ) else: - process_id_lookup.relative_path = ( - ref.relative_path - ) + process_id_lookup.relative_path = ref.relative_path db.session.add(process_id_lookup) db.session.commit() @@ -269,7 +277,7 @@ class SpecFileService(FileSystemService): @staticmethod def update_message_trigger_cache( - ref: SpecReference, process_model_info: ProcessModelInfo + ref: SpecReference, process_model_info: ProcessModelInfo ) -> None: """Assure we know which messages can trigger the start of a process.""" for message_model_identifier in ref.start_messages: diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index cad84bb4e..b02f1eb08 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,8 +9,6 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db - -from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec @@ -27,6 +25,7 @@ from spiffworkflow_backend.models.process_instance_report import ( ) from spiffworkflow_backend.models.process_model import NotificationType from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema +from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.file_system_service import FileSystemService @@ -441,45 +440,49 @@ class TestProcessApi(BaseTest): assert response.json["pagination"]["total"] == 5 assert response.json["pagination"]["pages"] == 2 - def test_process_list(self, - app: Flask, - client: FlaskClient, - with_db_and_bpmn_file_cleanup: None, - with_super_admin_user: UserModel, - ): + def test_process_list( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ): """It should be possible to get a list of all processes known to the system.""" load_test_spec( "test_group_one/simple_form", - process_model_source_directory='simple_form', - bpmn_file_name='simple_form' + process_model_source_directory="simple_form", + bpmn_file_name="simple_form", ) # When adding a process model with one Process, no decisions, and some json files, only one process is recorded. - assert(len(SpecReferenceCache.query.all()) == 1) + assert len(SpecReferenceCache.query.all()) == 1 self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, - process_group_id='test_group_two', - process_model_id='call_activity_nested', - bpmn_file_location='call_activity_nested' + process_group_id="test_group_two", + process_model_id="call_activity_nested", + bpmn_file_location="call_activity_nested", ) # When adding a process model with 4 processes and a decision, 5 new records will be in the Cache - assert(len(SpecReferenceCache.query.all()) == 6) + assert len(SpecReferenceCache.query.all()) == 6 # get the results - response = client.get("/v1.0/processes", headers=self.logged_in_headers(with_super_admin_user), + response = client.get( + "/v1.0/processes", + headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None # We should get 5 back, as one of the items in the cache is a decision. assert len(response.json) == 5 - simple_form = next(p for p in response.json if p['identifier'] == 'Proccess_WithForm') - assert(simple_form['display_name'] == 'Process With Form') - assert(simple_form['process_model_id'] == 'test_group_one/simple_form') - assert(simple_form['has_lanes'] == False) - assert(simple_form['is_executable'] == True) - assert(simple_form['is_primary'] == True) - + simple_form = next( + p for p in response.json if p["identifier"] == "Proccess_WithForm" + ) + assert simple_form["display_name"] == "Process With Form" + assert simple_form["process_model_id"] == "test_group_one/simple_form" + assert simple_form["has_lanes"] == False + assert simple_form["is_executable"] == True + assert simple_form["is_primary"] == True def test_process_group_add( self, diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py index 0d0939547..09421bc71 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py @@ -5,8 +5,8 @@ from flask_bpmn.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec -from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.process_model import ProcessModelInfo +from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py index 2e318936b..deec4a2d0 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -69,10 +69,7 @@ class TestSpecFileService(BaseTest): ) bpmn_process_id_lookups = SpecReferenceCache.query.all() assert len(bpmn_process_id_lookups) == 1 - assert ( - bpmn_process_id_lookups[0].identifier - == bpmn_process_identifier - ) + assert bpmn_process_id_lookups[0].identifier == bpmn_process_identifier assert ( bpmn_process_id_lookups[0].relative_path == self.call_activity_nested_relative_file_path @@ -115,10 +112,7 @@ class TestSpecFileService(BaseTest): bpmn_process_id_lookups = SpecReferenceCache.query.all() assert len(bpmn_process_id_lookups) == 1 - assert ( - bpmn_process_id_lookups[0].identifier - == bpmn_process_identifier - ) + assert bpmn_process_id_lookups[0].identifier == bpmn_process_identifier assert ( bpmn_process_id_lookups[0].relative_path == self.call_activity_nested_relative_file_path