From 28a28e353b5f63e76c65d67e97cbd149902de2a5 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 17 Jan 2023 12:56:06 -0500 Subject: [PATCH 1/8] Removing dependency on flask-bpmn and taking it out of SpiffArena Slightly updating the APIError code for recent updates to SpiffWorkflow's error refactoring. --- .../bin/import_tickets_for_command_line.py | 2 +- .../bin/import_tickets_for_script_task.py | 2 +- spiffworkflow-backend/conftest.py | 5 +- spiffworkflow-backend/poetry.lock | 48 +--- spiffworkflow-backend/pyproject.toml | 6 +- .../src/spiffworkflow_backend/__init__.py | 6 +- .../config/permissions/example.yml | 15 ++ .../exceptions/api_error.py | 206 ++++++++++++++++++ .../helpers/db_helper.py | 2 +- .../load_database_models.py | 2 +- .../src/spiffworkflow_backend/models/db.py | 85 ++++++++ .../src/spiffworkflow_backend/models/group.py | 7 +- .../models/human_task.py | 5 +- .../models/human_task_user.py | 5 +- .../models/message_correlation.py | 5 +- .../message_correlation_message_instance.py | 5 +- .../models/message_correlation_property.py | 5 +- .../models/message_instance.py | 5 +- .../models/message_model.py | 5 +- .../message_triggerable_process_model.py | 5 +- .../models/permission_assignment.py | 5 +- .../models/permission_target.py | 5 +- .../spiffworkflow_backend/models/principal.py | 5 +- .../models/process_instance.py | 5 +- .../models/process_instance_metadata.py | 5 +- .../models/process_instance_report.py | 5 +- .../models/refresh_token.py | 5 +- .../models/secret_model.py | 5 +- .../models/spec_reference.py | 5 +- .../models/spiff_logging.py | 5 +- .../models/spiff_step_details.py | 5 +- .../src/spiffworkflow_backend/models/user.py | 5 +- .../models/user_group_assignment.py | 5 +- .../models/user_group_assignment_waiting.py | 5 +- .../routes/messages_controller.py | 2 +- .../routes/process_api_blueprint.py | 4 +- .../routes/process_groups_controller.py | 2 +- .../routes/process_instances_controller.py | 4 +- .../routes/process_models_controller.py | 4 +- .../routes/script_unit_tests_controller.py | 2 +- .../routes/tasks_controller.py | 4 +- .../src/spiffworkflow_backend/routes/user.py | 2 +- .../routes/user_blueprint.py | 4 +- .../delete_process_instances_with_criteria.py | 2 +- .../scripts/get_localtime.py | 2 +- .../scripts/save_process_instance_metadata.py | 2 +- .../spiffworkflow_backend/scripts/script.py | 2 +- .../services/acceptance_test_fixtures.py | 2 +- .../services/authentication_service.py | 4 +- .../services/authorization_service.py | 4 +- .../services/data_setup_service.py | 2 +- .../services/error_handling_service.py | 4 +- .../services/file_system_service.py | 2 +- .../services/group_service.py | 2 +- .../services/logging_service.py | 2 +- .../services/message_service.py | 2 +- .../services/process_instance_processor.py | 14 +- .../process_instance_report_service.py | 5 +- .../services/process_instance_service.py | 4 +- .../services/process_model_service.py | 2 +- .../services/script_unit_test_runner.py | 6 +- .../services/secret_service.py | 4 +- .../services/spec_file_service.py | 8 +- .../services/user_service.py | 4 +- .../helpers/base_test.py | 4 +- .../integration/test_process_api.py | 2 +- .../integration/test_secret_service.py | 2 +- .../scripts/test_get_group_members.py | 2 +- .../scripts/test_refresh_permissions.py | 2 +- .../unit/test_message_instance.py | 2 +- .../unit/test_permission_target.py | 2 +- .../unit/test_permissions.py | 2 +- .../test_process_instance_report_service.py | 2 +- .../unit/test_process_model.py | 2 +- .../unit/test_restricted_script_engine.py | 2 +- .../unit/test_spec_file_service.py | 2 +- .../unit/test_spiff_logging.py | 2 +- 77 files changed, 462 insertions(+), 169 deletions(-) create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/db.py diff --git a/spiffworkflow-backend/bin/import_tickets_for_command_line.py b/spiffworkflow-backend/bin/import_tickets_for_command_line.py index cc94ba545..36b627968 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_command_line.py +++ b/spiffworkflow-backend/bin/import_tickets_for_command_line.py @@ -1,7 +1,7 @@ """Grabs tickets from csv and makes process instances.""" import csv -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend import get_hacked_up_app_for_script from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/bin/import_tickets_for_script_task.py b/spiffworkflow-backend/bin/import_tickets_for_script_task.py index 6b12699be..1e9f6d196 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_script_task.py +++ b/spiffworkflow-backend/bin/import_tickets_for_script_task.py @@ -5,7 +5,7 @@ def main(): """Use main to avoid global namespace.""" import csv - from flask_bpmn.models.db import db + from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index b24a7ed1b..8d1191965 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -5,8 +5,9 @@ import shutil import pytest from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from tests.spiffworkflow_backend.helpers.base_test import BaseTest from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel diff --git a/spiffworkflow-backend/poetry.lock b/spiffworkflow-backend/poetry.lock index 2e001a93f..433abf204 100644 --- a/spiffworkflow-backend/poetry.lock +++ b/spiffworkflow-backend/poetry.lock @@ -610,37 +610,6 @@ python-versions = "*" bcrypt = ">=3.1.1" Flask = "*" -[[package]] -name = "flask-bpmn" -version = "0.0.0" -description = "Flask Bpmn" -category = "main" -optional = false -python-versions = "^3.7" -develop = false - -[package.dependencies] -click = "^8.0.1" -flask = "*" -flask-admin = "*" -flask-bcrypt = "*" -flask-cors = "*" -flask-mail = "*" -flask-marshmallow = "*" -flask-migrate = "*" -flask-restful = "*" -greenlet = "^2.0.1" -sentry-sdk = "*" -sphinx-autoapi = "^2.0.0" -spiffworkflow = "*" -werkzeug = "*" - -[package.source] -type = "git" -url = "https://github.com/sartography/flask-bpmn" -reference = "main" -resolved_reference = "c18306300f4312b8d36e0197fd6b62399180d0b1" - [[package]] name = "Flask-Cors" version = "3.0.10" @@ -1776,7 +1745,7 @@ description = "A workflow framework and BPMN/DMN Processor" category = "main" optional = false python-versions = "*" -develop = false +develop = true [package.dependencies] celery = "*" @@ -1784,10 +1753,8 @@ configparser = "*" lxml = "*" [package.source] -type = "git" -url = "https://github.com/sartography/SpiffWorkflow" -reference = "main" -resolved_reference = "be26100bcbef8026e26312c665dae42faf476485" +type = "directory" +url = "../../SpiffWorkflow" [[package]] name = "SQLAlchemy" @@ -2158,7 +2125,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = ">=3.9,<3.12" -content-hash = "8592e94ba80b7d0338a9c003ca4d0e189b5f470d97391438ddc1fc9050febedb" +content-hash = "f646836512a18f2a0e9ba4979926e004abd17790da5178e06e87092fdf23c35f" [metadata.files] alabaster = [ @@ -2421,7 +2388,6 @@ Flask-Bcrypt = [ {file = "Flask-Bcrypt-1.0.1.tar.gz", hash = "sha256:f07b66b811417ea64eb188ae6455b0b708a793d966e1a80ceec4a23bc42a4369"}, {file = "Flask_Bcrypt-1.0.1-py3-none-any.whl", hash = "sha256:062fd991dc9118d05ac0583675507b9fe4670e44416c97e0e6819d03d01f808a"}, ] -flask-bpmn = [] Flask-Cors = [ {file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"}, {file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"}, @@ -2499,6 +2465,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, + {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, @@ -2507,6 +2474,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, + {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, @@ -2515,6 +2483,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, + {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, @@ -2813,10 +2782,7 @@ orjson = [ {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"}, {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"}, {file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"}, - {file = "orjson-3.8.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:200eae21c33f1f8b02a11f5d88d76950cd6fd986d88f1afe497a8ae2627c49aa"}, - {file = "orjson-3.8.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9529990f3eab54b976d327360aa1ff244a4b12cb5e4c5b3712fcdd96e8fe56d4"}, {file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"}, - {file = "orjson-3.8.0-cp311-none-win_amd64.whl", hash = "sha256:b21c7af0ff6228ca7105f54f0800636eb49201133e15ddb80ac20c1ce973ef07"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"}, {file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"}, diff --git a/spiffworkflow-backend/pyproject.toml b/spiffworkflow-backend/pyproject.toml index 83a434821..c72f9e792 100644 --- a/spiffworkflow-backend/pyproject.toml +++ b/spiffworkflow-backend/pyproject.toml @@ -27,12 +27,10 @@ flask-marshmallow = "*" flask-migrate = "*" flask-restful = "*" werkzeug = "*" -SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"} -#SpiffWorkflow = {develop = true, path = "../SpiffWorkflow" } +#SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"} +SpiffWorkflow = {develop = true, path = "/home/dan/code/workflow/SpiffWorkflow" } sentry-sdk = "^1.10" sphinx-autoapi = "^2.0" -flask-bpmn = {git = "https://github.com/sartography/flask-bpmn", rev = "main"} -# flask-bpmn = {develop = true, path = "../flask-bpmn"} mysql-connector-python = "*" pytest-flask = "^1.2.0" pytest-flask-sqlalchemy = "^1.1.0" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py index f67dccc05..95e11570a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py @@ -9,9 +9,9 @@ import sqlalchemy from apscheduler.schedulers.background import BackgroundScheduler # type: ignore from apscheduler.schedulers.base import BaseScheduler # type: ignore from flask.json.provider import DefaultJSONProvider -from flask_bpmn.api.api_error import api_error_blueprint -from flask_bpmn.models.db import db -from flask_bpmn.models.db import migrate +from spiffworkflow_backend.exceptions.api_error import api_error_blueprint +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import migrate from flask_cors import CORS # type: ignore from flask_mail import Mail # type: ignore from werkzeug.exceptions import NotFound diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml index 248a400b4..c80b15112 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml @@ -16,12 +16,19 @@ users: email: malala@spiffworkflow.org password: malala preferred_username: Malala + oskar: + service: local_open_id + email: oskar@spiffworkflow.org + password: oskar + preferred_username: Oskar + groups: admin: users: [ admin@spiffworkflow.org, + oskar@spiffworkflow.org ] Education: users: @@ -88,3 +95,11 @@ permissions: users: [] allowed_permissions: [create, read] uri: /process-instances/misc:category_number_one:process-model-with-form/* + + # Anyone can see their own user groups. + groups-everybody: + groups: [everybody] + users: [] + allowed_permissions: [create, read] + uri: /v1.0/user-groups/for-current-user + diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py new file mode 100644 index 000000000..0dfce83a8 --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py @@ -0,0 +1,206 @@ +"""API Error functionality.""" +from __future__ import annotations + +import json +from dataclasses import dataclass +from dataclasses import field +from typing import Any + +import flask.wrappers +import sentry_sdk +from flask import Blueprint +from flask import current_app +from flask import g +from flask import jsonify +from flask import make_response +from sentry_sdk import capture_exception +from sentry_sdk import set_tag +from SpiffWorkflow.exceptions import WorkflowException, WorkflowTaskException # type: ignore +from SpiffWorkflow.specs.base import TaskSpec # type: ignore +from SpiffWorkflow.task import Task # type: ignore + + +api_error_blueprint = Blueprint("api_error_blueprint", __name__) + + +@dataclass +class ApiError(Exception): + """ApiError Class to help handle exceptions.""" + + error_code: str + message: str + error_line: str = "" + error_type: str = "" + file_name: str = "" + line_number: int = 0 + offset: int = 0 + sentry_link: str | None = None + status_code: int = 400 + tag: str = "" + task_data: dict | str | None = field(default_factory=dict) + task_id: str = "" + task_name: str = "" + task_trace: dict | None = field(default_factory=dict) + + def __str__(self) -> str: + """Instructions to print instance as a string.""" + msg = "ApiError: % s. " % self.message + if self.task_name: + msg += f"Error in task '{self.task_name}' ({self.task_id}). " + if self.line_number: + msg += "Error is on line %i. " % self.line_number + if self.file_name: + msg += "In file %s. " % self.file_name + return msg + + @classmethod + def from_task( + cls, + error_code: str, + message: str, + task: Task, + status_code: int = 400, + line_number: int = 0, + offset: int = 0, + error_type: str = "", + error_line: str = "", + task_trace: dict | None = None, + ) -> ApiError: + """Constructs an API Error with details pulled from the current task.""" + instance = cls(error_code, message, status_code=status_code) + instance.task_id = task.task_spec.name or "" + instance.task_name = task.task_spec.description or "" + instance.file_name = task.workflow.spec.file or "" + instance.line_number = line_number + instance.offset = offset + instance.error_type = error_type + instance.error_line = error_line + if task_trace: + instance.task_trace = task_trace + else: + instance.task_trace = WorkflowTaskException.get_task_trace(task) + + # spiffworkflow is doing something weird where task ends up referenced in the data in some cases. + if "task" in task.data: + task.data.pop("task") + + # Assure that there is nothing in the json data that can't be serialized. + instance.task_data = ApiError.remove_unserializeable_from_dict(task.data) + + return instance + + @staticmethod + def remove_unserializeable_from_dict(my_dict: dict) -> dict: + """Removes unserializeable from dict.""" + keys_to_delete = [] + for key, value in my_dict.items(): + if not ApiError.is_jsonable(value): + keys_to_delete.append(key) + for key in keys_to_delete: + del my_dict[key] + return my_dict + + @staticmethod + def is_jsonable(x: Any) -> bool: + """Attempts a json.dump on given input and returns false if it cannot.""" + try: + json.dumps(x) + return True + except (TypeError, OverflowError, ValueError): + return False + + @classmethod + def from_task_spec( + cls, + code: str, + message: str, + task_spec: TaskSpec, + status_code: int = 400, + ) -> ApiError: + """Constructs an API Error with details pulled from the current task.""" + instance = cls(code, message, status_code=status_code) + instance.task_id = task_spec.name or "" + instance.task_name = task_spec.description or "" + if task_spec._wf_spec: + instance.file_name = task_spec._wf_spec.file + return instance + + @classmethod + def from_workflow_exception( + cls, + error_code: str, + message: str, + exp: WorkflowException, + ) -> ApiError: + """Deals with workflow exceptions. + + We catch a lot of workflow exception errors, + so consolidating the error_code, and doing the best things + we can with the data we have. + """ + if isinstance(exp, WorkflowTaskException): + return ApiError.from_task( + error_code, + message, + exp.task, + line_number=exp.line_number, + offset=exp.offset, + error_type=exp.error_type, + error_line=exp.error_line, + task_trace=exp.task_trace, + ) + + else: + return ApiError.from_task_spec(error_code, message, exp.sender) + + +def set_user_sentry_context() -> None: + """Set_user_sentry_context.""" + try: + username = g.user.username + except Exception: + username = "Unknown" + # This is for sentry logging into Slack + sentry_sdk.set_context("User", {"user": username}) + set_tag("username", username) + + +@api_error_blueprint.app_errorhandler(Exception) +def handle_exception(exception: Exception) -> flask.wrappers.Response: + """Handles unexpected exceptions.""" + set_user_sentry_context() + + sentry_link = None + if not isinstance(exception, ApiError) or exception.error_code != "invalid_token": + id = capture_exception(exception) + + if isinstance(exception, ApiError): + current_app.logger.info( + f"Sending ApiError exception to sentry: {exception} with error code {exception.error_code}") + + organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") + project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") + if organization_slug and project_slug: + sentry_link = ( + f"https://sentry.io/{organization_slug}/{project_slug}/events/{id}" + ) + + # !!!NOTE!!!: do this after sentry stuff since calling logger.exception + # seems to break the sentry sdk context where we no longer get back + # an event id or send out tags like username + current_app.logger.exception(exception) + + # set api_exception like this to avoid confusing mypy + # and what type the object is + api_exception = None + if isinstance(exception, ApiError): + api_exception = exception + else: + api_exception = ApiError( + error_code="internal_server_error", + message=f"{exception.__class__.__name__}", + sentry_link=sentry_link, + status_code=500, + ) + + return make_response(jsonify(api_exception), api_exception.status_code) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py index 45cd38f7a..4a836b1e6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py @@ -2,7 +2,7 @@ import time import sqlalchemy -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db def try_to_connect(start_time: float) -> None: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py index bc79a8e39..2ebd11347 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py @@ -8,7 +8,7 @@ avoid circular imports """ -from flask_bpmn.models.db import add_listeners +from spiffworkflow_backend.models.db import add_listeners # must load these before UserModel and GroupModel for relationships from spiffworkflow_backend.models.user_group_assignment import ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py new file mode 100644 index 000000000..643e1a85d --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py @@ -0,0 +1,85 @@ +"""Db.""" +from __future__ import annotations + +import enum +import time +from typing import Any + +from flask_migrate import Migrate # type: ignore +from flask_sqlalchemy import SQLAlchemy # type: ignore +from sqlalchemy import event # type: ignore +from sqlalchemy.engine.base import Connection # type: ignore +from sqlalchemy.orm.mapper import Mapper # type: ignore + +db = SQLAlchemy() +migrate = Migrate() + + +class SpiffworkflowBaseDBModel(db.Model): # type: ignore + """SpiffworkflowBaseDBModel.""" + + __abstract__ = True + + @classmethod + def _all_subclasses(cls) -> list[type[SpiffworkflowBaseDBModel]]: + """Get all subclasses of cls, descending. + + So, if A is a subclass of B is a subclass of cls, this + will include A and B. + (Does not include cls) + """ + children = cls.__subclasses__() + result = [] + while children: + next = children.pop() + subclasses = next.__subclasses__() + result.append(next) + # check subclasses of subclasses SpiffworkflowBaseDBModel. i guess we only go down to grandchildren, which seems cool. + for subclass in subclasses: + children.append(subclass) + return result + + def validate_enum_field( + self, key: str, value: Any, enum_variable: enum.EnumMeta + ) -> Any: + """Validate_enum_field.""" + try: + m_type = getattr(enum_variable, value, None) + except Exception as e: + raise ValueError( + f"{self.__class__.__name__}: invalid {key}: {value}" + ) from e + + if m_type is None: + raise ValueError(f"{self.__class__.__name__}: invalid {key}: {value}") + + return m_type.value + + +def update_created_modified_on_create_listener( + mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel +) -> None: + """Event listener that runs before a record is updated, and sets the create/modified field accordingly.""" + if "created_at_in_seconds" in mapper.columns.keys(): + target.created_at_in_seconds = round(time.time()) + if "updated_at_in_seconds" in mapper.columns.keys(): + target.updated_at_in_seconds = round(time.time()) + + +def update_modified_on_update_listener( + mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel +) -> None: + """Event listener that runs before a record is updated, and sets the modified field accordingly.""" + if "updated_at_in_seconds" in mapper.columns.keys(): + if db.session.is_modified(target, include_collections=False): + target.updated_at_in_seconds = round(time.time()) + + +def add_listeners() -> None: + """Adds the listeners to all subclasses. + + This should be called after importing all subclasses + """ + for cls in SpiffworkflowBaseDBModel._all_subclasses(): + event.listen(cls, "before_insert", update_created_modified_on_create_listener) + event.listen(cls, "before_update", update_modified_on_update_listener) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py index 980fc9302..7038ad6f3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py @@ -3,8 +3,7 @@ from __future__ import annotations from typing import TYPE_CHECKING -from flask_bpmn.models.db import db -from flask_bpmn.models.group import FlaskBpmnGroupModel +from spiffworkflow_backend.models.db import db, SpiffworkflowBaseDBModel from sqlalchemy.orm import relationship if TYPE_CHECKING: @@ -18,12 +17,14 @@ class GroupNotFoundError(Exception): """GroupNotFoundError.""" -class GroupModel(FlaskBpmnGroupModel): +class GroupModel(SpiffworkflowBaseDBModel): """GroupModel.""" __tablename__ = "group" __table_args__ = {"extend_existing": True} + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(255)) identifier = db.Column(db.String(255)) user_group_assignments = relationship("UserGroupAssignmentModel", cascade="delete") diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py index f74da5cca..398053423 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py @@ -4,8 +4,9 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py index 31823af82..1ac0824e3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py @@ -3,8 +3,9 @@ from __future__ import annotations from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from spiffworkflow_backend.models.human_task import HumanTaskModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py index 08bc1cb12..3e03f32eb 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py @@ -2,8 +2,9 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py index 320dfba3e..7b1ddfbdf 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py @@ -1,8 +1,9 @@ """Message_correlation_message_instance.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py index b84b7140c..6b03c91a5 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py @@ -1,6 +1,7 @@ """Message_correlation_property.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from spiffworkflow_backend.models.message_model import MessageModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py index b0cc2aa34..60c2fc92b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py @@ -5,8 +5,9 @@ from typing import Any from typing import Optional from typing import TYPE_CHECKING -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.event import listens_for from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py index 601b6d405..7fe78f707 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py @@ -1,6 +1,7 @@ """Message_model.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + class MessageModel(SpiffworkflowBaseDBModel): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py index cc8834654..acd44eac3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -1,6 +1,7 @@ """Message_correlation_property.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from spiffworkflow_backend.models.message_model import MessageModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py index 04dfb5fac..2e09d888e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py @@ -2,8 +2,9 @@ import enum from typing import Any -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import validates diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py index 53334baf0..a9fe7111c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py @@ -3,8 +3,9 @@ import re from dataclasses import dataclass from typing import Optional -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy.orm import validates diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py index ac8ee6a4e..f3818e9d9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py @@ -1,8 +1,9 @@ """Principal.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.schema import CheckConstraint diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 42a903648..bb262b4c2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -5,8 +5,9 @@ from typing import Any from typing import cast import marshmallow -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from marshmallow import INCLUDE from marshmallow import Schema from marshmallow_enum import EnumField # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py index f2e4c2221..c4114dda2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py @@ -1,8 +1,9 @@ """Process_instance_metadata.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py index b1288b3f1..19f98a06e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py @@ -7,8 +7,9 @@ from typing import cast from typing import Optional from typing import TypedDict -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import deferred from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py index 2e96b7f05..5cf23609c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py @@ -1,8 +1,9 @@ """Refresh_token.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey # from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py index 91a4f23bb..37f47b935 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py @@ -1,8 +1,9 @@ """Secret_model.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from marshmallow import Schema from sqlalchemy import ForeignKey diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py index 50b73fbae..e7b2ab98e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py @@ -1,8 +1,9 @@ """Message_model.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from flask_marshmallow import Schema # type: ignore from marshmallow import INCLUDE from sqlalchemy import UniqueConstraint diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py index 532a6c09c..9fc82a01e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py @@ -2,8 +2,9 @@ from dataclasses import dataclass from typing import Optional -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + @dataclass diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py index 11c3aeada..8d807493f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py @@ -1,8 +1,9 @@ """Spiff_step_details.""" from dataclasses import dataclass -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import deferred diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py index c4838aafa..f3838a06c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py @@ -6,8 +6,9 @@ from dataclasses import dataclass import jwt import marshmallow from flask import current_app -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from marshmallow import Schema from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py index 9c1567fb7..2c5638bb9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py @@ -1,6 +1,7 @@ """UserGroupAssignment.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py index ac2747c85..fe9c6b885 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py @@ -1,6 +1,7 @@ """UserGroupAssignment.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py index 30456c934..35befc612 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py @@ -9,7 +9,7 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel 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 4a6cc1c42..55b0afcaf 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -11,8 +11,8 @@ from flask import jsonify from flask import make_response from flask import request from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py index 2a516f9d3..98da1901a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py @@ -8,7 +8,7 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index 0a218e0ed..0a1eaa497 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -11,8 +11,8 @@ from flask import jsonify from flask import make_response from flask import request from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import TaskState # type: ignore from sqlalchemy import and_ from sqlalchemy import or_ diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py index 8a6e63066..cda5dd6f9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py @@ -14,7 +14,7 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from werkzeug.datastructures import FileStorage from spiffworkflow_backend.interfaces import IdToProcessGroupMapping @@ -519,7 +519,7 @@ def _create_or_update_process_model_file( ApiError( error_code="process_model_file_invalid", message=( - f"Invalid Process model file cannot be save: {request_file.name}." + f"Invalid Process model file: {request_file.filename}." f" Received error: {str(exception)}" ), status_code=400, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py index e97b26ae6..29d2461e6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py @@ -10,7 +10,7 @@ from flask import current_app from flask import jsonify from flask import make_response from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from lxml import etree # type: ignore from lxml.builder import ElementMaker # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index c4f557726..8f700a0ff 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -15,8 +15,8 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from sqlalchemy import and_ diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py index 5a3aa53dc..f580651e9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py @@ -14,7 +14,7 @@ from flask import current_app from flask import g from flask import redirect from flask import request -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from werkzeug.wrappers import Response from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py index fd5c1ae90..807b08c1a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py @@ -7,8 +7,8 @@ import flask.wrappers from flask import Blueprint from flask import request from flask import Response -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from sqlalchemy.exc import IntegrityError from spiffworkflow_backend.models.group import GroupModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py index 5b4225253..3345ef641 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py @@ -2,7 +2,7 @@ from time import time from typing import Any -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from sqlalchemy import or_ from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py index 7c688e56f..c5742f84a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Any import pytz -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py index d9c1959aa..38daf193c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py @@ -1,7 +1,7 @@ """Save process instance metadata.""" from typing import Any -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance_metadata import ( ProcessInstanceMetadataModel, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py index 7ca798466..4f2300feb 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py @@ -8,7 +8,7 @@ from abc import abstractmethod from typing import Any from typing import Callable -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceNotFoundError diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index 6bbcad331..028f47a64 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -2,7 +2,7 @@ import time from flask import current_app -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py index 77082a927..c15f31d26 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py @@ -9,8 +9,8 @@ import jwt import requests from flask import current_app from flask import redirect -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from werkzeug.wrappers import Response from spiffworkflow_backend.models.refresh_token import RefreshTokenModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py index ba43439ed..a1915a5d1 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py @@ -17,8 +17,8 @@ from flask import current_app from flask import g from flask import request from flask import scaffold -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore from sqlalchemy import or_ from sqlalchemy import text diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py index 1dd384acf..25aa143ca 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py @@ -1,6 +1,6 @@ """Data_setup_service.""" from flask import current_app -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index 51f402fac..b5509eb79 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -5,8 +5,8 @@ from typing import Union from flask import current_app from flask import g from flask.wrappers import Response -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_triggerable_process_model import ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py index cb8b44c6d..96b8e6ba0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py @@ -8,7 +8,7 @@ from typing import Optional import pytz from flask import current_app -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.file import CONTENT_TYPES from spiffworkflow_backend.models.file import File diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py index 911d41ac4..c417d8eb4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py @@ -1,7 +1,7 @@ """Group_service.""" from typing import Optional -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py index 599d5228d..d09d3c0de 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py @@ -7,7 +7,7 @@ from typing import Optional from flask import g from flask.app import Flask -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py index b659b13e2..3ac4b5745 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py @@ -2,7 +2,7 @@ from typing import Any from typing import Optional -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from sqlalchemy import and_ from sqlalchemy import or_ from sqlalchemy import select 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 510c66fda..711ccc353 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -22,11 +22,11 @@ from uuid import UUID import dateparser import pytz from flask import current_app -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from lxml import etree # type: ignore from RestrictedPython import safe_globals # type: ignore -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore +from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine @@ -222,7 +222,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore % (expression, str(exception)), ) from exception else: - raise WorkflowTaskExecException( + raise WorkflowTaskException( task, "Error evaluating expression '%s', %s" % (expression, str(exception)), @@ -240,7 +240,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore except WorkflowException as e: raise e except Exception as e: - raise WorkflowTaskExecException(task, f" {script}, {e}", e) from e + raise WorkflowTaskException(task, f" {script}, {e}", e) from e def call_service( self, @@ -1284,7 +1284,7 @@ class ProcessInstanceProcessor: handler.bulk_insert_logs() # type: ignore db.session.commit() - except WorkflowTaskExecException as we: + except WorkflowTaskException as we: raise ApiError.from_workflow_exception("task_error", str(we), we) from we finally: @@ -1304,7 +1304,7 @@ class ProcessInstanceProcessor: bpmn_process_instance.catch(CancelEventDefinition()) # Due to this being static, can't save granular step details in this case bpmn_process_instance.do_engine_steps() - except WorkflowTaskExecException as we: + except WorkflowTaskException as we: raise ApiError.from_workflow_exception("task_error", str(we), we) from we def user_defined_task_data(self, task_data: dict) -> dict: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index 0b75ea619..134f0f7b2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -6,8 +6,9 @@ from typing import Optional from typing import Type import sqlalchemy -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + from sqlalchemy import and_ from sqlalchemy import func from sqlalchemy import or_ diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index 9812609fe..abe8e6940 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -5,8 +5,8 @@ from typing import List from typing import Optional from flask import current_app -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore from spiffworkflow_backend.models.human_task import HumanTaskModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py index 893baaeae..9b53a98ed 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py @@ -8,7 +8,7 @@ from typing import List from typing import Optional from typing import TypeVar -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py index ed331672c..1fafb5487 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from typing import Any from typing import Optional -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore +from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from spiffworkflow_backend.services.process_instance_processor import ( @@ -54,9 +54,9 @@ class ScriptUnitTestRunner: offset=ex.offset, ) except Exception as ex: - if isinstance(ex, WorkflowTaskExecException): + if isinstance(ex, WorkflowTaskException): # we never expect this to happen, so we want to know about it. - # if indeed we are always getting WorkflowTaskExecException, + # if indeed we are always getting WorkflowTaskException, # we can simplify this error handling and replace it with the # except block from revision cccd523ea39499c10f7f3c2e3f061852970973ac raise ex diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py index aa9e6d147..7c2d27fea 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py @@ -1,8 +1,8 @@ """Secret_service.""" from typing import Optional -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.secret_model import SecretModel 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 868d0fcdf..69901674d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -5,7 +5,7 @@ from datetime import datetime from typing import List from typing import Optional -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from lxml import etree # type: ignore from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator # type: ignore @@ -173,10 +173,8 @@ class SpecFileService(FileSystemService): parser = MyCustomParser(validator=validator) try: parser.add_bpmn_xml(etree.fromstring(binary_data), filename=file_name) - except etree.XMLSyntaxError as exception: - raise ProcessModelFileInvalidError( - f"Received error trying to parse bpmn xml: {str(exception)}" - ) from exception + except Exception as exception: + raise ProcessModelFileInvalidError(str(exception)) @classmethod def update_file( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py index 20412e549..b460bad28 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py @@ -4,8 +4,8 @@ from typing import Optional from flask import current_app from flask import g -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py index df62f5be1..61bf5a404 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py @@ -9,8 +9,8 @@ from typing import Optional from flask import current_app from flask.testing import FlaskClient -from flask_bpmn.api.api_error import ApiError -from flask_bpmn.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from werkzeug.test import TestResponse # type: ignore 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 d146d0b22..9e6199443 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,7 +9,7 @@ from typing import Dict import pytest from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py index c71f67f23..631df9b56 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -5,7 +5,7 @@ from typing import Optional import pytest from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from werkzeug.test import TestResponse # type: ignore diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py index 8a6046b5b..00cc4e65a 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py @@ -1,7 +1,7 @@ """Test_get_localtime.""" from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py index 67cf55c85..e3d8563bc 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py @@ -2,7 +2,7 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py index 2c091eeb1..f9f764cd2 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -2,7 +2,7 @@ import pytest from flask import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from spiffworkflow_backend.models.message_instance import MessageInstanceModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py index 567681428..7ad9765b4 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py @@ -1,7 +1,7 @@ """Process Model.""" import pytest from flask.app import Flask -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from spiffworkflow_backend.models.permission_target import ( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py index a96989697..b3991eeb2 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py @@ -1,7 +1,7 @@ """Test Permissions.""" from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py index b40412ff8..46a67b2a6 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py @@ -3,7 +3,7 @@ from typing import Optional from flask import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec 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 9eb6901b9..86a6f648c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py @@ -1,7 +1,7 @@ """Process Model.""" from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index d31ea424f..e9e164b6f 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -2,7 +2,7 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient -from flask_bpmn.api.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec 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 2ce011b23..82b96f125 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 @@ -4,7 +4,7 @@ import os import pytest from flask import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db +from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py index d8680b719..3f4b117d9 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py @@ -2,7 +2,7 @@ from decimal import Decimal from flask.app import Flask -from flask_bpmn.models.db import db +from spiffworkflow_backend.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 48d0643320fbf22d9023ebc42a52b543234f0b94 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 17 Jan 2023 13:13:16 -0500 Subject: [PATCH 2/8] Remove the flask-bpmn directory. --- flask-bpmn/.cookiecutter.json | 12 - flask-bpmn/.darglint | 2 - flask-bpmn/.flake8 | 12 - flask-bpmn/.gitattributes | 1 - flask-bpmn/.github/dependabot.yml | 18 - flask-bpmn/.github/labels.yml | 66 - flask-bpmn/.github/release-drafter.yml | 29 - .../workflows/auto-merge-dependabot-prs.yml | 72 - flask-bpmn/.github/workflows/constraints.txt | 5 - flask-bpmn/.github/workflows/labeler.yml | 19 - flask-bpmn/.github/workflows/tests.yml | 189 -- flask-bpmn/.gitignore | 12 - flask-bpmn/.pre-commit-config.yaml | 58 - flask-bpmn/.readthedocs.yml | 12 - flask-bpmn/.tool-versions | 1 - flask-bpmn/CODE_OF_CONDUCT.rst | 105 - flask-bpmn/CONTRIBUTING.rst | 123 - flask-bpmn/LICENSE.rst | 22 - flask-bpmn/README.rst | 102 - flask-bpmn/codecov.yml | 9 - flask-bpmn/docs/codeofconduct.rst | 1 - flask-bpmn/docs/conf.py | 17 - flask-bpmn/docs/contributing.rst | 4 - flask-bpmn/docs/index.rst | 16 - flask-bpmn/docs/license.rst | 1 - flask-bpmn/docs/reference.rst | 9 - flask-bpmn/docs/requirements.txt | 3 - flask-bpmn/docs/usage.rst | 6 - flask-bpmn/noxfile.py | 205 -- flask-bpmn/poetry.lock | 2842 ----------------- flask-bpmn/pyproject.toml | 111 - flask-bpmn/sonar-project.properties | 7 - flask-bpmn/src/flask_bpmn/__init__.py | 1 - flask-bpmn/src/flask_bpmn/__main__.py | 13 - flask-bpmn/src/flask_bpmn/api/api_error.py | 207 -- flask-bpmn/src/flask_bpmn/models/__init__.py | 1 - flask-bpmn/src/flask_bpmn/models/db.py | 85 - flask-bpmn/src/flask_bpmn/models/group.py | 11 - flask-bpmn/src/flask_bpmn/py.typed | 0 flask-bpmn/tests/__init__.py | 1 - .../tests/flask_bpmn/api/test_api_error.py | 29 - .../tests/flask_bpmn/models/test_group.py | 20 - flask-bpmn/tests/test_main.py | 17 - 43 files changed, 4476 deletions(-) delete mode 100644 flask-bpmn/.cookiecutter.json delete mode 100644 flask-bpmn/.darglint delete mode 100644 flask-bpmn/.flake8 delete mode 100644 flask-bpmn/.gitattributes delete mode 100644 flask-bpmn/.github/dependabot.yml delete mode 100644 flask-bpmn/.github/labels.yml delete mode 100644 flask-bpmn/.github/release-drafter.yml delete mode 100644 flask-bpmn/.github/workflows/auto-merge-dependabot-prs.yml delete mode 100644 flask-bpmn/.github/workflows/constraints.txt delete mode 100644 flask-bpmn/.github/workflows/labeler.yml delete mode 100644 flask-bpmn/.github/workflows/tests.yml delete mode 100644 flask-bpmn/.gitignore delete mode 100644 flask-bpmn/.pre-commit-config.yaml delete mode 100644 flask-bpmn/.readthedocs.yml delete mode 100644 flask-bpmn/.tool-versions delete mode 100644 flask-bpmn/CODE_OF_CONDUCT.rst delete mode 100644 flask-bpmn/CONTRIBUTING.rst delete mode 100644 flask-bpmn/LICENSE.rst delete mode 100644 flask-bpmn/README.rst delete mode 100644 flask-bpmn/codecov.yml delete mode 100644 flask-bpmn/docs/codeofconduct.rst delete mode 100644 flask-bpmn/docs/conf.py delete mode 100644 flask-bpmn/docs/contributing.rst delete mode 100644 flask-bpmn/docs/index.rst delete mode 100644 flask-bpmn/docs/license.rst delete mode 100644 flask-bpmn/docs/reference.rst delete mode 100644 flask-bpmn/docs/requirements.txt delete mode 100644 flask-bpmn/docs/usage.rst delete mode 100644 flask-bpmn/noxfile.py delete mode 100644 flask-bpmn/poetry.lock delete mode 100644 flask-bpmn/pyproject.toml delete mode 100644 flask-bpmn/sonar-project.properties delete mode 100644 flask-bpmn/src/flask_bpmn/__init__.py delete mode 100644 flask-bpmn/src/flask_bpmn/__main__.py delete mode 100644 flask-bpmn/src/flask_bpmn/api/api_error.py delete mode 100644 flask-bpmn/src/flask_bpmn/models/__init__.py delete mode 100644 flask-bpmn/src/flask_bpmn/models/db.py delete mode 100644 flask-bpmn/src/flask_bpmn/models/group.py delete mode 100644 flask-bpmn/src/flask_bpmn/py.typed delete mode 100644 flask-bpmn/tests/__init__.py delete mode 100644 flask-bpmn/tests/flask_bpmn/api/test_api_error.py delete mode 100644 flask-bpmn/tests/flask_bpmn/models/test_group.py delete mode 100644 flask-bpmn/tests/test_main.py diff --git a/flask-bpmn/.cookiecutter.json b/flask-bpmn/.cookiecutter.json deleted file mode 100644 index f09c5bfd6..000000000 --- a/flask-bpmn/.cookiecutter.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "_template": "gh:cjolowicz/cookiecutter-hypermodern-python", - "author": "Sartography", - "development_status": "Development Status :: 1 - Planning", - "email": "sartography@users.noreply.github.com", - "friendly_name": "Flask Bpmn", - "github_user": "sartography", - "license": "MIT", - "package_name": "flask_bpmn", - "project_name": "flask-bpmn", - "version": "0.0.1" -} diff --git a/flask-bpmn/.darglint b/flask-bpmn/.darglint deleted file mode 100644 index 72ccc6c53..000000000 --- a/flask-bpmn/.darglint +++ /dev/null @@ -1,2 +0,0 @@ -[darglint] -strictness = long diff --git a/flask-bpmn/.flake8 b/flask-bpmn/.flake8 deleted file mode 100644 index 2a7ae7765..000000000 --- a/flask-bpmn/.flake8 +++ /dev/null @@ -1,12 +0,0 @@ -[flake8] -select = B,B9,C,D,DAR,E,F,N,RST,S,W -ignore = E203,E501,RST201,RST203,RST301,W503 -max-line-length = 120 -max-complexity = 30 -docstring-convention = google -rst-roles = class,const,func,meth,mod,ref -rst-directives = deprecated - -per-file-ignores = - # prefer naming tests descriptively rather than forcing comments - tests/*:S101,D103 diff --git a/flask-bpmn/.gitattributes b/flask-bpmn/.gitattributes deleted file mode 100644 index 6313b56c5..000000000 --- a/flask-bpmn/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf diff --git a/flask-bpmn/.github/dependabot.yml b/flask-bpmn/.github/dependabot.yml deleted file mode 100644 index a0a5c7350..000000000 --- a/flask-bpmn/.github/dependabot.yml +++ /dev/null @@ -1,18 +0,0 @@ -version: 2 -updates: - - package-ecosystem: github-actions - directory: "/" - schedule: - interval: daily - - package-ecosystem: pip - directory: "/.github/workflows" - schedule: - interval: daily - - package-ecosystem: pip - directory: "/docs" - schedule: - interval: daily - - package-ecosystem: pip - directory: "/" - schedule: - interval: daily diff --git a/flask-bpmn/.github/labels.yml b/flask-bpmn/.github/labels.yml deleted file mode 100644 index f7f83aad8..000000000 --- a/flask-bpmn/.github/labels.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Labels names are important as they are used by Release Drafter to decide -# regarding where to record them in changelog or if to skip them. -# -# The repository labels will be automatically configured using this file and -# the GitHub Action https://github.com/marketplace/actions/github-labeler. -- name: breaking - description: Breaking Changes - color: bfd4f2 -- name: bug - description: Something isn't working - color: d73a4a -- name: build - description: Build System and Dependencies - color: bfdadc -- name: ci - description: Continuous Integration - color: 4a97d6 -- name: dependencies - description: Pull requests that update a dependency file - color: 0366d6 -- name: documentation - description: Improvements or additions to documentation - color: 0075ca -- name: duplicate - description: This issue or pull request already exists - color: cfd3d7 -- name: enhancement - description: New feature or request - color: a2eeef -- name: github_actions - description: Pull requests that update Github_actions code - color: "000000" -- name: good first issue - description: Good for newcomers - color: 7057ff -- name: help wanted - description: Extra attention is needed - color: 008672 -- name: invalid - description: This doesn't seem right - color: e4e669 -- name: performance - description: Performance - color: "016175" -- name: python - description: Pull requests that update Python code - color: 2b67c6 -- name: question - description: Further information is requested - color: d876e3 -- name: refactoring - description: Refactoring - color: ef67c4 -- name: removal - description: Removals and Deprecations - color: 9ae7ea -- name: style - description: Style - color: c120e5 -- name: testing - description: Testing - color: b1fc6f -- name: wontfix - description: This will not be worked on - color: ffffff diff --git a/flask-bpmn/.github/release-drafter.yml b/flask-bpmn/.github/release-drafter.yml deleted file mode 100644 index 7a04410f9..000000000 --- a/flask-bpmn/.github/release-drafter.yml +++ /dev/null @@ -1,29 +0,0 @@ -categories: - - title: ":boom: Breaking Changes" - label: "breaking" - - title: ":rocket: Features" - label: "enhancement" - - title: ":fire: Removals and Deprecations" - label: "removal" - - title: ":beetle: Fixes" - label: "bug" - - title: ":racehorse: Performance" - label: "performance" - - title: ":rotating_light: Testing" - label: "testing" - - title: ":construction_worker: Continuous Integration" - label: "ci" - - title: ":books: Documentation" - label: "documentation" - - title: ":hammer: Refactoring" - label: "refactoring" - - title: ":lipstick: Style" - label: "style" - - title: ":package: Dependencies" - labels: - - "dependencies" - - "build" -template: | - ## Changes - - $CHANGES diff --git a/flask-bpmn/.github/workflows/auto-merge-dependabot-prs.yml b/flask-bpmn/.github/workflows/auto-merge-dependabot-prs.yml deleted file mode 100644 index b5c60e1da..000000000 --- a/flask-bpmn/.github/workflows/auto-merge-dependabot-prs.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Dependabot auto-merge -on: - workflow_run: - workflows: ["Tests"] - # completed does not mean success of Tests workflow. see below checking github.event.workflow_run.conclusion - types: - - completed - -# workflow_call is used to indicate that a workflow can be called by another workflow. When a workflow is triggered with the workflow_call event, the event payload in the called workflow is the same event payload from the calling workflow. For more information see, "Reusing workflows." - -# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request -# maybe hook into this instead of workflow_run: -# on: -# pull_request: -# pull_request_target: -# types: [labeled] - -permissions: - contents: write - -jobs: - # print the context for debugging in case a job gets skipped - printJob: - name: Print event - runs-on: ubuntu-latest - steps: - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: | - echo "$GITHUB_CONTEXT" - - dependabot: - runs-on: ubuntu-latest - if: ${{ github.actor == 'dependabot[bot]' && github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }} - steps: - - name: Development Code - uses: actions/checkout@v3 - - ###### GET PR NUMBER - # we saved the pr_number in tests.yml. fetch it so we can merge the correct PR. - # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run - - name: "Download artifact" - uses: actions/github-script@v6 - with: - script: | - let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.payload.workflow_run.id, - }); - let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { - return artifact.name == "pr_number" - })[0]; - let download = await github.rest.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - let fs = require('fs'); - fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_number.zip`, Buffer.from(download.data)); - - name: "Unzip artifact" - run: unzip pr_number.zip - ########### - - - name: print pr number - run: cat pr_number - - name: actually merge it - run: gh pr merge --auto --merge "$(cat pr_number)" - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/flask-bpmn/.github/workflows/constraints.txt b/flask-bpmn/.github/workflows/constraints.txt deleted file mode 100644 index f30a60fc1..000000000 --- a/flask-bpmn/.github/workflows/constraints.txt +++ /dev/null @@ -1,5 +0,0 @@ -pip==22.3.1 -nox==2022.8.7 -nox-poetry==1.0.2 -poetry==1.2.2 -virtualenv==20.16.7 diff --git a/flask-bpmn/.github/workflows/labeler.yml b/flask-bpmn/.github/workflows/labeler.yml deleted file mode 100644 index f39cfa6c7..000000000 --- a/flask-bpmn/.github/workflows/labeler.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Labeler - -on: - push: - branches: - - main - - master - -jobs: - labeler: - runs-on: ubuntu-latest - steps: - - name: Check out the repository - uses: actions/checkout@v3.0.2 - - - name: Run Labeler - uses: crazy-max/ghaction-github-labeler@v3.1.1 - with: - skip-delete: true diff --git a/flask-bpmn/.github/workflows/tests.yml b/flask-bpmn/.github/workflows/tests.yml deleted file mode 100644 index aad6cd840..000000000 --- a/flask-bpmn/.github/workflows/tests.yml +++ /dev/null @@ -1,189 +0,0 @@ -name: Tests - -on: - - push - - pull_request - -jobs: - tests: - name: ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - { python: "3.10", os: "ubuntu-latest", session: "pre-commit" } - - { python: "3.10", os: "ubuntu-latest", session: "safety" } - - { python: "3.10", os: "ubuntu-latest", session: "mypy" } - - { python: "3.9", os: "ubuntu-latest", session: "mypy" } - - { python: "3.8", os: "ubuntu-latest", session: "mypy" } - - { python: "3.7", os: "ubuntu-latest", session: "mypy" } - - { python: "3.10", os: "ubuntu-latest", session: "tests" } - - { python: "3.9", os: "ubuntu-latest", session: "tests" } - - { python: "3.8", os: "ubuntu-latest", session: "tests" } - - { python: "3.7", os: "ubuntu-latest", session: "tests" } - - { python: "3.10", os: "windows-latest", session: "tests" } - - { python: "3.10", os: "macos-latest", session: "tests" } - - { python: "3.10", os: "ubuntu-latest", session: "typeguard" } - - { python: "3.10", os: "ubuntu-latest", session: "xdoctest" } - - { python: "3.10", os: "ubuntu-latest", session: "docs-build" } - - env: - NOXSESSION: ${{ matrix.session }} - FORCE_COLOR: "1" - PRE_COMMIT_COLOR: "always" - - steps: - - name: Check out the repository - uses: actions/checkout@v3.0.2 - - - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4.2.0 - with: - python-version: ${{ matrix.python }} - - - name: Upgrade pip - run: | - pip install --constraint=.github/workflows/constraints.txt pip - pip --version - - - name: Upgrade pip in virtual environments - shell: python - run: | - import os - import pip - - with open(os.environ["GITHUB_ENV"], mode="a") as io: - print(f"VIRTUALENV_PIP={pip.__version__}", file=io) - - - name: Install Poetry - run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry - poetry --version - - - name: Install Nox - run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox - pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry - nox --version - - - name: Compute pre-commit cache key - if: matrix.session == 'pre-commit' - id: pre-commit-cache - shell: python - run: | - import hashlib - import sys - - python = "py{}.{}".format(*sys.version_info[:2]) - payload = sys.version.encode() + sys.executable.encode() - digest = hashlib.sha256(payload).hexdigest() - result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) - - print("::set-output name=result::{}".format(result)) - - - name: Restore pre-commit cache - uses: actions/cache@v3.0.6 - if: matrix.session == 'pre-commit' - with: - path: ~/.cache/pre-commit - key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - ${{ steps.pre-commit-cache.outputs.result }}- - - - name: Run Nox - run: | - nox --force-color --python=${{ matrix.python }} - - - name: Upload coverage data - # pin to upload coverage from only one matrix entry, otherwise coverage gets confused later - if: always() && matrix.session == 'tests' && matrix.python == '3.10' && matrix.os == 'ubuntu-latest' - uses: "actions/upload-artifact@v3.1.1" - with: - name: coverage-data - path: ".coverage.*" - - - name: Upload documentation - if: matrix.session == 'docs-build' - uses: actions/upload-artifact@v3.1.1 - with: - name: docs - path: docs/_build - - coverage: - runs-on: ubuntu-latest - needs: tests - steps: - - name: Check out the repository - uses: actions/checkout@v3.0.2 - with: - # Disabling shallow clone is recommended for improving relevancy of reporting in sonarcloud - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v4.2.0 - with: - python-version: "3.10" - - - name: Upgrade pip - run: | - pip install --constraint=.github/workflows/constraints.txt pip - pip --version - - - name: Install Poetry - run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry - poetry --version - - - name: Install Nox - run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox - pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry - nox --version - - - name: Download coverage data - uses: actions/download-artifact@v3.0.1 - with: - name: coverage-data - - - name: Combine coverage data and display human readable report - run: | - find . -name \*.pyc -delete - nox --force-color --session=coverage - - - name: Create coverage report - run: | - nox --force-color --session=coverage -- xml - - - name: Upload coverage report - uses: codecov/codecov-action@v3.1.0 - with: - # server is flaky. see https://github.com/codecov/codecov-action/issues/598 - fail_ci_if_error: false - - - name: SonarCloud Scan - # thought about just skipping dependabot - # if: ${{ github.actor != 'dependabot[bot]' }} - # but figured all pull requests seems better, since none of them will have access to sonarcloud. - # however, with just skipping pull requests, the build associated with "Triggered via push" is also associated with the pull request and also fails hitting sonarcloud - # if: ${{ github.event_name != 'pull_request' }} - # so just skip everything but main - if: github.ref_name == 'main' - uses: sonarsource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - # part about saving PR number and then using it from auto-merge-dependabot-prs from: - # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run - - name: Save PR number - if: ${{ github.event_name == 'pull_request' }} - env: - PR_NUMBER: ${{ github.event.number }} - run: | - mkdir -p ./pr - echo "$PR_NUMBER" > ./pr/pr_number - - uses: actions/upload-artifact@v3.1.1 - with: - name: pr_number - path: pr/ diff --git a/flask-bpmn/.gitignore b/flask-bpmn/.gitignore deleted file mode 100644 index cc7a61e61..000000000 --- a/flask-bpmn/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -.mypy_cache/ -/.coverage -/.coverage.* -/.nox/ -/.python-version -/.pytype/ -/dist/ -/docs/_build/ -/src/*.egg-info/ -__pycache__/ -*.sqlite3 -/pyrightconfig.json diff --git a/flask-bpmn/.pre-commit-config.yaml b/flask-bpmn/.pre-commit-config.yaml deleted file mode 100644 index f0546397a..000000000 --- a/flask-bpmn/.pre-commit-config.yaml +++ /dev/null @@ -1,58 +0,0 @@ -repos: - - repo: local - hooks: - - id: black - name: black - entry: black - language: system - types: [python] - require_serial: true - - id: check-added-large-files - name: Check for added large files - entry: check-added-large-files - language: system - - id: check-toml - name: Check Toml - entry: check-toml - language: system - types: [toml] - - id: check-yaml - name: Check Yaml - entry: check-yaml - language: system - types: [yaml] - - id: end-of-file-fixer - name: Fix End of Files - entry: end-of-file-fixer - language: system - types: [text] - stages: [commit, push, manual] - - id: flake8 - name: flake8 - entry: flake8 - language: system - types: [python] - require_serial: true - - id: pyupgrade - name: pyupgrade - description: Automatically upgrade syntax for newer versions. - entry: pyupgrade - language: system - types: [python] - args: [--py37-plus] - - id: reorder-python-imports - name: Reorder python imports - entry: reorder-python-imports - language: system - types: [python] - args: [--application-directories=src] - - id: trailing-whitespace - name: Trim Trailing Whitespace - entry: trailing-whitespace-fixer - language: system - types: [text] - stages: [commit, push, manual] - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.4.1 - hooks: - - id: prettier diff --git a/flask-bpmn/.readthedocs.yml b/flask-bpmn/.readthedocs.yml deleted file mode 100644 index 66f2a214b..000000000 --- a/flask-bpmn/.readthedocs.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: 2 -build: - os: ubuntu-20.04 - tools: - python: "3.10" -sphinx: - configuration: docs/conf.py -formats: all -python: - install: - - requirements: docs/requirements.txt - - path: . diff --git a/flask-bpmn/.tool-versions b/flask-bpmn/.tool-versions deleted file mode 100644 index a7b6ef2e7..000000000 --- a/flask-bpmn/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -python 3.11.0 diff --git a/flask-bpmn/CODE_OF_CONDUCT.rst b/flask-bpmn/CODE_OF_CONDUCT.rst deleted file mode 100644 index 0af086d54..000000000 --- a/flask-bpmn/CODE_OF_CONDUCT.rst +++ /dev/null @@ -1,105 +0,0 @@ -Contributor Covenant Code of Conduct -==================================== - -Our Pledge ----------- - -We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. - - -Our Standards -------------- - -Examples of behavior that contributes to a positive environment for our community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or - advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -Enforcement Responsibilities ----------------------------- - -Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. - - -Scope ------ - -This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. - - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at sartography@users.noreply.github.com. All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the reporter of any incident. - - -Enforcement Guidelines ----------------------- - -Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: - - -1. Correction -~~~~~~~~~~~~~ - -**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. - - -2. Warning -~~~~~~~~~~ - -**Community Impact**: A violation through a single incident or series of actions. - -**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. - - -3. Temporary Ban -~~~~~~~~~~~~~~~~ - -**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. - - -4. Permanent Ban -~~~~~~~~~~~~~~~~ - -**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the community. - - -Attribution ------------ - -This Code of Conduct is adapted from the `Contributor Covenant `__, version 2.0, -available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by `Mozilla’s code of conduct enforcement ladder `__. - -.. _homepage: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. diff --git a/flask-bpmn/CONTRIBUTING.rst b/flask-bpmn/CONTRIBUTING.rst deleted file mode 100644 index e160841d6..000000000 --- a/flask-bpmn/CONTRIBUTING.rst +++ /dev/null @@ -1,123 +0,0 @@ -Contributor Guide -================= - -Thank you for your interest in improving this project. -This project is open-source under the `MIT license`_ and -welcomes contributions in the form of bug reports, feature requests, and pull requests. - -Here is a list of important resources for contributors: - -- `Source Code`_ -- `Documentation`_ -- `Issue Tracker`_ -- `Code of Conduct`_ - -.. _MIT license: https://opensource.org/licenses/MIT -.. _Source Code: https://github.com/sartography/flask-bpmn -.. _Documentation: https://flask-bpmn.readthedocs.io/ -.. _Issue Tracker: https://github.com/sartography/flask-bpmn/issues - -How to report a bug -------------------- - -Report bugs on the `Issue Tracker`_. - -When filing an issue, make sure to answer these questions: - -- Which operating system and Python version are you using? -- Which version of this project are you using? -- What did you do? -- What did you expect to see? -- What did you see instead? - -The best way to get your bug fixed is to provide a test case, -and/or steps to reproduce the issue. - - -How to request a feature ------------------------- - -Request features on the `Issue Tracker`_. - - -How to set up your development environment ------------------------------------------- - -You need Python 3.7+ and the following tools: - -- Poetry_ -- Nox_ -- nox-poetry_ - -Install the package with development requirements: - -.. code:: console - - $ poetry install - -You can now run an interactive Python session, -or the command-line interface: - -.. code:: console - - $ poetry run python - $ poetry run flask-bpmn - -.. _Poetry: https://python-poetry.org/ -.. _Nox: https://nox.thea.codes/ -.. _nox-poetry: https://nox-poetry.readthedocs.io/ - - -How to test the project ------------------------ - -Run the full test suite: - -.. code:: console - - $ nox - -List the available Nox sessions: - -.. code:: console - - $ nox --list-sessions - -You can also run a specific Nox session. -For example, invoke the unit test suite like this: - -.. code:: console - - $ nox --session=tests - -Unit tests are located in the ``tests`` directory, -and are written using the pytest_ testing framework. - -.. _pytest: https://pytest.readthedocs.io/ - - -How to submit changes ---------------------- - -Open a `pull request`_ to submit changes to this project. - -Your pull request needs to meet the following guidelines for acceptance: - -- The Nox test suite must pass without errors and warnings. -- Include unit tests. This project maintains 100% code coverage. -- If your changes add functionality, update the documentation accordingly. - -Feel free to submit early, though—we can always iterate on this. - -To run linting and code formatting checks before committing your change, you can install pre-commit as a Git hook by running the following command: - -.. code:: console - - $ nox --session=pre-commit -- install - -It is recommended to open an issue before starting work on anything. -This will allow a chance to talk it over with the owners and validate your approach. - -.. _pull request: https://github.com/sartography/flask-bpmn/pulls -.. github-only -.. _Code of Conduct: CODE_OF_CONDUCT.rst diff --git a/flask-bpmn/LICENSE.rst b/flask-bpmn/LICENSE.rst deleted file mode 100644 index d22178855..000000000 --- a/flask-bpmn/LICENSE.rst +++ /dev/null @@ -1,22 +0,0 @@ -MIT License -=========== - -Copyright © 2022 Sartography - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -**The software is provided "as is", without warranty of any kind, express or -implied, including but not limited to the warranties of merchantability, -fitness for a particular purpose and noninfringement. In no event shall the -authors or copyright holders be liable for any claim, damages or other -liability, whether in an action of contract, tort or otherwise, arising from, -out of or in connection with the software or the use or other dealings in the -software.** diff --git a/flask-bpmn/README.rst b/flask-bpmn/README.rst deleted file mode 100644 index 219b9870e..000000000 --- a/flask-bpmn/README.rst +++ /dev/null @@ -1,102 +0,0 @@ -Flask Bpmn -========== - -|PyPI| |Status| |Python Version| |License| - -|Read the Docs| |Tests| |Codecov| - -|pre-commit| |Black| - -.. |PyPI| image:: https://img.shields.io/pypi/v/flask-bpmn.svg - :target: https://pypi.org/project/flask-bpmn/ - :alt: PyPI -.. |Status| image:: https://img.shields.io/pypi/status/flask-bpmn.svg - :target: https://pypi.org/project/flask-bpmn/ - :alt: Status -.. |Python Version| image:: https://img.shields.io/pypi/pyversions/flask-bpmn - :target: https://pypi.org/project/flask-bpmn - :alt: Python Version -.. |License| image:: https://img.shields.io/pypi/l/flask-bpmn - :target: https://opensource.org/licenses/MIT - :alt: License -.. |Read the Docs| image:: https://img.shields.io/readthedocs/flask-bpmn/latest.svg?label=Read%20the%20Docs - :target: https://flask-bpmn.readthedocs.io/ - :alt: Read the documentation at https://flask-bpmn.readthedocs.io/ -.. |Tests| image:: https://github.com/sartography/flask-bpmn/workflows/Tests/badge.svg - :target: https://github.com/sartography/flask-bpmn/actions?workflow=Tests - :alt: Tests -.. |Codecov| image:: https://codecov.io/gh/sartography/flask-bpmn/branch/main/graph/badge.svg - :target: https://codecov.io/gh/sartography/flask-bpmn - :alt: Codecov -.. |pre-commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white - :target: https://github.com/pre-commit/pre-commit - :alt: pre-commit -.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Black - - -Features --------- - -* Provides bmpn engine functionality for inclusion in a flask application. - - -Requirements ------------- - -* Python 3.7+ - - -Installation ------------- - -You can install *Flask Bpmn* via pip_ from PyPI_: - -.. code:: console - - $ pip install flask-bpmn - - -Usage ------ - -Please see the `Command-line Reference `_ for details. - - -Contributing ------------- - -Contributions are very welcome. -To learn more, see the `Contributor Guide`_. - - -License -------- - -Distributed under the terms of the `MIT license`_, -*Flask Bpmn* is free and open source software. - - -Issues ------- - -If you encounter any problems, -please `file an issue`_ along with a detailed description. - - -Credits -------- - -This project was generated from `@cjolowicz`_'s `Hypermodern Python Cookiecutter`_ template. - -.. _@cjolowicz: https://github.com/cjolowicz -.. _Cookiecutter: https://github.com/audreyr/cookiecutter -.. _MIT license: https://opensource.org/licenses/MIT -.. _PyPI: https://pypi.org/ -.. _Hypermodern Python Cookiecutter: https://github.com/cjolowicz/cookiecutter-hypermodern-python -.. _file an issue: https://github.com/sartography/flask-bpmn/issues -.. _pip: https://pip.pypa.io/ -.. github-only -.. _Contributor Guide: CONTRIBUTING.rst -.. _Usage: https://flask-bpmn.readthedocs.io/en/latest/usage.html diff --git a/flask-bpmn/codecov.yml b/flask-bpmn/codecov.yml deleted file mode 100644 index 9ac26504d..000000000 --- a/flask-bpmn/codecov.yml +++ /dev/null @@ -1,9 +0,0 @@ -comment: false -coverage: - status: - project: - default: - target: "100" - patch: - default: - target: "100" diff --git a/flask-bpmn/docs/codeofconduct.rst b/flask-bpmn/docs/codeofconduct.rst deleted file mode 100644 index 96e0ba2f5..000000000 --- a/flask-bpmn/docs/codeofconduct.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CODE_OF_CONDUCT.rst diff --git a/flask-bpmn/docs/conf.py b/flask-bpmn/docs/conf.py deleted file mode 100644 index 5cba81cfe..000000000 --- a/flask-bpmn/docs/conf.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Sphinx configuration.""" -from datetime import datetime - - -project = "Flask Bpmn" -author = "Sartography" -copyright = f"{datetime.now().year}, {author}" -extensions = [ - "sphinx.ext.napoleon", - "autoapi.extension", - "sphinx_click", -] - -# https://github.com/readthedocs/sphinx-autoapi -autoapi_type = "python" -autoapi_dirs = ["../src"] -html_theme = "furo" diff --git a/flask-bpmn/docs/contributing.rst b/flask-bpmn/docs/contributing.rst deleted file mode 100644 index c8670b6bb..000000000 --- a/flask-bpmn/docs/contributing.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. include:: ../CONTRIBUTING.rst - :end-before: github-only - -.. _Code of Conduct: codeofconduct.html diff --git a/flask-bpmn/docs/index.rst b/flask-bpmn/docs/index.rst deleted file mode 100644 index fef4a7ecf..000000000 --- a/flask-bpmn/docs/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. include:: ../README.rst - :end-before: github-only - -.. _Contributor Guide: contributing.html -.. _Usage: usage.html - -.. toctree:: - :hidden: - :maxdepth: 1 - - usage - reference - contributing - Code of Conduct - License - Changelog diff --git a/flask-bpmn/docs/license.rst b/flask-bpmn/docs/license.rst deleted file mode 100644 index 68c5792f0..000000000 --- a/flask-bpmn/docs/license.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../LICENSE.rst diff --git a/flask-bpmn/docs/reference.rst b/flask-bpmn/docs/reference.rst deleted file mode 100644 index 78844bfeb..000000000 --- a/flask-bpmn/docs/reference.rst +++ /dev/null @@ -1,9 +0,0 @@ -Reference -========= - - -flask_bpmn ----------- - -.. automodule:: flask_bpmn - :members: diff --git a/flask-bpmn/docs/requirements.txt b/flask-bpmn/docs/requirements.txt deleted file mode 100644 index 40b16b180..000000000 --- a/flask-bpmn/docs/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -furo==2022.9.29 -sphinx==5.3.0 -sphinx-click==4.3.0 diff --git a/flask-bpmn/docs/usage.rst b/flask-bpmn/docs/usage.rst deleted file mode 100644 index e29175966..000000000 --- a/flask-bpmn/docs/usage.rst +++ /dev/null @@ -1,6 +0,0 @@ -Usage -===== - -.. click:: flask_bpmn.__main__:main - :prog: flask-bpmn - :nested: full diff --git a/flask-bpmn/noxfile.py b/flask-bpmn/noxfile.py deleted file mode 100644 index 046bc6f2a..000000000 --- a/flask-bpmn/noxfile.py +++ /dev/null @@ -1,205 +0,0 @@ -"""Nox sessions.""" -import os -import shutil -import sys -from pathlib import Path -from textwrap import dedent - -import nox - -try: - from nox_poetry import Session - from nox_poetry import session -except ImportError: - message = f"""\ - Nox failed to import the 'nox-poetry' package. - - Please install it using the following command: - - {sys.executable} -m pip install nox-poetry""" - raise SystemExit(dedent(message)) from None - - -package = "flask_bpmn" -python_versions = ["3.10", "3.9", "3.8", "3.7"] -nox.needs_version = ">= 2021.6.6" -nox.options.sessions = ( - "pre-commit", - "safety", - "mypy", - "tests", - "typeguard", - "xdoctest", - "docs-build", -) - - -def activate_virtualenv_in_precommit_hooks(session: Session) -> None: - """Activate virtualenv in hooks installed by pre-commit. - - This function patches git hooks installed by pre-commit to activate the - session's virtual environment. This allows pre-commit to locate hooks in - that environment when invoked from git. - - Args: - session: The Session object. - """ - assert session.bin is not None # noqa: S101 - - virtualenv = session.env.get("VIRTUAL_ENV") - if virtualenv is None: - return - - hookdir = Path(".git") / "hooks" - if not hookdir.is_dir(): - return - - for hook in hookdir.iterdir(): - if hook.name.endswith(".sample") or not hook.is_file(): - continue - - text = hook.read_text() - bindir = repr(session.bin)[1:-1] # strip quotes - if not ( - Path("A") == Path("a") and bindir.lower() in text.lower() or bindir in text - ): - continue - - lines = text.splitlines() - if not (lines[0].startswith("#!") and "python" in lines[0].lower()): - continue - - header = dedent( - f"""\ - import os - os.environ["VIRTUAL_ENV"] = {virtualenv!r} - os.environ["PATH"] = os.pathsep.join(( - {session.bin!r}, - os.environ.get("PATH", ""), - )) - """ - ) - - lines.insert(1, header) - hook.write_text("\n".join(lines)) - - -@session(name="pre-commit", python="3.10") -def precommit(session: Session) -> None: - """Lint using pre-commit.""" - args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"] - session.install( - "black", - "darglint", - "flake8", - "flake8-bandit", - "flake8-bugbear", - "flake8-docstrings", - "flake8-rst-docstrings", - "pep8-naming", - "pre-commit", - "pre-commit-hooks", - "pyupgrade", - "reorder-python-imports", - ) - session.run("pre-commit", *args) - if args and args[0] == "install": - activate_virtualenv_in_precommit_hooks(session) - - -@session(python="3.10") -def safety(session: Session) -> None: - """Scan dependencies for insecure packages.""" - requirements = session.poetry.export_requirements() - session.install("safety") - session.run("safety", "check", "--full-report", f"--file={requirements}") - - -@session(python=python_versions) -def mypy(session: Session) -> None: - """Type-check using mypy.""" - args = session.posargs or ["src", "tests", "docs/conf.py"] - session.install(".") - session.install("mypy", "pytest") - session.run("mypy", *args) - if not session.posargs: - session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py") - - -@session(python=python_versions) -def tests(session: Session) -> None: - """Run the test suite.""" - session.install(".") - session.install("coverage[toml]", "pytest", "pygments") - try: - session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs) - finally: - if session.interactive: - session.notify("coverage", posargs=[]) - - -@session -def coverage(session: Session) -> None: - """Produce the coverage report.""" - args = session.posargs or ["report"] - - session.install("coverage[toml]") - - if not session.posargs and any(Path().glob(".coverage.*")): - session.run("coverage", "combine") - - session.run("coverage", *args) - - -@session(python=python_versions) -def typeguard(session: Session) -> None: - """Runtime type checking using Typeguard.""" - session.install(".") - session.install("pytest", "typeguard", "pygments") - session.run("pytest", f"--typeguard-packages={package}", *session.posargs) - - -@session(python=python_versions) -def xdoctest(session: Session) -> None: - """Run examples with xdoctest.""" - if session.posargs: - args = [package, *session.posargs] - else: - args = [f"--modname={package}", "--command=all"] - if "FORCE_COLOR" in os.environ: - args.append("--colored=1") - - session.install(".") - session.install("xdoctest[colors]") - session.run("python", "-m", "xdoctest", *args) - - -@session(name="docs-build", python="3.10") -def docs_build(session: Session) -> None: - """Build the documentation.""" - args = session.posargs or ["docs", "docs/_build"] - if not session.posargs and "FORCE_COLOR" in os.environ: - args.insert(0, "--color") - - session.install(".") - session.install("sphinx", "sphinx-click", "furo") - - build_dir = Path("docs", "_build") - if build_dir.exists(): - shutil.rmtree(build_dir) - - session.run("sphinx-build", *args) - - -@session(python="3.10") -def docs(session: Session) -> None: - """Build and serve the documentation with live reloading on file changes.""" - args = session.posargs or ["--open-browser", "docs", "docs/_build"] - session.install(".") - session.install("sphinx", "sphinx-autobuild", "sphinx-click", "furo") - - build_dir = Path("docs", "_build") - if build_dir.exists(): - shutil.rmtree(build_dir) - - session.run("sphinx-autobuild", *args) diff --git a/flask-bpmn/poetry.lock b/flask-bpmn/poetry.lock deleted file mode 100644 index e1ce1b3ad..000000000 --- a/flask-bpmn/poetry.lock +++ /dev/null @@ -1,2842 +0,0 @@ -[[package]] -name = "alabaster" -version = "0.7.12" -description = "A configurable sidebar-enabled Sphinx theme" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "alembic" -version = "1.7.7" -description = "A database migration tool for SQLAlchemy." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} -importlib-resources = {version = "*", markers = "python_version < \"3.9\""} -Mako = "*" -SQLAlchemy = ">=1.3.0" - -[package.extras] -tz = ["python-dateutil"] - -[[package]] -name = "amqp" -version = "5.1.1" -description = "Low-level AMQP client for Python (fork of amqplib)." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -vine = ">=5.0.0" - -[[package]] -name = "aniso8601" -version = "9.0.1" -description = "A library for parsing ISO 8601 strings." -category = "main" -optional = false -python-versions = "*" - -[package.extras] -dev = ["black", "coverage", "isort", "pre-commit", "pyenchant", "pylint"] - -[[package]] -name = "astroid" -version = "2.11.5" -description = "An abstract syntax tree for Python with inference support." -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -setuptools = ">=20.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" - -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "21.4.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] - -[[package]] -name = "babel" -version = "2.10.1" -description = "Internationalization utilities" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pytz = ">=2015.7" - -[[package]] -name = "bandit" -version = "1.7.2" -description = "Security oriented static analyser for python code." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -stevedore = ">=1.20.0" - -[package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] -yaml = ["PyYAML"] - -[[package]] -name = "bcrypt" -version = "3.2.2" -description = "Modern password hashing for your software and your servers" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cffi = ">=1.1" - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - -[[package]] -name = "beautifulsoup4" -version = "4.11.1" -description = "Screen-scraping library" -category = "dev" -optional = false -python-versions = ">=3.6.0" - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "billiard" -version = "3.6.4.0" -description = "Python multiprocessing fork with improvements and bugfixes" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "black" -version = "22.10.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "blinker" -version = "1.4" -description = "Fast, simple object-to-object and broadcast signaling" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "cached-property" -version = "1.5.2" -description = "A decorator for caching properties in classes." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "celery" -version = "5.2.7" -description = "Distributed Task Queue." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -billiard = ">=3.6.4.0,<4.0" -click = ">=8.0.3,<9.0" -click-didyoumean = ">=0.0.3" -click-plugins = ">=1.1.1" -click-repl = ">=0.2.0" -importlib-metadata = {version = ">=1.4.0", markers = "python_version < \"3.8\""} -kombu = ">=5.2.3,<6.0" -pytz = ">=2021.3" -vine = ">=5.0.0,<6.0" - -[package.extras] -arangodb = ["pyArango (>=1.3.2)"] -auth = ["cryptography"] -azureblockblob = ["azure-storage-blob (==12.9.0)"] -brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] -cassandra = ["cassandra-driver (<3.21.0)"] -consul = ["python-consul2"] -cosmosdbsql = ["pydocumentdb (==2.3.2)"] -couchbase = ["couchbase (>=3.0.0)"] -couchdb = ["pycouchdb"] -django = ["Django (>=1.11)"] -dynamodb = ["boto3 (>=1.9.178)"] -elasticsearch = ["elasticsearch"] -eventlet = ["eventlet (>=0.32.0)"] -gevent = ["gevent (>=1.5.0)"] -librabbitmq = ["librabbitmq (>=1.5.0)"] -memcache = ["pylibmc"] -mongodb = ["pymongo[srv] (>=3.11.1)"] -msgpack = ["msgpack"] -pymemcache = ["python-memcached"] -pyro = ["pyro4"] -pytest = ["pytest-celery"] -redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] -s3 = ["boto3 (>=1.9.125)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem"] -sqlalchemy = ["sqlalchemy"] -sqs = ["kombu[sqs]"] -tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard"] - -[[package]] -name = "certifi" -version = "2021.10.8" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "cffi" -version = "1.15.0" -description = "Foreign Function Interface for Python calling C code." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "cfgv" -version = "3.3.1" -description = "Validate configuration and produce human readable error messages." -category = "dev" -optional = false -python-versions = ">=3.6.1" - -[[package]] -name = "charset-normalizer" -version = "2.0.12" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode-backport = ["unicodedata2"] - -[[package]] -name = "classify-imports" -version = "4.1.0" -description = "Utilities for refactoring imports in python-like syntax." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[[package]] -name = "click-didyoumean" -version = "0.3.0" -description = "Enables git-like *did-you-mean* feature in click" -category = "main" -optional = false -python-versions = ">=3.6.2,<4.0.0" - -[package.dependencies] -click = ">=7" - -[[package]] -name = "click-plugins" -version = "1.1.1" -description = "An extension module for click to enable registering CLI commands via setuptools entry-points." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -click = ">=4.0" - -[package.extras] -dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] - -[[package]] -name = "click-repl" -version = "0.2.0" -description = "REPL plugin for Click" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -click = "*" -prompt-toolkit = "*" -six = "*" - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "configparser" -version = "5.2.0" -description = "Updated configparser from Python 3.8 for Python 2.6+." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy", "types-backports"] - -[[package]] -name = "coverage" -version = "6.5.0" -description = "Code coverage measurement for Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli"] - -[[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" - -[[package]] -name = "distlib" -version = "0.3.4" -description = "Distribution utilities" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "docutils" -version = "0.17.1" -description = "Docutils -- Python Documentation Utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "dparse" -version = "0.6.2" -description = "A parser for Python dependency files" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -packaging = "*" -toml = "*" - -[package.extras] -conda = ["pyyaml"] -pipenv = ["pipenv"] - -[[package]] -name = "filelock" -version = "3.7.0" -description = "A platform independent file lock." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] -testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] - -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = "<4.3", markers = "python_version < \"3.8\""} -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[[package]] -name = "flake8-bandit" -version = "2.1.2" -description = "Automated security testing with bandit and flake8." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -bandit = "*" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" - -[[package]] -name = "flake8-bugbear" -version = "22.10.27" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] - -[[package]] -name = "flake8-docstrings" -version = "1.6.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flake8-rst-docstrings" -version = "0.3.0" -description = "Python docstring reStructuredText (RST) validator for flake8" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -flake8 = ">=3" -pygments = "*" -restructuredtext-lint = "*" - -[package.extras] -develop = ["build", "twine"] - -[[package]] -name = "flask" -version = "2.2.2" -description = "A simple framework for building complex web applications." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0" -importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} -itsdangerous = ">=2.0" -Jinja2 = ">=3.0" -Werkzeug = ">=2.2.2" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "flask-admin" -version = "1.6.0" -description = "Simple and extensible admin interface framework for Flask" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Flask = ">=0.7" -wtforms = "*" - -[package.extras] -aws = ["boto"] -azure = ["azure-storage-blob"] - -[[package]] -name = "flask-bcrypt" -version = "1.0.1" -description = "Brcrypt hashing for Flask." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -bcrypt = ">=3.1.1" -Flask = "*" - -[[package]] -name = "flask-cors" -version = "3.0.10" -description = "A Flask extension adding a decorator for CORS support" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Flask = ">=0.9" -Six = "*" - -[[package]] -name = "flask-mail" -version = "0.9.1" -description = "Flask extension for sending email" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -blinker = "*" -Flask = "*" - -[[package]] -name = "flask-marshmallow" -version = "0.14.0" -description = "Flask + marshmallow for beautiful APIs" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Flask = "*" -marshmallow = ">=2.0.0" -six = ">=1.9.0" - -[package.extras] -dev = ["flake8 (==3.8.3)", "flake8-bugbear (==20.1.4)", "flask-sqlalchemy", "marshmallow-sqlalchemy (>=0.13.0)", "marshmallow-sqlalchemy (>=0.13.0,<0.19.0)", "mock", "pre-commit (>=2.4,<3.0)", "pytest", "tox"] -docs = ["Sphinx (==3.2.1)", "marshmallow-sqlalchemy (>=0.13.0)", "sphinx-issues (==1.2.0)"] -lint = ["flake8 (==3.8.3)", "flake8-bugbear (==20.1.4)", "pre-commit (>=2.4,<3.0)"] -sqlalchemy = ["flask-sqlalchemy", "marshmallow-sqlalchemy (>=0.13.0)", "marshmallow-sqlalchemy (>=0.13.0,<0.19.0)"] -tests = ["flask-sqlalchemy", "marshmallow-sqlalchemy (>=0.13.0)", "marshmallow-sqlalchemy (>=0.13.0,<0.19.0)", "mock", "pytest"] - -[[package]] -name = "flask-migrate" -version = "4.0.0" -description = "SQLAlchemy database migrations for Flask applications using Alembic." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -alembic = ">=0.7" -Flask = ">=0.9" -Flask-SQLAlchemy = ">=1.0" - -[[package]] -name = "flask-restful" -version = "0.3.9" -description = "Simple framework for creating REST APIs" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -aniso8601 = ">=0.82" -Flask = ">=0.8" -pytz = "*" -six = ">=1.3.0" - -[package.extras] -docs = ["sphinx"] - -[[package]] -name = "flask-sqlalchemy" -version = "2.5.1" -description = "Adds SQLAlchemy support to your Flask application." -category = "main" -optional = false -python-versions = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*" - -[package.dependencies] -Flask = ">=0.10" -SQLAlchemy = ">=0.8.0" - -[[package]] -name = "furo" -version = "2022.9.29" -description = "A clean customisable Sphinx documentation theme." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -beautifulsoup4 = "*" -pygments = ">=2.7" -sphinx = ">=4.0,<6.0" -sphinx-basic-ng = "*" - -[[package]] -name = "gitdb" -version = "4.0.9" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.27" -description = "GitPython is a python library used to interact with Git repositories" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} - -[[package]] -name = "greenlet" -version = "2.0.1" -description = "Lightweight in-process concurrent programming" -category = "main" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" - -[package.extras] -docs = ["Sphinx", "docutils (<0.18)"] -test = ["faulthandler", "objgraph", "psutil"] - -[[package]] -name = "identify" -version = "2.5.0" -description = "File identification library for Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.3" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "imagesize" -version = "1.3.0" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "importlib-metadata" -version = "4.2.0" -description = "Read metadata from Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] - -[[package]] -name = "importlib-resources" -version = "5.7.1" -description = "Read resources from Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "itsdangerous" -version = "2.1.2" -description = "Safely pass data to untrusted environments and back." -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "jinja2" -version = "3.1.2" -description = "A very fast and expressive template engine." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "kombu" -version = "5.2.4" -description = "Messaging library for Python." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -amqp = ">=5.0.9,<6.0.0" -cached-property = {version = "*", markers = "python_version < \"3.8\""} -importlib-metadata = {version = ">=0.18", markers = "python_version < \"3.8\""} -vine = "*" - -[package.extras] -azureservicebus = ["azure-servicebus (>=7.0.0)"] -azurestoragequeues = ["azure-storage-queue"] -consul = ["python-consul (>=0.6.0)"] -librabbitmq = ["librabbitmq (>=2.0.0)"] -mongodb = ["pymongo (>=3.3.0,<3.12.1)"] -msgpack = ["msgpack"] -pyro = ["pyro4"] -qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.12)", "pycurl (>=7.44.1,<7.45.0)", "urllib3 (>=1.26.7)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] - -[[package]] -name = "lazy-object-proxy" -version = "1.7.1" -description = "A fast and thorough lazy object proxy." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "livereload" -version = "2.6.3" -description = "Python LiveReload is an awesome tool for web developers" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -six = "*" -tornado = {version = "*", markers = "python_version > \"2.7\""} - -[[package]] -name = "lxml" -version = "4.9.1" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.7)"] - -[[package]] -name = "Mako" -version = "1.2.3" -description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -MarkupSafe = ">=0.9.2" - -[package.extras] -babel = ["Babel"] -lingua = ["lingua"] -testing = ["pytest"] - -[[package]] -name = "markupsafe" -version = "2.1.1" -description = "Safely add untrusted strings to HTML/XML markup." -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "marshmallow" -version = "3.15.0" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -packaging = "*" - -[package.extras] -dev = ["flake8 (==4.0.1)", "flake8-bugbear (==22.1.11)", "mypy (==0.940)", "pre-commit (>=2.4,<3.0)", "pytest", "pytz", "simplejson", "tox"] -docs = ["alabaster (==0.7.12)", "autodocsumm (==0.2.7)", "sphinx (==4.4.0)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"] -lint = ["flake8 (==4.0.1)", "flake8-bugbear (==22.1.11)", "mypy (==0.940)", "pre-commit (>=2.4,<3.0)"] -tests = ["pytest", "pytz", "simplejson"] - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "mypy" -version = "0.991" -description = "Optional static typing for Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -mypy-extensions = ">=0.4.3" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} -typing-extensions = ">=3.10" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "nodeenv" -version = "1.6.0" -description = "Node.js virtual environment builder" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "packaging" -version = "21.3" -description = "Core utilities for Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - -[[package]] -name = "pathspec" -version = "0.9.0" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[[package]] -name = "pbr" -version = "5.9.0" -description = "Python Build Reasonableness" -category = "dev" -optional = false -python-versions = ">=2.6" - -[[package]] -name = "pep8-naming" -version = "0.13.2" -description = "Check PEP-8 naming conventions, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -flake8 = ">=3.9.1" - -[[package]] -name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] - -[[package]] -name = "pluggy" -version = "1.0.0" -description = "plugin and hook calling mechanisms for python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pre-commit" -version = "2.20.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -toml = "*" -virtualenv = ">=20.0.8" - -[[package]] -name = "pre-commit-hooks" -version = "4.3.0" -description = "Some out-of-the-box hooks for pre-commit." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -"ruamel.yaml" = ">=0.15" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "prompt-toolkit" -version = "3.0.30" -description = "Library for building powerful interactive command lines in Python" -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -wcwidth = "*" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pydocstyle" -version = "6.1.1" -description = "Python docstring style checker" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -snowballstemmer = "*" - -[package.extras] -toml = ["toml"] - -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pygments" -version = "2.13.0" -description = "Pygments is a syntax highlighting package written in Python." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -plugins = ["importlib-metadata"] - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pytest" -version = "6.2.5" -description = "pytest: simple powerful testing with Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] - -[[package]] -name = "pytz" -version = "2022.1" -description = "World timezone definitions, modern and historical" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "pyupgrade" -version = "3.2.2" -description = "A tool to automatically upgrade syntax for newer versions." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -tokenize-rt = ">=3.2.0" - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "reorder-python-imports" -version = "3.9.0" -description = "Tool for reordering python imports" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -classify-imports = ">=4.1" - -[[package]] -name = "requests" -version = "2.27.1" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<5)"] - -[[package]] -name = "restructuredtext-lint" -version = "1.4.0" -description = "reStructuredText linter" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -docutils = ">=0.11,<1.0" - -[[package]] -name = "ruamel.yaml" -version = "0.17.21" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "dev" -optional = false -python-versions = ">=3" - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} - -[package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -name = "ruamel.yaml.clib" -version = "0.2.6" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "dev" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "safety" -version = "2.3.1" -description = "Checks installed dependencies for known vulnerabilities and licenses." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -Click = ">=8.0.2" -dparse = ">=0.6.2" -packaging = ">=21.0" -requests = "*" -"ruamel.yaml" = ">=0.17.21" -setuptools = ">=19.3" - -[package.extras] -github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] -gitlab = ["python-gitlab (>=1.3.0)"] - -[[package]] -name = "sentry-sdk" -version = "1.10.1" -description = "Python client for Sentry (https://sentry.io)" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -certifi = "*" -urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["apache-beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -chalice = ["chalice (>=1.16.0)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -fastapi = ["fastapi (>=0.79.0)"] -flask = ["blinker (>=1.1)", "flask (>=0.11)"] -httpx = ["httpx (>=0.16.0)"] -pure-eval = ["asttokens", "executing", "pure-eval"] -pyspark = ["pyspark (>=2.4.4)"] -quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] -rq = ["rq (>=0.6)"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -starlette = ["starlette (>=0.19.1)"] -tornado = ["tornado (>=5)"] - -[[package]] -name = "setuptools" -version = "65.4.1" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "soupsieve" -version = "2.3.2.post1" -description = "A modern CSS selector implementation for Beautiful Soup." -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "sphinx" -version = "4.3.2" -description = "Python documentation generator" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.18" -imagesize = "*" -Jinja2 = ">=2.3" -packaging = "*" -Pygments = ">=2.0" -requests = ">=2.5.0" -setuptools = "*" -snowballstemmer = ">=1.1" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.920)", "types-pkg-resources", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] - -[[package]] -name = "sphinx-autoapi" -version = "2.0.0" -description = "Sphinx API documentation generator" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -astroid = ">=2.7" -Jinja2 = "*" -PyYAML = "*" -sphinx = ">=4.0" -unidecode = "*" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -dotnet = ["sphinxcontrib-dotnetdomain"] -go = ["sphinxcontrib-golangdomain"] - -[[package]] -name = "sphinx-autobuild" -version = "2021.3.14" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -colorama = "*" -livereload = "*" -sphinx = "*" - -[package.extras] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "sphinx-basic-ng" -version = "0.0.1a12" -description = "A modern skeleton for Sphinx themes." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -sphinx = ">=4.0,<6.0" - -[package.extras] -docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-tabs"] - -[[package]] -name = "sphinx-click" -version = "4.3.0" -description = "Sphinx extension that automatically documents click applications" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=7.0" -docutils = "*" -sphinx = ">=2.0" - -[[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.2" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.0.0" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["html5lib", "pytest"] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -test = ["flake8", "mypy", "pytest"] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.5" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "SpiffWorkflow" -version = "1.2.1" -description = "A workflow framework and BPMN/DMN Processor" -category = "main" -optional = false -python-versions = "*" -develop = false - -[package.dependencies] -celery = "*" -configparser = "*" -importlib-metadata = {version = "<5.0", markers = "python_version <= \"3.7\""} -lxml = "*" - -[package.source] -type = "git" -url = "https://github.com/sartography/SpiffWorkflow" -reference = "main" -resolved_reference = "841bd63017bb1d92858456393f144b4e5b23c994" - -[[package]] -name = "sqlalchemy" -version = "1.4.36" -description = "Database Abstraction Library" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] -mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.16.6)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql", "pymysql (<1)"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "stevedore" -version = "3.5.0" -description = "Manage dynamic plugins for Python applications" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - -[[package]] -name = "tokenize-rt" -version = "4.2.1" -description = "A wrapper around the stdlib `tokenize` which roundtrips." -category = "dev" -optional = false -python-versions = ">=3.6.1" - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "tornado" -version = "6.1" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "dev" -optional = false -python-versions = ">= 3.5" - -[[package]] -name = "typed-ast" -version = "1.4.3" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "typeguard" -version = "2.13.3" -description = "Run-time type checker for Python" -category = "dev" -optional = false -python-versions = ">=3.5.3" - -[package.extras] -doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["mypy", "pytest", "typing-extensions"] - -[[package]] -name = "typing-extensions" -version = "4.2.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "unidecode" -version = "1.3.4" -description = "ASCII transliterations of Unicode text" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "urllib3" -version = "1.26.12" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "vine" -version = "5.0.0" -description = "Promises, promises, promises." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "virtualenv" -version = "20.14.1" -description = "Virtual Python Environment builder" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -platformdirs = ">=2,<3" -six = ">=1.9.0,<2" - -[package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] - -[[package]] -name = "wcwidth" -version = "0.2.5" -description = "Measures the displayed width of unicode strings in a terminal" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "werkzeug" -version = "2.2.2" -description = "The comprehensive WSGI web application library." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog"] - -[[package]] -name = "wrapt" -version = "1.14.1" -description = "Module for decorators, wrappers and monkey patching." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[[package]] -name = "wtforms" -version = "3.0.1" -description = "Form validation and rendering for Python web development." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -MarkupSafe = "*" - -[package.extras] -email = ["email-validator"] - -[[package]] -name = "xdoctest" -version = "1.1.0" -description = "A rewrite of the builtin doctest module" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -colorama = {version = "*", optional = true, markers = "platform_system == \"Windows\" and extra == \"colors\""} -Pygments = {version = "*", optional = true, markers = "python_version >= \"3.5.0\" and extra == \"colors\""} -six = "*" - -[package.extras] -all = ["IPython", "IPython", "Pygments", "Pygments", "attrs", "cmake", "codecov", "colorama", "debugpy", "debugpy", "debugpy", "debugpy", "debugpy", "ipykernel", "ipykernel", "ipython-genutils", "jedi", "jinja2", "jupyter-client", "jupyter-client", "jupyter-core", "nbconvert", "ninja", "pybind11", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "scikit-build", "six", "typing"] -all-strict = ["IPython (==7.10.0)", "IPython (==7.23.1)", "Pygments (==2.0.0)", "Pygments (==2.4.1)", "attrs (==19.2.0)", "cmake (==3.21.2)", "codecov (==2.0.15)", "colorama (==0.4.1)", "debugpy (==1.0.0)", "debugpy (==1.0.0)", "debugpy (==1.0.0)", "debugpy (==1.3.0)", "debugpy (==1.6.0)", "ipykernel (==5.2.0)", "ipykernel (==6.0.0)", "ipython-genutils (==0.2.0)", "jedi (==0.16)", "jinja2 (==3.0.0)", "jupyter-client (==6.1.5)", "jupyter-client (==7.0.0)", "jupyter-core (==4.7.0)", "nbconvert (==6.0.0)", "ninja (==1.10.2)", "pybind11 (==2.7.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scikit-build (==0.11.1)", "six (==1.11.0)", "typing (==3.7.4)"] -colors = ["Pygments", "Pygments", "colorama"] -jupyter = ["IPython", "IPython", "attrs", "debugpy", "debugpy", "debugpy", "debugpy", "debugpy", "ipykernel", "ipykernel", "ipython-genutils", "jedi", "jinja2", "jupyter-client", "jupyter-client", "jupyter-core", "nbconvert"] -optional = ["IPython", "IPython", "Pygments", "Pygments", "attrs", "colorama", "debugpy", "debugpy", "debugpy", "debugpy", "debugpy", "ipykernel", "ipykernel", "ipython-genutils", "jedi", "jinja2", "jupyter-client", "jupyter-client", "jupyter-core", "nbconvert", "pyflakes", "tomli"] -optional-strict = ["IPython (==7.10.0)", "IPython (==7.23.1)", "Pygments (==2.0.0)", "Pygments (==2.4.1)", "attrs (==19.2.0)", "colorama (==0.4.1)", "debugpy (==1.0.0)", "debugpy (==1.0.0)", "debugpy (==1.0.0)", "debugpy (==1.3.0)", "debugpy (==1.6.0)", "ipykernel (==5.2.0)", "ipykernel (==6.0.0)", "ipython-genutils (==0.2.0)", "jedi (==0.16)", "jinja2 (==3.0.0)", "jupyter-client (==6.1.5)", "jupyter-client (==7.0.0)", "jupyter-core (==4.7.0)", "nbconvert (==6.0.0)", "pyflakes (==2.2.0)", "tomli (==0.2.0)"] -runtime-strict = ["six (==1.11.0)"] -tests = ["cmake", "codecov", "ninja", "pybind11", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "scikit-build", "typing"] -tests-strict = ["cmake (==3.21.2)", "codecov (==2.0.15)", "ninja (==1.10.2)", "pybind11 (==2.7.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scikit-build (==0.11.1)", "typing (==3.7.4)"] - -[[package]] -name = "zipp" -version = "3.8.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"] -testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[metadata] -lock-version = "1.1" -python-versions = "^3.7" -content-hash = "45cac5741fa47e44710f5aae6dfdb4636fc4d60df2d6aba467052fdd5199e791" - -[metadata.files] -alabaster = [ - {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, - {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, -] -alembic = [ - {file = "alembic-1.7.7-py3-none-any.whl", hash = "sha256:29be0856ec7591c39f4e1cb10f198045d890e6e2274cf8da80cb5e721a09642b"}, - {file = "alembic-1.7.7.tar.gz", hash = "sha256:4961248173ead7ce8a21efb3de378f13b8398e6630fab0eb258dc74a8af24c58"}, -] -amqp = [ - {file = "amqp-5.1.1-py3-none-any.whl", hash = "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359"}, - {file = "amqp-5.1.1.tar.gz", hash = "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2"}, -] -aniso8601 = [ - {file = "aniso8601-9.0.1-py2.py3-none-any.whl", hash = "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f"}, - {file = "aniso8601-9.0.1.tar.gz", hash = "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"}, -] -astroid = [ - {file = "astroid-2.11.5-py3-none-any.whl", hash = "sha256:14ffbb4f6aa2cf474a0834014005487f7ecd8924996083ab411e7fa0b508ce0b"}, - {file = "astroid-2.11.5.tar.gz", hash = "sha256:f4e4ec5294c4b07ac38bab9ca5ddd3914d4bf46f9006eb5c0ae755755061044e"}, -] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] -attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, -] -babel = [ - {file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"}, - {file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"}, -] -bandit = [ - {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, - {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, -] -bcrypt = [ - {file = "bcrypt-3.2.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:7180d98a96f00b1050e93f5b0f556e658605dd9f524d0b0e68ae7944673f525e"}, - {file = "bcrypt-3.2.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:61bae49580dce88095d669226d5076d0b9d927754cedbdf76c6c9f5099ad6f26"}, - {file = "bcrypt-3.2.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88273d806ab3a50d06bc6a2fc7c87d737dd669b76ad955f449c43095389bc8fb"}, - {file = "bcrypt-3.2.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6d2cb9d969bfca5bc08e45864137276e4c3d3d7de2b162171def3d188bf9d34a"}, - {file = "bcrypt-3.2.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b02d6bfc6336d1094276f3f588aa1225a598e27f8e3388f4db9948cb707b521"}, - {file = "bcrypt-3.2.2-cp36-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2c46100e315c3a5b90fdc53e429c006c5f962529bc27e1dfd656292c20ccc40"}, - {file = "bcrypt-3.2.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7d9ba2e41e330d2af4af6b1b6ec9e6128e91343d0b4afb9282e54e5508f31baa"}, - {file = "bcrypt-3.2.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cd43303d6b8a165c29ec6756afd169faba9396a9472cdff753fe9f19b96ce2fa"}, - {file = "bcrypt-3.2.2-cp36-abi3-win32.whl", hash = "sha256:4e029cef560967fb0cf4a802bcf4d562d3d6b4b1bf81de5ec1abbe0f1adb027e"}, - {file = "bcrypt-3.2.2-cp36-abi3-win_amd64.whl", hash = "sha256:7ff2069240c6bbe49109fe84ca80508773a904f5a8cb960e02a977f7f519b129"}, - {file = "bcrypt-3.2.2.tar.gz", hash = "sha256:433c410c2177057705da2a9f2cd01dd157493b2a7ac14c8593a16b3dab6b6bfb"}, -] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, - {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, -] -billiard = [ - {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, - {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, -] -black = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, - {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, - {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, - {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, - {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, - {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, - {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, - {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, - {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, - {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, - {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, - {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, - {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, -] -blinker = [ - {file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"}, -] -cached-property = [ - {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, - {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, -] -celery = [ - {file = "celery-5.2.7-py3-none-any.whl", hash = "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14"}, - {file = "celery-5.2.7.tar.gz", hash = "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d"}, -] -certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, -] -cffi = [ - {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, - {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, - {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, - {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, - {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, - {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, - {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, - {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, - {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, - {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, - {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, - {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, - {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, - {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, - {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, - {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, - {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, -] -cfgv = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, - {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, -] -classify-imports = [ - {file = "classify_imports-4.1.0-py2.py3-none-any.whl", hash = "sha256:45436d3c4c886ca9092a2c90551b392ba120360e7a782574169ddeb866bbc08a"}, - {file = "classify_imports-4.1.0.tar.gz", hash = "sha256:69ddc4320690c26aa8baa66bf7e0fa0eecfda49d99cf71a59dee0b57dac82616"}, -] -click = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] -click-didyoumean = [ - {file = "click-didyoumean-0.3.0.tar.gz", hash = "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"}, - {file = "click_didyoumean-0.3.0-py3-none-any.whl", hash = "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667"}, -] -click-plugins = [ - {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, - {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, -] -click-repl = [ - {file = "click-repl-0.2.0.tar.gz", hash = "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8"}, - {file = "click_repl-0.2.0-py3-none-any.whl", hash = "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -configparser = [ - {file = "configparser-5.2.0-py3-none-any.whl", hash = "sha256:e8b39238fb6f0153a069aa253d349467c3c4737934f253ef6abac5fe0eca1e5d"}, - {file = "configparser-5.2.0.tar.gz", hash = "sha256:1b35798fdf1713f1c3139016cfcbc461f09edbf099d1fb658d4b7479fcaa3daa"}, -] -coverage = [ - {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, - {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, - {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, - {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, - {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, - {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, - {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, - {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, - {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, - {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, - {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, - {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, - {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, - {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, - {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, - {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, -] -darglint = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, -] -distlib = [ - {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, - {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, -] -docutils = [ - {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, - {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, -] -dparse = [ - {file = "dparse-0.6.2-py3-none-any.whl", hash = "sha256:8097076f1dd26c377f30d4745e6ec18fef42f3bf493933b842ac5bafad8c345f"}, - {file = "dparse-0.6.2.tar.gz", hash = "sha256:d45255bda21f998bc7ddf2afd5e62505ba6134756ba2d42a84c56b0826614dfe"}, -] -filelock = [ - {file = "filelock-3.7.0-py3-none-any.whl", hash = "sha256:c7b5fdb219b398a5b28c8e4c1893ef5f98ece6a38c6ab2c22e26ec161556fed6"}, - {file = "filelock-3.7.0.tar.gz", hash = "sha256:b795f1b42a61bbf8ec7113c341dad679d772567b936fbd1bf43c9a238e673e20"}, -] -flake8 = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] -flake8-bandit = [ - {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, -] -flake8-bugbear = [ - {file = "flake8-bugbear-22.10.27.tar.gz", hash = "sha256:a6708608965c9e0de5fff13904fed82e0ba21ac929fe4896459226a797e11cd5"}, - {file = "flake8_bugbear-22.10.27-py3-none-any.whl", hash = "sha256:6ad0ab754507319060695e2f2be80e6d8977cfcea082293089a9226276bd825d"}, -] -flake8-docstrings = [ - {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, - {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, -] -flake8-polyfill = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] -flake8-rst-docstrings = [ - {file = "flake8-rst-docstrings-0.3.0.tar.gz", hash = "sha256:d1ce22b4bd37b73cd86b8d980e946ef198cfcc18ed82fedb674ceaa2f8d1afa4"}, - {file = "flake8_rst_docstrings-0.3.0-py3-none-any.whl", hash = "sha256:f8c3c6892ff402292651c31983a38da082480ad3ba253743de52989bdc84ca1c"}, -] -flask = [ - {file = "Flask-2.2.2-py3-none-any.whl", hash = "sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526"}, - {file = "Flask-2.2.2.tar.gz", hash = "sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b"}, -] -flask-admin = [ - {file = "Flask-Admin-1.6.0.tar.gz", hash = "sha256:424ffc79b7b0dfff051555686ea12e86e48dffacac14beaa319fb4502ac40988"}, -] -flask-bcrypt = [ - {file = "Flask-Bcrypt-1.0.1.tar.gz", hash = "sha256:f07b66b811417ea64eb188ae6455b0b708a793d966e1a80ceec4a23bc42a4369"}, - {file = "Flask_Bcrypt-1.0.1-py3-none-any.whl", hash = "sha256:062fd991dc9118d05ac0583675507b9fe4670e44416c97e0e6819d03d01f808a"}, -] -flask-cors = [ - {file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"}, - {file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"}, -] -flask-mail = [ - {file = "Flask-Mail-0.9.1.tar.gz", hash = "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41"}, -] -flask-marshmallow = [ - {file = "flask-marshmallow-0.14.0.tar.gz", hash = "sha256:bd01a6372cbe50e36f205cfff0fc5dab0b7b662c4c8b2c4fc06a3151b2950950"}, - {file = "flask_marshmallow-0.14.0-py2.py3-none-any.whl", hash = "sha256:2adcd782b5a4a6c5ae3c96701f320d8ca6997995a52b2661093c56cc3ed24754"}, -] -flask-migrate = [ - {file = "Flask-Migrate-4.0.0.tar.gz", hash = "sha256:2a301c3040af6844f29d9149abe428a0f08ebc8fa149e72113bbb36fa341920a"}, - {file = "Flask_Migrate-4.0.0-py3-none-any.whl", hash = "sha256:e75a46b657e3062296b9f6e92f31e19662f76cfee8abd6ae94640cbcb79fe016"}, -] -flask-restful = [ - {file = "Flask-RESTful-0.3.9.tar.gz", hash = "sha256:ccec650b835d48192138c85329ae03735e6ced58e9b2d9c2146d6c84c06fa53e"}, - {file = "Flask_RESTful-0.3.9-py2.py3-none-any.whl", hash = "sha256:4970c49b6488e46c520b325f54833374dc2b98e211f1b272bd4b0c516232afe2"}, -] -flask-sqlalchemy = [ - {file = "Flask-SQLAlchemy-2.5.1.tar.gz", hash = "sha256:2bda44b43e7cacb15d4e05ff3cc1f8bc97936cc464623424102bfc2c35e95912"}, - {file = "Flask_SQLAlchemy-2.5.1-py2.py3-none-any.whl", hash = "sha256:f12c3d4cc5cc7fdcc148b9527ea05671718c3ea45d50c7e732cceb33f574b390"}, -] -furo = [ - {file = "furo-2022.9.29-py3-none-any.whl", hash = "sha256:559ee17999c0f52728481dcf6b1b0cf8c9743e68c5e3a18cb45a7992747869a9"}, - {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"}, -] -gitdb = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, -] -gitpython = [ - {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"}, - {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"}, -] -greenlet = [ - {file = "greenlet-2.0.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c"}, - {file = "greenlet-2.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515"}, - {file = "greenlet-2.0.1-cp27-cp27m-win32.whl", hash = "sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a"}, - {file = "greenlet-2.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524"}, - {file = "greenlet-2.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243"}, - {file = "greenlet-2.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da"}, - {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d"}, - {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"}, - {file = "greenlet-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617"}, - {file = "greenlet-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce"}, - {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72"}, - {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82"}, - {file = "greenlet-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd"}, - {file = "greenlet-2.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f"}, - {file = "greenlet-2.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f"}, - {file = "greenlet-2.0.1-cp35-cp35m-win32.whl", hash = "sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955"}, - {file = "greenlet-2.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77"}, - {file = "greenlet-2.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2"}, - {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39"}, - {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92"}, - {file = "greenlet-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928"}, - {file = "greenlet-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd"}, - {file = "greenlet-2.0.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, - {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, - {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, - {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, - {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, - {file = "greenlet-2.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, - {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, - {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, - {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, - {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, - {file = "greenlet-2.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, - {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, - {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, - {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, - {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, - {file = "greenlet-2.0.1.tar.gz", hash = "sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67"}, -] -identify = [ - {file = "identify-2.5.0-py2.py3-none-any.whl", hash = "sha256:3acfe15a96e4272b4ec5662ee3e231ceba976ef63fd9980ed2ce9cc415df393f"}, - {file = "identify-2.5.0.tar.gz", hash = "sha256:c83af514ea50bf2be2c4a3f2fb349442b59dc87284558ae9ff54191bff3541d2"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -imagesize = [ - {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, - {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, - {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, -] -importlib-resources = [ - {file = "importlib_resources-5.7.1-py3-none-any.whl", hash = "sha256:e447dc01619b1e951286f3929be820029d48c75eb25d265c28b92a16548212b8"}, - {file = "importlib_resources-5.7.1.tar.gz", hash = "sha256:b6062987dfc51f0fcb809187cffbd60f35df7acb4589091f154214af6d0d49d3"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -itsdangerous = [ - {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, - {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, -] -jinja2 = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] -kombu = [ - {file = "kombu-5.2.4-py3-none-any.whl", hash = "sha256:8b213b24293d3417bcf0d2f5537b7f756079e3ea232a8386dcc89a59fd2361a4"}, - {file = "kombu-5.2.4.tar.gz", hash = "sha256:37cee3ee725f94ea8bb173eaab7c1760203ea53bbebae226328600f9d2799610"}, -] -lazy-object-proxy = [ - {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, - {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, -] -livereload = [ - {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, -] -lxml = [ - {file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"}, - {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"}, - {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc"}, - {file = "lxml-4.9.1-cp27-cp27m-win32.whl", hash = "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3"}, - {file = "lxml-4.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627"}, - {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84"}, - {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8"}, - {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8"}, - {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d"}, - {file = "lxml-4.9.1-cp310-cp310-win32.whl", hash = "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7"}, - {file = "lxml-4.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b"}, - {file = "lxml-4.9.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d"}, - {file = "lxml-4.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3"}, - {file = "lxml-4.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29"}, - {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d"}, - {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318"}, - {file = "lxml-4.9.1-cp35-cp35m-win32.whl", hash = "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7"}, - {file = "lxml-4.9.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4"}, - {file = "lxml-4.9.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf"}, - {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3"}, - {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391"}, - {file = "lxml-4.9.1-cp36-cp36m-win32.whl", hash = "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e"}, - {file = "lxml-4.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7"}, - {file = "lxml-4.9.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca"}, - {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785"}, - {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785"}, - {file = "lxml-4.9.1-cp37-cp37m-win32.whl", hash = "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a"}, - {file = "lxml-4.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e"}, - {file = "lxml-4.9.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715"}, - {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036"}, - {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387"}, - {file = "lxml-4.9.1-cp38-cp38-win32.whl", hash = "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94"}, - {file = "lxml-4.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345"}, - {file = "lxml-4.9.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000"}, - {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25"}, - {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd"}, - {file = "lxml-4.9.1-cp39-cp39-win32.whl", hash = "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb"}, - {file = "lxml-4.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73"}, - {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c"}, - {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9"}, - {file = "lxml-4.9.1.tar.gz", hash = "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"}, -] -Mako = [ - {file = "Mako-1.2.3-py3-none-any.whl", hash = "sha256:c413a086e38cd885088d5e165305ee8eed04e8b3f8f62df343480da0a385735f"}, - {file = "Mako-1.2.3.tar.gz", hash = "sha256:7fde96466fcfeedb0eed94f187f20b23d85e4cb41444be0e542e2c8c65c396cd"}, -] -markupsafe = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, -] -marshmallow = [ - {file = "marshmallow-3.15.0-py3-none-any.whl", hash = "sha256:ff79885ed43b579782f48c251d262e062bce49c65c52412458769a4fb57ac30f"}, - {file = "marshmallow-3.15.0.tar.gz", hash = "sha256:2aaaab4f01ef4f5a011a21319af9fce17ab13bf28a026d1252adab0e035648d5"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -mypy = [ - {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, - {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, - {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, - {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, - {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, - {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, - {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, - {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, - {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, - {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, - {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, - {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, - {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, - {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, - {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, - {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, - {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, - {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, - {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, - {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, - {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, - {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, - {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, - {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -nodeenv = [ - {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, - {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] -pbr = [ - {file = "pbr-5.9.0-py2.py3-none-any.whl", hash = "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a"}, - {file = "pbr-5.9.0.tar.gz", hash = "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"}, -] -pep8-naming = [ - {file = "pep8-naming-0.13.2.tar.gz", hash = "sha256:93eef62f525fd12a6f8c98f4dcc17fa70baae2f37fa1f73bec00e3e44392fa48"}, - {file = "pep8_naming-0.13.2-py3-none-any.whl", hash = "sha256:59e29e55c478db69cffbe14ab24b5bd2cd615c0413edf790d47d3fb7ba9a4e23"}, -] -platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pre-commit = [ - {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, - {file = "pre_commit-2.20.0.tar.gz", hash = "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959"}, -] -pre-commit-hooks = [ - {file = "pre_commit_hooks-4.3.0-py2.py3-none-any.whl", hash = "sha256:9ccaf7c98794659d345080ee1ea0256a55ae059675045eebdbbc17c0be8c7e4b"}, - {file = "pre_commit_hooks-4.3.0.tar.gz", hash = "sha256:fda598a4c834d030727e6a615722718b47510f4bed72df4c949f95ba9f5aaf88"}, -] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.30-py3-none-any.whl", hash = "sha256:d8916d3f62a7b67ab353a952ce4ced6a1d2587dfe9ef8ebc30dd7c386751f289"}, - {file = "prompt_toolkit-3.0.30.tar.gz", hash = "sha256:859b283c50bde45f5f97829f77a4674d1c1fcd88539364f1b28a37805cfd89c0"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pycodestyle = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pydocstyle = [ - {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, - {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, -] -pyflakes = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] -pygments = [ - {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, - {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, -] -pytz = [ - {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, - {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, -] -pyupgrade = [ - {file = "pyupgrade-3.2.2-py2.py3-none-any.whl", hash = "sha256:16c0e3a6ac2d83cd0fd30c138af5504918c59d584344f60a15d5f8009b11a0ed"}, - {file = "pyupgrade-3.2.2.tar.gz", hash = "sha256:6bfa246fb9d94e490fad37980bcfc05b9494183ff29d9100ef4f7f22a952ce67"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -reorder-python-imports = [ - {file = "reorder_python_imports-3.9.0-py2.py3-none-any.whl", hash = "sha256:3f9c16e8781f54c944756d0d1eb34a8c863554f7a4eb3693f574fe19b1a29b56"}, - {file = "reorder_python_imports-3.9.0.tar.gz", hash = "sha256:49292ed537829a6bece9fb3746fc1bbe98f52643be5de01a4e13680268a5b0ec"}, -] -requests = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, -] -restructuredtext-lint = [ - {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, -] -"ruamel.yaml" = [ - {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, - {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, -] -"ruamel.yaml.clib" = [ - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:066f886bc90cc2ce44df8b5f7acfc6a7e2b2e672713f027136464492b0c34d7c"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d3c620a54748a3d4cf0bcfe623e388407c8e85a4b06b8188e126302bcab93ea8"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:210c8fcfeff90514b7133010bf14e3bad652c8efde6b20e00c43854bf94fa5a6"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:61bc5e5ca632d95925907c569daa559ea194a4d16084ba86084be98ab1cec1c6"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1b4139a6ffbca8ef60fdaf9b33dec05143ba746a6f0ae0f9d11d38239211d335"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, - {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, -] -safety = [ - {file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"}, - {file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"}, -] -sentry-sdk = [ - {file = "sentry-sdk-1.10.1.tar.gz", hash = "sha256:105faf7bd7b7fa25653404619ee261527266b14103fe1389e0ce077bd23a9691"}, - {file = "sentry_sdk-1.10.1-py2.py3-none-any.whl", hash = "sha256:06c0fa9ccfdc80d7e3b5d2021978d6eb9351fa49db9b5847cf4d1f2a473414ad"}, -] -setuptools = [ - {file = "setuptools-65.4.1-py3-none-any.whl", hash = "sha256:1b6bdc6161661409c5f21508763dc63ab20a9ac2f8ba20029aaaa7fdb9118012"}, - {file = "setuptools-65.4.1.tar.gz", hash = "sha256:3050e338e5871e70c72983072fe34f6032ae1cdeeeb67338199c2f74e083a80e"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -smmap = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] -snowballstemmer = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] -soupsieve = [ - {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, - {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, -] -sphinx = [ - {file = "Sphinx-4.3.2-py3-none-any.whl", hash = "sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851"}, - {file = "Sphinx-4.3.2.tar.gz", hash = "sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c"}, -] -sphinx-autoapi = [ - {file = "sphinx-autoapi-2.0.0.tar.gz", hash = "sha256:97dcf1b5b54cd0d8efef867594e4a4f3e2d3a2c0ec1e5a891e0a61bc77046006"}, - {file = "sphinx_autoapi-2.0.0-py2.py3-none-any.whl", hash = "sha256:dab2753a38cad907bf4e61473c0da365a26bfbe69fbf5aa6e4f7d48e1cf8a148"}, -] -sphinx-autobuild = [ - {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, - {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, -] -sphinx-basic-ng = [ - {file = "sphinx_basic_ng-0.0.1a12-py3-none-any.whl", hash = "sha256:e8b6efd2c5ece014156de76065eda01ddfca0fee465aa020b1e3c12f84570bbe"}, - {file = "sphinx_basic_ng-0.0.1a12.tar.gz", hash = "sha256:cffffb14914ddd26c94b1330df1d72dab5a42e220aaeb5953076a40b9c50e801"}, -] -sphinx-click = [ - {file = "sphinx-click-4.3.0.tar.gz", hash = "sha256:bd4db5d3c1bec345f07af07b8e28a76cfc5006d997984e38ae246bbf8b9a3b38"}, - {file = "sphinx_click-4.3.0-py3-none-any.whl", hash = "sha256:23e85a3cb0b728a421ea773699f6acadefae171d1a764a51dd8ec5981503ccbe"}, -] -sphinxcontrib-applehelp = [ - {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, - {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, -] -sphinxcontrib-devhelp = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, -] -sphinxcontrib-htmlhelp = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, -] -sphinxcontrib-jsmath = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] -sphinxcontrib-qthelp = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, -] -sphinxcontrib-serializinghtml = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, -] -SpiffWorkflow = [] -sqlalchemy = [ - {file = "SQLAlchemy-1.4.36-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:81e53bd383c2c33de9d578bfcc243f559bd3801a0e57f2bcc9a943c790662e0c"}, - {file = "SQLAlchemy-1.4.36-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6e1fe00ee85c768807f2a139b83469c1e52a9ffd58a6eb51aa7aeb524325ab18"}, - {file = "SQLAlchemy-1.4.36-cp27-cp27m-win32.whl", hash = "sha256:d57ac32f8dc731fddeb6f5d1358b4ca5456e72594e664769f0a9163f13df2a31"}, - {file = "SQLAlchemy-1.4.36-cp27-cp27m-win_amd64.whl", hash = "sha256:fca8322e04b2dde722fcb0558682740eebd3bd239bea7a0d0febbc190e99dc15"}, - {file = "SQLAlchemy-1.4.36-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:53d2d9ee93970c969bc4e3c78b1277d7129554642f6ffea039c282c7dc4577bc"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:f0394a3acfb8925db178f7728adb38c027ed7e303665b225906bfa8099dc1ce8"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c606d8238feae2f360b8742ffbe67741937eb0a05b57f536948d198a3def96"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8d07fe2de0325d06e7e73281e9a9b5e259fbd7cbfbe398a0433cbb0082ad8fa7"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5041474dcab7973baa91ec1f3112049a9dd4652898d6a95a6a895ff5c58beb6b"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-win32.whl", hash = "sha256:be094460930087e50fd08297db9d7aadaed8408ad896baf758e9190c335632da"}, - {file = "SQLAlchemy-1.4.36-cp310-cp310-win_amd64.whl", hash = "sha256:64d796e9af522162f7f2bf7a3c5531a0a550764c426782797bbeed809d0646c5"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a0ae3aa2e86a4613f2d4c49eb7da23da536e6ce80b2bfd60bbb2f55fc02b0b32"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d50cb71c1dbed70646d521a0975fb0f92b7c3f84c61fa59e07be23a1aaeecfc"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:16abf35af37a3d5af92725fc9ec507dd9e9183d261c2069b6606d60981ed1c6e"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864a83bd345871ad9699ce466388f836db7572003d67d9392a71998092210e3"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-win32.whl", hash = "sha256:fbf8c09fe9728168f8cc1b40c239eab10baf9c422c18be7f53213d70434dea43"}, - {file = "SQLAlchemy-1.4.36-cp36-cp36m-win_amd64.whl", hash = "sha256:6e859fa96605027bd50d8e966db1c4e1b03e7b3267abbc4b89ae658c99393c58"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:166a3887ec355f7d2f12738f7fa25dc8ac541867147a255f790f2f41f614cb44"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e885548da361aa3f8a9433db4cfb335b2107e533bf314359ae3952821d84b3e"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5c90ef955d429966d84326d772eb34333178737ebb669845f1d529eb00c75e72"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a052bd9f53004f8993c624c452dfad8ec600f572dd0ed0445fbe64b22f5570e"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-win32.whl", hash = "sha256:dce3468bf1fc12374a1a732c9efd146ce034f91bb0482b602a9311cb6166a920"}, - {file = "SQLAlchemy-1.4.36-cp37-cp37m-win_amd64.whl", hash = "sha256:6cb4c4f57a20710cea277edf720d249d514e587f796b75785ad2c25e1c0fed26"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:e74ce103b81c375c3853b436297952ef8d7863d801dcffb6728d01544e5191b5"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b20c4178ead9bc398be479428568ff31b6c296eb22e75776273781a6551973f"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:af2587ae11400157753115612d6c6ad255143efba791406ad8a0cbcccf2edcb3"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cf3077712be9f65c9aaa0b5bc47bc1a44789fd45053e2e3ecd59ff17c63fe9"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-win32.whl", hash = "sha256:ce20f5da141f8af26c123ebaa1b7771835ca6c161225ce728962a79054f528c3"}, - {file = "SQLAlchemy-1.4.36-cp38-cp38-win_amd64.whl", hash = "sha256:316c7e5304dda3e3ad711569ac5d02698bbc71299b168ac56a7076b86259f7ea"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:f522214f6749bc073262529c056f7dfd660f3b5ec4180c5354d985eb7219801e"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ecac4db8c1aa4a269f5829df7e706639a24b780d2ac46b3e485cbbd27ec0028"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3db741beaa983d4cbf9087558620e7787106319f7e63a066990a70657dd6b35"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ec89bf98cc6a0f5d1e28e3ad28e9be6f3b4bdbd521a4053c7ae8d5e1289a8a1"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-win32.whl", hash = "sha256:e12532c4d3f614678623da5d852f038ace1f01869b89f003ed6fe8c793f0c6a3"}, - {file = "SQLAlchemy-1.4.36-cp39-cp39-win_amd64.whl", hash = "sha256:cb441ca461bf97d00877b607f132772644b623518b39ced54da433215adce691"}, - {file = "SQLAlchemy-1.4.36.tar.gz", hash = "sha256:64678ac321d64a45901ef2e24725ec5e783f1f4a588305e196431447e7ace243"}, -] -stevedore = [ - {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, - {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, -] -tokenize-rt = [ - {file = "tokenize_rt-4.2.1-py2.py3-none-any.whl", hash = "sha256:08a27fa032a81cf45e8858d0ac706004fcd523e8463415ddf1442be38e204ea8"}, - {file = "tokenize_rt-4.2.1.tar.gz", hash = "sha256:0d4f69026fed520f8a1e0103aa36c406ef4661417f20ca643f913e33531b3b94"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -tornado = [ - {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, - {file = "tornado-6.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c"}, - {file = "tornado-6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b"}, - {file = "tornado-6.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675"}, - {file = "tornado-6.1-cp35-cp35m-win32.whl", hash = "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5"}, - {file = "tornado-6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68"}, - {file = "tornado-6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb"}, - {file = "tornado-6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c"}, - {file = "tornado-6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c"}, - {file = "tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085"}, - {file = "tornado-6.1-cp36-cp36m-win32.whl", hash = "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575"}, - {file = "tornado-6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795"}, - {file = "tornado-6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f"}, - {file = "tornado-6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102"}, - {file = "tornado-6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01"}, - {file = "tornado-6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d"}, - {file = "tornado-6.1-cp37-cp37m-win32.whl", hash = "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df"}, - {file = "tornado-6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37"}, - {file = "tornado-6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95"}, - {file = "tornado-6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a"}, - {file = "tornado-6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"}, - {file = "tornado-6.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288"}, - {file = "tornado-6.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f"}, - {file = "tornado-6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6"}, - {file = "tornado-6.1-cp38-cp38-win32.whl", hash = "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326"}, - {file = "tornado-6.1-cp38-cp38-win_amd64.whl", hash = "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c"}, - {file = "tornado-6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5"}, - {file = "tornado-6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe"}, - {file = "tornado-6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea"}, - {file = "tornado-6.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2"}, - {file = "tornado-6.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0"}, - {file = "tornado-6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd"}, - {file = "tornado-6.1-cp39-cp39-win32.whl", hash = "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c"}, - {file = "tornado-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4"}, - {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, -] -typed-ast = [ - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, - {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, - {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, - {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, - {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, - {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, - {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, - {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, - {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, - {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, -] -typeguard = [ - {file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"}, - {file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"}, -] -typing-extensions = [ - {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, - {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, -] -unidecode = [ - {file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"}, - {file = "Unidecode-1.3.4.tar.gz", hash = "sha256:8e4352fb93d5a735c788110d2e7ac8e8031eb06ccbfe8d324ab71735015f9342"}, -] -urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, -] -vine = [ - {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, - {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, -] -virtualenv = [ - {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, - {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, -] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] -werkzeug = [ - {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, - {file = "Werkzeug-2.2.2.tar.gz", hash = "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f"}, -] -wrapt = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, -] -wtforms = [ - {file = "WTForms-3.0.1-py3-none-any.whl", hash = "sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b"}, - {file = "WTForms-3.0.1.tar.gz", hash = "sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc"}, -] -xdoctest = [ - {file = "xdoctest-1.1.0-py3-none-any.whl", hash = "sha256:da330c4dacee51f3c785820bc743188fb6f7c64c5fa1c54bff8836b3cf23d69b"}, - {file = "xdoctest-1.1.0.tar.gz", hash = "sha256:0fd4fad7932f0a2f082dfdfb857dd6ca41603757586c39b1e5b4d333fc389f8a"}, -] -zipp = [ - {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, - {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, -] diff --git a/flask-bpmn/pyproject.toml b/flask-bpmn/pyproject.toml deleted file mode 100644 index 105fa15d6..000000000 --- a/flask-bpmn/pyproject.toml +++ /dev/null @@ -1,111 +0,0 @@ -[tool.poetry] -name = "flask-bpmn" -version = "0.0.0" -description = "Flask Bpmn" -authors = ["Jason Lantz "] -license = "MIT" -readme = "README.rst" -homepage = "https://github.com/sartography/flask-bpmn" -repository = "https://github.com/sartography/flask-bpmn" -documentation = "https://flask-bpmn.readthedocs.io" -classifiers = [ - "Development Status :: 1 - Planning", -] - -[tool.poetry.urls] -Changelog = "https://github.com/sartography/flask-bpmn/releases" - -[tool.poetry.dependencies] -python = "^3.7" -click = "^8.0.1" -flask = "*" -flask-admin = "*" -flask-bcrypt = "*" -flask-cors = "*" -flask-mail = "*" -flask-marshmallow = "*" -flask-migrate = "*" -flask-restful = "*" -werkzeug = "*" -spiffworkflow = "*" -sentry-sdk = "*" -sphinx-autoapi = "^2.0.0" -greenlet = "^2.0.1" - - -[tool.poetry.dev-dependencies] -pytest = "^6.2.5" -coverage = {extras = ["toml"], version = "^6.5"} -safety = "^2.3.1" -mypy = "^0.991" -typeguard = "^2.13.2" -xdoctest = {extras = ["colors"], version = "^1.1.0"} -sphinx = "^4.3.0" -sphinx-autobuild = ">=2021.3.14" -pre-commit = "^2.20.0" -flake8 = "^4.0.1" -black = ">=21.10b0" -flake8-bandit = "^2.1.2" - -# require git version here to avoid importlib but do not require this version for other apps -spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"} - -# 1.7.3 broke us. https://github.com/PyCQA/bandit/issues/841 -bandit = "1.7.2" - -flake8-bugbear = "^22.10.27" -flake8-docstrings = "^1.6.0" -flake8-rst-docstrings = "^0.3.0" -pep8-naming = "^0.13.2" -darglint = "^1.8.1" -reorder-python-imports = "^3.9.0" -pre-commit-hooks = "^4.3.0" -sphinx-click = "^4.3.0" -Pygments = "^2.13.0" -pyupgrade = "^3.2.2" -furo = ">=2021.11.12" - -[tool.poetry.scripts] -flask-bpmn = "flask_bpmn.__main__:main" - -[tool.coverage.paths] -source = ["src", "*/site-packages"] -tests = ["tests", "*/tests"] - -[tool.coverage.run] -branch = true -source = ["flask_bpmn", "tests"] - -[tool.coverage.report] -show_missing = true -fail_under = 50 - -[tool.pytest.ini_options] -# ignore deprecation warnings from various packages that we don't control -filterwarnings = [ - # note the use of single quote below to denote "raw" strings in TOML - # kombu/utils/compat.py:82 - 'ignore:SelectableGroups dict interface is deprecated. Use select.', - # flask_sqlalchemy/__init__.py:14 - "ignore:'_app_ctx_stack' is deprecated and will be removed in Flask 2.3", -] - -[tool.mypy] -strict = true -disallow_any_generics = false -warn_unreachable = true -pretty = true -show_column_numbers = true -show_error_codes = true -show_error_context = true - -# We get 'error: Module has no attribute "set_context"' for sentry-sdk without this option -implicit_reexport = true - -# allow for subdirs to NOT require __init__.py -namespace_packages = true -explicit_package_bases = false - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/flask-bpmn/sonar-project.properties b/flask-bpmn/sonar-project.properties deleted file mode 100644 index 46c394f34..000000000 --- a/flask-bpmn/sonar-project.properties +++ /dev/null @@ -1,7 +0,0 @@ -sonar.organization=sartography -sonar.projectKey=sartography_flask-bpmn -sonar.host.url=https://sonarcloud.io -sonar.python.version=3.7,3.8,3.9,3.10 -sonar.python.coverage.reportPaths=coverage.xml -sonar.test.inclusions=tests -sonar.coverage.exclusions=noxfile.py,conftest.py,conf.py diff --git a/flask-bpmn/src/flask_bpmn/__init__.py b/flask-bpmn/src/flask_bpmn/__init__.py deleted file mode 100644 index a45049736..000000000 --- a/flask-bpmn/src/flask_bpmn/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Flask Bpmn.""" diff --git a/flask-bpmn/src/flask_bpmn/__main__.py b/flask-bpmn/src/flask_bpmn/__main__.py deleted file mode 100644 index 4ba630e70..000000000 --- a/flask-bpmn/src/flask_bpmn/__main__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Command-line interface.""" -import click - - -@click.command() -@click.version_option() -def main() -> None: - """Flask Bpmn.""" - print("This does nothing") - - -if __name__ == "__main__": - main(prog_name="flask-bpmn") # pragma: no cover diff --git a/flask-bpmn/src/flask_bpmn/api/api_error.py b/flask-bpmn/src/flask_bpmn/api/api_error.py deleted file mode 100644 index ed792e7e8..000000000 --- a/flask-bpmn/src/flask_bpmn/api/api_error.py +++ /dev/null @@ -1,207 +0,0 @@ -"""API Error functionality.""" -from __future__ import annotations - -import json -from dataclasses import dataclass -from dataclasses import field -from typing import Any - -import flask.wrappers -import sentry_sdk -from flask import Blueprint -from flask import current_app -from flask import g -from flask import jsonify -from flask import make_response -from sentry_sdk import capture_exception -from sentry_sdk import set_tag -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore -from SpiffWorkflow.exceptions import WorkflowException # type: ignore -from SpiffWorkflow.specs.base import TaskSpec # type: ignore -from SpiffWorkflow.task import Task # type: ignore - - -api_error_blueprint = Blueprint("api_error_blueprint", __name__) - - -@dataclass -class ApiError(Exception): - """ApiError Class to help handle exceptions.""" - - error_code: str - message: str - error_line: str = "" - error_type: str = "" - file_name: str = "" - line_number: int = 0 - offset: int = 0 - sentry_link: str | None = None - status_code: int = 400 - tag: str = "" - task_data: dict | str | None = field(default_factory=dict) - task_id: str = "" - task_name: str = "" - task_trace: dict | None = field(default_factory=dict) - - def __str__(self) -> str: - """Instructions to print instance as a string.""" - msg = "ApiError: % s. " % self.message - if self.task_name: - msg += f"Error in task '{self.task_name}' ({self.task_id}). " - if self.line_number: - msg += "Error is on line %i. " % self.line_number - if self.file_name: - msg += "In file %s. " % self.file_name - return msg - - @classmethod - def from_task( - cls, - error_code: str, - message: str, - task: Task, - status_code: int = 400, - line_number: int = 0, - offset: int = 0, - error_type: str = "", - error_line: str = "", - task_trace: dict | None = None, - ) -> ApiError: - """Constructs an API Error with details pulled from the current task.""" - instance = cls(error_code, message, status_code=status_code) - instance.task_id = task.task_spec.name or "" - instance.task_name = task.task_spec.description or "" - instance.file_name = task.workflow.spec.file or "" - instance.line_number = line_number - instance.offset = offset - instance.error_type = error_type - instance.error_line = error_line - if task_trace: - instance.task_trace = task_trace - else: - instance.task_trace = WorkflowTaskExecException.get_task_trace(task) - - # spiffworkflow is doing something weird where task ends up referenced in the data in some cases. - if "task" in task.data: - task.data.pop("task") - - # Assure that there is nothing in the json data that can't be serialized. - instance.task_data = ApiError.remove_unserializeable_from_dict(task.data) - - return instance - - @staticmethod - def remove_unserializeable_from_dict(my_dict: dict) -> dict: - """Removes unserializeable from dict.""" - keys_to_delete = [] - for key, value in my_dict.items(): - if not ApiError.is_jsonable(value): - keys_to_delete.append(key) - for key in keys_to_delete: - del my_dict[key] - return my_dict - - @staticmethod - def is_jsonable(x: Any) -> bool: - """Attempts a json.dump on given input and returns false if it cannot.""" - try: - json.dumps(x) - return True - except (TypeError, OverflowError, ValueError): - return False - - @classmethod - def from_task_spec( - cls, - code: str, - message: str, - task_spec: TaskSpec, - status_code: int = 400, - ) -> ApiError: - """Constructs an API Error with details pulled from the current task.""" - instance = cls(code, message, status_code=status_code) - instance.task_id = task_spec.name or "" - instance.task_name = task_spec.description or "" - if task_spec._wf_spec: - instance.file_name = task_spec._wf_spec.file - return instance - - @classmethod - def from_workflow_exception( - cls, - error_code: str, - message: str, - exp: WorkflowException, - ) -> ApiError: - """Deals with workflow exceptions. - - We catch a lot of workflow exception errors, - so consolidating the error_code, and doing the best things - we can with the data we have. - """ - if isinstance(exp, WorkflowTaskExecException): - return ApiError.from_task( - error_code, - message, - exp.task, - line_number=exp.line_number, - offset=exp.offset, - error_type=exp.exception.__class__.__name__, - error_line=exp.error_line, - task_trace=exp.task_trace, - ) - - else: - return ApiError.from_task_spec(error_code, message, exp.sender) - - -def set_user_sentry_context() -> None: - """Set_user_sentry_context.""" - try: - username = g.user.username - except Exception: - username = "Unknown" - # This is for sentry logging into Slack - sentry_sdk.set_context("User", {"user": username}) - set_tag("username", username) - - -@api_error_blueprint.app_errorhandler(Exception) -def handle_exception(exception: Exception) -> flask.wrappers.Response: - """Handles unexpected exceptions.""" - set_user_sentry_context() - - sentry_link = None - if not isinstance(exception, ApiError) or exception.error_code != "invalid_token": - id = capture_exception(exception) - - if isinstance(exception, ApiError): - current_app.logger.info( - f"Sending ApiError exception to sentry: {exception} with error code {exception.error_code}") - - organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") - project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") - if organization_slug and project_slug: - sentry_link = ( - f"https://sentry.io/{organization_slug}/{project_slug}/events/{id}" - ) - - # !!!NOTE!!!: do this after sentry stuff since calling logger.exception - # seems to break the sentry sdk context where we no longer get back - # an event id or send out tags like username - current_app.logger.exception(exception) - - # set api_exception like this to avoid confusing mypy - # and what type the object is - api_exception = None - if isinstance(exception, ApiError): - api_exception = exception - else: - api_exception = ApiError( - error_code="internal_server_error", - message=f"{exception.__class__.__name__}", - sentry_link=sentry_link, - status_code=500, - ) - - return make_response(jsonify(api_exception), api_exception.status_code) diff --git a/flask-bpmn/src/flask_bpmn/models/__init__.py b/flask-bpmn/src/flask_bpmn/models/__init__.py deleted file mode 100644 index f520b09de..000000000 --- a/flask-bpmn/src/flask_bpmn/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""__init__.""" diff --git a/flask-bpmn/src/flask_bpmn/models/db.py b/flask-bpmn/src/flask_bpmn/models/db.py deleted file mode 100644 index 643e1a85d..000000000 --- a/flask-bpmn/src/flask_bpmn/models/db.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Db.""" -from __future__ import annotations - -import enum -import time -from typing import Any - -from flask_migrate import Migrate # type: ignore -from flask_sqlalchemy import SQLAlchemy # type: ignore -from sqlalchemy import event # type: ignore -from sqlalchemy.engine.base import Connection # type: ignore -from sqlalchemy.orm.mapper import Mapper # type: ignore - -db = SQLAlchemy() -migrate = Migrate() - - -class SpiffworkflowBaseDBModel(db.Model): # type: ignore - """SpiffworkflowBaseDBModel.""" - - __abstract__ = True - - @classmethod - def _all_subclasses(cls) -> list[type[SpiffworkflowBaseDBModel]]: - """Get all subclasses of cls, descending. - - So, if A is a subclass of B is a subclass of cls, this - will include A and B. - (Does not include cls) - """ - children = cls.__subclasses__() - result = [] - while children: - next = children.pop() - subclasses = next.__subclasses__() - result.append(next) - # check subclasses of subclasses SpiffworkflowBaseDBModel. i guess we only go down to grandchildren, which seems cool. - for subclass in subclasses: - children.append(subclass) - return result - - def validate_enum_field( - self, key: str, value: Any, enum_variable: enum.EnumMeta - ) -> Any: - """Validate_enum_field.""" - try: - m_type = getattr(enum_variable, value, None) - except Exception as e: - raise ValueError( - f"{self.__class__.__name__}: invalid {key}: {value}" - ) from e - - if m_type is None: - raise ValueError(f"{self.__class__.__name__}: invalid {key}: {value}") - - return m_type.value - - -def update_created_modified_on_create_listener( - mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel -) -> None: - """Event listener that runs before a record is updated, and sets the create/modified field accordingly.""" - if "created_at_in_seconds" in mapper.columns.keys(): - target.created_at_in_seconds = round(time.time()) - if "updated_at_in_seconds" in mapper.columns.keys(): - target.updated_at_in_seconds = round(time.time()) - - -def update_modified_on_update_listener( - mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel -) -> None: - """Event listener that runs before a record is updated, and sets the modified field accordingly.""" - if "updated_at_in_seconds" in mapper.columns.keys(): - if db.session.is_modified(target, include_collections=False): - target.updated_at_in_seconds = round(time.time()) - - -def add_listeners() -> None: - """Adds the listeners to all subclasses. - - This should be called after importing all subclasses - """ - for cls in SpiffworkflowBaseDBModel._all_subclasses(): - event.listen(cls, "before_insert", update_created_modified_on_create_listener) - event.listen(cls, "before_update", update_modified_on_update_listener) diff --git a/flask-bpmn/src/flask_bpmn/models/group.py b/flask-bpmn/src/flask_bpmn/models/group.py deleted file mode 100644 index 3c496a491..000000000 --- a/flask-bpmn/src/flask_bpmn/models/group.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Group.""" -from flask_bpmn.models.db import db -from flask_bpmn.models.db import SpiffworkflowBaseDBModel - - -class FlaskBpmnGroupModel(SpiffworkflowBaseDBModel): - """FlaskBpmnGroupModel.""" - - __tablename__ = "group" - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(255)) diff --git a/flask-bpmn/src/flask_bpmn/py.typed b/flask-bpmn/src/flask_bpmn/py.typed deleted file mode 100644 index e69de29bb..000000000 diff --git a/flask-bpmn/tests/__init__.py b/flask-bpmn/tests/__init__.py deleted file mode 100644 index ce3478a12..000000000 --- a/flask-bpmn/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Test suite for the flask_bpmn package.""" diff --git a/flask-bpmn/tests/flask_bpmn/api/test_api_error.py b/flask-bpmn/tests/flask_bpmn/api/test_api_error.py deleted file mode 100644 index 24315e392..000000000 --- a/flask-bpmn/tests/flask_bpmn/api/test_api_error.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Test cases for the __main__ module.""" -import io - -from flask_bpmn.api.api_error import ApiError - - -def test_is_jsonable_can_succeed() -> None: - """Test_is_jsonable_can_succeed.""" - result = ApiError.is_jsonable("This is a string and should pass json.dumps") - assert result is True - - -def test_is_jsonable_can_fail() -> None: - """Test_is_jsonable_can_fail.""" - result = ApiError.is_jsonable(io.StringIO("BAD JSON OBJECT")) - assert result is False - - -def test_remove_unserializeable_from_dict_succeeds() -> None: - """Test_remove_unserializeable_from_dict_succeeds.""" - initial_dict_object = { - "valid_key": "valid_value", - "invalid_key_value": io.StringIO("BAD JSON OBJECT"), - } - final_dict_object = { - "valid_key": "valid_value", - } - result = ApiError.remove_unserializeable_from_dict(initial_dict_object) - assert result == final_dict_object diff --git a/flask-bpmn/tests/flask_bpmn/models/test_group.py b/flask-bpmn/tests/flask_bpmn/models/test_group.py deleted file mode 100644 index ca3362244..000000000 --- a/flask-bpmn/tests/flask_bpmn/models/test_group.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Test cases for the group module.""" -from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from flask_bpmn.models.group import FlaskBpmnGroupModel - - -class AppGroupModel(FlaskBpmnGroupModel): - """AppGroupModel.""" - - -def test_table_names_are_singular_per_what_appear_to_be_flask_conventions() -> None: - """Test_is_jsonable_can_succeed.""" - assert FlaskBpmnGroupModel.__tablename__ == "group" - - -def test__all_subclasses_of_spiffworkflow_base_db_model_returns_all_subclasses_that_are_defined() -> None: - """Test_is_jsonable_can_succeed.""" - assert SpiffworkflowBaseDBModel._all_subclasses() == [ - FlaskBpmnGroupModel, - AppGroupModel, - ] diff --git a/flask-bpmn/tests/test_main.py b/flask-bpmn/tests/test_main.py deleted file mode 100644 index c53c41010..000000000 --- a/flask-bpmn/tests/test_main.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Test cases for the __main__ module.""" -import pytest -from click.testing import CliRunner - -from flask_bpmn import __main__ - - -@pytest.fixture -def runner() -> CliRunner: - """Fixture for invoking command-line interfaces.""" - return CliRunner() - - -def test_main_succeeds(runner: CliRunner) -> None: - """It exits with a status code of zero.""" - result = runner.invoke(__main__.main) - assert result.exit_code == 0 From 3c12e8ad35945002a59232a12ba17de0a982a6ba Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 19 Jan 2023 12:36:45 -0500 Subject: [PATCH 3/8] Lots of adjustments from running pyl Main change is in the ErrorDisplay.tsx to assure all error information is provided. and index.css to make it "pretty" --- bin/run_pyl | 15 +++- .../bin/import_tickets_for_command_line.py | 3 +- spiffworkflow-backend/conftest.py | 5 +- .../src/spiffworkflow_backend/__init__.py | 6 +- .../spiffworkflow_backend/config/__init__.py | 18 ++-- .../config/permissions/example.yml | 3 +- .../exceptions/api_error.py | 11 ++- .../helpers/db_helper.py | 1 + .../src/spiffworkflow_backend/models/db.py | 6 +- .../src/spiffworkflow_backend/models/group.py | 4 +- .../models/human_task.py | 5 +- .../models/human_task_user.py | 5 +- .../models/message_correlation.py | 5 +- .../message_correlation_message_instance.py | 5 +- .../models/message_correlation_property.py | 5 +- .../models/message_instance.py | 5 +- .../models/message_model.py | 1 - .../message_triggerable_process_model.py | 5 +- .../models/permission_assignment.py | 5 +- .../models/permission_target.py | 4 +- .../spiffworkflow_backend/models/principal.py | 5 +- .../models/process_instance.py | 5 +- .../models/process_instance_metadata.py | 5 +- .../models/process_instance_report.py | 5 +- .../models/refresh_token.py | 4 +- .../models/secret_model.py | 5 +- .../models/spec_reference.py | 9 +- .../models/spiff_logging.py | 1 - .../models/spiff_step_details.py | 5 +- .../src/spiffworkflow_backend/models/user.py | 5 +- .../models/user_group_assignment.py | 5 +- .../models/user_group_assignment_waiting.py | 5 +- .../routes/messages_controller.py | 2 +- .../routes/process_api_blueprint.py | 4 +- .../routes/process_groups_controller.py | 2 +- .../routes/process_instances_controller.py | 11 +-- .../routes/process_models_controller.py | 2 +- .../routes/script_unit_tests_controller.py | 2 +- .../routes/tasks_controller.py | 4 +- .../src/spiffworkflow_backend/routes/user.py | 2 +- .../routes/user_blueprint.py | 4 +- .../delete_process_instances_with_criteria.py | 2 +- .../scripts/get_localtime.py | 2 +- .../scripts/save_process_instance_metadata.py | 1 - .../spiffworkflow_backend/scripts/script.py | 4 +- .../services/acceptance_test_fixtures.py | 2 +- .../services/authentication_service.py | 10 ++- .../services/authorization_service.py | 33 ++++--- .../services/background_processing_service.py | 6 +- .../services/data_setup_service.py | 2 +- .../services/error_handling_service.py | 5 +- .../services/file_system_service.py | 5 +- .../services/group_service.py | 1 - .../services/logging_service.py | 5 +- .../services/message_service.py | 2 +- .../services/process_instance_processor.py | 87 ++++++++++--------- .../process_instance_report_service.py | 11 ++- .../services/process_instance_service.py | 7 +- .../services/process_model_service.py | 1 - .../services/secret_service.py | 1 - .../services/spec_file_service.py | 5 +- .../services/user_service.py | 2 +- .../helpers/base_test.py | 4 +- .../helpers/test_data.py | 3 +- .../integration/test_process_api.py | 5 +- .../integration/test_secret_service.py | 2 +- .../scripts/test_get_group_members.py | 2 +- .../scripts/test_refresh_permissions.py | 2 +- .../unit/test_message_instance.py | 2 +- .../unit/test_permission_target.py | 2 +- .../unit/test_permissions.py | 2 +- .../test_process_instance_report_service.py | 2 +- .../unit/test_process_model.py | 2 +- .../unit/test_restricted_script_engine.py | 2 +- .../unit/test_spec_file_service.py | 5 +- .../unit/test_spiff_logging.py | 2 +- .../src/components/ErrorDisplay.tsx | 57 ++++++++---- spiffworkflow-frontend/src/index.css | 9 ++ 78 files changed, 273 insertions(+), 233 deletions(-) diff --git a/bin/run_pyl b/bin/run_pyl index bceba187b..d97f68d85 100755 --- a/bin/run_pyl +++ b/bin/run_pyl @@ -57,10 +57,17 @@ function run_autoflake() { python_dirs=$(get_python_dirs) python_files=$(find $python_dirs -type f -name "*.py" ! -name '.null-ls*' ! -name '_null-ls*') - - autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files - autoflake --in-place --remove-all-unused-imports $python_files - autopep8 --in-place $python_files + echo Current dir: $(pwd) + echo dirs: $python_dirs + echo files: \"$python_files\" + if [ -z "$python_files" != ""] + then + autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files + autoflake --in-place --remove-all-unused-imports $python_files + autopep8 --in-place $python_files + else + echo "no files " + fi } function run_pre_commmit() { diff --git a/spiffworkflow-backend/bin/import_tickets_for_command_line.py b/spiffworkflow-backend/bin/import_tickets_for_command_line.py index 36b627968..c89cc2a74 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_command_line.py +++ b/spiffworkflow-backend/bin/import_tickets_for_command_line.py @@ -1,9 +1,8 @@ """Grabs tickets from csv and makes process instances.""" import csv -from spiffworkflow_backend.models.db import db - from spiffworkflow_backend import get_hacked_up_app_for_script +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index 8d1191965..448d18569 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -5,11 +5,10 @@ import shutil import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py index 95e11570a..64649048e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py @@ -9,16 +9,16 @@ import sqlalchemy from apscheduler.schedulers.background import BackgroundScheduler # type: ignore from apscheduler.schedulers.base import BaseScheduler # type: ignore from flask.json.provider import DefaultJSONProvider -from spiffworkflow_backend.exceptions.api_error import api_error_blueprint -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import migrate from flask_cors import CORS # type: ignore from flask_mail import Mail # type: ignore from werkzeug.exceptions import NotFound import spiffworkflow_backend.load_database_models # noqa: F401 from spiffworkflow_backend.config import setup_config +from spiffworkflow_backend.exceptions.api_error import api_error_blueprint from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import migrate from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint from spiffworkflow_backend.routes.openid_blueprint.openid_blueprint import ( openid_blueprint, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py index 7d915946b..29696fedb 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py @@ -17,21 +17,21 @@ def setup_database_uri(app: Flask) -> None: if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None: database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}" if app.config.get("SPIFF_DATABASE_TYPE") == "sqlite": - app.config["SQLALCHEMY_DATABASE_URI"] = ( - f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" - ) + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" elif app.config.get("SPIFF_DATABASE_TYPE") == "postgres": - app.config["SQLALCHEMY_DATABASE_URI"] = ( - f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" - ) + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" else: # use pswd to trick flake8 with hardcoded passwords db_pswd = os.environ.get("DB_PASSWORD") if db_pswd is None: db_pswd = "" - app.config["SQLALCHEMY_DATABASE_URI"] = ( - f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" - ) + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" else: app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get( "SPIFFWORKFLOW_BACKEND_DATABASE_URI" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml index c80b15112..659e01355 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/example.yml @@ -95,11 +95,10 @@ permissions: users: [] allowed_permissions: [create, read] uri: /process-instances/misc:category_number_one:process-model-with-form/* - + # Anyone can see their own user groups. groups-everybody: groups: [everybody] users: [] allowed_permissions: [create, read] uri: /v1.0/user-groups/for-current-user - diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py index 0dfce83a8..cc508e6c2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py @@ -15,7 +15,8 @@ from flask import jsonify from flask import make_response from sentry_sdk import capture_exception from sentry_sdk import set_tag -from SpiffWorkflow.exceptions import WorkflowException, WorkflowTaskException # type: ignore +from SpiffWorkflow.exceptions import WorkflowException +from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.specs.base import TaskSpec # type: ignore from SpiffWorkflow.task import Task # type: ignore @@ -40,7 +41,7 @@ class ApiError(Exception): task_data: dict | str | None = field(default_factory=dict) task_id: str = "" task_name: str = "" - task_trace: dict | None = field(default_factory=dict) + task_trace: list | None = field(default_factory=dict) def __str__(self) -> str: """Instructions to print instance as a string.""" @@ -151,7 +152,7 @@ class ApiError(Exception): ) else: - return ApiError.from_task_spec(error_code, message, exp.sender) + return ApiError.from_task_spec(error_code, message, exp.task_spec) def set_user_sentry_context() -> None: @@ -176,7 +177,9 @@ def handle_exception(exception: Exception) -> flask.wrappers.Response: if isinstance(exception, ApiError): current_app.logger.info( - f"Sending ApiError exception to sentry: {exception} with error code {exception.error_code}") + f"Sending ApiError exception to sentry: {exception} with error code" + f" {exception.error_code}" + ) organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py index 4a836b1e6..57108b6cd 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/db_helper.py @@ -2,6 +2,7 @@ import time import sqlalchemy + from spiffworkflow_backend.models.db import db diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py index 643e1a85d..762b47197 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py @@ -59,7 +59,8 @@ class SpiffworkflowBaseDBModel(db.Model): # type: ignore def update_created_modified_on_create_listener( mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel ) -> None: - """Event listener that runs before a record is updated, and sets the create/modified field accordingly.""" + """Event listener that runs before a record is updated, and sets the create/modified field accordingly. + """ if "created_at_in_seconds" in mapper.columns.keys(): target.created_at_in_seconds = round(time.time()) if "updated_at_in_seconds" in mapper.columns.keys(): @@ -69,7 +70,8 @@ def update_created_modified_on_create_listener( def update_modified_on_update_listener( mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel ) -> None: - """Event listener that runs before a record is updated, and sets the modified field accordingly.""" + """Event listener that runs before a record is updated, and sets the modified field accordingly. + """ if "updated_at_in_seconds" in mapper.columns.keys(): if db.session.is_modified(target, include_collections=False): target.updated_at_in_seconds = round(time.time()) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py index 7038ad6f3..f1017df96 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/group.py @@ -3,9 +3,11 @@ from __future__ import annotations from typing import TYPE_CHECKING -from spiffworkflow_backend.models.db import db, SpiffworkflowBaseDBModel from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + if TYPE_CHECKING: from spiffworkflow_backend.models.user_group_assignment import ( # noqa: F401 UserGroupAssignmentModel, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py index 398053423..7e5117a0f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task.py @@ -4,12 +4,11 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.task import Task diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py index 1ac0824e3..a0507f828 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/human_task_user.py @@ -3,11 +3,10 @@ from __future__ import annotations from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py index 3e03f32eb..e913938f5 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py @@ -2,12 +2,11 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.message_correlation_property import ( MessageCorrelationPropertyModel, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py index 7b1ddfbdf..58ded838b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py @@ -1,11 +1,10 @@ """Message_correlation_message_instance.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py index 6b03c91a5..1e09dc0c4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.message_model import MessageModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py index 60c2fc92b..c9ea515e6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py @@ -5,15 +5,14 @@ from typing import Any from typing import Optional from typing import TYPE_CHECKING -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.event import listens_for from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import validates +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py index 7fe78f707..8ebd15c56 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_model.py @@ -3,7 +3,6 @@ from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - class MessageModel(SpiffworkflowBaseDBModel): """MessageModel.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py index acd44eac3..edf648218 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.message_model import MessageModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py index 2e09d888e..a9db96cfa 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py @@ -2,12 +2,11 @@ import enum from typing import Any -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import validates +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py index a9fe7111c..773833a39 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_target.py @@ -3,11 +3,11 @@ import re from dataclasses import dataclass from typing import Optional +from sqlalchemy.orm import validates + from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel -from sqlalchemy.orm import validates - class InvalidPermissionTargetUriError(Exception): """InvalidPermissionTargetUriError.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py index f3818e9d9..6e46def5b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py @@ -1,13 +1,12 @@ """Principal.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.schema import CheckConstraint +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index bb262b4c2..75a580040 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -5,9 +5,6 @@ from typing import Any from typing import cast import marshmallow -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from marshmallow import INCLUDE from marshmallow import Schema from marshmallow_enum import EnumField # type: ignore @@ -18,6 +15,8 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import validates from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import TaskSchema from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py index c4114dda2..920e13a2c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py @@ -1,11 +1,10 @@ """Process_instance_metadata.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py index 19f98a06e..a8787da62 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py @@ -7,9 +7,6 @@ from typing import cast from typing import Optional from typing import TypedDict -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import deferred from sqlalchemy.orm import relationship @@ -17,6 +14,8 @@ from sqlalchemy.orm import relationship from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py index 5cf23609c..d7bf0fe1e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/refresh_token.py @@ -1,11 +1,11 @@ """Refresh_token.""" from dataclasses import dataclass +from sqlalchemy import ForeignKey + from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - # from sqlalchemy.orm import relationship # from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py index 37f47b935..026831eda 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py @@ -1,12 +1,11 @@ """Secret_model.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from marshmallow import Schema from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py index e7b2ab98e..01ae8f0d9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py @@ -1,13 +1,13 @@ """Message_model.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from flask_marshmallow import Schema # type: ignore from marshmallow import INCLUDE from sqlalchemy import UniqueConstraint +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + class SpecReferenceNotFoundError(Exception): """SpecReferenceNotFoundError.""" @@ -38,7 +38,8 @@ class SpecReference: 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" __table_args__ = ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py index 9fc82a01e..71e1bbfbd 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py @@ -6,7 +6,6 @@ from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - @dataclass class SpiffLoggingModel(SpiffworkflowBaseDBModel): """SpiffLoggingModel.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py index 8d807493f..50bf4520d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py @@ -1,12 +1,11 @@ """Spiff_step_details.""" from dataclasses import dataclass -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import deferred +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py index f3838a06c..7f8c88da9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py @@ -6,12 +6,11 @@ from dataclasses import dataclass import jwt import marshmallow from flask import current_app -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from marshmallow import Schema from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py index 2c5638bb9..acd6c30b2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py @@ -1,10 +1,9 @@ """UserGroupAssignment.""" -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py index fe9c6b885..7db1676f9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment_waiting.py @@ -1,10 +1,9 @@ """UserGroupAssignment.""" -from spiffworkflow_backend.models.db import db -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py index 35befc612..0db93a4a6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/messages_controller.py @@ -9,8 +9,8 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_model import MessageModel 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 55b0afcaf..0e9bd581d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -11,12 +11,12 @@ from flask import jsonify from flask import make_response from flask import request from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py index 98da1901a..65dca25f7 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_groups_controller.py @@ -8,8 +8,8 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index 0a1eaa497..08e665ca9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -11,12 +11,12 @@ from flask import jsonify from flask import make_response from flask import request from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import TaskState # type: ignore from sqlalchemy import and_ from sqlalchemy import or_ +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema @@ -556,9 +556,10 @@ def process_instance_task_list( else: spiff_tasks = processor.get_all_user_tasks() - subprocesses_by_child_task_ids, task_typename_by_task_id = ( - processor.get_subprocesses_by_child_task_ids() - ) + ( + subprocesses_by_child_task_ids, + task_typename_by_task_id, + ) = processor.get_subprocesses_by_child_task_ids() processor.get_highest_level_calling_subprocesses_by_child_task_ids( subprocesses_by_child_task_ids, task_typename_by_task_id ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py index cda5dd6f9..bad5af7b6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py @@ -14,9 +14,9 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError from werkzeug.datastructures import FileStorage +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.interfaces import IdToProcessGroupMapping from spiffworkflow_backend.models.file import FileSchema from spiffworkflow_backend.models.process_group import ProcessGroup diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py index 29d2461e6..3a6d11435 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/script_unit_tests_controller.py @@ -10,10 +10,10 @@ from flask import current_app from flask import jsonify from flask import make_response from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError from lxml import etree # type: ignore from lxml.builder import ElementMaker # type: ignore +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.routes.process_api_blueprint import _get_process_model from spiffworkflow_backend.routes.process_api_blueprint import ( _get_required_parameter_or_raise, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index 8f700a0ff..86472f6a4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -15,8 +15,6 @@ from flask import g from flask import jsonify from flask import make_response from flask.wrappers import Response -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from sqlalchemy import and_ @@ -26,6 +24,8 @@ from sqlalchemy import func from sqlalchemy.orm import aliased from sqlalchemy.orm.util import AliasedClass +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py index f580651e9..072acfaa6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py @@ -14,9 +14,9 @@ from flask import current_app from flask import g from flask import redirect from flask import request -from spiffworkflow_backend.exceptions.api_error import ApiError from werkzeug.wrappers import Response +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authentication_service import AuthenticationService from spiffworkflow_backend.services.authentication_service import ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py index 807b08c1a..e8807c776 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py @@ -7,10 +7,10 @@ import flask.wrappers from flask import Blueprint from flask import request from flask import Response -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from sqlalchemy.exc import IntegrityError +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py index 3345ef641..6d65ea758 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/delete_process_instances_with_criteria.py @@ -2,9 +2,9 @@ from time import time from typing import Any -from spiffworkflow_backend.models.db import db from sqlalchemy import or_ +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py index c5742f84a..e16ee23b3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py @@ -3,8 +3,8 @@ from datetime import datetime from typing import Any import pytz -from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py index 38daf193c..3d2054df2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/save_process_instance_metadata.py @@ -2,7 +2,6 @@ from typing import Any from spiffworkflow_backend.models.db import db - from spiffworkflow_backend.models.process_instance_metadata import ( ProcessInstanceMetadataModel, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py index 4f2300feb..2d75961b7 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py @@ -9,7 +9,6 @@ from typing import Any from typing import Callable from spiffworkflow_backend.exceptions.api_error import ApiError - from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceNotFoundError from spiffworkflow_backend.models.script_attributes_context import ( @@ -28,7 +27,8 @@ class ScriptUnauthorizedForUserError(Exception): class Script: - """Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks.""" + """Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks. + """ @abstractmethod def get_description(self) -> str: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index 028f47a64..89fbc8a88 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -2,9 +2,9 @@ import time from flask import current_app -from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.services.process_instance_service import ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py index c15f31d26..925f4ed91 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py @@ -9,10 +9,10 @@ import jwt import requests from flask import current_app from flask import redirect -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from werkzeug.wrappers import Response +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.refresh_token import RefreshTokenModel @@ -60,7 +60,8 @@ class AuthenticationService: @classmethod def open_id_endpoint_for_name(cls, name: str) -> str: - """All openid systems provide a mapping of static names to the full path of that endpoint.""" + """All openid systems provide a mapping of static names to the full path of that endpoint. + """ openid_config_url = f"{cls.server_url()}/.well-known/openid-configuration" if name not in AuthenticationService.ENDPOINT_CACHE: response = requests.get(openid_config_url) @@ -200,7 +201,8 @@ class AuthenticationService: @classmethod def get_auth_token_from_refresh_token(cls, refresh_token: str) -> dict: - """Converts a refresh token to an Auth Token by calling the openid's auth endpoint.""" + """Converts a refresh token to an Auth Token by calling the openid's auth endpoint. + """ backend_basic_auth_string = f"{cls.client_id()}:{cls.secret_key()}" backend_basic_auth_bytes = bytes(backend_basic_auth_string, encoding="ascii") backend_basic_auth = base64.b64encode(backend_basic_auth_bytes) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py index a1915a5d1..234f0e04e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py @@ -17,13 +17,13 @@ from flask import current_app from flask import g from flask import request from flask import scaffold -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore from sqlalchemy import or_ from sqlalchemy import text +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel @@ -171,7 +171,8 @@ class AuthorizationService: @classmethod def delete_all_permissions(cls) -> None: - """Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user?""" + """Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user? + """ for model in [PermissionAssignmentModel, PermissionTargetModel]: db.session.query(model).delete() @@ -282,9 +283,9 @@ class AuthorizationService: """Find_or_create_permission_target.""" uri_with_percent = re.sub(r"\*", "%", uri) target_uri_normalized = uri_with_percent.removeprefix(V1_API_PATH_PREFIX) - permission_target: Optional[PermissionTargetModel] = ( - PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first() - ) + permission_target: Optional[ + PermissionTargetModel + ] = PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first() if permission_target is None: permission_target = PermissionTargetModel(uri=target_uri_normalized) db.session.add(permission_target) @@ -299,13 +300,13 @@ class AuthorizationService: permission: str, ) -> PermissionAssignmentModel: """Create_permission_for_principal.""" - permission_assignment: Optional[PermissionAssignmentModel] = ( - PermissionAssignmentModel.query.filter_by( - principal_id=principal.id, - permission_target_id=permission_target.id, - permission=permission, - ).first() - ) + permission_assignment: Optional[ + PermissionAssignmentModel + ] = PermissionAssignmentModel.query.filter_by( + principal_id=principal.id, + permission_target_id=permission_target.id, + permission=permission, + ).first() if permission_assignment is None: permission_assignment = PermissionAssignmentModel( principal_id=principal.id, @@ -434,10 +435,8 @@ class AuthorizationService: except jwt.InvalidTokenError as exception: raise ApiError( "token_invalid", - ( - "The Authentication token you provided is invalid. You need a new" - " token. " - ), + "The Authentication token you provided is invalid. You need a new" + " token. ", ) from exception @staticmethod diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py index 1771c2c8b..bc0b283ba 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py @@ -15,11 +15,13 @@ class BackgroundProcessingService: self.app = app def process_waiting_process_instances(self) -> None: - """Since this runs in a scheduler, we need to specify the app context as well.""" + """Since this runs in a scheduler, we need to specify the app context as well. + """ with self.app.app_context(): ProcessInstanceService.do_waiting() def process_message_instances_with_app_context(self) -> None: - """Since this runs in a scheduler, we need to specify the app context as well.""" + """Since this runs in a scheduler, we need to specify the app context as well. + """ with self.app.app_context(): MessageService.process_message_instances() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py index 25aa143ca..39f14ca5e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py @@ -1,7 +1,7 @@ """Data_setup_service.""" from flask import current_app -from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index b5509eb79..1db619f08 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -5,9 +5,9 @@ from typing import Union from flask import current_app from flask import g from flask.wrappers import Response + from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.db import db - from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_triggerable_process_model import ( MessageTriggerableProcessModel, @@ -41,7 +41,8 @@ class ErrorHandlingService: def handle_error( self, _processor: ProcessInstanceProcessor, _error: Union[ApiError, Exception] ) -> None: - """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.""" + """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception. + """ process_model = ProcessModelService.get_process_model( _processor.process_model_identifier ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py index 96b8e6ba0..3201199ef 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py @@ -8,8 +8,8 @@ from typing import Optional import pytz from flask import current_app -from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.file import CONTENT_TYPES from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType @@ -151,7 +151,8 @@ class FileSystemService: @staticmethod def _get_files(file_path: str, file_name: Optional[str] = None) -> List[File]: - """Returns an array of File objects at the given path, can be restricted to just one file.""" + """Returns an array of File objects at the given path, can be restricted to just one file. + """ files = [] items = os.scandir(file_path) for item in items: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py index c417d8eb4..abc111511 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py @@ -2,7 +2,6 @@ from typing import Optional from spiffworkflow_backend.models.db import db - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.user_service import UserService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py index d09d3c0de..85c788dd8 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py @@ -7,8 +7,8 @@ from typing import Optional from flask import g from flask.app import Flask -from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel @@ -52,7 +52,8 @@ class JsonFormatter(logging.Formatter): self.datefmt = None def usesTime(self) -> bool: - """Overwritten to look for the attribute in the format dict values instead of the fmt string.""" + """Overwritten to look for the attribute in the format dict values instead of the fmt string. + """ return "asctime" in self.fmt_dict.values() # we are overriding a method that returns a string and returning a dict, hence the Any diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py index 3ac4b5745..0e4799ca0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py @@ -2,11 +2,11 @@ from typing import Any from typing import Optional -from spiffworkflow_backend.models.db import db from sqlalchemy import and_ from sqlalchemy import or_ from sqlalchemy import select +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation_message_instance import ( MessageCorrelationMessageInstanceModel, 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 711ccc353..51b011cd4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -22,11 +22,9 @@ from uuid import UUID import dateparser import pytz from flask import current_app -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from lxml import etree # type: ignore +from lxml.etree import XMLSyntaxError from RestrictedPython import safe_globals # type: ignore -from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine @@ -40,6 +38,7 @@ from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore from SpiffWorkflow.dmn.serializer.task_spec_converters import BusinessRuleTaskConverter # type: ignore from SpiffWorkflow.exceptions import WorkflowException # type: ignore +from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore from SpiffWorkflow.spiff.serializer.task_spec_converters import BoundaryEventConverter # type: ignore from SpiffWorkflow.spiff.serializer.task_spec_converters import ( @@ -71,6 +70,8 @@ from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.group import GroupModel @@ -217,15 +218,16 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore return super()._evaluate(expression, context, external_methods=methods) except Exception as exception: if task is None: - raise ProcessInstanceProcessorError( - "Error evaluating expression: '%s', exception: %s" + raise WorkflowException( + "Error evaluating expression: '%s', %s" % (expression, str(exception)), ) from exception else: raise WorkflowTaskException( - task, "Error evaluating expression '%s', %s" % (expression, str(exception)), + task=task, + exception=exception, ) from exception def execute( @@ -240,7 +242,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore except WorkflowException as e: raise e except Exception as e: - raise WorkflowTaskException(task, f" {script}, {e}", e) from e + raise self.create_task_exec_exception(task, script, e) def call_service( self, @@ -297,7 +299,8 @@ class ProcessInstanceProcessor: def __init__( self, process_instance_model: ProcessInstanceModel, validate_only: bool = False ) -> None: - """Create a Workflow Processor based on the serialized information available in the process_instance model.""" + """Create a Workflow Processor based on the serialized information available in the process_instance model. + """ tld = current_app.config["THREAD_LOCAL_DATA"] tld.process_instance_id = process_instance_model.id tld.spiff_step = process_instance_model.spiff_step @@ -403,10 +406,8 @@ class ProcessInstanceProcessor: raise ( ApiError( "process_model_not_found", - ( - "The given process model was not found:" - f" {process_model_identifier}." - ), + "The given process model was not found:" + f" {process_model_identifier}.", ) ) spec_files = SpecFileService.get_files(process_model_info) @@ -536,11 +537,9 @@ class ProcessInstanceProcessor: potential_owner_ids.append(lane_owner_user.id) self.raise_if_no_potential_owners( potential_owner_ids, - ( - "No users found in task data lane owner list for lane:" - f" {task_lane}. The user list used:" - f" {task.data['lane_owners'][task_lane]}" - ), + "No users found in task data lane owner list for lane:" + f" {task_lane}. The user list used:" + f" {task.data['lane_owners'][task_lane]}", ) else: group_model = GroupModel.query.filter_by(identifier=task_lane).first() @@ -693,9 +692,9 @@ class ProcessInstanceProcessor: ): continue - subprocesses_by_child_task_ids[task_id] = ( - subprocesses_by_child_task_ids[subprocess_id] - ) + subprocesses_by_child_task_ids[ + task_id + ] = subprocesses_by_child_task_ids[subprocess_id] self.get_highest_level_calling_subprocesses_by_child_task_ids( subprocesses_by_child_task_ids, task_typename_by_task_id ) @@ -1015,17 +1014,24 @@ class ProcessInstanceProcessor: def get_spec( files: List[File], process_model_info: ProcessModelInfo ) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]: - """Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided.""" + """Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided. + """ parser = ProcessInstanceProcessor.get_parser() for file in files: data = SpecFileService.get_data(process_model_info, file.name) - if file.type == FileType.bpmn.value: - bpmn: etree.Element = etree.fromstring(data) - parser.add_bpmn_xml(bpmn, filename=file.name) - elif file.type == FileType.dmn.value: - dmn: etree.Element = etree.fromstring(data) - parser.add_dmn_xml(dmn, filename=file.name) + try: + if file.type == FileType.bpmn.value: + bpmn: etree.Element = etree.fromstring(data) + parser.add_bpmn_xml(bpmn, filename=file.name) + elif file.type == FileType.dmn.value: + dmn: etree.Element = etree.fromstring(data) + parser.add_dmn_xml(dmn, filename=file.name) + except XMLSyntaxError as xse: + raise ApiError( + error_code="invalid_xml", + message=f"'{file.name}' is not a valid xml file." + str(xse), + ) if ( process_model_info.primary_process_id is None or process_model_info.primary_process_id == "" @@ -1056,7 +1062,8 @@ class ProcessInstanceProcessor: error_code="process_instance_validation_error", message="Failed to parse the Workflow Specification. " + "Error is '%s.'" % str(ve), - file_name=ve.filename, + file_name=ve.file_name, + task_name=ve.name, task_id=ve.id, tag=ve.tag, ) from ve @@ -1097,10 +1104,8 @@ class ProcessInstanceProcessor: if not bpmn_message.correlations: raise ApiError( "message_correlations_missing", - ( - "Could not find any message correlations bpmn_message:" - f" {bpmn_message.name}" - ), + "Could not find any message correlations bpmn_message:" + f" {bpmn_message.name}", ) message_correlations = [] @@ -1120,10 +1125,8 @@ class ProcessInstanceProcessor: if message_correlation_property is None: raise ApiError( "message_correlations_missing_from_process", - ( - "Could not find a known message correlation with" - f" identifier:{message_correlation_property_identifier}" - ), + "Could not find a known message correlation with" + f" identifier:{message_correlation_property_identifier}", ) message_correlations.append( { @@ -1186,10 +1189,8 @@ class ProcessInstanceProcessor: if message_model is None: raise ApiError( "invalid_message_name", - ( - "Invalid message name:" - f" {waiting_task.task_spec.event_definition.name}." - ), + "Invalid message name:" + f" {waiting_task.task_spec.event_definition.name}.", ) # Ensure we are only creating one message instance for each waiting message @@ -1474,7 +1475,8 @@ class ProcessInstanceProcessor: return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore def get_current_user_tasks(self) -> list[SpiffTask]: - """Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task.""" + """Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task. + """ ready_tasks = self.bpmn_process_instance.get_ready_user_tasks() additional_tasks = [] if len(ready_tasks) > 0: @@ -1531,7 +1533,8 @@ class ProcessInstanceProcessor: return None def find_spec_and_field(self, spec_name: str, field_id: Union[str, int]) -> Any: - """Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form.""" + """Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form. + """ process_instances = [self.bpmn_process_instance] for task in self.bpmn_process_instance.get_ready_user_tasks(): if task.process_instance not in process_instances: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index 134f0f7b2..ce4e0183b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -6,15 +6,14 @@ from typing import Optional from typing import Type import sqlalchemy -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel - from sqlalchemy import and_ from sqlalchemy import func from sqlalchemy import or_ from sqlalchemy.orm import aliased from sqlalchemy.orm import selectinload +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel @@ -313,9 +312,9 @@ class ProcessInstanceReportService: process_instance_dict = process_instance["ProcessInstanceModel"].serialized for metadata_column in metadata_columns: if metadata_column["accessor"] not in process_instance_dict: - process_instance_dict[metadata_column["accessor"]] = ( - process_instance[metadata_column["accessor"]] - ) + process_instance_dict[ + metadata_column["accessor"] + ] = process_instance[metadata_column["accessor"]] results.append(process_instance_dict) return results diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index abe8e6940..a9c2f4d01 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -5,10 +5,10 @@ from typing import List from typing import Optional from flask import current_app -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceModel @@ -224,7 +224,8 @@ class ProcessInstanceService: @staticmethod def extract_form_data(latest_data: dict, task: SpiffTask) -> dict: - """Extracts data from the latest_data that is directly related to the form that is being submitted.""" + """Extracts data from the latest_data that is directly related to the form that is being submitted. + """ data = {} if hasattr(task.task_spec, "form"): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py index 9b53a98ed..9ac175945 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py @@ -9,7 +9,6 @@ from typing import Optional from typing import TypeVar from spiffworkflow_backend.exceptions.api_error import ApiError - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py index 7c2d27fea..f34be93d6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py @@ -3,7 +3,6 @@ from typing import Optional from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.db import db - from spiffworkflow_backend.models.secret_model import SecretModel # from cryptography.fernet import Fernet 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 69901674d..7273fd6c3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -5,10 +5,10 @@ from datetime import datetime from typing import List from typing import Optional -from spiffworkflow_backend.models.db import db from lxml import etree # type: ignore from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator # type: ignore +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import SpecReference @@ -325,7 +325,8 @@ class SpecFileService(FileSystemService): @staticmethod def update_message_cache(ref: SpecReference) -> None: - """Assure we have a record in the database of all possible message ids and names.""" + """Assure we have a record in the database of all possible message ids and names. + """ for message_model_identifier in ref.messages.keys(): message_model = MessageModel.query.filter_by( identifier=message_model_identifier diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py index b460bad28..d43fa2013 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py @@ -4,9 +4,9 @@ from typing import Optional from flask import current_app from flask import g + from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.db import db - from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py index 61bf5a404..4d0d7c1a5 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py @@ -9,11 +9,11 @@ from typing import Optional from flask import current_app from flask.testing import FlaskClient -from spiffworkflow_backend.exceptions.api_error import ApiError -from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from werkzeug.test import TestResponse # type: ignore +from spiffworkflow_backend.exceptions.api_error import ApiError +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.permission_assignment import Permission from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.process_group import ProcessGroup diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py index d6b4f730c..40cb89b1e 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py @@ -40,7 +40,8 @@ def load_test_spec( bpmn_file_name: Optional[str] = None, process_model_source_directory: Optional[str] = None, ) -> ProcessModelInfo: - """Loads a bpmn file into the process model dir based on a directory in tests/data.""" + """Loads a bpmn file into the process model dir based on a directory in tests/data. + """ if process_model_source_directory is None: raise Exception("You must inclode a `process_model_source_directory`.") 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 9e6199443..660bdca38 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,13 +9,13 @@ from typing import Dict import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.process_group import ProcessGroup @@ -3103,7 +3103,8 @@ class TestProcessApi(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """Test_can_get_process_instance_list_with_report_metadata_and_process_initator.""" + """Test_can_get_process_instance_list_with_report_metadata_and_process_initator. + """ user_one = self.create_user_with_permission(username="user_one") process_model = load_test_spec( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py index 631df9b56..f7f5b5621 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -5,10 +5,10 @@ from typing import Optional import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from werkzeug.test import TestResponse # type: ignore +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModelSchema diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py index 00cc4e65a..6e57b1bf6 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py @@ -1,10 +1,10 @@ """Test_get_localtime.""" from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py index e3d8563bc..20176dd84 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_refresh_permissions.py @@ -2,10 +2,10 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py index f9f764cd2..6c90eb254 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -2,9 +2,9 @@ import pytest from flask import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py index 7ad9765b4..6ae126dd5 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py @@ -1,9 +1,9 @@ """Process Model.""" import pytest from flask.app import Flask -from spiffworkflow_backend.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.permission_target import ( InvalidPermissionTargetUriError, ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py index b3991eeb2..f45f4ef5d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py @@ -1,10 +1,10 @@ """Test Permissions.""" from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py index 46a67b2a6..a0e694dc6 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report_service.py @@ -3,10 +3,10 @@ from typing import Optional from flask import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.process_instance_report import ( 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 86a6f648c..a5ac6c96d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py @@ -1,10 +1,10 @@ """Process Model.""" from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.process_instance_metadata import ( ProcessInstanceMetadataModel, ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index e9e164b6f..0f5d47702 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -2,10 +2,10 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.exceptions.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.exceptions.api_error import ApiError 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 82b96f125..b3e19067f 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 @@ -4,10 +4,10 @@ import os import pytest from flask import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService @@ -136,7 +136,8 @@ class TestSpecFileService(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """When a BPMN processes identifier is changed in a file, the old id is removed from the cache.""" + """When a BPMN processes identifier is changed in a file, the old id is removed from the cache. + """ old_identifier = "ye_old_identifier" process_id_lookup = SpecReferenceCache( identifier=old_identifier, diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py index 3f4b117d9..a47983fe3 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py @@ -2,10 +2,10 @@ from decimal import Decimal from flask.app import Flask -from spiffworkflow_backend.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.db import db from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel diff --git a/spiffworkflow-frontend/src/components/ErrorDisplay.tsx b/spiffworkflow-frontend/src/components/ErrorDisplay.tsx index cdbed75a0..b64654857 100644 --- a/spiffworkflow-frontend/src/components/ErrorDisplay.tsx +++ b/spiffworkflow-frontend/src/components/ErrorDisplay.tsx @@ -2,6 +2,23 @@ import { useContext } from 'react'; import ErrorContext from '../contexts/ErrorContext'; import { Notification } from './Notification'; +function errorDetailDisplay( + errorObject: any, + propertyName: string, + title: string +) { + // Creates a bit of html for displaying a single error property if it exists. + if (propertyName in errorObject && errorObject[propertyName]) { + return ( +
+ {title}: + {errorObject[propertyName]} +
+ ); + } + return null; +} + export default function ErrorDisplay() { const [errorObject, setErrorObject] = (useContext as any)(ErrorContext); @@ -21,21 +38,24 @@ export default function ErrorDisplay() { ); } - let message =
{errorObject.message}
; - let title = 'Error:'; - if ('task_name' in errorObject && errorObject.task_name) { - title = 'Error in python script:'; - message = ( - <> -
-
- Task: {errorObject.task_name} ({errorObject.task_id}) -
-
File name: {errorObject.file_name}
-
Line number in script task: {errorObject.line_number}
-
-
{errorObject.message}
- + const message =
{errorObject.message}
; + const title = 'Error:'; + const taskName = errorDetailDisplay(errorObject, 'task_name', 'Task Name'); + const taskId = errorDetailDisplay(errorObject, 'task_id', 'Task ID'); + const fileName = errorDetailDisplay(errorObject, 'file_name', 'File Name'); + const lineNumber = errorDetailDisplay( + errorObject, + 'line_number', + 'Line Number' + ); + const errorLine = errorDetailDisplay(errorObject, 'error_line', 'Context'); + let taskTrace = null; + if ('task_trace' in errorObject && errorObject.task_trace.length > 1) { + taskTrace = ( +
+ Call Activity Trace: + {errorObject.task_trace.reverse().join(' -> ')} +
); } @@ -46,7 +66,14 @@ export default function ErrorDisplay() { type="error" > {message} +
{sentryLinkTag} + {taskName} + {taskId} + {fileName} + {lineNumber} + {errorLine} + {taskTrace} ); } diff --git a/spiffworkflow-frontend/src/index.css b/spiffworkflow-frontend/src/index.css index 614bbf739..5b79d9fa1 100644 --- a/spiffworkflow-frontend/src/index.css +++ b/spiffworkflow-frontend/src/index.css @@ -374,3 +374,12 @@ svg.notification-icon { .tag-type-green:hover { background-color: #80ee90; } + +/* Errors and notifications */ +.error_info .error_title { + display: inline-block; + font-weight: lighter; + width: 100px; + text-align: right; + margin-right: 10px; +} From 9d58cffa58f8178220dcc7c517cdb5b103fe4e1b Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 19 Jan 2023 12:37:17 -0500 Subject: [PATCH 4/8] Squashed 'SpiffWorkflow/' changes from 4195453a4..1f51db962 1f51db962 Merge pull request #283 from sartography/feature/better_errors 69fb4967e Patching up some bugs and logical disconnects as I test out the errors. cf5be0096 * Making a few more things consistent in the error messages -- so there isn't filename for validation errors, and file_name for WorkflowExceptions. Same for line_number vs sourceline. * Assure than an error_type is consistently set on exceptions. * ValidationExceptions should not bild up a detailed error message that replicates information available within it. 440ee16c8 Responding to some excellent suggestions from Elizabeth: 655e415e1 Merge pull request #282 from subhakarks/fix-workfowspec-dump 1f6d3cf4e Explain that the error happened in a pre-script or post script. 8119abd14 Added a top level SpiffWorklowException that all exceptions inherit from. Aside from a message string you can append information to these exceptions with "add_note", which is a new method that all exceptions have starting in python 3.11 Switched arguments to the WorkflowException, WorkflowTaskException - which now always takes a string message as the first argument, and named arguments thereafter to be consistent with all other error messages in Python. Consistently raise ValidationExceptions whenever we encounter an error anywhere during parsing of xml. The BPMN/WorkflowTaskExecException is removed, in favor of just calling a WorkflowTaskException. There is nothing BPMN Specific in the logic, so no need for this. Consolidated error message logic so that things like "Did you mean" just get added by default if possible. So we don't have to separately deal with that logic each time. Better Error messages for DMN (include row number as a part of the error information) 13463b5c5 fix for workflowspec dump be26100bc Merge pull request #280 from sartography/feature/remove-unused-bpmn-attributes-and-methods 23a5c1d70 remove 'entering_* methods 4e5875ec8 remove sequence flow 5eed83ab1 Merge pull request #278 from sartography/feature/remove-old-serializer 614f1c68a remove compact serializer and references e7e410d4a remove old serializer and references git-subtree-dir: SpiffWorkflow git-subtree-split: 1f51db962ccaed5810f5d0f7d76a932f056430ab --- doc/errors.rst | 90 +++++++++++ graphics/spiffworkflow_logo_ideas.svg | 131 ++++++++++++++- tests/SpiffWorkflow/bpmn/ApprovalsTest.py | 89 +--------- .../SpiffWorkflow/bpmn/BpmnSerializerTest.py | 118 -------------- .../bpmn/BpmnWorkflowSerializerTest.py | 9 -- .../bpmn/BpmnWorkflowTestCase.py | 8 +- .../bpmn/CallActivityEndEventTest.py | 4 +- tests/SpiffWorkflow/bpmn/CustomScriptTest.py | 4 +- .../bpmn/InvalidWorkflowsTest.py | 24 +-- tests/SpiffWorkflow/bpmn/ParserTest.py | 17 +- tests/SpiffWorkflow/bpmn/ScriptTest.py | 4 +- tests/SpiffWorkflow/bpmn/ServiceTaskTest.py | 5 +- .../bpmn/data/data_object_invalid.bpmn | 152 ++++++++++++++++++ .../SpiffWorkflow/bpmn/serializer/dictTest.py | 73 --------- .../SpiffWorkflow/bpmn/serializer/jsonTest.py | 38 ----- .../InvalidBusinessRuleTaskParserTest.py | 16 +- .../camunda/data/DMNMultiInstance.bpmn | 88 +++++----- .../data/dmn/test_integer_decision_multi.dmn | 4 +- .../camunda/specs/UserTaskSpecTest.py | 100 +++++------- .../spiff/PrescriptPostscriptTest.py | 18 ++- tests/SpiffWorkflow/spiff/ServiceTaskTest.py | 1 - .../spiff/ServiceTaskVariableTest.py | 1 - 22 files changed, 516 insertions(+), 478 deletions(-) create mode 100644 doc/errors.rst delete mode 100644 tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py create mode 100644 tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/serializer/dictTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/serializer/jsonTest.py diff --git a/doc/errors.rst b/doc/errors.rst new file mode 100644 index 000000000..31c606de2 --- /dev/null +++ b/doc/errors.rst @@ -0,0 +1,90 @@ +SpiffWorkflow Exceptions +==================================== +Details about the exceptions and exception hierarchy within SpiffWorkflow + +SpiffWorkflowException +---------- +Base exception for all exceptions raised by SpiffWorkflow + +ValidationException +---------- + +**Extends** +SpiffWorkflowException + +Thrown during the parsing of a workflow. + +**Attributes/Methods** + +- **tag**: The type of xml tag being parsed +- **id**: the id attribute of the xml tag, if available. +- **name**: the name attribute of the xml tag, if available. +- **line_number**: the line number where the tag occurs. +- **file_name**: The name of the file where the error occurred. +- **message**: a human readable error message. + + +WorkflowException +-------- +When an error occurs with a Task Specification (maybe should have been called +a SpecException) + +**Extends** +SpiffWorkflowException + +**Attributes/Methods** + +- **sender**: The TaskSpec - the specific Task, Gateway, etc... that caused the error to happen. +- **error**: a human readable error message describing the problem. +- **get_task_trace**: Provided a specific Task, will work it's way through the workflow / sub-processes +and call activities to show where an error occurred. Useful if the error happened within a deeply nested structure (where call activities include call activities ....) + +WorkflowDataException +------------------ +When an exception occurs moving data between tasks and Data Objects (including +data inputs and data outputs.) + +**Extends** +WorkflowException + +**Attributes/Methods** + +(in addition to the values in a WorkflowException) + + - **task**: The specific task (not the task spec, but the actual executing task) + - **data_input**: The spec of the input variable + - **data_output**: The spec of the output variable + +WorkflowTaskException +-------- +**Extends** +WorkflowException + +**Attributes/Methods** + +(in addition to the values in a WorkflowException) + + - **task**: The specific task (not the task spec, but the actual executing task) + - **error_msg**: The detailed human readable message. (conflicts with error above) + - **exception**: The original exception this wraps around. + - **line_number** The line number that contains the error + - **offset** The point in the line that caused the error + - **error_line** The content of the line that caused the error. + +It will accept the line_number and error_line as arguments - if the +underlying error provided is a SyntaxError it will try to derive this +information from the error. +If this is a name error, it will attempt to calculate a did-you-mean +error_msg. + +Unused / Deprecated errors +-------------------- + +** StorageException ** +Deprecated -- Used only by the PrettyXmlSerializer - which is not under active +support. + +** DeadMethodCalled ** +Something related to WeakMethod -- which doesn't look to be utilized anymore. + + diff --git a/graphics/spiffworkflow_logo_ideas.svg b/graphics/spiffworkflow_logo_ideas.svg index 28e5d8ac5..b51b8b521 100644 --- a/graphics/spiffworkflow_logo_ideas.svg +++ b/graphics/spiffworkflow_logo_ideas.svg @@ -26,13 +26,13 @@ showgrid="false" showguides="true" inkscape:guide-bbox="true" - inkscape:zoom="0.27433373" - inkscape:cx="-586.87643" - inkscape:cy="1882.7433" + inkscape:zoom="1.5518659" + inkscape:cx="2265.0153" + inkscape:cy="3541.2209" inkscape:window-width="1916" - inkscape:window-height="1076" + inkscape:window-height="916" inkscape:window-x="0" - inkscape:window-y="0" + inkscape:window-y="162" inkscape:window-maximized="1" inkscape:current-layer="layer1"> + + + @@ -839,6 +851,91 @@ x="-580.08496" y="716.69928">Draw the code + + + + + + + + + + + + + + + + + + Draw the code + + + + + diff --git a/tests/SpiffWorkflow/bpmn/ApprovalsTest.py b/tests/SpiffWorkflow/bpmn/ApprovalsTest.py index 7576a23fe..857c81f07 100644 --- a/tests/SpiffWorkflow/bpmn/ApprovalsTest.py +++ b/tests/SpiffWorkflow/bpmn/ApprovalsTest.py @@ -2,7 +2,6 @@ import unittest from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.bpmn.specs.events.event_definitions import MessageEventDefinition from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase __author__ = 'matth' @@ -86,8 +85,7 @@ class ApprovalsTest(BpmnWorkflowTestCase): self.save_restore() self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval') self.do_next_exclusive_step('Parallel_Approvals_SP.Step1') - self.do_next_exclusive_step( - 'Parallel_Approvals_SP.Supervisor_Approval') + self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval') self.do_next_exclusive_step('Approvals.Parallel_SP_Done') def testSaveRestoreWaiting(self): @@ -108,93 +106,10 @@ class ApprovalsTest(BpmnWorkflowTestCase): self.save_restore() self.do_next_exclusive_step('Parallel_Approvals_SP.Step1') self.save_restore() - self.do_next_exclusive_step( - 'Parallel_Approvals_SP.Supervisor_Approval') + self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval') self.save_restore() self.do_next_exclusive_step('Approvals.Parallel_SP_Done') - def testReadonlyWaiting(self): - - self.do_next_named_step('First_Approval_Wins.Manager_Approval') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Approvals.First_Approval_Wins_Done', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises(AssertionError, readonly.do_engine_steps) - self.assertRaises(AssertionError, readonly.refresh_waiting_tasks) - self.assertRaises(AssertionError, readonly.catch, MessageEventDefinition('Cheese')) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - - self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done') - - readonly = self.get_read_only_workflow() - self.assertEqual(2, len(readonly.get_ready_user_tasks())) - self.assertEqual( - ['Approvals.Manager_Approval__P_', - 'Approvals.Supervisor_Approval__P_'], - sorted(t.task_spec.name for t in readonly.get_ready_user_tasks())) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - - self.do_next_named_step('Approvals.Supervisor_Approval__P_') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Approvals.Manager_Approval__P_', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_named_step('Approvals.Manager_Approval__P_') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Approvals.Parallel_Approvals_Done', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_exclusive_step('Approvals.Parallel_Approvals_Done') - - readonly = self.get_read_only_workflow() - self.assertEqual(2, len(readonly.get_ready_user_tasks())) - self.assertEqual( - ['Parallel_Approvals_SP.Manager_Approval', - 'Parallel_Approvals_SP.Step1'], - sorted(t.task_spec.name for t in readonly.get_ready_user_tasks())) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Parallel_Approvals_SP.Step1', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_exclusive_step('Parallel_Approvals_SP.Step1') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Parallel_Approvals_SP.Supervisor_Approval', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_exclusive_step( - 'Parallel_Approvals_SP.Supervisor_Approval') - - readonly = self.get_read_only_workflow() - self.assertEqual(1, len(readonly.get_ready_user_tasks())) - self.assertEqual('Approvals.Parallel_SP_Done', - readonly.get_ready_user_tasks()[0].task_spec.name) - self.assertRaises( - AssertionError, readonly.get_ready_user_tasks()[0].complete) - self.do_next_exclusive_step('Approvals.Parallel_SP_Done') - - readonly = self.get_read_only_workflow() - self.assertEqual(0, len(readonly.get_ready_user_tasks())) - self.assertEqual(0, len(readonly.get_waiting_tasks())) - def suite(): return unittest.TestLoader().loadTestsFromTestCase(ApprovalsTest) diff --git a/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py b/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py deleted file mode 100644 index a8b6ebd53..000000000 --- a/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py +++ /dev/null @@ -1,118 +0,0 @@ -import os -import unittest - -from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine -from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from .BpmnLoaderForTests import TestBpmnParser - - -class BpmnSerializerTest(unittest.TestCase): - CORRELATE = BpmnSerializer - - def load_workflow_spec(self, filename, process_name): - f = os.path.join(os.path.dirname(__file__), 'data', filename) - parser = TestBpmnParser() - parser.add_bpmn_files_by_glob(f) - top_level_spec = parser.get_spec(process_name) - subprocesses = parser.get_subprocess_specs(process_name) - return top_level_spec, subprocesses - - def setUp(self): - super(BpmnSerializerTest, self).setUp() - self.serializer = BpmnSerializer() - self.spec, subprocesses = self.load_workflow_spec('random_fact.bpmn', 'random_fact') - self.workflow = BpmnWorkflow(self.spec, subprocesses) - - def testDeserializeWorkflowSpec(self): - self.assertIsNotNone(self.spec) - - def testSerializeWorkflowSpec(self): - spec_serialized = self.serializer.serialize_workflow_spec(self.spec) - result = self.serializer.deserialize_workflow_spec(spec_serialized) - spec_serialized2 = self.serializer.serialize_workflow_spec(result) - self.assertEqual(spec_serialized, spec_serialized2) - - def testSerializeWorkflow(self): - json = self.serializer.serialize_workflow(self.workflow) - print(json) - - def testDeserializeWorkflow(self): - self._compare_with_deserialized_copy(self.workflow) - - def testDeserializeCallActivityChildren(self): - """Tested as a part of deserialize workflow.""" - pass - - def testSerializeTask(self): - json = self.serializer.serialize_workflow(self.workflow) - print(json) - - def testDeserializeTask(self): - self._compare_with_deserialized_copy(self.workflow) - - def testDeserializeActiveWorkflow(self): - self.workflow.do_engine_steps() - self._compare_with_deserialized_copy(self.workflow) - - def testDeserializeWithData(self): - self.workflow.data["test"] = "my_test" - json = self.serializer.serialize_workflow(self.workflow) - wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec) - self.assertEqual('my_test', wf2.get_data("test")) - - def testDeserializeWithDefaultScriptEngineClass(self): - json = self.serializer.serialize_workflow(self.workflow) - wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec) - self.assertIsNotNone(self.workflow.script_engine) - self.assertIsNotNone(wf2.script_engine) - self.assertEqual(self.workflow.script_engine.__class__, - wf2.script_engine.__class__) - - @unittest.skip("Deserialize does not persist the script engine, Fix me.") - def testDeserializeWithCustomScriptEngine(self): - class CustomScriptEngine(PythonScriptEngine): - pass - - self.workflow.script_engine = CustomScriptEngine() - json = self.serializer.serialize_workflow(self.workflow) - wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec) - self.assertEqual(self.workflow.script_engine.__class__, - wf2.script_engine.__class__) - - def testDeserializeWithDataOnTask(self): - self.workflow.do_engine_steps() - user_task = self.workflow.get_ready_user_tasks()[0] - user_task.data = {"test":"my_test"} - self._compare_with_deserialized_copy(self.workflow) - - def testLastTaskIsSetAndWorksThroughRestore(self): - self.workflow.do_engine_steps() - json = self.serializer.serialize_workflow(self.workflow) - wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec) - self.assertIsNotNone(self.workflow.last_task) - self.assertIsNotNone(wf2.last_task) - self._compare_workflows(self.workflow, wf2) - - def _compare_with_deserialized_copy(self, wf): - json = self.serializer.serialize_workflow(wf) - wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec) - self._compare_workflows(wf, wf2) - - def _compare_workflows(self, w1, w2): - self.assertIsInstance(w1, BpmnWorkflow) - self.assertIsInstance(w2, BpmnWorkflow) - self.assertEqual(w1.data, w2.data) - self.assertEqual(w1.name, w2.name) - for task in w1.get_ready_user_tasks(): - w2_task = w2.get_task(task.id) - self.assertIsNotNone(w2_task) - self.assertEqual(task.data, w2_task.data) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(BpmnSerializerTest) - - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py index ac2ae463c..e5b771564 100644 --- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py +++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py @@ -1,13 +1,11 @@ import os import unittest import json -from uuid import uuid4 from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer -from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from tests.SpiffWorkflow.bpmn.BpmnLoaderForTests import TestUserTaskConverter @@ -48,13 +46,6 @@ class BpmnWorkflowSerializerTest(unittest.TestCase): version = self.serializer.get_version(spec_serialized) self.assertEqual(version, self.SERIALIZER_VERSION) - def testSerializeToOldSerializerThenNewSerializer(self): - old_serializer = BpmnSerializer() - old_json = old_serializer.serialize_workflow(self.workflow) - new_workflow = old_serializer.deserialize_workflow(old_json) - new_json = self.serializer.serialize_json(new_workflow) - new_workflow_2 = self.serializer.deserialize_json(new_json) - def testSerializeWorkflow(self): serialized = self.serializer.serialize_json(self.workflow) json.loads(serialized) diff --git a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py index 9b7865bd6..8f2f0af53 100644 --- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py +++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py @@ -122,7 +122,7 @@ class BpmnWorkflowTestCase(unittest.TestCase): before_dump = self.workflow.get_dump() # Check that we can actully convert this to JSON json_str = json.dumps(before_state) - after = self.serializer.workflow_from_dict(json.loads(json_str), read_only=False) + after = self.serializer.workflow_from_dict(json.loads(json_str)) # Check that serializing and deserializing results in the same workflow after_state = self.serializer.workflow_to_dict(after) after_dump = after.get_dump() @@ -132,11 +132,7 @@ class BpmnWorkflowTestCase(unittest.TestCase): self.workflow = after def restore(self, state): - self.workflow = self.serializer.workflow_from_dict(state, read_only=False) - - def get_read_only_workflow(self): - state = self._get_workflow_state() - return self.serializer.workflow_from_dict(state, read_only=True) + self.workflow = self.serializer.workflow_from_dict(state) def _get_workflow_state(self, do_steps=True): if do_steps: diff --git a/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py b/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py index f3d1522da..1e3d158e7 100644 --- a/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py +++ b/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py @@ -3,9 +3,9 @@ import unittest from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.exceptions import WorkflowTaskException from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase __author__ = 'kellym' @@ -60,7 +60,7 @@ class CallActivityTest(BpmnWorkflowTestCase): def test_call_acitivity_errors_include_task_trace(self): error_spec = self.subprocesses.get('ErroringBPMN') error_spec, subprocesses = self.load_workflow_spec('call_activity_*.bpmn', 'ErroringBPMN') - with self.assertRaises(WorkflowTaskExecException) as context: + with self.assertRaises(WorkflowTaskException) as context: self.workflow = BpmnWorkflow(error_spec, subprocesses) self.workflow.do_engine_steps() self.assertEquals(2, len(context.exception.task_trace)) diff --git a/tests/SpiffWorkflow/bpmn/CustomScriptTest.py b/tests/SpiffWorkflow/bpmn/CustomScriptTest.py index 12f69a2aa..8cbca47f5 100644 --- a/tests/SpiffWorkflow/bpmn/CustomScriptTest.py +++ b/tests/SpiffWorkflow/bpmn/CustomScriptTest.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- import unittest +from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase __author__ = 'McDonald, danfunk' @@ -46,7 +46,7 @@ class CustomInlineScriptTest(BpmnWorkflowTestCase): def test_overwrite_function_with_local_variable(self): ready_task = self.workflow.get_tasks(TaskState.READY)[0] ready_task.data = {'custom_function': "bill"} - with self.assertRaises(WorkflowTaskExecException) as e: + with self.assertRaises(WorkflowTaskException) as e: self.workflow.do_engine_steps() self.assertTrue('' in str(e.exception)) self.assertTrue('custom_function' in str(e.exception)) diff --git a/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py b/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py index ffb8f0242..9987567a5 100644 --- a/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py +++ b/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py @@ -31,18 +31,11 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase): except ValidationException as ex: self.assertTrue('No start event found' in ('%r' % ex), '\'No start event found\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('No-Start-Event.bpmn20.xml' in ('%r' % ex), + self.assertTrue('No-Start-Event.bpmn20.xml' in ex.file_name, '\'No-Start-Event.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('process' in ('%r' % ex), - '\'process\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue( - 'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983' in ('%r' % ex), - '\'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('No Start Event' in ('%r' % ex), - '\'No Start Event\' should be a substring of error message: \'%r\'' % ex) def testSubprocessNotFound(self): - + with self.assertRaises(ValidationException) as exc: self.load_workflow_spec('Invalid-Workflows/Subprocess-Not-Found.bpmn20.xml', 'Subprocess Not Found') self.assertIn("The process 'Missing subprocess' was not found.", str(exc)) @@ -60,15 +53,12 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase): 'There is no support implemented for this task type' in ( '%r' % ex), '\'There is no support implemented for this task type\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('Unsupported-Task.bpmn20.xml' in ('%r' % ex), + self.assertTrue('Unsupported-Task.bpmn20.xml' in ex.file_name, '\'Unsupported-Task.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('businessRuleTask' in ('%r' % ex), - '\'businessRuleTask\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue( - 'sid-75EEAB28-3B69-4282-B91A-0F3C97931834' in ('%r' % ex), - '\'sid-75EEAB28-3B69-4282-B91A-0F3C97931834\' should be a substring of error message: \'%r\'' % ex) - self.assertTrue('Business Rule Task' in ('%r' % ex), - '\'Business Rule Task\' should be a substring of error message: \'%r\'' % ex) + self.assertTrue('businessRuleTask' in ex.tag, + '\'businessRuleTask\' should be a substring of the tag: \'%r\'' % ex) + self.assertTrue('Business Rule Task' in ex.name, + '\'Business Rule Task\' should be the name: \'%s\'' % ex.name) def suite(): diff --git a/tests/SpiffWorkflow/bpmn/ParserTest.py b/tests/SpiffWorkflow/bpmn/ParserTest.py index 5703273e8..59a327758 100644 --- a/tests/SpiffWorkflow/bpmn/ParserTest.py +++ b/tests/SpiffWorkflow/bpmn/ParserTest.py @@ -1,7 +1,8 @@ import unittest import os -from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser +from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser, BpmnValidator +from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException class ParserTest(unittest.TestCase): @@ -27,3 +28,17 @@ class ParserTest(unittest.TestCase): self.assertEqual(generate.data_output_associations[0].name, 'obj_1') self.assertEqual(len(read.data_input_associations), 1) self.assertEqual(read.data_input_associations[0].name, 'obj_1') + + def testValidatorError(self): + parser = BpmnParser(validator=BpmnValidator()) + bpmn_file = os.path.join(os.path.dirname(__file__), 'data', + 'data_object_invalid.bpmn') + errored = False + try: + parser.add_bpmn_file(bpmn_file) + except ValidationException as ex: + errored = True + self.assertEqual(ex.file_name, bpmn_file) + self.assertEqual(14, ex.line_number) + self.assertIn('DataObjectReference_0cm8dnh', str(ex)) + assert(errored, "This should have errored out with a validation exception.") diff --git a/tests/SpiffWorkflow/bpmn/ScriptTest.py b/tests/SpiffWorkflow/bpmn/ScriptTest.py index efe9f1c85..da0a4a29f 100644 --- a/tests/SpiffWorkflow/bpmn/ScriptTest.py +++ b/tests/SpiffWorkflow/bpmn/ScriptTest.py @@ -2,7 +2,7 @@ import unittest -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException +from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase @@ -39,7 +39,7 @@ class InlineScriptTest(BpmnWorkflowTestCase): # StartTask doesn't know about testvar, it happened earlier. # calling an exec that references testvar, in the context of the # start task should fail. - with self.assertRaises(WorkflowTaskExecException): + with self.assertRaises(WorkflowTaskException): result = self.workflow.script_engine.evaluate(startTask, 'testvar == True') diff --git a/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py b/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py index 290607081..a0112efea 100644 --- a/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py +++ b/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py @@ -8,16 +8,15 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..')) from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase class ServiceTaskTest(BpmnWorkflowTestCase): def setUp(self): - spec, subprocesses = self.load_workflow_spec('service_task.bpmn', + spec, subprocesses = self.load_workflow_spec('service_task.bpmn', 'service_task_example1') - self.workflow = BpmnWorkflow(spec, subprocesses) + self.workflow = BpmnWorkflow(spec, subprocesses) def testRunThroughHappy(self): self.workflow.do_engine_steps() diff --git a/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn b/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn new file mode 100644 index 000000000..1d2d2ed87 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn @@ -0,0 +1,152 @@ + + + + + + Flow_18858hr + + + + + + + + + + Flow_19pyf8s + + + + Flow_1r7v9yo + Flow_1tnu3ej + + + DataObjectReference_0pztwm3 + Property_1uusomz + + + + Flow_18858hr + Flow_0gbxq9s + + DataObjectReference_17fhr1j + + + + Flow_0gbxq9s + Flow_1r7v9yo + + + Flow_1tnu3ej + Flow_19pyf8s + + + DataObjectReference_0cm8dnh + Property_1q5wp77 + + + Flow_0yx8lkz + + + Flow_0yx8lkz + Flow_0rk4i35 + + + + Flow_0rk4i35 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/serializer/dictTest.py b/tests/SpiffWorkflow/bpmn/serializer/dictTest.py deleted file mode 100644 index 3556bee19..000000000 --- a/tests/SpiffWorkflow/bpmn/serializer/dictTest.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- - -from builtins import str -import sys -import unittest -import os -dirname = os.path.dirname(__file__) -sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..')) - -import uuid -from SpiffWorkflow.bpmn.serializer.dict import BPMNDictionarySerializer -from tests.SpiffWorkflow.serializer.baseTest import SerializerTest -from SpiffWorkflow.workflow import Workflow - - -class BPMNDictionarySerializerTest(SerializerTest): - - def setUp(self): - super(BPMNDictionarySerializerTest, self).setUp() - self.serializer = BPMNDictionarySerializer() - self.return_type = dict - - def _compare_results(self, item1, item2, - exclude_dynamic=False, - exclude_items=None): - exclude_items = exclude_items if exclude_items is not None else [] - if exclude_dynamic: - if 'last_state_change' not in exclude_items: - exclude_items.append('last_state_change') - if 'last_task' not in exclude_items: - exclude_items.append('last_task') - if uuid.UUID not in exclude_items: - exclude_items.append(uuid.UUID) - if type(item1) in exclude_items: - return - - if isinstance(item1, dict): - self.assertIsInstance(item2, dict) - for key, value in list(item1.items()): - self.assertIn(key, item2) - if key in exclude_items: - continue - self._compare_results(value, item2[key], - exclude_dynamic=exclude_dynamic, - exclude_items=exclude_items) - for key in item2: - self.assertIn(key, item1) - - elif isinstance(item1, list): - msg = "item is not a list (is a " + str(type(item2)) + ")" - self.assertIsInstance(item2, list, msg) - msg = "list lengths differ: {} vs {}".format( - len(item1), len(item2)) - self.assertEqual(len(item1), len(item2), msg) - for i, listitem in enumerate(item1): - self._compare_results(listitem, item2[i], - exclude_dynamic=exclude_dynamic, - exclude_items=exclude_items) - - elif isinstance(item1, Workflow): - raise Exception("Item is a Workflow") - - else: - msg = "{}: types differ: {} vs {}".format( - str(item2), type(item1), type(item2)) - self.assertEqual(type(item1), type(item2), msg) - self.assertEqual(item1, item2) - - -def suite(): - return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNDictionarySerializerTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py b/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py deleted file mode 100644 index 89ee05428..000000000 --- a/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import unittest -import os -dirname = os.path.dirname(__file__) -sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..')) - -import json -from SpiffWorkflow.bpmn.serializer.json import BPMNJSONSerializer -from tests.SpiffWorkflow.serializer.dictTest import DictionarySerializerTest - - -class BPMNJSONSerializerTest(DictionarySerializerTest): - - def setUp(self): - super(BPMNJSONSerializerTest, self).setUp() - self.serializer = BPMNJSONSerializer() - self.return_type = str - - def _prepare_result(self, item): - return json.loads(item) - - def _compare_results(self, item1, item2, exclude_dynamic=False, - exclude_items=None): - if exclude_dynamic: - exclude_items = ['__uuid__'] - else: - exclude_items = [] - super(BPMNJSONSerializerTest, self)._compare_results(item1, item2, - exclude_dynamic=exclude_dynamic, - exclude_items=exclude_items) - - -def suite(): - return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNJSONSerializerTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py b/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py index 3ca9f3d05..757767d68 100644 --- a/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py +++ b/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py @@ -1,7 +1,7 @@ import os import unittest -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException +from SpiffWorkflow.exceptions import SpiffWorkflowException, WorkflowException from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.workflow import BpmnWorkflow @@ -15,17 +15,23 @@ class BusinessRuleTaskParserTest(BaseTestCase): 'invalid/InvalidDecision.bpmn', 'Process_1', 'invalid_decision.dmn') self.workflow = BpmnWorkflow(self.spec) + def testExceptionPrint(self): + e1 = Exception("test 1") + print (e1) + e = SpiffWorkflowException("test") + print (e) + def testDmnRaisesTaskErrors(self): self.workflow = BpmnWorkflow(self.spec) self.workflow.get_tasks(TaskState.READY)[0].set_data(x=3) try: self.workflow.do_engine_steps() self.assertTrue(False, "An error should have been raised.") - except WorkflowTaskExecException as we: + except WorkflowException as we: self.assertTrue(True, "An error was raised..") - self.assertEquals("InvalidDecisionTaskId", we.sender.name) - self.maxDiff = 1000 - self.assertEquals("Error evaluating expression spam= 1", str(we)) + self.assertEqual("InvalidDecisionTaskId", we.task_spec.name) + self.maxDiff = 1000 + self.assertEquals("Error evaluating expression 'spam= 1'. Rule failed on row 1. Business Rule Task 'Invalid Decision'.", str(we)) def suite(): return unittest.TestLoader().loadTestsFromTestCase(BusinessRuleTaskParserTest) diff --git a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn index ddf2c44e5..d00fd87d2 100644 --- a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn +++ b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn @@ -1,5 +1,5 @@ - + Flow_1b29lxw @@ -46,59 +46,59 @@ of documentation - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - + - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn b/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn index 7565b4c0e..a24c84000 100644 --- a/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn +++ b/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn @@ -1,8 +1,8 @@ - + - + item.x diff --git a/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py b/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py index 33f621912..3de8fa2a6 100644 --- a/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py +++ b/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py @@ -1,9 +1,7 @@ -import json import unittest -from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, \ - EnumFormField -from SpiffWorkflow.specs.base import TaskSpec +from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, EnumFormField +from SpiffWorkflow.camunda.serializer.task_spec_converters import UserTaskConverter from SpiffWorkflow.specs.WorkflowSpec import WorkflowSpec @@ -13,7 +11,6 @@ class UserTaskSpecTest(unittest.TestCase): def create_instance(self): if 'testtask' in self.wf_spec.task_specs: del self.wf_spec.task_specs['testtask'] - task_spec = TaskSpec(self.wf_spec, 'testtask', description='foo') self.form = Form() return UserTask(self.wf_spec, 'userTask', self.form) @@ -33,43 +30,6 @@ class UserTaskSpecTest(unittest.TestCase): self.assertEqual(self.form, self.user_spec.form) def testSerialize(self): - pass - - def test_text_field(self): - form_field = FormField(form_type="text") - form_field.id = "1234" - self.form.add_field(form_field) - self.assertEqual(form_field, self.user_spec.form.fields[0]) - - def test_enum_field(self): - enum_field = EnumFormField() - enum_field.label = "Which kind of fool are you" - enum_field.add_option('old fool', 'This is old, therefor it is good.') - enum_field.add_option('new fool', - 'This is new, therefor it is better.') - self.form.add_field(enum_field) - self.assertEqual(enum_field, self.user_spec.form.fields[-1]) - - def test_properties(self): - form_field = FormField(form_type="text") - self.assertFalse(form_field.has_property("wilma")) - form_field.add_property("wilma", "flintstone") - self.assertTrue(form_field.has_property("wilma")) - self.assertEquals("flintstone", form_field.get_property("wilma")) - - def test_validations(self): - form_field = FormField(form_type="text") - self.assertFalse(form_field.has_validation("barney")) - form_field.add_validation("barney", "rubble") - self.assertTrue(form_field.has_validation("barney")) - self.assertEquals("rubble", form_field.get_validation("barney")) - - def testIsEngineTask(self): - self.assertFalse(self.user_spec.is_engine_task()) - - def test_convert_to_dict(self): - form = Form() - field1 = FormField(form_type="text") field1.id = "quest" field1.label = "What is your quest?" @@ -89,21 +49,14 @@ class UserTaskSpecTest(unittest.TestCase): field2.add_property("description", "You know what to do.") field2.add_validation("maxlength", "25") - form.key = "formKey" - form.add_field(field1) - form.add_field(field2) + self.form.key = "formKey" + self.form.add_field(field1) + self.form.add_field(field2) - def JsonableHandler(Obj): - if hasattr(Obj, 'jsonable'): - return Obj.jsonable() - else: - raise 'Object of type %s with value of %s is not JSON serializable' % ( - type(Obj), repr(Obj)) - - json_form = json.dumps(form, default=JsonableHandler) - actual = json.loads(json_form) - - expected = { + converter = UserTaskConverter() + dct = converter.to_dict(self.user_spec) + self.assertEqual(dct['name'], 'userTask') + self.assertEqual(dct['form'], { "fields": [ { "default_value": "I seek the grail!", @@ -137,12 +90,39 @@ class UserTaskSpecTest(unittest.TestCase): } ], "key": "formKey", - } + }) - expected_parsed = json.loads(json.dumps(expected)) + def test_text_field(self): + form_field = FormField(form_type="text") + form_field.id = "1234" + self.form.add_field(form_field) + self.assertEqual(form_field, self.user_spec.form.fields[0]) - self.maxDiff = None - self.assertDictEqual(actual, expected_parsed) + def test_enum_field(self): + enum_field = EnumFormField() + enum_field.label = "Which kind of fool are you" + enum_field.add_option('old fool', 'This is old, therefor it is good.') + enum_field.add_option('new fool', + 'This is new, therefor it is better.') + self.form.add_field(enum_field) + self.assertEqual(enum_field, self.user_spec.form.fields[-1]) + + def test_properties(self): + form_field = FormField(form_type="text") + self.assertFalse(form_field.has_property("wilma")) + form_field.add_property("wilma", "flintstone") + self.assertTrue(form_field.has_property("wilma")) + self.assertEquals("flintstone", form_field.get_property("wilma")) + + def test_validations(self): + form_field = FormField(form_type="text") + self.assertFalse(form_field.has_validation("barney")) + form_field.add_validation("barney", "rubble") + self.assertTrue(form_field.has_validation("barney")) + self.assertEquals("rubble", form_field.get_validation("barney")) + + def testIsEngineTask(self): + self.assertFalse(self.user_spec.is_engine_task()) def suite(): diff --git a/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py b/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py index 52077059a..320586a9b 100644 --- a/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py +++ b/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py @@ -1,3 +1,4 @@ +from SpiffWorkflow.exceptions import SpiffWorkflowException from SpiffWorkflow.task import TaskState from .BaseTestCase import BaseTestCase from SpiffWorkflow.bpmn.workflow import BpmnWorkflow @@ -18,7 +19,7 @@ class PrescriptPostsciptTest(BaseTestCase): self.call_activity_test(True) def testDataObject(self): - + spec, subprocesses = self.load_workflow_spec('prescript_postscript_data_object.bpmn', 'Process_1') self.workflow = BpmnWorkflow(spec, subprocesses) # Set a on the workflow and b in the first task. @@ -45,8 +46,21 @@ class PrescriptPostsciptTest(BaseTestCase): ready_tasks[0].complete() self.assertDictEqual({'a': 1, 'b': 2, 'c': 12, 'z': 6}, ready_tasks[0].data) + def test_for_error(self, save_restore=False): + + spec, subprocesses = self.load_workflow_spec('prescript_postscript.bpmn', 'Process_1') + self.workflow = BpmnWorkflow(spec, subprocesses) + if save_restore: + self.save_restore() + ready_tasks = self.workflow.get_tasks(TaskState.READY) + # Calling do-engine steps without setting variables will raise an exception. + with self.assertRaises(SpiffWorkflowException) as se: + self.workflow.do_engine_steps() + ex = se.exception + self.assertIn("Error occurred in the Pre-Script", str(ex)) + def call_activity_test(self, save_restore=False): - + spec, subprocesses = self.load_workflow_spec('prescript_postscript_*.bpmn', 'parent') self.workflow = BpmnWorkflow(spec, subprocesses) if save_restore: diff --git a/tests/SpiffWorkflow/spiff/ServiceTaskTest.py b/tests/SpiffWorkflow/spiff/ServiceTaskTest.py index 1d3035b3f..66b2d86a0 100644 --- a/tests/SpiffWorkflow/spiff/ServiceTaskTest.py +++ b/tests/SpiffWorkflow/spiff/ServiceTaskTest.py @@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..')) from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException from .BaseTestCase import BaseTestCase class ServiceTaskDelegate: diff --git a/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py b/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py index 12237ae6b..834f0c6f1 100644 --- a/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py +++ b/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py @@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..')) from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException from .BaseTestCase import BaseTestCase class ServiceTaskDelegate: From cf1fcf9966fb87a29b337dfd5cb33c5887ac0cd8 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 19 Jan 2023 13:55:35 -0500 Subject: [PATCH 5/8] updating spiffworkflow version, and fixing the run_pyl (by removing the corft I stuck in earlier) --- bin/run_pyl | 15 +++------------ spiffworkflow-backend/poetry.lock | 12 ++++++------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/bin/run_pyl b/bin/run_pyl index 974b80600..9e1ce7c9a 100755 --- a/bin/run_pyl +++ b/bin/run_pyl @@ -8,7 +8,6 @@ trap 'error_handler ${LINENO} $?' ERR set -o errtrace -o errexit -o nounset -o pipefail python_projects=( - flask-bpmn spiffworkflow-backend ) @@ -51,17 +50,9 @@ function run_autoflake() { python_dirs=$(get_python_dirs) python_files=$(find $python_dirs -type f -name "*.py" ! -name '.null-ls*' ! -name '_null-ls*') - echo Current dir: $(pwd) - echo dirs: $python_dirs - echo files: \"$python_files\" - if [ -z "$python_files" != ""] - then - autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files - autoflake --in-place --remove-all-unused-imports $python_files - autopep8 --in-place $python_files - else - echo "no files " - fi + autoflake8 --in-place --remove-unused-variables --remove-duplicate-keys --expand-star-imports --exit-zero-even-if-changed $python_files + autoflake --in-place --remove-all-unused-imports $python_files + autopep8 --in-place $python_files } function run_pre_commmit() { diff --git a/spiffworkflow-backend/poetry.lock b/spiffworkflow-backend/poetry.lock index b32b4247e..50504333d 100644 --- a/spiffworkflow-backend/poetry.lock +++ b/spiffworkflow-backend/poetry.lock @@ -1786,8 +1786,8 @@ lxml = "*" [package.source] type = "git" url = "https://github.com/sartography/SpiffWorkflow" -reference = "be26100bcbef8026e26312c665dae42faf476485" -resolved_reference = "be26100bcbef8026e26312c665dae42faf476485" +reference = "main" +resolved_reference = "450ef3bcd639b6bc1c115fbe35bf3f93946cb0c7" [[package]] name = "SQLAlchemy" @@ -2158,7 +2158,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = ">=3.9,<3.12" -content-hash = "d804b8cbb34882f92cf19e5e59231aa7eac84764298fe7eae72bd03112e09496" +content-hash = "8592e94ba80b7d0338a9c003ca4d0e189b5f470d97391438ddc1fc9050febedb" [metadata.files] alabaster = [ @@ -2499,6 +2499,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, + {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, @@ -2507,6 +2508,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, + {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, @@ -2515,6 +2517,7 @@ greenlet = [ {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, + {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, @@ -2812,10 +2815,7 @@ orjson = [ {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"}, {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"}, {file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"}, - {file = "orjson-3.8.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:200eae21c33f1f8b02a11f5d88d76950cd6fd986d88f1afe497a8ae2627c49aa"}, - {file = "orjson-3.8.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9529990f3eab54b976d327360aa1ff244a4b12cb5e4c5b3712fcdd96e8fe56d4"}, {file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"}, - {file = "orjson-3.8.0-cp311-none-win_amd64.whl", hash = "sha256:b21c7af0ff6228ca7105f54f0800636eb49201133e15ddb80ac20c1ce973ef07"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"}, {file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"}, From d44b7d5d3450f5a34c47857b98908cbb5af5d4ff Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 19 Jan 2023 14:00:36 -0500 Subject: [PATCH 6/8] pre-commit-in-ci --- .../realm_exports/spiffworkflow-realm.json | 2 +- .../keycloak/test_user_lists/status | 1 - .../services/process_instance_processor.py | 5 +++-- .../unit/test_process_instance_service.py | 18 ++++++++++++------ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/spiffworkflow-backend/keycloak/realm_exports/spiffworkflow-realm.json b/spiffworkflow-backend/keycloak/realm_exports/spiffworkflow-realm.json index 270e4876f..43139573b 100644 --- a/spiffworkflow-backend/keycloak/realm_exports/spiffworkflow-realm.json +++ b/spiffworkflow-backend/keycloak/realm_exports/spiffworkflow-realm.json @@ -3036,4 +3036,4 @@ "clientPolicies" : { "policies" : [ ] } -} \ No newline at end of file +} diff --git a/spiffworkflow-backend/keycloak/test_user_lists/status b/spiffworkflow-backend/keycloak/test_user_lists/status index e9c518374..b44d0664c 100644 --- a/spiffworkflow-backend/keycloak/test_user_lists/status +++ b/spiffworkflow-backend/keycloak/test_user_lists/status @@ -6,4 +6,3 @@ finance.sme@status.im infra.sme@status.im legal.sme@status.im security.sme@status.im - 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 b99d52de8..0af4d2bde 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -692,8 +692,9 @@ class ProcessInstanceProcessor: ): continue - subprocesses_by_child_task_ids[task_id] =\ - subprocesses_by_child_task_ids[subprocess_id] + subprocesses_by_child_task_ids[ + task_id + ] = subprocesses_by_child_task_ids[subprocess_id] self.get_highest_level_calling_subprocesses_by_child_task_ids( subprocesses_by_child_task_ids, task_typename_by_task_id ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_service.py index bacde125b..2e104e0b3 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_service.py @@ -1,10 +1,11 @@ """Test_process_instance_processor.""" import os + from flask.app import Flask -from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -20,8 +21,9 @@ class TestProcessInstanceService(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """Test_does_not_log_set_data_when_calling_engine_steps_on_waiting_call_activity.""" - tmp_file = '/tmp/testfile.txt' + """Test_does_not_log_set_data_when_calling_engine_steps_on_waiting_call_activity. + """ + tmp_file = "/tmp/testfile.txt" if os.path.isfile(tmp_file): os.remove(tmp_file) process_model = load_test_spec( @@ -34,13 +36,17 @@ class TestProcessInstanceService(BaseTest): processor = ProcessInstanceProcessor(process_instance) processor.do_engine_steps(save=True) - process_instance_logs = SpiffLoggingModel.query.filter_by(process_instance_id=process_instance.id).all() + process_instance_logs = SpiffLoggingModel.query.filter_by( + process_instance_id=process_instance.id + ).all() initial_length = len(process_instance_logs) # logs should NOT increase after running this a second time since it's just waiting on a human task print("HEY NOW") - with open(tmp_file, 'w') as f: + with open(tmp_file, "w") as f: f.write("HEY") processor.do_engine_steps(save=True) - process_instance_logs = SpiffLoggingModel.query.filter_by(process_instance_id=process_instance.id).all() + process_instance_logs = SpiffLoggingModel.query.filter_by( + process_instance_id=process_instance.id + ).all() assert len(process_instance_logs) == initial_length From c5aff424b6f84c6363120769378320cee2ea5fc7 Mon Sep 17 00:00:00 2001 From: jasquat Date: Thu, 19 Jan 2023 15:37:55 -0500 Subject: [PATCH 7/8] pyl w/ burnettk --- .../spiffworkflow_backend/config/__init__.py | 18 +++--- .../exceptions/api_error.py | 8 +-- .../src/spiffworkflow_backend/models/db.py | 18 +++--- .../models/spec_reference.py | 3 +- .../spiffworkflow_backend/scripts/script.py | 3 +- .../services/authentication_service.py | 6 +- .../services/authorization_service.py | 29 +++++----- .../services/background_processing_service.py | 6 +- .../services/error_handling_service.py | 3 +- .../services/file_system_service.py | 3 +- .../services/logging_service.py | 3 +- .../services/process_instance_processor.py | 58 ++++++++++--------- .../process_instance_report_service.py | 6 +- .../services/process_instance_service.py | 3 +- .../services/spec_file_service.py | 4 +- .../helpers/test_data.py | 3 +- .../integration/test_process_api.py | 3 +- .../unit/test_spec_file_service.py | 4 +- 18 files changed, 85 insertions(+), 96 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py index cbaf751b0..759ac3395 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py @@ -17,21 +17,21 @@ def setup_database_uri(app: Flask) -> None: if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None: database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}" if app.config.get("SPIFF_DATABASE_TYPE") == "sqlite": - app.config[ - "SQLALCHEMY_DATABASE_URI" - ] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" + app.config["SQLALCHEMY_DATABASE_URI"] = ( + f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" + ) elif app.config.get("SPIFF_DATABASE_TYPE") == "postgres": - app.config[ - "SQLALCHEMY_DATABASE_URI" - ] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" + app.config["SQLALCHEMY_DATABASE_URI"] = ( + f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" + ) else: # use pswd to trick flake8 with hardcoded passwords db_pswd = os.environ.get("DB_PASSWORD") if db_pswd is None: db_pswd = "" - app.config[ - "SQLALCHEMY_DATABASE_URI" - ] = f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" + app.config["SQLALCHEMY_DATABASE_URI"] = ( + f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" + ) else: app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get( "SPIFFWORKFLOW_BACKEND_DATABASE_URI" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py index cc508e6c2..02a66a207 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/exceptions/api_error.py @@ -15,7 +15,7 @@ from flask import jsonify from flask import make_response from sentry_sdk import capture_exception from sentry_sdk import set_tag -from SpiffWorkflow.exceptions import WorkflowException +from SpiffWorkflow.exceptions import WorkflowException # type: ignore from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.specs.base import TaskSpec # type: ignore from SpiffWorkflow.task import Task # type: ignore @@ -41,7 +41,7 @@ class ApiError(Exception): task_data: dict | str | None = field(default_factory=dict) task_id: str = "" task_name: str = "" - task_trace: list | None = field(default_factory=dict) + task_trace: list | None = field(default_factory=list) def __str__(self) -> str: """Instructions to print instance as a string.""" @@ -65,7 +65,7 @@ class ApiError(Exception): offset: int = 0, error_type: str = "", error_line: str = "", - task_trace: dict | None = None, + task_trace: list | None = None, ) -> ApiError: """Constructs an API Error with details pulled from the current task.""" instance = cls(error_code, message, status_code=status_code) @@ -166,7 +166,7 @@ def set_user_sentry_context() -> None: set_tag("username", username) -@api_error_blueprint.app_errorhandler(Exception) +@api_error_blueprint.app_errorhandler(Exception) # type: ignore def handle_exception(exception: Exception) -> flask.wrappers.Response: """Handles unexpected exceptions.""" set_user_sentry_context() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py index 762b47197..5028ad1d5 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/db.py @@ -6,10 +6,10 @@ import time from typing import Any from flask_migrate import Migrate # type: ignore -from flask_sqlalchemy import SQLAlchemy # type: ignore -from sqlalchemy import event # type: ignore -from sqlalchemy.engine.base import Connection # type: ignore -from sqlalchemy.orm.mapper import Mapper # type: ignore +from flask_sqlalchemy import SQLAlchemy +from sqlalchemy import event +from sqlalchemy.engine.base import Connection +from sqlalchemy.orm.mapper import Mapper db = SQLAlchemy() migrate = Migrate() @@ -59,8 +59,7 @@ class SpiffworkflowBaseDBModel(db.Model): # type: ignore def update_created_modified_on_create_listener( mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel ) -> None: - """Event listener that runs before a record is updated, and sets the create/modified field accordingly. - """ + """Event listener that runs before a record is updated, and sets the create/modified field accordingly.""" if "created_at_in_seconds" in mapper.columns.keys(): target.created_at_in_seconds = round(time.time()) if "updated_at_in_seconds" in mapper.columns.keys(): @@ -70,8 +69,7 @@ def update_created_modified_on_create_listener( def update_modified_on_update_listener( mapper: Mapper, _connection: Connection, target: SpiffworkflowBaseDBModel ) -> None: - """Event listener that runs before a record is updated, and sets the modified field accordingly. - """ + """Event listener that runs before a record is updated, and sets the modified field accordingly.""" if "updated_at_in_seconds" in mapper.columns.keys(): if db.session.is_modified(target, include_collections=False): target.updated_at_in_seconds = round(time.time()) @@ -83,5 +81,5 @@ def add_listeners() -> None: This should be called after importing all subclasses """ for cls in SpiffworkflowBaseDBModel._all_subclasses(): - event.listen(cls, "before_insert", update_created_modified_on_create_listener) - event.listen(cls, "before_update", update_modified_on_update_listener) + event.listen(cls, "before_insert", update_created_modified_on_create_listener) # type: ignore + event.listen(cls, "before_update", update_modified_on_update_listener) # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py index 01ae8f0d9..090cf70a4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spec_reference.py @@ -38,8 +38,7 @@ class SpecReference: 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" __table_args__ = ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py index 2d75961b7..897bc1bee 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py @@ -27,8 +27,7 @@ class ScriptUnauthorizedForUserError(Exception): class Script: - """Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks. - """ + """Provides an abstract class that defines how scripts should work, this must be extended in all Script Tasks.""" @abstractmethod def get_description(self) -> str: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py index 925f4ed91..1793aab64 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py @@ -60,8 +60,7 @@ class AuthenticationService: @classmethod def open_id_endpoint_for_name(cls, name: str) -> str: - """All openid systems provide a mapping of static names to the full path of that endpoint. - """ + """All openid systems provide a mapping of static names to the full path of that endpoint.""" openid_config_url = f"{cls.server_url()}/.well-known/openid-configuration" if name not in AuthenticationService.ENDPOINT_CACHE: response = requests.get(openid_config_url) @@ -201,8 +200,7 @@ class AuthenticationService: @classmethod def get_auth_token_from_refresh_token(cls, refresh_token: str) -> dict: - """Converts a refresh token to an Auth Token by calling the openid's auth endpoint. - """ + """Converts a refresh token to an Auth Token by calling the openid's auth endpoint.""" backend_basic_auth_string = f"{cls.client_id()}:{cls.secret_key()}" backend_basic_auth_bytes = bytes(backend_basic_auth_string, encoding="ascii") backend_basic_auth = base64.b64encode(backend_basic_auth_bytes) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py index 234f0e04e..4b17f5ade 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py @@ -171,8 +171,7 @@ class AuthorizationService: @classmethod def delete_all_permissions(cls) -> None: - """Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user? - """ + """Delete_all_permissions_and_recreate. EXCEPT For permissions for the current user?""" for model in [PermissionAssignmentModel, PermissionTargetModel]: db.session.query(model).delete() @@ -283,9 +282,9 @@ class AuthorizationService: """Find_or_create_permission_target.""" uri_with_percent = re.sub(r"\*", "%", uri) target_uri_normalized = uri_with_percent.removeprefix(V1_API_PATH_PREFIX) - permission_target: Optional[ - PermissionTargetModel - ] = PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first() + permission_target: Optional[PermissionTargetModel] = ( + PermissionTargetModel.query.filter_by(uri=target_uri_normalized).first() + ) if permission_target is None: permission_target = PermissionTargetModel(uri=target_uri_normalized) db.session.add(permission_target) @@ -300,13 +299,13 @@ class AuthorizationService: permission: str, ) -> PermissionAssignmentModel: """Create_permission_for_principal.""" - permission_assignment: Optional[ - PermissionAssignmentModel - ] = PermissionAssignmentModel.query.filter_by( - principal_id=principal.id, - permission_target_id=permission_target.id, - permission=permission, - ).first() + permission_assignment: Optional[PermissionAssignmentModel] = ( + PermissionAssignmentModel.query.filter_by( + principal_id=principal.id, + permission_target_id=permission_target.id, + permission=permission, + ).first() + ) if permission_assignment is None: permission_assignment = PermissionAssignmentModel( principal_id=principal.id, @@ -435,8 +434,10 @@ class AuthorizationService: except jwt.InvalidTokenError as exception: raise ApiError( "token_invalid", - "The Authentication token you provided is invalid. You need a new" - " token. ", + ( + "The Authentication token you provided is invalid. You need a new" + " token. " + ), ) from exception @staticmethod diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py index bc0b283ba..1771c2c8b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py @@ -15,13 +15,11 @@ class BackgroundProcessingService: self.app = app def process_waiting_process_instances(self) -> None: - """Since this runs in a scheduler, we need to specify the app context as well. - """ + """Since this runs in a scheduler, we need to specify the app context as well.""" with self.app.app_context(): ProcessInstanceService.do_waiting() def process_message_instances_with_app_context(self) -> None: - """Since this runs in a scheduler, we need to specify the app context as well. - """ + """Since this runs in a scheduler, we need to specify the app context as well.""" with self.app.app_context(): MessageService.process_message_instances() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index 1db619f08..ec1f5d36a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -41,8 +41,7 @@ class ErrorHandlingService: def handle_error( self, _processor: ProcessInstanceProcessor, _error: Union[ApiError, Exception] ) -> None: - """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception. - """ + """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.""" process_model = ProcessModelService.get_process_model( _processor.process_model_identifier ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py index 3201199ef..ffca4f2c2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py @@ -151,8 +151,7 @@ class FileSystemService: @staticmethod def _get_files(file_path: str, file_name: Optional[str] = None) -> List[File]: - """Returns an array of File objects at the given path, can be restricted to just one file. - """ + """Returns an array of File objects at the given path, can be restricted to just one file.""" files = [] items = os.scandir(file_path) for item in items: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py index 85c788dd8..6a60944e6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py @@ -52,8 +52,7 @@ class JsonFormatter(logging.Formatter): self.datefmt = None def usesTime(self) -> bool: - """Overwritten to look for the attribute in the format dict values instead of the fmt string. - """ + """Overwritten to look for the attribute in the format dict values instead of the fmt string.""" return "asctime" in self.fmt_dict.values() # we are overriding a method that returns a string and returning a dict, hence the Any 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 0af4d2bde..c42fa5f28 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -23,7 +23,7 @@ import dateparser import pytz from flask import current_app from lxml import etree # type: ignore -from lxml.etree import XMLSyntaxError +from lxml.etree import XMLSyntaxError # type: ignore from RestrictedPython import safe_globals # type: ignore from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore from SpiffWorkflow.bpmn.PythonScriptEngine import Box # type: ignore @@ -38,7 +38,7 @@ from SpiffWorkflow.bpmn.workflow import BpmnWorkflow # type: ignore from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore from SpiffWorkflow.dmn.serializer.task_spec_converters import BusinessRuleTaskConverter # type: ignore from SpiffWorkflow.exceptions import WorkflowException # type: ignore -from SpiffWorkflow.exceptions import WorkflowTaskException # type: ignore +from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore from SpiffWorkflow.spiff.serializer.task_spec_converters import BoundaryEventConverter # type: ignore from SpiffWorkflow.spiff.serializer.task_spec_converters import ( @@ -242,7 +242,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore except WorkflowException as e: raise e except Exception as e: - raise self.create_task_exec_exception(task, script, e) + raise self.create_task_exec_exception(task, script, e) from e def call_service( self, @@ -299,8 +299,7 @@ class ProcessInstanceProcessor: def __init__( self, process_instance_model: ProcessInstanceModel, validate_only: bool = False ) -> None: - """Create a Workflow Processor based on the serialized information available in the process_instance model. - """ + """Create a Workflow Processor based on the serialized information available in the process_instance model.""" tld = current_app.config["THREAD_LOCAL_DATA"] tld.process_instance_id = process_instance_model.id tld.spiff_step = process_instance_model.spiff_step @@ -406,8 +405,10 @@ class ProcessInstanceProcessor: raise ( ApiError( "process_model_not_found", - "The given process model was not found:" - f" {process_model_identifier}.", + ( + "The given process model was not found:" + f" {process_model_identifier}." + ), ) ) spec_files = SpecFileService.get_files(process_model_info) @@ -537,9 +538,11 @@ class ProcessInstanceProcessor: potential_owner_ids.append(lane_owner_user.id) self.raise_if_no_potential_owners( potential_owner_ids, - "No users found in task data lane owner list for lane:" - f" {task_lane}. The user list used:" - f" {task.data['lane_owners'][task_lane]}", + ( + "No users found in task data lane owner list for lane:" + f" {task_lane}. The user list used:" + f" {task.data['lane_owners'][task_lane]}" + ), ) else: group_model = GroupModel.query.filter_by(identifier=task_lane).first() @@ -692,9 +695,9 @@ class ProcessInstanceProcessor: ): continue - subprocesses_by_child_task_ids[ - task_id - ] = subprocesses_by_child_task_ids[subprocess_id] + subprocesses_by_child_task_ids[task_id] = ( + subprocesses_by_child_task_ids[subprocess_id] + ) self.get_highest_level_calling_subprocesses_by_child_task_ids( subprocesses_by_child_task_ids, task_typename_by_task_id ) @@ -1014,8 +1017,7 @@ class ProcessInstanceProcessor: def get_spec( files: List[File], process_model_info: ProcessModelInfo ) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]: - """Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided. - """ + """Returns a SpiffWorkflow specification for the given process_instance spec, using the files provided.""" parser = ProcessInstanceProcessor.get_parser() for file in files: @@ -1031,7 +1033,7 @@ class ProcessInstanceProcessor: raise ApiError( error_code="invalid_xml", message=f"'{file.name}' is not a valid xml file." + str(xse), - ) + ) from xse if ( process_model_info.primary_process_id is None or process_model_info.primary_process_id == "" @@ -1108,8 +1110,10 @@ class ProcessInstanceProcessor: if not bpmn_message.correlations: raise ApiError( "message_correlations_missing", - "Could not find any message correlations bpmn_message:" - f" {bpmn_message.name}", + ( + "Could not find any message correlations bpmn_message:" + f" {bpmn_message.name}" + ), ) message_correlations = [] @@ -1129,8 +1133,10 @@ class ProcessInstanceProcessor: if message_correlation_property is None: raise ApiError( "message_correlations_missing_from_process", - "Could not find a known message correlation with" - f" identifier:{message_correlation_property_identifier}", + ( + "Could not find a known message correlation with" + f" identifier:{message_correlation_property_identifier}" + ), ) message_correlations.append( { @@ -1193,8 +1199,10 @@ class ProcessInstanceProcessor: if message_model is None: raise ApiError( "invalid_message_name", - "Invalid message name:" - f" {waiting_task.task_spec.event_definition.name}.", + ( + "Invalid message name:" + f" {waiting_task.task_spec.event_definition.name}." + ), ) # Ensure we are only creating one message instance for each waiting message @@ -1479,8 +1487,7 @@ class ProcessInstanceProcessor: return self.bpmn_process_instance.get_ready_user_tasks() # type: ignore def get_current_user_tasks(self) -> list[SpiffTask]: - """Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task. - """ + """Return a list of all user tasks that are READY or COMPLETE and are parallel to the READY Task.""" ready_tasks = self.bpmn_process_instance.get_ready_user_tasks() additional_tasks = [] if len(ready_tasks) > 0: @@ -1537,8 +1544,7 @@ class ProcessInstanceProcessor: return None def find_spec_and_field(self, spec_name: str, field_id: Union[str, int]) -> Any: - """Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form. - """ + """Tracks down a form field by name in the process_instance spec(s), Returns a tuple of the task, and form.""" process_instances = [self.bpmn_process_instance] for task in self.bpmn_process_instance.get_ready_user_tasks(): if task.process_instance not in process_instances: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index ce4e0183b..809b6ae13 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -312,9 +312,9 @@ class ProcessInstanceReportService: process_instance_dict = process_instance["ProcessInstanceModel"].serialized for metadata_column in metadata_columns: if metadata_column["accessor"] not in process_instance_dict: - process_instance_dict[ - metadata_column["accessor"] - ] = process_instance[metadata_column["accessor"]] + process_instance_dict[metadata_column["accessor"]] = ( + process_instance[metadata_column["accessor"]] + ) results.append(process_instance_dict) return results diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index a9c2f4d01..cf86def97 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -224,8 +224,7 @@ class ProcessInstanceService: @staticmethod def extract_form_data(latest_data: dict, task: SpiffTask) -> dict: - """Extracts data from the latest_data that is directly related to the form that is being submitted. - """ + """Extracts data from the latest_data that is directly related to the form that is being submitted.""" data = {} if hasattr(task.task_spec, "form"): 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 1e8233ec2..13cc41243 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -5,7 +5,6 @@ from datetime import datetime from typing import List from typing import Optional -from flask_bpmn.models.db import db from lxml import etree # type: ignore from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator # type: ignore @@ -336,8 +335,7 @@ class SpecFileService(FileSystemService): @staticmethod def update_message_cache(ref: SpecReference) -> None: - """Assure we have a record in the database of all possible message ids and names. - """ + """Assure we have a record in the database of all possible message ids and names.""" for message_model_identifier in ref.messages.keys(): message_model = MessageModel.query.filter_by( identifier=message_model_identifier diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py index 40cb89b1e..d6b4f730c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py @@ -40,8 +40,7 @@ def load_test_spec( bpmn_file_name: Optional[str] = None, process_model_source_directory: Optional[str] = None, ) -> ProcessModelInfo: - """Loads a bpmn file into the process model dir based on a directory in tests/data. - """ + """Loads a bpmn file into the process model dir based on a directory in tests/data.""" if process_model_source_directory is None: raise Exception("You must inclode a `process_model_source_directory`.") 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 660bdca38..ebc26ac6d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -3103,8 +3103,7 @@ class TestProcessApi(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """Test_can_get_process_instance_list_with_report_metadata_and_process_initator. - """ + """Test_can_get_process_instance_list_with_report_metadata_and_process_initator.""" user_one = self.create_user_with_permission(username="user_one") process_model = load_test_spec( 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 eb7726c6e..6ae498607 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 @@ -5,7 +5,6 @@ import sys import pytest from flask import Flask from flask.testing import FlaskClient -from flask_bpmn.models.db import db from lxml import etree # type: ignore from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec @@ -139,8 +138,7 @@ class TestSpecFileService(BaseTest): with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel, ) -> None: - """When a BPMN processes identifier is changed in a file, the old id is removed from the cache. - """ + """When a BPMN processes identifier is changed in a file, the old id is removed from the cache.""" old_identifier = "ye_old_identifier" process_id_lookup = SpecReferenceCache( identifier=old_identifier, From 9e3c0823fd51dacbe3a9e04808e3031ff0b7375b Mon Sep 17 00:00:00 2001 From: jasquat Date: Thu, 19 Jan 2023 15:40:36 -0500 Subject: [PATCH 8/8] use the correct place for keycloak w/ burnettk --- .github/workflows/frontend_tests.yml | 2 +- spiffworkflow-frontend/.github/workflows/tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/frontend_tests.yml b/.github/workflows/frontend_tests.yml index 969a3ae89..e02b319dc 100644 --- a/.github/workflows/frontend_tests.yml +++ b/.github/workflows/frontend_tests.yml @@ -67,7 +67,7 @@ jobs: path: sample-process-models - name: start_keycloak working-directory: ./spiffworkflow-backend - run: ./bin/start_keycloak + run: ./keycloak/bin/start_keycloak 5 - name: start_backend working-directory: ./spiffworkflow-backend run: ./bin/build_and_run_with_docker_compose diff --git a/spiffworkflow-frontend/.github/workflows/tests.yml b/spiffworkflow-frontend/.github/workflows/tests.yml index 464ed5ebd..d1011ea06 100644 --- a/spiffworkflow-frontend/.github/workflows/tests.yml +++ b/spiffworkflow-frontend/.github/workflows/tests.yml @@ -68,7 +68,7 @@ jobs: path: sample-process-models - name: start_keycloak working-directory: ./spiffworkflow-backend - run: ./bin/start_keycloak + run: ./keycloak/bin/start_keycloak - name: start_backend working-directory: ./spiffworkflow-backend run: ./bin/build_and_run_with_docker_compose