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 cc94ba54..36b62796 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 6b12699b..1e9f6d19 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 b24a7ed1..8d119196 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 2e001a93..433abf20 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 83a43482..c72f9e79 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 f67dccc0..95e11570 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 248a400b..c80b1511 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 00000000..0dfce83a --- /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 45cd38f7..4a836b1e 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 bc79a8e3..2ebd1134 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 00000000..643e1a85 --- /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 980fc930..7038ad6f 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 f74da5cc..39805342 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 31823af8..1ac0824e 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 08bc1cb1..3e03f32e 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 320dfba3..7b1ddfbd 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 b84b7140..6b03c91a 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 b0cc2aa3..60c2fc92 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 601b6d40..7fe78f70 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 cc883465..acd44eac 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 04dfb5fa..2e09d888 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 53334baf..a9fe7111 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 ac8ee6a4..f3818e9d 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 42a90364..bb262b4c 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 f2e4c222..c4114dda 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 b1288b3f..19f98a06 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 2e96b7f0..5cf23609 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 91a4f23b..37f47b93 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 50b73fba..e7b2ab98 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 532a6c09..9fc82a01 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 11c3aead..8d807493 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 c4838aaf..f3838a06 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 9c1567fb..2c5638bb 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 ac2747c8..fe9c6b88 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 30456c93..35befc61 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 4a6cc1c4..55b0afca 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 2a516f9d..98da1901 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 0a218e0e..0a1eaa49 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 8a6e6306..cda5dd6f 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 e97b26ae..29d2461e 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 c4f55772..8f700a0f 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 5a3aa53d..f580651e 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 fd5c1ae9..807b08c1 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 5b422525..3345ef64 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 7c688e56..c5742f84 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 d9c1959a..38daf193 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 7ca79846..4f2300fe 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 6bbcad33..028f47a6 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 77082a92..c15f31d2 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 ba43439e..a1915a5d 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 1dd384ac..25aa143c 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 51f402fa..b5509eb7 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 cb8b44c6..96b8e6ba 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 911d41ac..c417d8eb 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 599d5228..d09d3c0d 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 b659b13e..3ac4b574 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 510c66fd..711ccc35 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 0b75ea61..134f0f7b 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 9812609f..abe8e694 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 893baaea..9b53a98e 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 ed331672..1fafb548 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 aa9e6d14..7c2d27fe 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 868d0fcd..69901674 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 20412e54..b460bad2 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 df62f5be..61bf5a40 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 d146d0b2..9e619944 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 c71f67f2..631df9b5 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 8a6046b5..00cc4e65 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 67cf55c8..e3d8563b 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 2c091eeb..f9f764cd 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 56768142..7ad9765b 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 a9698969..b3991eeb 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 b40412ff..46a67b2a 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 9eb6901b..86a6f648 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 d31ea424..e9e164b6 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 2ce011b2..82b96f12 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 d8680b71..3f4b117d 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 f09c5bfd..00000000 --- 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 72ccc6c5..00000000 --- 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 2a7ae776..00000000 --- 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 6313b56c..00000000 --- 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 a0a5c735..00000000 --- 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 f7f83aad..00000000 --- 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 7a04410f..00000000 --- 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 b5c60e1d..00000000 --- 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 f30a60fc..00000000 --- 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 f39cfa6c..00000000 --- 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 aad6cd84..00000000 --- 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 cc7a61e6..00000000 --- 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 f0546397..00000000 --- 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 66f2a214..00000000 --- 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 a7b6ef2e..00000000 --- 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 0af086d5..00000000 --- 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 e160841d..00000000 --- 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 d2217885..00000000 --- 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 219b9870..00000000 --- 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 9ac26504..00000000 --- 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 96e0ba2f..00000000 --- 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 5cba81cf..00000000 --- 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 c8670b6b..00000000 --- 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 fef4a7ec..00000000 --- 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 68c5792f..00000000 --- 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 78844bfe..00000000 --- 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 40b16b18..00000000 --- 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 e2917596..00000000 --- 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 046bc6f2..00000000 --- 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 e1ce1b3a..00000000 --- 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 105fa15d..00000000 --- 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 46c394f3..00000000 --- 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 a4504973..00000000 --- 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 4ba630e7..00000000 --- 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 ed792e7e..00000000 --- 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 f520b09d..00000000 --- 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 643e1a85..00000000 --- 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 3c496a49..00000000 --- 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 e69de29b..00000000 diff --git a/flask-bpmn/tests/__init__.py b/flask-bpmn/tests/__init__.py deleted file mode 100644 index ce3478a1..00000000 --- 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 24315e39..00000000 --- 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 ca336224..00000000 --- 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 c53c4101..00000000 --- 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 bceba187..d97f68d8 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 36b62796..c89cc2a7 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 8d119196..448d1856 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 95e11570..64649048 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 7d915946..29696fed 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 c80b1511..659e0135 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 0dfce83a..cc508e6c 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 4a836b1e..57108b6c 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 643e1a85..762b4719 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 7038ad6f..f1017df9 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 39805342..7e5117a0 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 1ac0824e..a0507f82 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 3e03f32e..e913938f 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 7b1ddfbd..58ded838 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 6b03c91a..1e09dc0c 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 60c2fc92..c9ea515e 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 7fe78f70..8ebd15c5 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 acd44eac..edf64821 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 2e09d888..a9db96cf 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 a9fe7111..773833a3 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 f3818e9d..6e46def5 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 bb262b4c..75a58004 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 c4114dda..920e13a2 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 19f98a06..a8787da6 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 5cf23609..d7bf0fe1 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 37f47b93..026831ed 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 e7b2ab98..01ae8f0d 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 9fc82a01..71e1bbfb 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 8d807493..50bf4520 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 f3838a06..7f8c88da 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 2c5638bb..acd6c30b 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 fe9c6b88..7db1676f 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 35befc61..0db93a4a 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 55b0afca..0e9bd581 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 98da1901..65dca25f 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 0a1eaa49..08e665ca 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 cda5dd6f..bad5af7b 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 29d2461e..3a6d1143 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 8f700a0f..86472f6a 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 f580651e..072acfaa 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 807b08c1..e8807c77 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 3345ef64..6d65ea75 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 c5742f84..e16ee23b 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 38daf193..3d2054df 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 4f2300fe..2d75961b 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 028f47a6..89fbc8a8 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 c15f31d2..925f4ed9 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 a1915a5d..234f0e04 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 1771c2c8..bc0b283b 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 25aa143c..39f14ca5 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 b5509eb7..1db619f0 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 96b8e6ba..3201199e 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 c417d8eb..abc11151 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 d09d3c0d..85c788dd 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 3ac4b574..0e4799ca 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 711ccc35..51b011cd 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 134f0f7b..ce4e0183 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 abe8e694..a9c2f4d0 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 9b53a98e..9ac17594 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 7c2d27fe..f34be93d 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 69901674..7273fd6c 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 b460bad2..d43fa201 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 61bf5a40..4d0d7c1a 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 d6b4f730..40cb89b1 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 9e619944..660bdca3 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 631df9b5..f7f5b562 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 00cc4e65..6e57b1bf 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 e3d8563b..20176dd8 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 f9f764cd..6c90eb25 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 7ad9765b..6ae126dd 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 b3991eeb..f45f4ef5 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 46a67b2a..a0e694dc 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 86a6f648..a5ac6c96 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 e9e164b6..0f5d4770 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 82b96f12..b3e19067 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 3f4b117d..a47983fe 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 cdbed75a..b6465485 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 614bbf73..5b79d9fa 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 00000000..31c606de --- /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 28e5d8ac..b51b8b52 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 7576a23f..857c81f0 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 a8b6ebd5..00000000 --- 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 ac2ae463..e5b77156 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 9b7865bd..8f2f0af5 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 f3d1522d..1e3d158e 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 12f69a2a..8cbca47f 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 ffb8f024..9987567a 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 5703273e..59a32775 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 efe9f1c8..da0a4a29 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 29060708..a0112efe 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 00000000..1d2d2ed8 --- /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 3556bee1..00000000 --- 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 89ee0542..00000000 --- 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 3ca9f3d0..757767d6 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 ddf2c44e..d00fd87d 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 7565b4c0..a24c8400 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 33f62191..3de8fa2a 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 52077059..320586a9 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 1d3035b3..66b2d86a 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 12237ae6..834f0c6f 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 974b8060..9e1ce7c9 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 b32b4247..50504333 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 270e4876..43139573 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 e9c51837..b44d0664 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 b99d52de..0af4d2bd 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 bacde125..2e104e0b 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 cbaf751b..759ac339 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 cc508e6c..02a66a20 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 762b4719..5028ad1d 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 01ae8f0d..090cf70a 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 2d75961b..897bc1be 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 925f4ed9..1793aab6 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 234f0e04..4b17f5ad 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 bc0b283b..1771c2c8 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 1db619f0..ec1f5d36 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 3201199e..ffca4f2c 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 85c788dd..6a60944e 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 0af4d2bd..c42fa5f2 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 ce4e0183..809b6ae1 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 a9c2f4d0..cf86def9 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 1e8233ec..13cc4124 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 40cb89b1..d6b4f730 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 660bdca3..ebc26ac6 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 eb7726c6..6ae49860 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 969a3ae8..e02b319d 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 464ed5eb..d1011ea0 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