Merge branch 'main' into feature/nested-groups

This commit is contained in:
mike cullerton 2022-11-01 16:49:55 -04:00
commit 89d73614af
59 changed files with 5196 additions and 520 deletions

2
.darglint Normal file
View File

@ -0,0 +1,2 @@
[darglint]
strictness = long

29
.flake8 Normal file
View File

@ -0,0 +1,29 @@
[flake8]
select = B,B9,C,D,DAR,E,F,N,RST,S,W
ignore = E203,E501,RST201,RST203,RST301,W503,S410,S320
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
spiffworkflow-backend/tests/*:S101,D103
spiffworkflow-backend/bin/keycloak_test_server.py:B950,D
spiffworkflow-backend/conftest.py:S105
spiffworkflow-backend/wsgi.py:S104
# allow writing to /tmp for throwaway script output
spiffworkflow-backend/bin/get_bpmn_json_for_process_instance:S108
# the exclude=./migrations option doesn't seem to work with pre-commit
# migrations are autogenerated from "flask db migration" so ignore them
spiffworkflow-backend/migrations/*:D
spiffworkflow-backend/src/spiffworkflow_backend/config/testing.py:S105
spiffworkflow-backend/src/spiffworkflow_backend/load_database_models.py:F401
# this file overwrites methods from the logging library so we can't change them
# and ignore long comment line
spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py:N802,B950

75
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,75 @@
repos:
- repo: local
hooks:
- id: black
name: black
# entry: bash -c 'cd spiffworkflow-backend && black'
entry: black
language: system
files: ^spiffworkflow-backend/
types: [python]
require_serial: true
# exclude: ^migrations/
exclude: "/migrations/"
- id: check-added-large-files
files: ^spiffworkflow-backend/
name: Check for added large files
entry: check-added-large-files
language: system
- id: check-toml
files: ^spiffworkflow-backend/
name: Check Toml
entry: check-toml
language: system
types: [toml]
- id: check-yaml
files: ^spiffworkflow-backend/
name: Check Yaml
entry: check-yaml
language: system
types: [yaml]
- id: end-of-file-fixer
files: ^spiffworkflow-backend/
name: Fix End of Files
entry: end-of-file-fixer
language: system
types: [text]
stages: [commit, push, manual]
- id: flake8
files: ^spiffworkflow-backend/
name: flake8
entry: flake8
language: system
types: [python]
require_serial: true
exclude: "/migrations/"
- id: pyupgrade
files: ^spiffworkflow-backend/
name: pyupgrade
description: Automatically upgrade syntax for newer versions.
entry: pyupgrade
language: system
types: [python]
args: [--py37-plus]
- id: reorder-python-imports
files: ^spiffworkflow-backend/
name: Reorder python imports
entry: reorder-python-imports
language: system
types: [python]
args: [--application-directories=spiffworkflow-backend/src]
exclude: "(/migrations/|load_database_models)"
- id: trailing-whitespace
files: ^spiffworkflow-backend/
name: Trim Trailing Whitespace
entry: trailing-whitespace-fixer
language: system
types: [text]
stages: [commit, push, manual]
exclude: "/migrations/"
# - repo: https://github.com/pre-commit/mirrors-prettier
# rev: v2.4.1
# hooks:
# - id: prettier
# files: ^spiffworkflow-backend/
# exclude_types: [html]

View File

@ -3,5 +3,11 @@
git subtree push --prefix=spiffworkflow-frontend git@github.com:sartography/spiffworkflow-frontend.git add_md_file
# run pyl
`./bin/run_pyl`
Requires at root:
- .darglint
- .flake8
- .pre-commit-config.yaml
- pyproject.toml

16
bin/push_all_subtrees Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
subtrees=$("${script_dir}/get_subtree_prefixes")
for subtree in $subtrees ; do
echo -e "\n$subtree"
"${script_dir}/push_subtree" "$subtree"
done

36
bin/run_pyl Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail
python_projects=(
flask-bpmn
spiffworkflow-backend
)
function run_fix_docstrings() {
fix_python_docstrings $(get_top_level_directories_containing_python_files)
}
function run_pre_commmit() {
poetry run pre-commit run --verbose --all-files
}
for python_project in "${python_projects[@]}" ; do
pushd "$python_project"
run_fix_docstrings || run_fix_docstrings
popd
done
run_pre_commmit || run_pre_commmit
for python_project in "${python_projects[@]}"; do
pushd "$python_project"
poet i
poet mypy
poet test
popd
done

20
bin/run_servers_locally Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail
# HELP: runs backend and frontend in tmux. REQUIRES running in a current TMUX session.
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
# https://stackoverflow.com/a/39523222/6090676
# The syntax for a specific pane is tmux send-keys -t {session}:{window}.{pane}, so tmux send-keys -t Test:Test1.1 "TEST" C-m would send that to the first pane.
pane_uid=$(tmux split-window -t backend.2 -c "${script_dir}/../spiffworkflow-backend" -P -F '#{pane_id}')
tmux send-keys -t "$pane_uid" "./bin/run_server_locally" Enter
pane_uid=$(tmux split-window -t frontend.2 -c "${script_dir}/../spiffworkflow-frontend" -P -F '#{pane_id}')
tmux send-keys -t "$pane_uid" "npm start" Enter

View File

@ -2,4 +2,4 @@ pip==22.3
nox==2022.8.7
nox-poetry==1.0.1
poetry==1.2.2
virtualenv==20.16.3
virtualenv==20.16.6

185
flask-bpmn/poetry.lock generated
View File

@ -370,7 +370,7 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)",
[[package]]
name = "coverage"
version = "6.4.4"
version = "6.5.0"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
@ -483,18 +483,18 @@ pycodestyle = "*"
[[package]]
name = "flake8-bugbear"
version = "22.7.1"
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.6"
python-versions = ">=3.7"
[package.dependencies]
attrs = ">=19.2.0"
flake8 = ">=3.0.0"
[package.extras]
dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"]
dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"]
[[package]]
name = "flake8-docstrings"
@ -945,11 +945,11 @@ mypy-extensions = "*"
[[package]]
name = "mypy"
version = "0.971"
version = "0.982"
description = "Optional static typing for Python"
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[package.dependencies]
mypy-extensions = ">=0.4.3"
@ -1206,7 +1206,7 @@ tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]]
name = "pyupgrade"
version = "2.37.3"
version = "3.1.0"
description = "A tool to automatically upgrade syntax for newer versions."
category = "dev"
optional = false
@ -1233,7 +1233,7 @@ python-versions = ">=3.6"
[[package]]
name = "reorder-python-imports"
version = "3.8.5"
version = "3.9.0"
description = "Tool for reordering python imports"
category = "dev"
optional = false
@ -1316,7 +1316,7 @@ gitlab = ["python-gitlab (>=1.3.0)"]
[[package]]
name = "sentry-sdk"
version = "1.9.10"
version = "1.10.1"
description = "Python client for Sentry (https://sentry.io)"
category = "main"
optional = false
@ -1578,7 +1578,7 @@ pytz = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
resolved_reference = "a094adad8767f82e9c5fa806a46597e066252a72"
resolved_reference = "2d3bd00854ab483e823c4b386430abc9267f536b"
[[package]]
name = "sqlalchemy"
@ -1853,7 +1853,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
content-hash = "6f6900d191eca1b800dded9dc844a82d858c7c592cac88e2d76d8a919b56eeca"
content-hash = "f5c0fcc30ff491c23da05e4d24c2dc9c66f43a2dfde028345f9dffd5e91f3f0a"
[metadata.files]
alabaster = [
@ -2058,56 +2058,56 @@ configparser = [
{file = "configparser-5.2.0.tar.gz", hash = "sha256:1b35798fdf1713f1c3139016cfcbc461f09edbf099d1fb658d4b7479fcaa3daa"},
]
coverage = [
{file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"},
{file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"},
{file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"},
{file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"},
{file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"},
{file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"},
{file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"},
{file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"},
{file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"},
{file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"},
{file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"},
{file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"},
{file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"},
{file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"},
{file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"},
{file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"},
{file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"},
{file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"},
{file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"},
{file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"},
{file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"},
{file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"},
{file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"},
{file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"},
{file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"},
{file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"},
{file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"},
{file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"},
{file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"},
{file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"},
{file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"},
{file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"},
{file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"},
{file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"},
{file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"},
{file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"},
{file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"},
{file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"},
{file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"},
{file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"},
{file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"},
{file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"},
{file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"},
{file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"},
{file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"},
{file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"},
{file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"},
{file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"},
{file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"},
{file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"},
{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"},
@ -2141,8 +2141,8 @@ flake8-bandit = [
{file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"},
]
flake8-bugbear = [
{file = "flake8-bugbear-22.7.1.tar.gz", hash = "sha256:e450976a07e4f9d6c043d4f72b17ec1baf717fe37f7997009c8ae58064f88305"},
{file = "flake8_bugbear-22.7.1-py3-none-any.whl", hash = "sha256:db5d7a831ef4412a224b26c708967ff816818cabae415e76b8c58df156c4b8e5"},
{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"},
@ -2494,29 +2494,30 @@ monkeytype = [
{file = "MonkeyType-22.2.0.tar.gz", hash = "sha256:6b0c00b49dcc5095a2c08d28246cf005e05673fc51f64d203f9a6bca2036dfab"},
]
mypy = [
{file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"},
{file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"},
{file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"},
{file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"},
{file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"},
{file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"},
{file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"},
{file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"},
{file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"},
{file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"},
{file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"},
{file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"},
{file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"},
{file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"},
{file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"},
{file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"},
{file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"},
{file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"},
{file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"},
{file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"},
{file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"},
{file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"},
{file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"},
{file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"},
{file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"},
{file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"},
{file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"},
{file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"},
{file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"},
{file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"},
{file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"},
{file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"},
{file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"},
{file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"},
{file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"},
{file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"},
{file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"},
{file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"},
{file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"},
{file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"},
{file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"},
{file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"},
{file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"},
{file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"},
{file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"},
{file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"},
{file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"},
]
mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
@ -2607,8 +2608,8 @@ pytz-deprecation-shim = [
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
]
pyupgrade = [
{file = "pyupgrade-2.37.3-py2.py3-none-any.whl", hash = "sha256:9746efd064dbf53d7f86d6f88a1d48120f58dbfc378f517768634740ea2225e2"},
{file = "pyupgrade-2.37.3.tar.gz", hash = "sha256:1414c7a7c558004cf610e6180716b876814b639b5a5789c3da023c5cdaebcd49"},
{file = "pyupgrade-3.1.0-py2.py3-none-any.whl", hash = "sha256:77c6101a710be3e24804891e43388cedbee617258e93b09c8c5e58de08617758"},
{file = "pyupgrade-3.1.0.tar.gz", hash = "sha256:7a8d393d85e15e0e2753e90b7b2e173b9d29dfd71e61f93d93e985b242627ed3"},
]
pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
@ -2729,8 +2730,8 @@ regex = [
{file = "regex-2022.3.2.tar.gz", hash = "sha256:79e5af1ff258bc0fe0bdd6f69bc4ae33935a898e3cbefbbccf22e88a27fa053b"},
]
reorder-python-imports = [
{file = "reorder_python_imports-3.8.5-py2.py3-none-any.whl", hash = "sha256:6c36b84add1a8125479e1de97a21b7797ee6df51530b5340857d65c79d6882ac"},
{file = "reorder_python_imports-3.8.5.tar.gz", hash = "sha256:5e018dceb889688eafd41a1b217420f810e0400f5a26c679a08f7f9de956ca3b"},
{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"},
@ -2780,8 +2781,8 @@ safety = [
{file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"},
]
sentry-sdk = [
{file = "sentry-sdk-1.9.10.tar.gz", hash = "sha256:4fbace9a763285b608c06f01a807b51acb35f6059da6a01236654e08b0ee81ff"},
{file = "sentry_sdk-1.9.10-py2.py3-none-any.whl", hash = "sha256:2469240f6190aaebcb453033519eae69cfe8cc602065b4667e18ee14fc1e35dc"},
{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"},

View File

@ -34,9 +34,9 @@ sphinx-autoapi = "^2.0.0"
[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
coverage = {extras = ["toml"], version = "^6.4"}
coverage = {extras = ["toml"], version = "^6.5"}
safety = "^2.3.1"
mypy = "^0.971"
mypy = "^0.982"
typeguard = "^2.13.2"
xdoctest = {extras = ["colors"], version = "^1.1.0"}
sphinx = "^4.3.0"
@ -52,16 +52,16 @@ spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "ma
# 1.7.3 broke us. https://github.com/PyCQA/bandit/issues/841
bandit = "1.7.2"
flake8-bugbear = "^22.7.1"
flake8-bugbear = "^22.10.27"
flake8-docstrings = "^1.6.0"
flake8-rst-docstrings = "^0.2.7"
pep8-naming = "^0.13.2"
darglint = "^1.8.1"
reorder-python-imports = "^3.8.5"
reorder-python-imports = "^3.9.0"
pre-commit-hooks = "^4.3.0"
sphinx-click = "^4.3.0"
Pygments = "^2.13.0"
pyupgrade = "^2.37.3"
pyupgrade = "^3.1.0"
furo = ">=2021.11.12"
MonkeyType = "^22.2.0"

View File

@ -88,7 +88,6 @@ class ApiError(Exception):
# Assure that there is nothing in the json data that can't be serialized.
instance.task_data = ApiError.remove_unserializeable_from_dict(task.data)
current_app.logger.error(message, exc_info=True)
return instance
@staticmethod
@ -125,7 +124,6 @@ class ApiError(Exception):
instance.task_name = task_spec.description or ""
if task_spec._wf_spec:
instance.file_name = task_spec._wf_spec.file
current_app.logger.error(message, exc_info=True)
return instance
@classmethod

3686
poetry.lock generated Normal file

File diff suppressed because it is too large Load Diff

158
pyproject.toml Normal file
View File

@ -0,0 +1,158 @@
[tool.poetry]
name = "spiffworkflow-arean"
version = "0.0.0"
description = "Spiffworkflow Arena"
authors = ["Jason Lantz <sartography@users.noreply.github.com>"]
license = "MIT"
readme = "README.rst"
homepage = "https://github.com/sartography/spiffworkflow-arena"
repository = "https://github.com/sartography/spiffworkflow-arena"
classifiers = [
"Development Status :: 1 - Planning",
]
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
click = "^8.0.1"
flask = "2.2.2"
flask-admin = "*"
flask-bcrypt = "*"
flask-cors = "*"
flask-mail = "*"
flask-marshmallow = "*"
flask-migrate = "*"
flask-restful = "*"
werkzeug = "*"
# go back to main once https://github.com/sartography/SpiffWorkflow/pull/241 is merged
SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
# SpiffWorkflow = {develop = true, path = "/Users/kevin/projects/github/sartography/SpiffWorkflow"}
# SpiffWorkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
sentry-sdk = "^1.10"
sphinx-autoapi = "^2.0"
# flask-bpmn = {develop = true, path = "/home/jason/projects/github/sartography/flask-bpmn"}
# flask-bpmn = {develop = true, path = "/Users/kevin/projects/github/sartography/flask-bpmn"}
flask-bpmn = {git = "https://github.com/sartography/flask-bpmn", rev = "main"}
mysql-connector-python = "^8.0.29"
pytest-flask = "^1.2.0"
pytest-flask-sqlalchemy = "^1.1.0"
psycopg2 = "^2.9.3"
typing-extensions = "^4.4.0"
connexion = {extras = [ "swagger-ui",], version = "^2"}
lxml = "^4.9.1"
marshmallow-enum = "^1.5.1"
marshmallow-sqlalchemy = "^0.28.0"
PyJWT = "^2.6.0"
gunicorn = "^20.1.0"
python-keycloak = "^2.5.0"
APScheduler = "^3.9.1"
Jinja2 = "^3.1.2"
RestrictedPython = "^5.2"
Flask-SQLAlchemy = "^3"
orjson = "^3.8.0"
# type hinting stuff
# these need to be in the normal (non dev-dependencies) section
# because if not then poetry export won't have them and nox -s mypy --pythons 3.10
# will fail
types-Werkzeug = "^1.0.9"
types-PyYAML = "^6.0.12"
types-Flask = "^1.1.6"
types-requests = "^2.28.6"
types-pytz = "^2022.1.1"
# https://github.com/dropbox/sqlalchemy-stubs/pull/251
# someday get off github
# sqlalchemy-stubs = "^0.4"
# sqlalchemy-stubs = { git = "https://github.com/dropbox/sqlalchemy-stubs.git", rev = "master" }
# sqlalchemy-stubs = {develop = true, path = "/Users/kevin/projects/github/sqlalchemy-stubs"}
# for now use my fork
sqlalchemy-stubs = { git = "https://github.com/burnettk/sqlalchemy-stubs.git", rev = "scoped-session-delete" }
simplejson = "^3.17.6"
[tool.poetry.dev-dependencies]
pytest = "^7.1.2"
coverage = {extras = ["toml"], version = "^6.1"}
safety = "^2.3.1"
mypy = ">=0.961"
typeguard = "^2.13.2"
xdoctest = {extras = ["colors"], version = "^1.0.1"}
sphinx = "^5.0.2"
sphinx-autobuild = ">=2021.3.14"
pre-commit = "^2.20.0"
flake8 = "^4.0.1"
black = ">=21.10b0"
flake8-bandit = "^2.1.2"
# 1.7.3 broke us. https://github.com/PyCQA/bandit/issues/841
bandit = "1.7.2"
flake8-bugbear = "^22.10.25"
flake8-docstrings = "^1.6.0"
flake8-rst-docstrings = "^0.2.7"
# flask-sqlalchemy-stubs = "^0.2"
pep8-naming = "^0.13.2"
darglint = "^1.8.1"
reorder-python-imports = "^3.9.0"
pre-commit-hooks = "^4.0.1"
sphinx-click = "^4.3.0"
Pygments = "^2.10.0"
pyupgrade = "^3.1.0"
furo = ">=2021.11.12"
MonkeyType = "^22.2.0"
[tool.poetry.scripts]
spiffworkflow-backend = "spiffworkflow_backend.__main__:main"
[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_marshmallow/__init__.py:34
# marshmallow_sqlalchemy/convert.py:17
'ignore:distutils Version classes are deprecated. Use packaging.version instead.',
# connexion/spec.py:50
'ignore:Passing a schema to Validator.iter_errors is deprecated and will be removed in a future release',
# connexion/decorators/validation.py:16
'ignore:Accessing jsonschema.draft4_format_checker is deprecated and will be removed in a future release.',
# connexion/apis/flask_api.py:236
"ignore:'_request_ctx_stack' is deprecated and will be removed in Flask 2.3",
"ignore:Setting 'json_encoder' on the app or a blueprint is deprecated and will be removed in Flask 2.3",
"ignore:'JSONEncoder' is deprecated and will be removed in Flask 2.3",
"ignore:'app.json_encoder' is deprecated and will be removed in Flask 2.3"
]
[tool.coverage.paths]
source = ["src", "*/site-packages"]
tests = ["tests", "*/tests"]
[tool.coverage.run]
branch = true
source = ["spiffworkflow_backend", "tests"]
[tool.coverage.report]
show_missing = true
fail_under = 50
[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
plugins = "sqlmypy"
# 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"

View File

@ -9,6 +9,20 @@ set -o errtrace -o errexit -o nounset -o pipefail
export FLASK_SESSION_SECRET_KEY="this_is_recreate_db_secret_key"
if [[ -z "${BPMN_SPEC_ABSOLUTE_DIR:-}" ]]; then
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
BPMN_SPEC_ABSOLUTE_DIR="${script_dir}/../../../sample-process-models"
if [[ ! -d "$BPMN_SPEC_ABSOLUTE_DIR" ]]; then
BPMN_SPEC_ABSOLUTE_DIR="${script_dir}/../../sample-process-models"
if [[ ! -d "$BPMN_SPEC_ABSOLUTE_DIR" ]]; then
>&2 echo "ERROR: Could not find a location for the sample processes. Last tried: $BPMN_SPEC_ABSOLUTE_DIR"
exit 1
fi
fi
export BPMN_SPEC_ABSOLUTE_DIR
fi
tasks=""
if [[ "${1:-}" == "clean" ]]; then
subcommand="${2:-}"

View File

@ -19,7 +19,16 @@ fi
if [[ -z "${BPMN_SPEC_ABSOLUTE_DIR:-}" ]]; then
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
export BPMN_SPEC_ABSOLUTE_DIR="$script_dir/../../sample-process-models"
BPMN_SPEC_ABSOLUTE_DIR="${script_dir}/../../../sample-process-models"
if [[ ! -d "$BPMN_SPEC_ABSOLUTE_DIR" ]]; then
BPMN_SPEC_ABSOLUTE_DIR="${script_dir}/../../sample-process-models"
if [[ ! -d "$BPMN_SPEC_ABSOLUTE_DIR" ]]; then
>&2 echo "ERROR: Could not find a location for the sample processes. Last tried: $BPMN_SPEC_ABSOLUTE_DIR"
exit 1
fi
fi
export BPMN_SPEC_ABSOLUTE_DIR
fi
export FLASK_SESSION_SECRET_KEY=super_secret_key

View File

@ -1280,6 +1280,7 @@
"http://localhost:7000/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7000/*",
"https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*",
"https://api.demo.spiffworkflow.org/*"
],
"webOrigins": [],
@ -1552,6 +1553,7 @@
"http://localhost:7001/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7001/*",
"https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*",
"https://api.demo.spiffworkflow.org/*"
],
"webOrigins": ["*"],
@ -1623,6 +1625,7 @@
"http://localhost:7001/*",
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7001/*",
"https://api.{{SPIFF_SUBDOMAIN}}.spiffworkflow.org/*",
"https://api.demo.spiffworkflow.org/*"
],
"webOrigins": [],

View File

@ -18,7 +18,7 @@ set -o errtrace -o errexit -o nounset -o pipefail
if ! docker network inspect spiffworkflow > /dev/null 2>&1; then
docker network create spiffworkflow
fi
docker rm keycloak 2>/dev/null || echo 'no keycloak container found'
docker rm keycloak 2>/dev/null || echo 'no keycloak container found, safe to start new container'
docker run \
-p 7002:8080 \
-d \
@ -31,7 +31,11 @@ docker run \
-Dkeycloak.profile.feature.token_exchange=enabled \
-Dkeycloak.profile.feature.admin_fine_grained_authz=enabled
docker cp bin/spiffworkflow-realm.json keycloak:/tmp
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
cp "${script_dir}/spiffworkflow-realm.json" /tmp/spiffworkflow-realm.json
spiff_subdomain="unused-for-local-dev"
perl -pi -e "s/{{SPIFF_SUBDOMAIN}}/${spiff_subdomain}/g" /tmp/spiffworkflow-realm.json
docker cp /tmp/spiffworkflow-realm.json keycloak:/tmp
sleep 20
remove_traps

View File

@ -37,21 +37,9 @@ from spiffworkflow_backend import create_app # noqa: E402
def app() -> Flask:
"""App."""
os.environ["SPIFFWORKFLOW_BACKEND_ENV"] = "testing"
# os.environ["FLASK_SESSION_SECRET_KEY"] = "this_is_testing_secret_key"
os.environ["FLASK_SESSION_SECRET_KEY"] = "super_secret_key"
app = create_app()
# NOTE: set this here since nox shoves tests and src code to
# different places and this allows us to know exactly where we are at the start
app.config["BPMN_SPEC_ABSOLUTE_DIR"] = os.path.join(
os.path.dirname(__file__),
"tests",
"spiffworkflow_backend",
"files",
"bpmn_specs",
)
return app

View File

@ -6,7 +6,7 @@ ENV KC_HEALTH_ENABLED="true"
# ENV KC_METRICS_ENABLED=true
ENV PROXY_ADDRESS_FORWARDING="true"
# ENV KC_HOSTNAME="keycloak.demo.spiffworkflow.org"
ENV KC_HOSTNAME_URL="https://keycloak.demo.spiffworkflow.org"
# ENV KC_HOSTNAME_URL="https://keycloak.demo.spiffworkflow.org"
ENV KC_FEATURES="token-exchange,admin-fine-grained-authz"
# ENV KC_DB=postgres
# Install custom providers

View File

@ -639,7 +639,7 @@ werkzeug = "*"
type = "git"
url = "https://github.com/sartography/flask-bpmn"
reference = "main"
resolved_reference = "aae17b7b4152fe09d4a365ac5ec85289218c663b"
resolved_reference = "cedc5253add81a18a274f2cd3289fe36bb138f8b"
[[package]]
name = "Flask-Cors"
@ -1873,7 +1873,7 @@ pytz = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
resolved_reference = "a094adad8767f82e9c5fa806a46597e066252a72"
resolved_reference = "2d3bd00854ab483e823c4b386430abc9267f536b"
[[package]]
name = "SQLAlchemy"

View File

@ -27,15 +27,11 @@ flask-marshmallow = "*"
flask-migrate = "*"
flask-restful = "*"
werkzeug = "*"
# go back to main once https://github.com/sartography/SpiffWorkflow/pull/241 is merged
SpiffWorkflow = {git = "https://github.com/sartography/SpiffWorkflow", rev = "main"}
# SpiffWorkflow = {develop = true, path = "/Users/kevin/projects/github/sartography/SpiffWorkflow"}
# SpiffWorkflow = {develop = true, path = "/home/jason/projects/github/sartography/SpiffWorkflow"}
sentry-sdk = "^1.10"
sphinx-autoapi = "^2.0"
# flask-bpmn = {develop = true, path = "/home/jason/projects/github/sartography/flask-bpmn"}
# flask-bpmn = {develop = true, path = "/Users/kevin/projects/github/sartography/flask-bpmn"}
flask-bpmn = {git = "https://github.com/sartography/flask-bpmn", rev = "main"}
# flask-bpmn = {develop = true, path = "../flask-bpmn"}
mysql-connector-python = "^8.0.29"
pytest-flask = "^1.2.0"
pytest-flask-sqlalchemy = "^1.1.0"

View File

@ -148,6 +148,7 @@ def configure_sentry(app: flask.app.Flask) -> None:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
# get rid of NotFound errors
def before_send(event: Any, hint: Any) -> Any:
"""Before_send."""
if "exc_info" in hint:
@ -157,18 +158,26 @@ def configure_sentry(app: flask.app.Flask) -> None:
return None
return event
sentry_sample_rate = app.config.get("SENTRY_SAMPLE_RATE")
if sentry_sample_rate is None:
return
sentry_errors_sample_rate = app.config.get("SENTRY_ERRORS_SAMPLE_RATE")
if sentry_errors_sample_rate is None:
raise Exception("SENTRY_ERRORS_SAMPLE_RATE is not set somehow")
sentry_traces_sample_rate = app.config.get("SENTRY_TRACES_SAMPLE_RATE")
if sentry_traces_sample_rate is None:
raise Exception("SENTRY_TRACES_SAMPLE_RATE is not set somehow")
sentry_sdk.init(
dsn=app.config.get("SENTRY_DSN"),
integrations=[
FlaskIntegration(),
],
environment=app.config["ENV_IDENTIFIER"],
# Set traces_sample_rate to 1.0 to capture 100%
# sample_rate is the errors sample rate. we usually set it to 1 (100%)
# so we get all errors in sentry.
sample_rate=float(sentry_errors_sample_rate),
# Set traces_sample_rate to capture a certain percentage
# of transactions for performance monitoring.
# We recommend adjusting this value in production.
traces_sample_rate=float(sentry_sample_rate),
# We recommend adjusting this value to less than 1(00%) in production.
traces_sample_rate=float(sentry_traces_sample_rate),
before_send=before_send,
)

View File

@ -8,6 +8,10 @@ from werkzeug.utils import ImportStringError
from spiffworkflow_backend.services.logging_service import setup_logger
class ConfigurationError(Exception):
"""ConfigurationError."""
def setup_database_uri(app: Flask) -> None:
"""Setup_database_uri."""
if os.environ.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None:
@ -54,13 +58,20 @@ def setup_config(app: Flask) -> None:
else:
app.config.from_pyfile(f"{app.instance_path}/config.py", silent=True)
env_config_module = "spiffworkflow_backend.config." + app.config["ENV_IDENTIFIER"]
env_config_prefix = "spiffworkflow_backend.config."
env_config_module = env_config_prefix + app.config["ENV_IDENTIFIER"]
try:
app.config.from_object(env_config_module)
except ImportStringError as exception:
raise ModuleNotFoundError(
f"Cannot find config module: {env_config_module}"
) from exception
if (
os.environ.get("TERRAFORM_DEPLOYED_ENVIRONMENT") == "true"
and os.environ.get("SPIFFWORKFLOW_BACKEND_ENV") is not None
):
app.config.from_object("{env_config_prefix}terraform_deployed_environment")
else:
raise ModuleNotFoundError(
f"Cannot find config module: {env_config_module}"
) from exception
setup_database_uri(app)
setup_logger(app)
@ -78,5 +89,8 @@ def setup_config(app: Flask) -> None:
# src/spiffworkflow_backend/config/secrets.py
app.config.from_pyfile(os.path.join("config", "secrets.py"), silent=True)
if app.config["BPMN_SPEC_ABSOLUTE_DIR"] is None:
raise ConfigurationError("BPMN_SPEC_ABSOLUTE_DIR config must be set")
thread_local_data = threading.local()
app.config["THREAD_LOCAL_DATA"] = thread_local_data

View File

@ -7,7 +7,7 @@ SELF_REGISTRATION = environ.get("SELF_REGISTRATION", default=False)
DEVELOPMENT = False
BPMN_SPEC_ABSOLUTE_DIR = environ.get("BPMN_SPEC_ABSOLUTE_DIR", default="")
BPMN_SPEC_ABSOLUTE_DIR = environ.get("BPMN_SPEC_ABSOLUTE_DIR")
CORS_DEFAULT = "*"
CORS_ALLOW_ORIGINS = re.split(
r",\s*", environ.get("CORS_ALLOW_ORIGINS", default=CORS_DEFAULT)
@ -47,7 +47,12 @@ SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(
# Sentry Configuration
SENTRY_DSN = environ.get("SENTRY_DSN", default="")
SENTRY_SAMPLE_RATE = environ.get("SENTRY_SAMPLE_RATE", default="1.0")
SENTRY_ERRORS_SAMPLE_RATE = environ.get(
"SENTRY_ERRORS_SAMPLE_RATE", default="1"
) # send all errors
SENTRY_TRACES_SAMPLE_RATE = environ.get(
"SENTRY_TRACES_SAMPLE_RATE", default="0.01"
) # send 1% of traces
SPIFFWORKFLOW_BACKEND_LOG_LEVEL = environ.get(
"SPIFFWORKFLOW_BACKEND_LOG_LEVEL", default="info"

View File

@ -1,11 +1,12 @@
"""Staging."""
"""Demo environment."""
from os import environ
GIT_COMMIT_ON_SAVE = True
GIT_COMMIT_USERNAME = "demo"
GIT_COMMIT_EMAIL = "demo@example.com"
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(
"SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME", default="demo.yml"
"SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME",
default="terraform_deployed_environment.yml",
)
RUN_BACKGROUND_SCHEDULER = (

View File

@ -20,8 +20,23 @@ groups:
natalia,
]
finance:
users: [finance_user1]
Finance Team:
users: [finance_user1, jason]
Project Lead:
users:
[
jakub,
alex,
dan,
mike,
jason,
jarrad,
elizabeth,
jon,
natalia,
manuchehr,
]
permissions:
admin:
@ -30,14 +45,27 @@ permissions:
allowed_permissions: [create, read, update, delete, list, instantiate]
uri: /*
finance-admin:
groups: [finance]
tasks-crud:
groups: [everybody]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-groups/execute-procure-to-pay/*
uri: /v1.0/tasks/*
# TODO: all uris should really have the same structure
finance-admin-group:
groups: ["Finance Team"]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-groups/finance/*
finance-admin-model:
groups: ["Finance Team"]
users: []
allowed_permissions: [create, read, update, delete]
uri: /v1.0/process-models/finance/*
read-all:
groups: [finance, admin]
groups: [admin, "Project Lead"]
users: []
allowed_permissions: [read]
uri: /*

View File

@ -0,0 +1,16 @@
"""Terraform-deployed environment."""
from os import environ
# default.py already ensured that this key existed as was not None
environment_identifier_for_this_config_file_only = environ["SPIFFWORKFLOW_BACKEND_ENV"]
GIT_COMMIT_ON_SAVE = True
GIT_COMMIT_USERNAME = environment_identifier_for_this_config_file_only
GIT_COMMIT_EMAIL = f"{environment_identifier_for_this_config_file_only}@example.com"
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(
"SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME", default="terraform_deployed_environment.yml"
)
RUN_BACKGROUND_SCHEDULER = (
environ.get("RUN_BACKGROUND_SCHEDULER", default="false") == "true"
)

View File

@ -1,7 +1,7 @@
"""Testing.py."""
import os
from os import environ
TESTING = True
SECRET_KEY = "the_secret_key"
SPIFFWORKFLOW_BACKEND_LOG_TO_FILE = (
@ -15,3 +15,13 @@ SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME = environ.get(
SPIFFWORKFLOW_BACKEND_LOG_LEVEL = environ.get(
"SPIFFWORKFLOW_BACKEND_LOG_LEVEL", default="debug"
)
# NOTE: set this here since nox shoves tests and src code to
# different places and this allows us to know exactly where we are at the start
BPMN_SPEC_ABSOLUTE_DIR = os.path.join(
os.path.dirname(__file__),
"tests",
"spiffworkflow_backend",
"files",
"bpmn_specs",
)

View File

@ -1,7 +1,8 @@
"""Db_helper."""
import time
import sqlalchemy
from flask_bpmn.models.db import db
import time
def try_to_connect(start_time: float) -> None:

View File

@ -46,12 +46,12 @@ class ActiveTaskModel(SpiffworkflowBaseDBModel):
updated_at_in_seconds: int = db.Column(db.Integer)
created_at_in_seconds: int = db.Column(db.Integer)
task_id = db.Column(db.String(50))
task_name = db.Column(db.String(50))
task_title = db.Column(db.String(50))
task_type = db.Column(db.String(50))
task_status = db.Column(db.String(50))
process_model_display_name = db.Column(db.String(255))
task_id: str = db.Column(db.String(50))
task_name: str = db.Column(db.String(50))
task_title: str = db.Column(db.String(50))
task_type: str = db.Column(db.String(50))
task_status: str = db.Column(db.String(50))
process_model_display_name: str = db.Column(db.String(255))
active_task_users = relationship("ActiveTaskUserModel", cascade="delete")
potential_owners = relationship( # type: ignore

View File

@ -14,6 +14,10 @@ if TYPE_CHECKING:
from spiffworkflow_backend.models.user import UserModel # noqa: F401
class GroupNotFoundError(Exception):
"""GroupNotFoundError."""
class GroupModel(FlaskBpmnGroupModel):
"""GroupModel."""

View File

@ -0,0 +1,14 @@
"""Script_attributes_context."""
from dataclasses import dataclass
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
@dataclass
class ScriptAttributesContext:
"""ScriptAttributesContext."""
task: SpiffTask
environment_identifier: str
process_instance_id: int
process_model_identifier: str

View File

@ -871,7 +871,6 @@ def process_instance_delete(
"""Create_process_instance."""
process_instance = find_process_instance_by_id_or_raise(process_instance_id)
# import pdb; pdb.set_trace()
# (Pdb) db.session.delete
# <bound method delete of <sqlalchemy.orm.scoping.scoped_session object at 0x103eaab30>>
db.session.delete(process_instance)
@ -1212,12 +1211,13 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
)
if ui_form_contents:
task.form_ui_schema = ui_form_contents
elif task.type == "Manual Task":
if task.properties and task.data:
if task.properties["instructionsForEndUser"]:
task.properties["instructionsForEndUser"] = render_jinja_template(
task.properties["instructionsForEndUser"], task.data
)
if task.properties and task.data and "instructionsForEndUser" in task.properties:
print(f"task.properties['instructionsForEndUser']: {task.properties['instructionsForEndUser']}")
if task.properties["instructionsForEndUser"]:
task.properties["instructionsForEndUser"] = render_jinja_template(
task.properties["instructionsForEndUser"], task.data
)
return make_response(jsonify(task), 200)

View File

@ -1,9 +1,9 @@
"""Fact_service."""
from typing import Any
from typing import Optional
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
@ -17,8 +17,7 @@ class FactService(Script):
def run(
self,
task: Optional[SpiffTask],
environment_identifier: str,
script_attributes_context: ScriptAttributesContext,
*args: Any,
**kwargs: Any
) -> Any:

View File

@ -1,10 +1,11 @@
"""Get_env."""
from typing import Any
from flask import g
from typing import Optional
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
@ -17,8 +18,7 @@ class GetUser(Script):
def run(
self,
task: Optional[SpiffTask],
environment_identifier: str,
script_attributes_context: ScriptAttributesContext,
*_args: Any,
**kwargs: Any
) -> Any:

View File

@ -1,9 +1,9 @@
"""Get_env."""
from typing import Any
from typing import Optional
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
@ -16,10 +16,9 @@ class GetEnv(Script):
def run(
self,
task: Optional[SpiffTask],
environment_identifier: str,
script_attributes_context: ScriptAttributesContext,
*_args: Any,
**kwargs: Any
) -> Any:
"""Run."""
return environment_identifier
return script_attributes_context.environment_identifier

View File

@ -0,0 +1,25 @@
"""Get_env."""
from typing import Any
from flask import current_app
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
class GetFrontendUrl(Script):
"""GetFrontendUrl."""
def get_description(self) -> str:
"""Get_description."""
return """Return the url to the frontend."""
def run(
self,
script_attributes_context: ScriptAttributesContext,
*args: Any,
**kwargs: Any
) -> Any:
"""Run."""
return current_app.config['SPIFFWORKFLOW_FRONTEND_URL']

View File

@ -0,0 +1,34 @@
"""Get_env."""
from typing import Any
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.group import GroupNotFoundError
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
class GetGroupMembers(Script):
"""GetGroupMembers."""
def get_description(self) -> str:
"""Get_description."""
return """Return the list of usernames of the users in the given group."""
def run(
self,
script_attributes_context: ScriptAttributesContext,
*args: Any,
**kwargs: Any,
) -> Any:
"""Run."""
group_identifier = args[0]
group = GroupModel.query.filter_by(identifier=group_identifier).first()
if group is None:
raise GroupNotFoundError(
f"Script 'get_group_members' could not find group with identifier '{group_identifier}'."
)
usernames = [u.username for u in group.users]
return usernames

View File

@ -1,43 +1,47 @@
"""Get_localtime."""
from datetime import datetime
from typing import Any
import pytz
from flask_bpmn.api.api_error import ApiError
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
from datetime import datetime
import pytz
from typing import Any
from typing import Optional
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
class GetLocaltime(Script):
"""GetLocaltime."""
def get_description(self) -> str:
"""Get_description."""
return """Converts a Datetime object into a Datetime object for a specific timezone.
Defaults to US/Eastern"""
Defaults to US/Eastern."""
def run(
self,
task: Optional[SpiffTask],
environment_identifier: str,
script_attributes_context: ScriptAttributesContext,
*args: Any,
**kwargs: Any
) -> datetime:
if len(args) > 0 or 'datetime' in kwargs:
if 'datetime' in kwargs:
date_time = kwargs['datetime']
"""Run."""
if len(args) > 0 or "datetime" in kwargs:
if "datetime" in kwargs:
date_time = kwargs["datetime"]
else:
date_time = args[0]
if 'timezone' in kwargs:
timezone = kwargs['timezone']
if "timezone" in kwargs:
timezone = kwargs["timezone"]
elif len(args) > 1:
timezone = args[1]
else:
timezone = 'US/Eastern'
timezone = "US/Eastern"
localtime: datetime = date_time.astimezone(pytz.timezone(timezone))
return localtime
else:
raise ApiError(error_code='missing_datetime',
message='You must include a datetime to convert.')
raise ApiError(
error_code="missing_datetime",
message="You must include a datetime to convert.",
)

View File

@ -0,0 +1,27 @@
"""Get_process_info."""
from typing import Any
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.script import Script
class GetProcessInfo(Script):
"""GetUser."""
def get_description(self) -> str:
"""Get_description."""
return """Returns a dictionary of information about the currently running process."""
def run(
self,
script_attributes_context: ScriptAttributesContext,
*_args: Any,
**kwargs: Any
) -> Any:
"""Run."""
return {
"process_instance_id": script_attributes_context.process_instance_id,
"process_model_identifier": script_attributes_context.process_model_identifier,
}

View File

@ -9,7 +9,10 @@ from typing import Any
from typing import Callable
from flask_bpmn.api.api_error import ApiError
from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
# Generally speaking, having some global in a flask app is TERRIBLE.
# This is here, because after loading the application this will never change under
@ -28,8 +31,7 @@ class Script:
@abstractmethod
def run(
self,
task: SpiffTask,
environment_identifier: str,
script_attributes_context: ScriptAttributesContext,
*args: Any,
**kwargs: Any,
) -> Any:
@ -43,7 +45,7 @@ class Script:
@staticmethod
def generate_augmented_list(
task: SpiffTask, environment_identifier: str
script_attributes_context: ScriptAttributesContext,
) -> dict[str, Callable]:
"""This makes a dictionary of lambda functions that are closed over the class instance that they represent.
@ -56,7 +58,8 @@ class Script:
"""
def make_closure(
subclass: type[Script], task: SpiffTask, environment_identifier: str
subclass: type[Script],
script_attributes_context: ScriptAttributesContext,
) -> Callable:
"""Yes - this is black magic.
@ -70,8 +73,7 @@ class Script:
instance = subclass()
return lambda *ar, **kw: subclass.run(
instance,
task,
environment_identifier,
script_attributes_context,
*ar,
**kw,
)
@ -81,7 +83,7 @@ class Script:
for x in range(len(subclasses)):
subclass = subclasses[x]
execlist[subclass.__module__.split(".")[-1]] = make_closure(
subclass, task=task, environment_identifier=environment_identifier
subclass, script_attributes_context=script_attributes_context
)
return execlist

View File

@ -22,6 +22,7 @@ from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user import UserNotFoundError
from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel
from spiffworkflow_backend.services.group_service import GroupService
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
@ -138,25 +139,11 @@ class AuthorizationService:
default_group = None
if "default_group" in permission_configs:
default_group_identifier = permission_configs["default_group"]
default_group = GroupModel.query.filter_by(
identifier=default_group_identifier
).first()
if default_group is None:
default_group = GroupModel(identifier=default_group_identifier)
db.session.add(default_group)
db.session.commit()
UserService.create_principal(
default_group.id, id_column_name="group_id"
)
default_group = GroupService.find_or_create_group(default_group_identifier)
if "groups" in permission_configs:
for group_identifier, group_config in permission_configs["groups"].items():
group = GroupModel.query.filter_by(identifier=group_identifier).first()
if group is None:
group = GroupModel(identifier=group_identifier)
db.session.add(group)
db.session.commit()
UserService.create_principal(group.id, id_column_name="group_id")
group = GroupService.find_or_create_group(group_identifier)
for username in group_config["users"]:
user = UserModel.query.filter_by(username=username).first()
if user is None:
@ -186,13 +173,9 @@ class AuthorizationService:
for allowed_permission in permission_config["allowed_permissions"]:
if "groups" in permission_config:
for group_identifier in permission_config["groups"]:
principal = (
PrincipalModel.query.join(GroupModel)
.filter(GroupModel.identifier == group_identifier)
.first()
)
group = GroupService.find_or_create_group(group_identifier)
cls.create_permission_for_principal(
principal, permission_target, allowed_permission
group.principal, permission_target, allowed_permission
)
if "users" in permission_config:
for username in permission_config["users"]:

View File

@ -20,10 +20,12 @@ class DataSetupService:
failing_process_models = []
process_models = ProcessModelService().get_process_models()
for process_model in process_models:
if process_model.primary_file_name:
process_model_files = SpecFileService.get_files(
process_model, extension_filter=".bpmn"
)
for process_model_file in process_model_files:
bpmn_xml_file_contents = SpecFileService.get_data(
process_model, process_model.primary_file_name
process_model, process_model_file.name
)
bad_files = [
"B.1.0.bpmn",
@ -32,21 +34,21 @@ class DataSetupService:
"C.6.0.bpmn",
"TC-5.1.bpmn",
]
if process_model.primary_file_name in bad_files:
if process_model_file.name in bad_files:
continue
current_app.logger.debug(
f"primary_file_name: {process_model.primary_file_name}"
f"primary_file_name: {process_model_file.name}"
)
try:
SpecFileService.update_file(
process_model,
process_model.primary_file_name,
process_model_file.name,
bpmn_xml_file_contents,
)
except Exception as ex:
failing_process_models.append(
(
f"{process_model.process_group_id}/{process_model.id}/{process_model.primary_file_name}",
f"{process_model.process_group_id}/{process_model.id}/{process_model_file.name}",
str(ex),
)
)

View File

@ -24,26 +24,19 @@ class EmailService:
"""We will receive all data related to an email and send it."""
mail = current_app.config["MAIL_APP"]
# Send mail
try:
msg = Message(
subject,
sender=sender,
recipients=recipients,
body=content,
html=content_html,
cc=cc,
bcc=bcc,
reply_to=reply_to,
)
msg = Message(
subject,
sender=sender,
recipients=recipients,
body=content,
html=content_html,
cc=cc,
bcc=bcc,
reply_to=reply_to,
)
if attachment_files is not None:
for file in attachment_files:
msg.attach(file["name"], file["type"], file["data"])
if attachment_files is not None:
for file in attachment_files:
msg.attach(file["name"], file["type"], file["data"])
mail.send(msg)
except Exception as e:
# app.logger.error('An exception happened in EmailService', exc_info=True)
# app.logger.error(str(e))
raise e
mail.send(msg)

View File

@ -0,0 +1,24 @@
"""Group_service."""
from typing import Optional
from flask_bpmn.models.db import db
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.services.user_service import UserService
class GroupService:
"""GroupService."""
@classmethod
def find_or_create_group(cls, group_identifier: str) -> GroupModel:
"""Find_or_create_group."""
group: Optional[GroupModel] = GroupModel.query.filter_by(
identifier=group_identifier
).first()
if group is None:
group = GroupModel(identifier=group_identifier)
db.session.add(group)
db.session.commit()
UserService.create_principal(group.id, id_column_name="group_id")
return group

View File

@ -74,6 +74,9 @@ from spiffworkflow_backend.models.message_instance import MessageModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.models.task_event import TaskAction
from spiffworkflow_backend.models.task_event import TaskEventModel
from spiffworkflow_backend.models.user import UserModel
@ -127,6 +130,10 @@ class PotentialOwnerUserNotFoundError(Exception):
"""PotentialOwnerUserNotFoundError."""
class MissingProcessInfoError(Exception):
"""MissingProcessInfoError."""
class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
"""This is a custom script processor that can be easily injected into Spiff Workflow.
@ -140,9 +147,26 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
def __get_augment_methods(self, task: SpiffTask) -> Dict[str, Callable]:
"""__get_augment_methods."""
return Script.generate_augmented_list(
task, current_app.config["ENV_IDENTIFIER"]
tld = current_app.config["THREAD_LOCAL_DATA"]
if not hasattr(tld, "process_model_identifier"):
raise MissingProcessInfoError(
"Could not find process_model_identifier from app config"
)
if not hasattr(tld, "process_instance_id"):
raise MissingProcessInfoError(
"Could not find process_instance_id from app config"
)
process_model_identifier = tld.process_model_identifier
process_instance_id = tld.process_instance_id
script_attributes_context = ScriptAttributesContext(
task=task,
environment_identifier=current_app.config["ENV_IDENTIFIER"],
process_instance_id=process_instance_id,
process_model_identifier=process_model_identifier,
)
return Script.generate_augmented_list(script_attributes_context)
def evaluate(self, task: SpiffTask, expression: str) -> Any:
"""Evaluate."""
@ -255,6 +279,12 @@ class ProcessInstanceProcessor:
"THREAD_LOCAL_DATA"
].process_instance_id = process_instance_model.id
# we want this to be the fully qualified path to the process model including all group subcomponents
current_app.config["THREAD_LOCAL_DATA"].process_model_identifier = (
f"{process_instance_model.process_group_identifier}/"
f"{process_instance_model.process_model_identifier}"
)
self.process_instance_model = process_instance_model
self.process_model_service = ProcessModelService()
bpmn_process_spec = None

View File

@ -166,9 +166,7 @@ class ProcessInstanceService:
f"task {spiff_task.task_spec.name}, it is not in the task event model, "
f"and it should be."
)
current_app.logger.error(
"missing_form_data", missing_form_error, exc_info=True
)
current_app.logger.exception("missing_form_data", missing_form_error)
return {}
else:
return {}

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="test_groups" isExecutable="true">
<bpmn:startEvent id="Event_0r6oru6">
<bpmn:outgoing>Flow_1j4jzft</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1j4jzft" sourceRef="Event_0r6oru6" targetRef="get_group_a" />
<bpmn:endEvent id="Event_1s123jg">
<bpmn:incoming>Flow_01xr2ac</bpmn:incoming>
</bpmn:endEvent>
<bpmn:scriptTask id="get_group_a">
<bpmn:incoming>Flow_1j4jzft</bpmn:incoming>
<bpmn:outgoing>Flow_10xyk22</bpmn:outgoing>
<bpmn:script>members_a = get_group_members("GroupA")</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_10xyk22" sourceRef="get_group_a" targetRef="get_group_b" />
<bpmn:scriptTask id="get_group_b">
<bpmn:incoming>Flow_10xyk22</bpmn:incoming>
<bpmn:outgoing>Flow_01xr2ac</bpmn:outgoing>
<bpmn:script>members_b = get_group_members("GroupB")</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_01xr2ac" sourceRef="get_group_b" targetRef="Event_1s123jg" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="test_groups">
<bpmndi:BPMNShape id="Event_0r6oru6_di" bpmnElement="Event_0r6oru6">
<dc:Bounds x="162" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0zfzev2_di" bpmnElement="get_group_a">
<dc:Bounds x="250" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0d1q8x4_di" bpmnElement="get_group_b">
<dc:Bounds x="410" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1s123jg_di" bpmnElement="Event_1s123jg">
<dc:Bounds x="582" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1j4jzft_di" bpmnElement="Flow_1j4jzft">
<di:waypoint x="198" y="180" />
<di:waypoint x="250" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10xyk22_di" bpmnElement="Flow_10xyk22">
<di:waypoint x="350" y="180" />
<di:waypoint x="410" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_01xr2ac_di" bpmnElement="Flow_01xr2ac">
<di:waypoint x="510" y="180" />
<di:waypoint x="582" y="180" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -2,19 +2,12 @@
"title": "Get Timezone",
"description": "Form to select a timezone.",
"type": "object",
"required": [
"timezone"
],
"required": ["timezone"],
"properties": {
"timezone": {
"type": "string",
"title": "Timezone",
"enum": [
"US/Eastern",
"US/Pacific",
"Europe/Berlin",
"Australia/ACT"
]
"enum": ["US/Eastern", "US/Pacific", "Europe/Berlin", "Australia/ACT"]
}
}
}
}

View File

@ -81,7 +81,7 @@
<bpmn:scriptTask id="Activity_1s1855p" scriptFormat="python">
<bpmn:incoming>Flow_0bgkfue</bpmn:incoming>
<bpmn:outgoing>Flow_1ivhu7x</bpmn:outgoing>
<bpmn:script>approver = get_user()
<bpmn:script>approver = get_current_user()
lane_owners["Finance Team"].remove(approver)</bpmn:script>
</bpmn:scriptTask>
</bpmn:process>

View File

@ -0,0 +1,52 @@
"""Test_get_localtime."""
from flask.app import Flask
from flask_bpmn.models.db import db
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
from spiffworkflow_backend.services.user_service import UserService
class TestGetGroupMembers(BaseTest):
"""TestGetGroupMembers."""
def test_can_get_members_of_a_group(
self,
app: Flask,
with_db_and_bpmn_file_cleanup: None,
) -> None:
"""Test_can_get_members_of_a_group."""
initiator_user = self.find_or_create_user("initiator_user")
testuser1 = self.find_or_create_user("testuser1")
testuser2 = self.find_or_create_user("testuser2")
testuser3 = self.find_or_create_user("testuser3")
group_a = GroupModel(identifier="groupA")
group_b = GroupModel(identifier="groupB")
db.session.add(group_a)
db.session.add(group_b)
db.session.commit()
UserService.add_user_to_group(testuser1, group_a)
UserService.add_user_to_group(testuser2, group_a)
UserService.add_user_to_group(testuser3, group_b)
process_model = load_test_spec(
process_model_id="get_group_members",
bpmn_file_name="get_group_members.bpmn",
)
process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=initiator_user
)
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps(save=True)
assert processor.bpmn_process_instance.data
assert processor.bpmn_process_instance.data["members_a"] == [
"testuser1",
"testuser2",
]
assert processor.bpmn_process_instance.data["members_b"] == ["testuser3"]

View File

@ -1,24 +1,44 @@
"""Test_get_localtime."""
import datetime
import pytz
import pytz
from flask.app import Flask
from flask.testing import FlaskClient
from spiffworkflow_backend.scripts.get_localtime import GetLocaltime
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.script_attributes_context import (
ScriptAttributesContext,
)
from spiffworkflow_backend.scripts.get_localtime import GetLocaltime
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
class TestGetLocaltime(BaseTest):
"""TestProcessAPi."""
def test_get_localtime_script_directly(self) -> None:
"""Test_get_localtime_script_directly."""
current_time = datetime.datetime.now()
timezone = "US/Pacific"
result = GetLocaltime().run(task=None, environment_identifier='testing', datetime=current_time, timezone=timezone)
process_model_identifier = "test_process_model"
process_instance_id = 1
script_attributes_context = ScriptAttributesContext(
task=None,
environment_identifier="testing",
process_instance_id=process_instance_id,
process_model_identifier=process_model_identifier,
)
result = GetLocaltime().run(
script_attributes_context,
datetime=current_time,
timezone=timezone,
)
assert result == current_time.astimezone(pytz.timezone(timezone))
def test_get_localtime_script_through_bpmn(
@ -60,8 +80,8 @@ class TestGetLocaltime(BaseTest):
assert spiff_task
data = spiff_task.data
some_time = data['some_time']
localtime = data['localtime']
timezone = data['timezone']
some_time = data["some_time"]
localtime = data["localtime"]
timezone = data["timezone"]
assert localtime == some_time.astimezone(pytz.timezone(timezone))

View File

@ -11,7 +11,6 @@
"@babel/core": "^7.18.10",
"@babel/plugin-transform-react-jsx": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@bpmn-io/properties-panel": "^0.19.0",
"@ginkgo-bioworks/react-json-schema-form-builder": "^2.9.0",
"@monaco-editor/react": "^4.4.5",
"@rjsf/core": "^4.2.0",
@ -27,13 +26,13 @@
"axios": "^0.27.2",
"bootstrap": "^5.2.0",
"bpmn-js": "^9.3.2",
"bpmn-js-properties-panel": "^1.5.0",
"bpmn-js-properties-panel": "^1.10.0",
"bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#main",
"craco": "^0.0.3",
"date-fns": "^2.28.0",
"diagram-js": "^8.5.0",
"dmn-js": "^12.2.0",
"dmn-js-properties-panel": "^1.1.0",
"dmn-js-properties-panel": "^1.1",
"dmn-js-shared": "^12.1.1",
"jwt-decode": "^3.1.2",
"keycloak-js": "^18.0.1",
@ -2039,49 +2038,96 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
},
"node_modules/@bpmn-io/element-templates-validator": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/element-templates-validator/-/element-templates-validator-0.9.0.tgz",
"integrity": "sha512-oS5eaXPKxl5bV8x4dJYPCWJpWMumr16TTS39S1oJEh/bKke/nhMBuhsk6wWCp7+G3jWWDkUcS1jGAAaKtvQneA==",
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/element-templates-validator/-/element-templates-validator-0.11.0.tgz",
"integrity": "sha512-4eZCPLuWf1N4lL8jIKZjWgwLJ2IUTgkQ4VDnfbDiSvjGJqHaLA4XBcC5smvb8Q/MqsJFxWZumolJJb1h7gt39Q==",
"dependencies": {
"@camunda/element-templates-json-schema": "^0.10.0",
"@camunda/zeebe-element-templates-json-schema": "^0.5.0",
"@camunda/element-templates-json-schema": "^0.10.1",
"@camunda/zeebe-element-templates-json-schema": "^0.6.0",
"json-source-map": "^0.6.1",
"min-dash": "^3.8.1"
"min-dash": "^4.0.0"
}
},
"node_modules/@bpmn-io/element-templates-validator/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
},
"node_modules/@bpmn-io/extract-process-variables": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@bpmn-io/extract-process-variables/-/extract-process-variables-0.5.1.tgz",
"integrity": "sha512-Kx0zknI9GRli1EDkgmkUV34cKYsqppsgbcnfrSaT2Tmh7CGXEo8b6UzuGFlZtCZt4488UxjP7UhdrONTt5Si/A==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/extract-process-variables/-/extract-process-variables-0.6.0.tgz",
"integrity": "sha512-vq4jwGXDO11jwQgj9lvpVxVxjnRAz4C4TqPnhromcsllH5iRBrUNtBKgK0c/RWxiEGNTBhTYm19sP+LN1UcLWA==",
"dependencies": {
"min-dash": "^3.8.1"
"min-dash": "^4.0.0"
}
},
"node_modules/@bpmn-io/extract-process-variables/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
},
"node_modules/@bpmn-io/feel-editor": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-0.2.0.tgz",
"integrity": "sha512-R85p56nFxffNp0fStNxz561EXJmcTdVZL7NyVhuB3qKS/mt4thuvK1B43YnXKdLx8WessjsbHzjvWkbCYZRWkQ==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-0.4.1.tgz",
"integrity": "sha512-+UGpofI09xGxs1Rr/1V3NLeNSfeKrIGcWvwDY5M3xb4tP6nOQfwqmQA1761Wni9fl3RuLzf6gOx7vGWeQ7afIA==",
"peer": true,
"dependencies": {
"@codemirror/autocomplete": "^6.0.3",
"@codemirror/autocomplete": "^6.1.1",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0",
"lezer-feel": "^0.4.0"
"lang-feel": "^0.0.3",
"lezer-feel": "^0.14.1",
"min-dom": "^4.0.1"
}
},
"node_modules/@bpmn-io/feel-editor/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
},
"node_modules/@bpmn-io/feel-editor/node_modules/min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"peer": true,
"dependencies": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
},
"node_modules/@bpmn-io/properties-panel": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-0.19.0.tgz",
"integrity": "sha512-cw+MfA2gpCBsa9Q0+JT3Gc7OvR1NGXuyQj4yOk5QoQHNzxuIMNuz6EX2NvDsCrf0oSzc9z0FapbzDuJB+DSC1g==",
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-0.23.0.tgz",
"integrity": "sha512-K/KHAf/XEhTPEeVmMdj9j6Al8XLz0eVdTBfKbyvAgSCbq4GVrEU/ylJVRyZo4KGRhj4O4AUo1zaal8pyhaAxdg==",
"peer": true,
"dependencies": {
"@bpmn-io/feel-editor": "0.2.0",
"@bpmn-io/feel-editor": "0.4.1",
"classnames": "^2.3.1",
"diagram-js": "^8.1.2",
"min-dash": "^3.7.0",
"min-dom": "^3.1.3"
"min-dash": "^4.0.0",
"min-dom": "^4.0.3"
}
},
"node_modules/@bpmn-io/properties-panel/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
},
"node_modules/@bpmn-io/properties-panel/node_modules/min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"peer": true,
"dependencies": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
},
"node_modules/@camunda/element-templates-json-schema": {
@ -2090,14 +2136,15 @@
"integrity": "sha512-sw8RNecjQgY7tX26PMLRJGNX/2QCnlwCvZfxQWh606qlJZsLbpvEbvfgIGCRoYlHYTlsP6PxVcWYx5LPo7yisg=="
},
"node_modules/@camunda/zeebe-element-templates-json-schema": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@camunda/zeebe-element-templates-json-schema/-/zeebe-element-templates-json-schema-0.5.0.tgz",
"integrity": "sha512-BVHVl4cuK9LxL1eDSdWs8AzuZd981/+CPkw7xlwcB1Xkn6Di8E2iRbDUCBhOIqkahjJYq957nVtbM6jlqXX5qw=="
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@camunda/zeebe-element-templates-json-schema/-/zeebe-element-templates-json-schema-0.6.0.tgz",
"integrity": "sha512-qawIFM52lp1hW2vWrHaX8ywguZsp2olE0DRTHUY+KWH5GwszZwGWECP3tji1KVih2TasQyf28kcQVh8TeQ6dAg=="
},
"node_modules/@codemirror/autocomplete": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.1.0.tgz",
"integrity": "sha512-wtO4O5WDyXhhCd4q4utDIDZxnQfmJ++3dGBCG9LMtI79+92OcA1DVk/n7BEupKmjIr8AzvptDz7YQ9ud6OkU+A==",
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.3.0.tgz",
"integrity": "sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==",
"peer": true,
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
@ -2112,9 +2159,10 @@
}
},
"node_modules/@codemirror/commands": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.0.tgz",
"integrity": "sha512-qCj2YqmbBjj0P1iumnlL5lBqZvJPzT+t2UvgjcaXErp5ZvMqFRVgQyrEfdXX6SX5UcvcHKBjXqno+MkUp0aYvQ==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.2.tgz",
"integrity": "sha512-sO3jdX1s0pam6lIdeSJLMN3DQ6mPEbM4yLvyKkdqtmd/UDwhXA5+AwFJ89rRXm6vTeOXBsE5cAmlos/t7MJdgg==",
"peer": true,
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
@ -2123,9 +2171,10 @@
}
},
"node_modules/@codemirror/language": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz",
"integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==",
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.3.0.tgz",
"integrity": "sha512-6jOE5DEt6sKD46SXhn3xPbBehn+l48ACcA6Uxs2k+E2YNH9XGF5WdGMTYr2DlggfK4h0QZBK6zEb5S7lkTriWA==",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@ -2139,6 +2188,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.0.0.tgz",
"integrity": "sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@ -2146,14 +2196,16 @@
}
},
"node_modules/@codemirror/state": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.1.tgz",
"integrity": "sha512-2s+aXsxmAwnR3Rd+JDHPG/1lw0YsA9PEwl7Re88gHJHGfxyfEzKBmsN4rr53RyPIR4lzbbhJX0DCq0WlqlBIRw=="
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz",
"integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==",
"peer": true
},
"node_modules/@codemirror/view": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.2.0.tgz",
"integrity": "sha512-3emW1symh+GoteFMBPsltjmF790U/trouLILATh3JodbF/z98HvcQh2g3+H6dfNIHx16uNonsAF4mNzVr1TJNA==",
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.4.0.tgz",
"integrity": "sha512-Kv32b6Tn7QVwFbj/EDswTLSocjk5kgggF6zzBFAL4o4hZ/vmtFD155+EjH1pVlbfoDyVC2M6SedPsMrwYscgNg==",
"peer": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"style-mod": "^4.0.0",
@ -4107,14 +4159,16 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
"node_modules/@lezer/common": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz",
"integrity": "sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA=="
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz",
"integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==",
"peer": true
},
"node_modules/@lezer/highlight": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.0.0.tgz",
"integrity": "sha512-nsCnNtim90UKsB5YxoX65v3GEIw3iCHw9RM2DtdgkiqAbKh9pCdvi8AWNwkYf10Lu6fxNhXPpkpHbW6mihhvJA==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.2.tgz",
"integrity": "sha512-CAun1WR1glxG9ZdOokTZwXbcwB7PXkIEyZRUMFBVwSrhTcogWq634/ByNImrkUnQhjju6xsIaOBIxvcRJtplXQ==",
"peer": true,
"dependencies": {
"@lezer/common": "^1.0.0"
}
@ -4123,6 +4177,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz",
"integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==",
"peer": true,
"dependencies": {
"@lezer/common": "^1.0.0"
}
@ -7192,42 +7247,58 @@
}
},
"node_modules/bpmn-js-properties-panel": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-1.5.0.tgz",
"integrity": "sha512-0VAPk6xK/u+GepjGjt8HAXtBa2ab5o4Dkn5II8UgnFMoQThpvrsLras3vh1il8j/2vPhngAsfiA8z7Y9nJ6/Hw==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-1.10.0.tgz",
"integrity": "sha512-Vu6YTS70zGS8aCGUuiABfR5JmpEpq2xZuQ1qGHMpwQcf2Mu7k7GXaaWlHv8qwzIBIPddpTdpWQJBvVMPBw834g==",
"dependencies": {
"@bpmn-io/element-templates-validator": "^0.9.0",
"@bpmn-io/extract-process-variables": "^0.5.0",
"@bpmn-io/element-templates-validator": "^0.11.0",
"@bpmn-io/extract-process-variables": "^0.6.0",
"array-move": "^3.0.1",
"classnames": "^2.3.1",
"ids": "^1.0.0",
"min-dash": "^3.8.1",
"min-dom": "^3.1.3",
"min-dash": "^4.0.0",
"min-dom": "^4.0.3",
"preact-markup": "^2.1.1",
"semver-compare": "^1.0.0"
},
"peerDependencies": {
"@bpmn-io/properties-panel": "0.19.x",
"bpmn-js": "8.x || 9.x",
"camunda-bpmn-js-behaviors": "0.1.x",
"diagram-js": "7.x || 8.x"
"@bpmn-io/properties-panel": ">= 0.21",
"bpmn-js": ">= 8",
"camunda-bpmn-js-behaviors": ">= 0.2",
"diagram-js": ">= 7"
}
},
"node_modules/bpmn-js-properties-panel/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
},
"node_modules/bpmn-js-properties-panel/node_modules/min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"dependencies": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
},
"node_modules/bpmn-js-spiffworkflow": {
"version": "0.0.8",
"resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#9c0da02406ecbc51cfd7fd1ed1f2f311101d9987",
"resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#999ea7e4c0e5157546625fbd7b1eb5cc8a79c0c0",
"license": "MIT",
"dependencies": {
"@bpmn-io/properties-panel": "^0.19.0",
"bpmn-js": "^9.4.0",
"bpmn-js-properties-panel": "^1.5.0",
"diagram-js": "^8.5.0",
"inherits": "^2.0.4",
"inherits-browser": "^0.0.1",
"min-dash": "^3.8.1",
"min-dom": "^3.2.1",
"moddle": "^5.0.3",
"tiny-svg": "^2.2.3"
},
"peerDependencies": {
"bpmn-js": "*",
"bpmn-js-properties-panel": "*",
"diagram-js": "*"
}
},
"node_modules/bpmn-moddle": {
@ -7581,32 +7652,31 @@
}
},
"node_modules/camunda-bpmn-js-behaviors": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-0.1.1.tgz",
"integrity": "sha512-8hRxOuOgd9fEWFZ7rfB+TpxYnXm9uGJ2xjmZdCUBSKqF8yEbtDPRO3/NUJIf1YT7iHK+lYJaG4S+wRbbZX7wEw==",
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-0.3.0.tgz",
"integrity": "sha512-isD424Lwgh4+v3IWDnqLkkA/oIQcwFHQ6TmxUYBNuF5WshO25a2u/6SgAtBiWpg2xqjD5x8zi5/0JWr/Yp7WEg==",
"peer": true,
"dependencies": {
"ids": "^1.0.0",
"min-dash": "^3.7.0"
"min-dash": "^4.0.0"
},
"peerDependencies": {
"bpmn-js": "9.x",
"camunda-bpmn-moddle": "6.x",
"zeebe-bpmn-moddle": "0.12.x"
"bpmn-js": ">= 9",
"camunda-bpmn-moddle": ">= 7",
"zeebe-bpmn-moddle": ">= 0.15"
}
},
"node_modules/camunda-bpmn-js-behaviors/node_modules/min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
},
"node_modules/camunda-bpmn-moddle": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/camunda-bpmn-moddle/-/camunda-bpmn-moddle-6.1.2.tgz",
"integrity": "sha512-DfhOTeq8oN01cB5sLE6Rq34/9xGD15/Y14pEM+YBIjgvV6Rclh+BgIa/2aRMm8An4Kc/itm2tECYiDr8p/FyTQ==",
"peer": true,
"dependencies": {
"min-dash": "^3.8.1"
},
"peerDependencies": {
"bpmn-js": "^6.x || ^7.x || ^8.x || ^9.x",
"diagram-js": "^5.x || ^6.x || ^7.x || ^8.x"
}
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/camunda-bpmn-moddle/-/camunda-bpmn-moddle-7.0.1.tgz",
"integrity": "sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==",
"peer": true
},
"node_modules/caniuse-api": {
"version": "3.0.0",
@ -8607,7 +8677,8 @@
"node_modules/crelt": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==",
"peer": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
@ -9589,16 +9660,17 @@
}
},
"node_modules/dmn-js-properties-panel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/dmn-js-properties-panel/-/dmn-js-properties-panel-1.1.0.tgz",
"integrity": "sha512-IclTOU4O3zTRPVvhgGl2TOayVUPPmGqHGyF/OwahE3qKwwMTqwfyZCE73bkqAiQbhunH6qjPWmGWE7vpH4OvVQ==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/dmn-js-properties-panel/-/dmn-js-properties-panel-1.2.1.tgz",
"integrity": "sha512-bHWH8z5v7KpjrJ/PJ/ZU/RDlZhEiFnxAOYSkjmmXDbpZ6FKmtTxcC/UenWmqFQhMoACxDHrmajt/owRHt8t3uw==",
"dependencies": {
"diagram-js": "^8.9.0",
"min-dash": "^3.8.1",
"min-dom": "^3.1.3"
},
"peerDependencies": {
"@bpmn-io/properties-panel": "0.11.x || 0.12.x || 0.13.x || 0.14.x || 0.15.x",
"dmn-js": "11.x || 12.x"
"@bpmn-io/properties-panel": ">=0.11.0 <=0.23.x",
"dmn-js": "11.x || 12.x || 13.x"
}
},
"node_modules/dmn-js-shared": {
@ -18012,6 +18084,20 @@
"node": ">= 8"
}
},
"node_modules/lang-feel": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/lang-feel/-/lang-feel-0.0.3.tgz",
"integrity": "sha512-YEs49jXQfLetXUr4Sj+pq9kcwHyNFcEYiXvm/bRvQyUwVfUEAHQdeFneqw+5zGeDuKDgIGxawXVs7uysXaLrjQ==",
"peer": true,
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0",
"lezer-feel": "^0.14.1"
}
},
"node_modules/language-subtag-registry": {
"version": "0.3.22",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
@ -18055,24 +18141,13 @@
}
},
"node_modules/lezer-feel": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-0.4.0.tgz",
"integrity": "sha512-yd+AWsOE4NGVeW4x50HXUA9dKs9MUa7H8PATPNEmBiXKfIijPlC6+FEy8OLjOzb4b9y9pPPpAqnZ2/kvLmvZVw==",
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-0.14.1.tgz",
"integrity": "sha512-sfpzZvAtObFon74XiFp1L8pS1FminnfM8JAm4S2Kxk7Wk8qYe7crjJdhHqju/MKl9dV5s44NHDhbq5tCDWMTlw==",
"peer": true,
"dependencies": {
"@lezer/lr": "^0.16.0"
}
},
"node_modules/lezer-feel/node_modules/@lezer/common": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
"integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA=="
},
"node_modules/lezer-feel/node_modules/@lezer/lr": {
"version": "0.16.3",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz",
"integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==",
"dependencies": {
"@lezer/common": "^0.16.0"
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.2.3"
}
},
"node_modules/lilconfig": {
@ -25390,7 +25465,8 @@
"node_modules/style-mod": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw=="
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
"peer": true
},
"node_modules/style-to-object": {
"version": "0.3.0",
@ -27895,7 +27971,8 @@
"node_modules/w3c-keyname": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg=="
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
"peer": true
},
"node_modules/w3c-xmlserializer": {
"version": "3.0.0",
@ -29309,9 +29386,9 @@
}
},
"node_modules/zeebe-bpmn-moddle": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-0.12.2.tgz",
"integrity": "sha512-5oMdxaApO3msNEP+RxVapyWxuIHBNwi9WTVoCV99x/SAEuCK+VDYZloa9MCG4DX3dbuXUWA0VpzP4YJ+oNTapg==",
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-0.15.0.tgz",
"integrity": "sha512-cgn6bjkjrtOGcRumrgWnT1J93wTKmnFlSGGuwGXjF7pOksPF28ssbKiwKVMU6IXHnBDIVLQdf8fVNZn7JiBtQQ==",
"peer": true
},
"node_modules/zwitch": {
@ -30649,49 +30726,104 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
},
"@bpmn-io/element-templates-validator": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/element-templates-validator/-/element-templates-validator-0.9.0.tgz",
"integrity": "sha512-oS5eaXPKxl5bV8x4dJYPCWJpWMumr16TTS39S1oJEh/bKke/nhMBuhsk6wWCp7+G3jWWDkUcS1jGAAaKtvQneA==",
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/element-templates-validator/-/element-templates-validator-0.11.0.tgz",
"integrity": "sha512-4eZCPLuWf1N4lL8jIKZjWgwLJ2IUTgkQ4VDnfbDiSvjGJqHaLA4XBcC5smvb8Q/MqsJFxWZumolJJb1h7gt39Q==",
"requires": {
"@camunda/element-templates-json-schema": "^0.10.0",
"@camunda/zeebe-element-templates-json-schema": "^0.5.0",
"@camunda/element-templates-json-schema": "^0.10.1",
"@camunda/zeebe-element-templates-json-schema": "^0.6.0",
"json-source-map": "^0.6.1",
"min-dash": "^3.8.1"
"min-dash": "^4.0.0"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
}
}
},
"@bpmn-io/extract-process-variables": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@bpmn-io/extract-process-variables/-/extract-process-variables-0.5.1.tgz",
"integrity": "sha512-Kx0zknI9GRli1EDkgmkUV34cKYsqppsgbcnfrSaT2Tmh7CGXEo8b6UzuGFlZtCZt4488UxjP7UhdrONTt5Si/A==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/extract-process-variables/-/extract-process-variables-0.6.0.tgz",
"integrity": "sha512-vq4jwGXDO11jwQgj9lvpVxVxjnRAz4C4TqPnhromcsllH5iRBrUNtBKgK0c/RWxiEGNTBhTYm19sP+LN1UcLWA==",
"requires": {
"min-dash": "^3.8.1"
"min-dash": "^4.0.0"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
}
}
},
"@bpmn-io/feel-editor": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-0.2.0.tgz",
"integrity": "sha512-R85p56nFxffNp0fStNxz561EXJmcTdVZL7NyVhuB3qKS/mt4thuvK1B43YnXKdLx8WessjsbHzjvWkbCYZRWkQ==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@bpmn-io/feel-editor/-/feel-editor-0.4.1.tgz",
"integrity": "sha512-+UGpofI09xGxs1Rr/1V3NLeNSfeKrIGcWvwDY5M3xb4tP6nOQfwqmQA1761Wni9fl3RuLzf6gOx7vGWeQ7afIA==",
"peer": true,
"requires": {
"@codemirror/autocomplete": "^6.0.3",
"@codemirror/autocomplete": "^6.1.1",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0",
"lezer-feel": "^0.4.0"
"lang-feel": "^0.0.3",
"lezer-feel": "^0.14.1",
"min-dom": "^4.0.1"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
},
"min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"peer": true,
"requires": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
}
}
},
"@bpmn-io/properties-panel": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-0.19.0.tgz",
"integrity": "sha512-cw+MfA2gpCBsa9Q0+JT3Gc7OvR1NGXuyQj4yOk5QoQHNzxuIMNuz6EX2NvDsCrf0oSzc9z0FapbzDuJB+DSC1g==",
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@bpmn-io/properties-panel/-/properties-panel-0.23.0.tgz",
"integrity": "sha512-K/KHAf/XEhTPEeVmMdj9j6Al8XLz0eVdTBfKbyvAgSCbq4GVrEU/ylJVRyZo4KGRhj4O4AUo1zaal8pyhaAxdg==",
"peer": true,
"requires": {
"@bpmn-io/feel-editor": "0.2.0",
"@bpmn-io/feel-editor": "0.4.1",
"classnames": "^2.3.1",
"diagram-js": "^8.1.2",
"min-dash": "^3.7.0",
"min-dom": "^3.1.3"
"min-dash": "^4.0.0",
"min-dom": "^4.0.3"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
},
"min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"peer": true,
"requires": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
}
}
},
"@camunda/element-templates-json-schema": {
@ -30700,14 +30832,15 @@
"integrity": "sha512-sw8RNecjQgY7tX26PMLRJGNX/2QCnlwCvZfxQWh606qlJZsLbpvEbvfgIGCRoYlHYTlsP6PxVcWYx5LPo7yisg=="
},
"@camunda/zeebe-element-templates-json-schema": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@camunda/zeebe-element-templates-json-schema/-/zeebe-element-templates-json-schema-0.5.0.tgz",
"integrity": "sha512-BVHVl4cuK9LxL1eDSdWs8AzuZd981/+CPkw7xlwcB1Xkn6Di8E2iRbDUCBhOIqkahjJYq957nVtbM6jlqXX5qw=="
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@camunda/zeebe-element-templates-json-schema/-/zeebe-element-templates-json-schema-0.6.0.tgz",
"integrity": "sha512-qawIFM52lp1hW2vWrHaX8ywguZsp2olE0DRTHUY+KWH5GwszZwGWECP3tji1KVih2TasQyf28kcQVh8TeQ6dAg=="
},
"@codemirror/autocomplete": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.1.0.tgz",
"integrity": "sha512-wtO4O5WDyXhhCd4q4utDIDZxnQfmJ++3dGBCG9LMtI79+92OcA1DVk/n7BEupKmjIr8AzvptDz7YQ9ud6OkU+A==",
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.3.0.tgz",
"integrity": "sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==",
"peer": true,
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
@ -30716,9 +30849,10 @@
}
},
"@codemirror/commands": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.0.tgz",
"integrity": "sha512-qCj2YqmbBjj0P1iumnlL5lBqZvJPzT+t2UvgjcaXErp5ZvMqFRVgQyrEfdXX6SX5UcvcHKBjXqno+MkUp0aYvQ==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.2.tgz",
"integrity": "sha512-sO3jdX1s0pam6lIdeSJLMN3DQ6mPEbM4yLvyKkdqtmd/UDwhXA5+AwFJ89rRXm6vTeOXBsE5cAmlos/t7MJdgg==",
"peer": true,
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
@ -30727,9 +30861,10 @@
}
},
"@codemirror/language": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz",
"integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==",
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.3.0.tgz",
"integrity": "sha512-6jOE5DEt6sKD46SXhn3xPbBehn+l48ACcA6Uxs2k+E2YNH9XGF5WdGMTYr2DlggfK4h0QZBK6zEb5S7lkTriWA==",
"peer": true,
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@ -30743,6 +30878,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.0.0.tgz",
"integrity": "sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==",
"peer": true,
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@ -30750,14 +30886,16 @@
}
},
"@codemirror/state": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.1.tgz",
"integrity": "sha512-2s+aXsxmAwnR3Rd+JDHPG/1lw0YsA9PEwl7Re88gHJHGfxyfEzKBmsN4rr53RyPIR4lzbbhJX0DCq0WlqlBIRw=="
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz",
"integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==",
"peer": true
},
"@codemirror/view": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.2.0.tgz",
"integrity": "sha512-3emW1symh+GoteFMBPsltjmF790U/trouLILATh3JodbF/z98HvcQh2g3+H6dfNIHx16uNonsAF4mNzVr1TJNA==",
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.4.0.tgz",
"integrity": "sha512-Kv32b6Tn7QVwFbj/EDswTLSocjk5kgggF6zzBFAL4o4hZ/vmtFD155+EjH1pVlbfoDyVC2M6SedPsMrwYscgNg==",
"peer": true,
"requires": {
"@codemirror/state": "^6.0.0",
"style-mod": "^4.0.0",
@ -32194,14 +32332,16 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
"@lezer/common": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz",
"integrity": "sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA=="
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz",
"integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==",
"peer": true
},
"@lezer/highlight": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.0.0.tgz",
"integrity": "sha512-nsCnNtim90UKsB5YxoX65v3GEIw3iCHw9RM2DtdgkiqAbKh9pCdvi8AWNwkYf10Lu6fxNhXPpkpHbW6mihhvJA==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.2.tgz",
"integrity": "sha512-CAun1WR1glxG9ZdOokTZwXbcwB7PXkIEyZRUMFBVwSrhTcogWq634/ByNImrkUnQhjju6xsIaOBIxvcRJtplXQ==",
"peer": true,
"requires": {
"@lezer/common": "^1.0.0"
}
@ -32210,6 +32350,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz",
"integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==",
"peer": true,
"requires": {
"@lezer/common": "^1.0.0"
}
@ -34516,29 +34657,42 @@
}
},
"bpmn-js-properties-panel": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-1.5.0.tgz",
"integrity": "sha512-0VAPk6xK/u+GepjGjt8HAXtBa2ab5o4Dkn5II8UgnFMoQThpvrsLras3vh1il8j/2vPhngAsfiA8z7Y9nJ6/Hw==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/bpmn-js-properties-panel/-/bpmn-js-properties-panel-1.10.0.tgz",
"integrity": "sha512-Vu6YTS70zGS8aCGUuiABfR5JmpEpq2xZuQ1qGHMpwQcf2Mu7k7GXaaWlHv8qwzIBIPddpTdpWQJBvVMPBw834g==",
"requires": {
"@bpmn-io/element-templates-validator": "^0.9.0",
"@bpmn-io/extract-process-variables": "^0.5.0",
"@bpmn-io/element-templates-validator": "^0.11.0",
"@bpmn-io/extract-process-variables": "^0.6.0",
"array-move": "^3.0.1",
"classnames": "^2.3.1",
"ids": "^1.0.0",
"min-dash": "^3.8.1",
"min-dom": "^3.1.3",
"min-dash": "^4.0.0",
"min-dom": "^4.0.3",
"preact-markup": "^2.1.1",
"semver-compare": "^1.0.0"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA=="
},
"min-dom": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/min-dom/-/min-dom-4.0.3.tgz",
"integrity": "sha512-5zQyCMe8rtGiDIRjfGeqnF2YPJ7OAPFdJQeC7MakHais3dh4VG4PV2a0FacziKTzJjYK5qnPKm2sq1wSXB1wTQ==",
"requires": {
"component-event": "^0.1.4",
"domify": "^1.4.1",
"min-dash": "^4.0.0"
}
}
}
},
"bpmn-js-spiffworkflow": {
"version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#9c0da02406ecbc51cfd7fd1ed1f2f311101d9987",
"version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#999ea7e4c0e5157546625fbd7b1eb5cc8a79c0c0",
"from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#main",
"requires": {
"@bpmn-io/properties-panel": "^0.19.0",
"bpmn-js": "^9.4.0",
"bpmn-js-properties-panel": "^1.5.0",
"diagram-js": "^8.5.0",
"inherits": "^2.0.4",
"inherits-browser": "^0.0.1",
"min-dash": "^3.8.1",
@ -34816,23 +34970,28 @@
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
},
"camunda-bpmn-js-behaviors": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-0.1.1.tgz",
"integrity": "sha512-8hRxOuOgd9fEWFZ7rfB+TpxYnXm9uGJ2xjmZdCUBSKqF8yEbtDPRO3/NUJIf1YT7iHK+lYJaG4S+wRbbZX7wEw==",
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/camunda-bpmn-js-behaviors/-/camunda-bpmn-js-behaviors-0.3.0.tgz",
"integrity": "sha512-isD424Lwgh4+v3IWDnqLkkA/oIQcwFHQ6TmxUYBNuF5WshO25a2u/6SgAtBiWpg2xqjD5x8zi5/0JWr/Yp7WEg==",
"peer": true,
"requires": {
"ids": "^1.0.0",
"min-dash": "^3.7.0"
"min-dash": "^4.0.0"
},
"dependencies": {
"min-dash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/min-dash/-/min-dash-4.0.0.tgz",
"integrity": "sha512-piIvVJ/nxuA4+LpnYIzF6oCtRvdtDvQJteSC+H768H2UvPKFKIt5oiJnUVtr0ZdchneXTcvUZ91vIrvWVIN0AA==",
"peer": true
}
}
},
"camunda-bpmn-moddle": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/camunda-bpmn-moddle/-/camunda-bpmn-moddle-6.1.2.tgz",
"integrity": "sha512-DfhOTeq8oN01cB5sLE6Rq34/9xGD15/Y14pEM+YBIjgvV6Rclh+BgIa/2aRMm8An4Kc/itm2tECYiDr8p/FyTQ==",
"peer": true,
"requires": {
"min-dash": "^3.8.1"
}
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/camunda-bpmn-moddle/-/camunda-bpmn-moddle-7.0.1.tgz",
"integrity": "sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==",
"peer": true
},
"caniuse-api": {
"version": "3.0.0",
@ -35618,7 +35777,8 @@
"crelt": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==",
"peer": true
},
"cross-spawn": {
"version": "7.0.3",
@ -36375,10 +36535,11 @@
}
},
"dmn-js-properties-panel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/dmn-js-properties-panel/-/dmn-js-properties-panel-1.1.0.tgz",
"integrity": "sha512-IclTOU4O3zTRPVvhgGl2TOayVUPPmGqHGyF/OwahE3qKwwMTqwfyZCE73bkqAiQbhunH6qjPWmGWE7vpH4OvVQ==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/dmn-js-properties-panel/-/dmn-js-properties-panel-1.2.1.tgz",
"integrity": "sha512-bHWH8z5v7KpjrJ/PJ/ZU/RDlZhEiFnxAOYSkjmmXDbpZ6FKmtTxcC/UenWmqFQhMoACxDHrmajt/owRHt8t3uw==",
"requires": {
"diagram-js": "^8.9.0",
"min-dash": "^3.8.1",
"min-dom": "^3.1.3"
}
@ -42718,6 +42879,20 @@
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz",
"integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ=="
},
"lang-feel": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/lang-feel/-/lang-feel-0.0.3.tgz",
"integrity": "sha512-YEs49jXQfLetXUr4Sj+pq9kcwHyNFcEYiXvm/bRvQyUwVfUEAHQdeFneqw+5zGeDuKDgIGxawXVs7uysXaLrjQ==",
"peer": true,
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0",
"lezer-feel": "^0.14.1"
}
},
"language-subtag-registry": {
"version": "0.3.22",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
@ -42752,26 +42927,13 @@
}
},
"lezer-feel": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-0.4.0.tgz",
"integrity": "sha512-yd+AWsOE4NGVeW4x50HXUA9dKs9MUa7H8PATPNEmBiXKfIijPlC6+FEy8OLjOzb4b9y9pPPpAqnZ2/kvLmvZVw==",
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/lezer-feel/-/lezer-feel-0.14.1.tgz",
"integrity": "sha512-sfpzZvAtObFon74XiFp1L8pS1FminnfM8JAm4S2Kxk7Wk8qYe7crjJdhHqju/MKl9dV5s44NHDhbq5tCDWMTlw==",
"peer": true,
"requires": {
"@lezer/lr": "^0.16.0"
},
"dependencies": {
"@lezer/common": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.1.tgz",
"integrity": "sha512-qPmG7YTZ6lATyTOAWf8vXE+iRrt1NJd4cm2nJHK+v7X9TsOF6+HtuU/ctaZy2RCrluxDb89hI6KWQ5LfQGQWuA=="
},
"@lezer/lr": {
"version": "0.16.3",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz",
"integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==",
"requires": {
"@lezer/common": "^0.16.0"
}
}
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.2.3"
}
},
"lilconfig": {
@ -48001,7 +48163,8 @@
"style-mod": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw=="
"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
"peer": true
},
"style-to-object": {
"version": "0.3.0",
@ -49919,7 +50082,8 @@
"w3c-keyname": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg=="
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
"peer": true
},
"w3c-xmlserializer": {
"version": "3.0.0",
@ -51039,9 +51203,9 @@
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
},
"zeebe-bpmn-moddle": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-0.12.2.tgz",
"integrity": "sha512-5oMdxaApO3msNEP+RxVapyWxuIHBNwi9WTVoCV99x/SAEuCK+VDYZloa9MCG4DX3dbuXUWA0VpzP4YJ+oNTapg==",
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/zeebe-bpmn-moddle/-/zeebe-bpmn-moddle-0.15.0.tgz",
"integrity": "sha512-cgn6bjkjrtOGcRumrgWnT1J93wTKmnFlSGGuwGXjF7pOksPF28ssbKiwKVMU6IXHnBDIVLQdf8fVNZn7JiBtQQ==",
"peer": true
},
"zwitch": {

View File

@ -6,7 +6,6 @@
"@babel/core": "^7.18.10",
"@babel/plugin-transform-react-jsx": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@bpmn-io/properties-panel": "^0.19.0",
"@ginkgo-bioworks/react-json-schema-form-builder": "^2.9.0",
"@monaco-editor/react": "^4.4.5",
"@rjsf/core": "^4.2.0",
@ -22,13 +21,13 @@
"axios": "^0.27.2",
"bootstrap": "^5.2.0",
"bpmn-js": "^9.3.2",
"bpmn-js-properties-panel": "^1.5.0",
"bpmn-js-properties-panel": "^1.10.0",
"bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#main",
"craco": "^0.0.3",
"date-fns": "^2.28.0",
"diagram-js": "^8.5.0",
"dmn-js": "^12.2.0",
"dmn-js-properties-panel": "^1.1.0",
"dmn-js-properties-panel": "^1.1",
"dmn-js-shared": "^12.1.1",
"jwt-decode": "^3.1.2",
"keycloak-js": "^18.0.1",
@ -56,9 +55,6 @@
"@ginkgo-bioworks/react-json-schema-form-builder": {
"react": "^18.2.0",
"bootstrap": "^5.2.0-beta1"
},
"dmn-js-properties-panel": {
"@bpmn-io/properties-panel": "^0.19.0"
}
},
"scripts": {

View File

@ -177,11 +177,16 @@ export default function ReactDiagramEditor({
});
}
function handleLaunchScriptEditor(element: any) {
function handleLaunchScriptEditor(
element: any,
script: string,
scriptType: string,
eventBus: any
) {
if (onLaunchScriptEditor) {
setPerformingXmlUpdates(true);
const modeling = diagramModeler.get('modeling');
onLaunchScriptEditor(element, modeling);
onLaunchScriptEditor(element, script, scriptType, eventBus, modeling);
}
}
@ -199,12 +204,12 @@ export default function ReactDiagramEditor({
setDiagramModelerState(diagramModeler);
diagramModeler.on('launch.script.editor', (event: any) => {
const { error, element } = event;
diagramModeler.on('script.editor.launch', (event: any) => {
const { error, element, scriptType, script, eventBus } = event;
if (error) {
console.log(error);
}
handleLaunchScriptEditor(element);
handleLaunchScriptEditor(element, script, scriptType, eventBus);
});
// 'element.hover',

View File

@ -1,4 +1,5 @@
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import Editor from '@monaco-editor/react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { Button, Modal, Stack } from 'react-bootstrap';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
@ -6,6 +7,7 @@ import HttpService from '../services/HttpService';
import ReactDiagramEditor from '../components/ReactDiagramEditor';
import { convertSecondsToFormattedDate } from '../helpers';
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
import ErrorContext from '../contexts/ErrorContext';
export default function ProcessInstanceShow() {
const navigate = useNavigate();
@ -14,6 +16,10 @@ export default function ProcessInstanceShow() {
const [processInstance, setProcessInstance] = useState(null);
const [tasks, setTasks] = useState<Array<object> | null>(null);
const [taskToDisplay, setTaskToDisplay] = useState<object | null>(null);
const [taskDataToDisplay, setTaskDataToDisplay] = useState<string>('');
const [editingTaskData, setEditingTaskData] = useState<boolean>(false);
const setErrorMessage = (useContext as any)(ErrorContext)[1];
const navigateToProcessInstances = (_result: any) => {
navigate(
@ -168,19 +174,29 @@ export default function ProcessInstanceShow() {
return <div />;
};
const initializeTaskDataToDisplay = (task: any) => {
if (task == null) {
setTaskDataToDisplay('');
} else {
setTaskDataToDisplay(JSON.stringify(task.data, null, 2));
}
};
const handleClickedDiagramTask = (shapeElement: any) => {
if (tasks) {
const matchingTask = tasks.find(
const matchingTask: any = tasks.find(
(task: any) => task.name === shapeElement.id
);
if (matchingTask) {
setTaskToDisplay(matchingTask);
initializeTaskDataToDisplay(matchingTask);
}
}
};
const handleTaskDataDisplayClose = () => {
setTaskToDisplay(null);
initializeTaskDataToDisplay(null);
};
const getTaskById = (taskId: string) => {
@ -211,29 +227,127 @@ export default function ProcessInstanceShow() {
}
};
const taskDataDisplayArea = () => {
const taskToUse: any = taskToDisplay;
if (taskToDisplay) {
let createScriptUnitTestElement = null;
if (taskToUse.type === 'Script Task') {
createScriptUnitTestElement = (
const canEditTaskData = (task: any) => {
return task.state === 'READY';
};
const cancelEditingTaskData = () => {
setEditingTaskData(false);
initializeTaskDataToDisplay(taskToDisplay);
setErrorMessage(null);
};
const taskDataStringToObject = (dataString: string) => {
return JSON.parse(dataString);
};
const saveTaskDataResult = (_: any) => {
setEditingTaskData(false);
const dataObject = taskDataStringToObject(taskDataToDisplay);
const taskToDisplayCopy = { ...taskToDisplay, data: dataObject }; // spread operator
setTaskToDisplay(taskToDisplayCopy);
refreshPage();
};
const saveTaskDataFailure = (result: any) => {
setErrorMessage({ message: result.toString() });
};
const saveTaskData = () => {
if (!taskToDisplay) {
return;
}
setErrorMessage(null);
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay };
HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/task/${taskToUse.id}/update`,
httpMethod: 'POST',
successCallback: saveTaskDataResult,
failureCallback: saveTaskDataFailure,
postBody: {
new_task_data: taskToUse.data,
},
});
};
const taskDataButtons = (task: any) => {
const buttons = [];
if (task.type === 'Script Task') {
buttons.push(
<Button
data-qa="create-script-unit-test-button"
onClick={createScriptUnitTest}
>
Create Script Unit Test
</Button>
);
}
if (canEditTaskData(task)) {
if (editingTaskData) {
buttons.push(
<Button
data-qa="create-script-unit-test-button"
onClick={createScriptUnitTest}
onClick={saveTaskData}
>
Create Script Unit Test
Save
</Button>
);
buttons.push(
<Button
data-qa="create-script-unit-test-button"
onClick={cancelEditingTaskData}
>
Cancel
</Button>
);
} else {
buttons.push(
<Button
data-qa="create-script-unit-test-button"
onClick={() => setEditingTaskData(true)}
>
Edit
</Button>
);
}
}
return buttons;
};
const taskDataContainer = () => {
return editingTaskData ? (
<Editor
height={600}
width="auto"
defaultLanguage="json"
defaultValue={taskDataToDisplay}
onChange={(value) => setTaskDataToDisplay(value || '')}
/>
) : (
<pre>{taskDataToDisplay}</pre>
);
};
const taskDataDisplayArea = () => {
const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay };
if (taskToDisplay) {
return (
<Modal show={!!taskToUse} onHide={handleTaskDataDisplayClose}>
<Modal.Header closeButton>
<Modal.Title>
{taskToUse.name} ({taskToUse.type}): {taskToUse.state}
{createScriptUnitTestElement}
<Stack direction="horizontal" gap={2}>
{taskToUse.name} ({taskToUse.type}): {taskToUse.state}
{taskDataButtons(taskToUse)}
</Stack>
</Modal.Title>
</Modal.Header>
<pre>{JSON.stringify(taskToUse.data, null, 2)}</pre>
{taskDataContainer()}
</Modal>
);
}

View File

@ -18,7 +18,9 @@ export default function ProcessModelEditDiagram() {
const [showFileNameEditor, setShowFileNameEditor] = useState(false);
const handleShowFileNameEditor = () => setShowFileNameEditor(true);
const [scriptText, setScriptText] = useState('');
const [scriptText, setScriptText] = useState<string>('');
const [scriptType, setScriptType] = useState<string>('');
const [scriptEventBus, setScriptEventBus] = useState<any>(null);
const [scriptModeling, setScriptModeling] = useState(null);
const [scriptElement, setScriptElement] = useState(null);
const [showScriptEditor, setShowScriptEditor] = useState(false);
@ -275,25 +277,39 @@ export default function ProcessModelEditDiagram() {
}
};
const onLaunchScriptEditor = (element: any, modeling: any) => {
setScriptText(element.businessObject.script || '');
const onLaunchScriptEditor = (
element: any,
script: string,
scriptTypeString: string,
eventBus: any,
modeling: any
) => {
// TODO: modeling is only needed for script unit tests.
// we should update this to act like updating scripts
// where we pass an event to bpmn-js
setScriptModeling(modeling);
setScriptText(script || '');
setScriptType(scriptTypeString);
setScriptEventBus(eventBus);
setScriptElement(element);
setScriptUnitTestElementWithIndex(0, element);
handleShowScriptEditor();
};
const handleScriptEditorClose = () => {
scriptEventBus.fire('script.editor.update', {
scriptType,
script: scriptText,
element: scriptElement,
});
resetUnitTextResult();
setShowScriptEditor(false);
};
const handleEditorScriptChange = (value: any) => {
setScriptText(value);
(scriptModeling as any).updateProperties(scriptElement, {
scriptFormat: 'python',
script: value,
});
};
const handleEditorScriptTestUnitInputChange = (value: any) => {

View File

@ -20,13 +20,14 @@ export default function TaskShow() {
HttpService.makeCallToBackend({
path: `/tasks/${params.process_instance_id}/${params.task_id}`,
successCallback: setTask,
failureCallback: setErrorMessage,
// This causes the page to continuously reload
// failureCallback: setErrorMessage,
});
HttpService.makeCallToBackend({
path: `/process-instance/${params.process_instance_id}/tasks`,
successCallback: setUserTasks,
});
}, [params, setErrorMessage]);
}, [params]);
const processSubmitResult = (result: any) => {
setErrorMessage(null);
@ -143,7 +144,7 @@ export default function TaskShow() {
const instructionsElement = (taskToUse: any) => {
let instructions = '';
if (taskToUse.type === 'Manual Task') {
if (taskToUse.properties.instructionsForEndUser) {
instructions = taskToUse.properties.instructionsForEndUser;
}
return (