Merge branch 'main' into feature/nested-groups-2

# Conflicts:
#	spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
#	spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py
#	spiffworkflow-frontend/src/components/ProcessModelForm.tsx
#	spiffworkflow-frontend/src/helpers.tsx
This commit is contained in:
mike cullerton 2022-11-09 16:49:15 -05:00
commit bd586f6a43
73 changed files with 1031 additions and 1240 deletions

1
.tool-versions Normal file
View File

@ -0,0 +1 @@
python 3.11.0

View File

@ -1,16 +1,19 @@
# .readthedocs.yaml # .readthedocs.yaml
# Read the Docs configuration file # Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
build: build:
image: latest os: ubuntu-20.04
tools:
python: "3.10"
# Optionally build your docs in additional formats such as PDF # Optionally build your docs in additional formats such as PDF
formats: [] formats: []
python: python:
pip_install: true install:
version: 3.10 - method: pip
extra_requirements: path: .
extra_requirements:
- docs - docs

View File

@ -1 +1 @@
python 3.10.4 python 3.11.0

View File

@ -46,9 +46,9 @@ export function SpiffExtensionSelect(props) {
if ( if (
!(optionType in spiffExtensionOptions) || !(optionType in spiffExtensionOptions) ||
spiffExtensionOptions[optionType].length === 0 spiffExtensionOptions[optionType] === null
) { ) {
spiffExtensionOptions[optionType] = []; spiffExtensionOptions[optionType] = null;
requestOptions(eventBus, element, commandStack, optionType); requestOptions(eventBus, element, commandStack, optionType);
} }
const getOptions = () => { const getOptions = () => {

View File

@ -33,23 +33,21 @@ describe('Business Rule Properties Panel', function () {
}) })
); );
function addOptionsToEventBus(bpmnModeler) {
bpmnModeler.on('spiff.dmn_files.requested', (event) => { const return_files = (event) => {
event.eventBus.fire('spiff.dmn_files.returned', { event.eventBus.fire('spiff.dmn_files.returned', {
options: [ options: [
{ label: 'Calculate Pizza Price', value: 'Decision_Pizza_Price' }, { label: 'Calculate Pizza Price', value: 'Decision_Pizza_Price' },
{ label: 'Viking Availability', value: 'Decision_Vikings' }, { label: 'Viking Availability', value: 'Decision_Vikings' },
{ label: 'Test Decision', value: 'test_decision' }, { label: 'Test Decision', value: 'test_decision' },
], ],
});
}); });
} }
it('should display a dropdown to select from available decision tables', async function () { it('should display a dropdown to select from available decision tables', async function () {
const modeler = getBpmnJS(); const modeler = getBpmnJS();
addOptionsToEventBus(modeler); modeler.get('eventBus').once('spiff.dmn_files.requested', return_files);
expectSelected('business_rule_task'); expectSelected('business_rule_task');
// THEN - a properties panel exists with a section for editing that script // THEN - a properties panel exists with a section for editing that script
const entry = findEntry('extension_spiffworkflow:calledDecisionId', getPropertiesPanel()); const entry = findEntry('extension_spiffworkflow:calledDecisionId', getPropertiesPanel());
expect(entry, 'No Entry').to.exist; expect(entry, 'No Entry').to.exist;
@ -60,7 +58,7 @@ describe('Business Rule Properties Panel', function () {
it('should update the spiffworkflow:calledDecisionId tag when you modify the called decision select box', async function () { it('should update the spiffworkflow:calledDecisionId tag when you modify the called decision select box', async function () {
// IF - a script tag is selected, and you change the script in the properties panel // IF - a script tag is selected, and you change the script in the properties panel
const modeler = getBpmnJS(); const modeler = getBpmnJS();
addOptionsToEventBus(modeler); modeler.get('eventBus').once('spiff.dmn_files.requested', return_files);
const businessRuleTask = await expectSelected('business_rule_task'); const businessRuleTask = await expectSelected('business_rule_task');
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel()); const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
const selectList = findSelect(entry); const selectList = findSelect(entry);
@ -85,4 +83,5 @@ describe('Business Rule Properties Panel', function () {
const element = businessObject.extensionElements.values[0]; const element = businessObject.extensionElements.values[0];
expect(element.value).to.equal('test_decision'); expect(element.value).to.equal('test_decision');
}); });
}); });

View File

@ -1,5 +1,5 @@
pip==22.3 pip==22.3.1
nox==2022.8.7 nox==2022.8.7
nox-poetry==1.0.1 nox-poetry==1.0.2
poetry==1.2.2 poetry==1.2.2
virtualenv==20.16.6 virtualenv==20.16.6

View File

@ -1 +1 @@
python 3.10.4 python 3.11.0

382
flask-bpmn/poetry.lock generated
View File

@ -93,17 +93,6 @@ python-versions = ">=3.6"
[package.dependencies] [package.dependencies]
pytz = ">=2015.7" pytz = ">=2015.7"
[[package]]
name = "backports.zoneinfo"
version = "0.2.1"
description = "Backport of the standard library zoneinfo module"
category = "main"
optional = false
python-versions = ">=3.6"
[package.extras]
tzdata = ["tzdata"]
[[package]] [[package]]
name = "bandit" name = "bandit"
version = "1.7.2" version = "1.7.2"
@ -390,25 +379,6 @@ category = "dev"
optional = false optional = false
python-versions = ">=3.6,<4.0" python-versions = ">=3.6,<4.0"
[[package]]
name = "dateparser"
version = "1.1.1"
description = "Date parsing library designed to parse dates from HTML pages"
category = "main"
optional = false
python-versions = ">=3.5"
[package.dependencies]
python-dateutil = "*"
pytz = "*"
regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27,<2022.3.15"
tzlocal = "*"
[package.extras]
calendars = ["convertdate", "convertdate", "hijri-converter"]
fasttext = ["fasttext"]
langdetect = ["langdetect"]
[[package]] [[package]]
name = "distlib" name = "distlib"
version = "0.3.4" version = "0.3.4"
@ -704,14 +674,15 @@ typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""
[[package]] [[package]]
name = "greenlet" name = "greenlet"
version = "1.1.2" version = "2.0.1"
description = "Lightweight in-process concurrent programming" description = "Lightweight in-process concurrent programming"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
[package.extras] [package.extras]
docs = ["Sphinx"] docs = ["Sphinx", "docutils (<0.18)"]
test = ["faulthandler", "objgraph", "psutil"]
[[package]] [[package]]
name = "identify" name = "identify"
@ -945,7 +916,7 @@ mypy-extensions = "*"
[[package]] [[package]]
name = "mypy" name = "mypy"
version = "0.982" version = "0.990"
description = "Optional static typing for Python" description = "Optional static typing for Python"
category = "dev" category = "dev"
optional = false optional = false
@ -959,6 +930,7 @@ typing-extensions = ">=3.10"
[package.extras] [package.extras]
dmypy = ["psutil (>=4.0)"] dmypy = ["psutil (>=4.0)"]
install-types = ["pip"]
python2 = ["typed-ast (>=1.4.0,<2)"] python2 = ["typed-ast (>=1.4.0,<2)"]
reports = ["lxml"] reports = ["lxml"]
@ -1173,17 +1145,6 @@ toml = "*"
[package.extras] [package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
[package.dependencies]
six = ">=1.5"
[[package]] [[package]]
name = "pytz" name = "pytz"
version = "2022.1" version = "2022.1"
@ -1192,18 +1153,6 @@ category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "pytz-deprecation-shim"
version = "0.1.0.post0"
description = "Shims to make deprecation of pytz easier"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
[package.dependencies]
"backports.zoneinfo" = {version = "*", markers = "python_version >= \"3.6\" and python_version < \"3.9\""}
tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]] [[package]]
name = "pyupgrade" name = "pyupgrade"
version = "3.2.0" version = "3.2.0"
@ -1223,14 +1172,6 @@ category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "regex"
version = "2022.3.2"
description = "Alternative regular expression module, to replace re."
category = "main"
optional = false
python-versions = ">=3.6"
[[package]] [[package]]
name = "reorder-python-imports" name = "reorder-python-imports"
version = "3.9.0" version = "3.9.0"
@ -1560,7 +1501,7 @@ test = ["pytest"]
[[package]] [[package]]
name = "SpiffWorkflow" name = "SpiffWorkflow"
version = "1.2.1" version = "1.2.1"
description = "" description = "A workflow framework and BPMN/DMN Processor"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
@ -1569,16 +1510,14 @@ develop = false
[package.dependencies] [package.dependencies]
celery = "*" celery = "*"
configparser = "*" configparser = "*"
dateparser = "*"
importlib-metadata = {version = "<5.0", markers = "python_version <= \"3.7\""} importlib-metadata = {version = "<5.0", markers = "python_version <= \"3.7\""}
lxml = "*" lxml = "*"
pytz = "*"
[package.source] [package.source]
type = "git" type = "git"
url = "https://github.com/sartography/SpiffWorkflow" url = "https://github.com/sartography/SpiffWorkflow"
reference = "main" reference = "main"
resolved_reference = "5cdb881edc4621502bfd61ce67565cf1148199f0" resolved_reference = "580939cc8cb0b7ade1571483bd1e28f554434ac4"
[[package]] [[package]]
name = "sqlalchemy" name = "sqlalchemy"
@ -1697,31 +1636,6 @@ python-versions = "*"
mypy-extensions = ">=0.3.0" mypy-extensions = ">=0.3.0"
typing-extensions = ">=3.7.4" typing-extensions = ">=3.7.4"
[[package]]
name = "tzdata"
version = "2022.2"
description = "Provider of IANA time zone data"
category = "main"
optional = false
python-versions = ">=2"
[[package]]
name = "tzlocal"
version = "4.2"
description = "tzinfo object for the local timezone"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""}
pytz-deprecation-shim = "*"
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"]
[[package]] [[package]]
name = "unidecode" name = "unidecode"
version = "1.3.4" version = "1.3.4"
@ -1853,7 +1767,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.7" python-versions = "^3.7"
content-hash = "7d1d5e13f2546566277c6f0b5935753c89804db2abb7a1e76498b582f40f9a01" content-hash = "a92b31afb86b91dba0101ae04a6e4cbc5b7bed657f422d53f417fac969e7552f"
[metadata.files] [metadata.files]
alabaster = [ alabaster = [
@ -1888,24 +1802,6 @@ babel = [
{file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"}, {file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"},
{file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"}, {file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"},
] ]
"backports.zoneinfo" = [
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"},
{file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"},
]
bandit = [ bandit = [
{file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"},
{file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"},
@ -2113,10 +2009,6 @@ darglint = [
{file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"},
{file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
] ]
dateparser = [
{file = "dateparser-1.1.1-py2.py3-none-any.whl", hash = "sha256:9600874312ff28a41f96ec7ccdc73be1d1c44435719da47fea3339d55ff5a628"},
{file = "dateparser-1.1.1.tar.gz", hash = "sha256:038196b1f12c7397e38aad3d61588833257f6f552baa63a1499e6987fa8d42d9"},
]
distlib = [ distlib = [
{file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
@ -2203,61 +2095,63 @@ gitpython = [
{file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"}, {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"},
] ]
greenlet = [ greenlet = [
{file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, {file = "greenlet-2.0.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c"},
{file = "greenlet-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a"}, {file = "greenlet-2.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515"},
{file = "greenlet-1.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d"}, {file = "greenlet-2.0.1-cp27-cp27m-win32.whl", hash = "sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a"},
{file = "greenlet-1.1.2-cp27-cp27m-win32.whl", hash = "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713"}, {file = "greenlet-2.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524"},
{file = "greenlet-1.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40"}, {file = "greenlet-2.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243"},
{file = "greenlet-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d"}, {file = "greenlet-2.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26"},
{file = "greenlet-1.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd"},
{file = "greenlet-1.1.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45"},
{file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da"},
{file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1"}, {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d"},
{file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58"}, {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"},
{file = "greenlet-1.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965"}, {file = "greenlet-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617"},
{file = "greenlet-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708"}, {file = "greenlet-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9"},
{file = "greenlet-1.1.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94"},
{file = "greenlet-1.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a"},
{file = "greenlet-1.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce"},
{file = "greenlet-1.1.2-cp35-cp35m-win32.whl", hash = "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963"}, {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72"},
{file = "greenlet-1.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e"}, {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82"},
{file = "greenlet-1.1.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073"}, {file = "greenlet-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd"},
{file = "greenlet-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c"}, {file = "greenlet-2.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f"},
{file = "greenlet-1.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e"}, {file = "greenlet-2.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f"},
{file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce"}, {file = "greenlet-2.0.1-cp35-cp35m-win32.whl", hash = "sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955"},
{file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08"}, {file = "greenlet-2.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77"},
{file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168"}, {file = "greenlet-2.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581"},
{file = "greenlet-1.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9"},
{file = "greenlet-1.1.2-cp36-cp36m-win32.whl", hash = "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51"},
{file = "greenlet-1.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148"},
{file = "greenlet-1.1.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2"},
{file = "greenlet-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"}, {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39"},
{file = "greenlet-1.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c"}, {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92"},
{file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1"}, {file = "greenlet-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928"},
{file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28"}, {file = "greenlet-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd"},
{file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5"}, {file = "greenlet-2.0.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963"},
{file = "greenlet-1.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5"},
{file = "greenlet-1.1.2-cp37-cp37m-win32.whl", hash = "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"},
{file = "greenlet-1.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"},
{file = "greenlet-1.1.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"},
{file = "greenlet-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627"}, {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"},
{file = "greenlet-1.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478"}, {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"},
{file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43"}, {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"},
{file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711"}, {file = "greenlet-2.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d"},
{file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68"},
{file = "greenlet-1.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"},
{file = "greenlet-1.1.2-cp38-cp38-win32.whl", hash = "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"},
{file = "greenlet-1.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"},
{file = "greenlet-1.1.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67"}, {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"},
{file = "greenlet-1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab"}, {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"},
{file = "greenlet-1.1.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5"}, {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"},
{file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88"}, {file = "greenlet-2.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb"},
{file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19"},
{file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"},
{file = "greenlet-1.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"},
{file = "greenlet-1.1.2-cp39-cp39-win32.whl", hash = "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"},
{file = "greenlet-1.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd"}, {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"},
{file = "greenlet-1.1.2.tar.gz", hash = "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a"}, {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"},
{file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"},
{file = "greenlet-2.0.1.tar.gz", hash = "sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67"},
] ]
identify = [ identify = [
{file = "identify-2.5.0-py2.py3-none-any.whl", hash = "sha256:3acfe15a96e4272b4ec5662ee3e231ceba976ef63fd9980ed2ce9cc415df393f"}, {file = "identify-2.5.0-py2.py3-none-any.whl", hash = "sha256:3acfe15a96e4272b4ec5662ee3e231ceba976ef63fd9980ed2ce9cc415df393f"},
@ -2494,30 +2388,36 @@ monkeytype = [
{file = "MonkeyType-22.2.0.tar.gz", hash = "sha256:6b0c00b49dcc5095a2c08d28246cf005e05673fc51f64d203f9a6bca2036dfab"}, {file = "MonkeyType-22.2.0.tar.gz", hash = "sha256:6b0c00b49dcc5095a2c08d28246cf005e05673fc51f64d203f9a6bca2036dfab"},
] ]
mypy = [ mypy = [
{file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, {file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"},
{file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, {file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"},
{file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, {file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"},
{file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, {file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"},
{file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, {file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"},
{file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, {file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"},
{file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, {file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"},
{file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, {file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"},
{file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, {file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"},
{file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, {file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"},
{file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, {file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"},
{file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, {file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"},
{file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, {file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"},
{file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, {file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"},
{file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, {file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"},
{file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, {file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"},
{file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, {file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"},
{file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, {file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"},
{file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, {file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"},
{file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, {file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"},
{file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, {file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"},
{file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, {file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"},
{file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, {file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"},
{file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, {file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"},
{file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"},
{file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"},
{file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"},
{file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"},
{file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"},
{file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"},
] ]
mypy-extensions = [ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
@ -2595,18 +2495,10 @@ pytest = [
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
{file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
] ]
python-dateutil = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
pytz = [ pytz = [
{file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
{file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
] ]
pytz-deprecation-shim = [
{file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"},
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
]
pyupgrade = [ pyupgrade = [
{file = "pyupgrade-3.2.0-py2.py3-none-any.whl", hash = "sha256:2aa6c40e49ea5a350e6e45b8c7847b1741aef274a35d4f0b2bf91731ec8ab796"}, {file = "pyupgrade-3.2.0-py2.py3-none-any.whl", hash = "sha256:2aa6c40e49ea5a350e6e45b8c7847b1741aef274a35d4f0b2bf91731ec8ab796"},
{file = "pyupgrade-3.2.0.tar.gz", hash = "sha256:70e1ac1e6b34a90fb21f5cada1907ef035b12dfc1d9f13cefd367acf3b530310"}, {file = "pyupgrade-3.2.0.tar.gz", hash = "sha256:70e1ac1e6b34a90fb21f5cada1907ef035b12dfc1d9f13cefd367acf3b530310"},
@ -2653,82 +2545,6 @@ pyyaml = [
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
] ]
regex = [
{file = "regex-2022.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab69b4fe09e296261377d209068d52402fb85ef89dc78a9ac4a29a895f4e24a7"},
{file = "regex-2022.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5bc5f921be39ccb65fdda741e04b2555917a4bced24b4df14eddc7569be3b493"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43eba5c46208deedec833663201752e865feddc840433285fbadee07b84b464d"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c68d2c04f7701a418ec2e5631b7f3552efc32f6bcc1739369c6eeb1af55f62e0"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:caa2734ada16a44ae57b229d45091f06e30a9a52ace76d7574546ab23008c635"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef806f684f17dbd6263d72a54ad4073af42b42effa3eb42b877e750c24c76f86"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be319f4eb400ee567b722e9ea63d5b2bb31464e3cf1b016502e3ee2de4f86f5c"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:42bb37e2b2d25d958c25903f6125a41aaaa1ed49ca62c103331f24b8a459142f"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fbc88d3ba402b5d041d204ec2449c4078898f89c4a6e6f0ed1c1a510ef1e221d"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:91e0f7e7be77250b808a5f46d90bf0032527d3c032b2131b63dee54753a4d729"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:cb3652bbe6720786b9137862205986f3ae54a09dec8499a995ed58292bdf77c2"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:878c626cbca3b649e14e972c14539a01191d79e58934e3f3ef4a9e17f90277f8"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6df070a986fc064d865c381aecf0aaff914178fdf6874da2f2387e82d93cc5bd"},
{file = "regex-2022.3.2-cp310-cp310-win32.whl", hash = "sha256:b549d851f91a4efb3e65498bd4249b1447ab6035a9972f7fc215eb1f59328834"},
{file = "regex-2022.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:8babb2b5751105dc0aef2a2e539f4ba391e738c62038d8cb331c710f6b0f3da7"},
{file = "regex-2022.3.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1977bb64264815d3ef016625adc9df90e6d0e27e76260280c63eca993e3f455f"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e73652057473ad3e6934944af090852a02590c349357b79182c1b681da2c772"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b22ff939a8856a44f4822da38ef4868bd3a9ade22bb6d9062b36957c850e404f"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:878f5d649ba1db9f52cc4ef491f7dba2d061cdc48dd444c54260eebc0b1729b9"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0008650041531d0eadecc96a73d37c2dc4821cf51b0766e374cb4f1ddc4e1c14"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:06b1df01cf2aef3a9790858af524ae2588762c8a90e784ba00d003f045306204"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57484d39447f94967e83e56db1b1108c68918c44ab519b8ecfc34b790ca52bf7"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:74d86e8924835f863c34e646392ef39039405f6ce52956d8af16497af4064a30"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:ae17fc8103f3b63345709d3e9654a274eee1c6072592aec32b026efd401931d0"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5f92a7cdc6a0ae2abd184e8dfd6ef2279989d24c85d2c85d0423206284103ede"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:5dcc4168536c8f68654f014a3db49b6b4a26b226f735708be2054314ed4964f4"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:1e30762ddddb22f7f14c4f59c34d3addabc789216d813b0f3e2788d7bcf0cf29"},
{file = "regex-2022.3.2-cp36-cp36m-win32.whl", hash = "sha256:286ff9ec2709d56ae7517040be0d6c502642517ce9937ab6d89b1e7d0904f863"},
{file = "regex-2022.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d326ff80ed531bf2507cba93011c30fff2dd51454c85f55df0f59f2030b1687b"},
{file = "regex-2022.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9d828c5987d543d052b53c579a01a52d96b86f937b1777bbfe11ef2728929357"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87ac58b9baaf50b6c1b81a18d20eda7e2883aa9a4fb4f1ca70f2e443bfcdc57"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6c2441538e4fadd4291c8420853431a229fcbefc1bf521810fbc2629d8ae8c2"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f3356afbb301ec34a500b8ba8b47cba0b44ed4641c306e1dd981a08b416170b5"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d96eec8550fd2fd26f8e675f6d8b61b159482ad8ffa26991b894ed5ee19038b"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf668f26604e9f7aee9f8eaae4ca07a948168af90b96be97a4b7fa902a6d2ac1"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb0e2845e81bdea92b8281a3969632686502565abf4a0b9e4ab1471c863d8f3"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:87bc01226cd288f0bd9a4f9f07bf6827134dc97a96c22e2d28628e824c8de231"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:09b4b6ccc61d4119342b26246ddd5a04accdeebe36bdfe865ad87a0784efd77f"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:9557545c10d52c845f270b665b52a6a972884725aa5cf12777374e18f2ea8960"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:0be0c34a39e5d04a62fd5342f0886d0e57592a4f4993b3f9d257c1f688b19737"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7b103dffb9f6a47ed7ffdf352b78cfe058b1777617371226c1894e1be443afec"},
{file = "regex-2022.3.2-cp37-cp37m-win32.whl", hash = "sha256:f8169ec628880bdbca67082a9196e2106060a4a5cbd486ac51881a4df805a36f"},
{file = "regex-2022.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:4b9c16a807b17b17c4fa3a1d8c242467237be67ba92ad24ff51425329e7ae3d0"},
{file = "regex-2022.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:67250b36edfa714ba62dc62d3f238e86db1065fccb538278804790f578253640"},
{file = "regex-2022.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5510932596a0f33399b7fff1bd61c59c977f2b8ee987b36539ba97eb3513584a"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f7ee2289176cb1d2c59a24f50900f8b9580259fa9f1a739432242e7d254f93"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d7a68fa53688e1f612c3246044157117403c7ce19ebab7d02daf45bd63913e"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf5317c961d93c1a200b9370fb1c6b6836cc7144fef3e5a951326912bf1f5a3"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad397bc7d51d69cb07ef89e44243f971a04ce1dca9bf24c992c362406c0c6573"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:297c42ede2c81f0cb6f34ea60b5cf6dc965d97fa6936c11fc3286019231f0d66"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:af4d8cc28e4c7a2f6a9fed544228c567340f8258b6d7ea815b62a72817bbd178"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:452519bc4c973e961b1620c815ea6dd8944a12d68e71002be5a7aff0a8361571"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cb34c2d66355fb70ae47b5595aafd7218e59bb9c00ad8cc3abd1406ca5874f07"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d146e5591cb67c5e836229a04723a30af795ef9b70a0bbd913572e14b7b940f"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:03299b0bcaa7824eb7c0ebd7ef1e3663302d1b533653bfe9dc7e595d453e2ae9"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9ccb0a4ab926016867260c24c192d9df9586e834f5db83dfa2c8fffb3a6e5056"},
{file = "regex-2022.3.2-cp38-cp38-win32.whl", hash = "sha256:f7e8f1ee28e0a05831c92dc1c0c1c94af5289963b7cf09eca5b5e3ce4f8c91b0"},
{file = "regex-2022.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:35ed2f3c918a00b109157428abfc4e8d1ffabc37c8f9abc5939ebd1e95dabc47"},
{file = "regex-2022.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:55820bc631684172b9b56a991d217ec7c2e580d956591dc2144985113980f5a3"},
{file = "regex-2022.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:83f03f0bd88c12e63ca2d024adeee75234d69808b341e88343b0232329e1f1a1"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42d6007722d46bd2c95cce700181570b56edc0dcbadbfe7855ec26c3f2d7e008"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:320c2f4106962ecea0f33d8d31b985d3c185757c49c1fb735501515f963715ed"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbd3fe37353c62fd0eb19fb76f78aa693716262bcd5f9c14bb9e5aca4b3f0dc4"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17e51ad1e6131c496b58d317bc9abec71f44eb1957d32629d06013a21bc99cac"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72bc3a5effa5974be6d965ed8301ac1e869bc18425c8a8fac179fbe7876e3aee"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e5602a9b5074dcacc113bba4d2f011d2748f50e3201c8139ac5b68cf2a76bd8b"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:729aa8ca624c42f309397c5fc9e21db90bf7e2fdd872461aabdbada33de9063c"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d6ecfd1970b3380a569d7b3ecc5dd70dba295897418ed9e31ec3c16a5ab099a5"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:13bbf0c9453c6d16e5867bda7f6c0c7cff1decf96c5498318bb87f8136d2abd4"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:58ba41e462653eaf68fc4a84ec4d350b26a98d030be1ab24aba1adcc78ffe447"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c0446b2871335d5a5e9fcf1462f954586b09a845832263db95059dcd01442015"},
{file = "regex-2022.3.2-cp39-cp39-win32.whl", hash = "sha256:20e6a27959f162f979165e496add0d7d56d7038237092d1aba20b46de79158f1"},
{file = "regex-2022.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9efa41d1527b366c88f265a227b20bcec65bda879962e3fc8a2aee11e81266d7"},
{file = "regex-2022.3.2.tar.gz", hash = "sha256:79e5af1ff258bc0fe0bdd6f69bc4ae33935a898e3cbefbbccf22e88a27fa053b"},
]
reorder-python-imports = [ reorder-python-imports = [
{file = "reorder_python_imports-3.9.0-py2.py3-none-any.whl", hash = "sha256:3f9c16e8781f54c944756d0d1eb34a8c863554f7a4eb3693f574fe19b1a29b56"}, {file = "reorder_python_imports-3.9.0-py2.py3-none-any.whl", hash = "sha256:3f9c16e8781f54c944756d0d1eb34a8c863554f7a4eb3693f574fe19b1a29b56"},
{file = "reorder_python_imports-3.9.0.tar.gz", hash = "sha256:49292ed537829a6bece9fb3746fc1bbe98f52643be5de01a4e13680268a5b0ec"}, {file = "reorder_python_imports-3.9.0.tar.gz", hash = "sha256:49292ed537829a6bece9fb3746fc1bbe98f52643be5de01a4e13680268a5b0ec"},
@ -2991,14 +2807,6 @@ typing-inspect = [
{file = "typing_inspect-0.7.1-py3-none-any.whl", hash = "sha256:3cd7d4563e997719a710a3bfe7ffb544c6b72069b6812a02e9b414a8fa3aaa6b"}, {file = "typing_inspect-0.7.1-py3-none-any.whl", hash = "sha256:3cd7d4563e997719a710a3bfe7ffb544c6b72069b6812a02e9b414a8fa3aaa6b"},
{file = "typing_inspect-0.7.1.tar.gz", hash = "sha256:047d4097d9b17f46531bf6f014356111a1b6fb821a24fe7ac909853ca2a782aa"}, {file = "typing_inspect-0.7.1.tar.gz", hash = "sha256:047d4097d9b17f46531bf6f014356111a1b6fb821a24fe7ac909853ca2a782aa"},
] ]
tzdata = [
{file = "tzdata-2022.2-py2.py3-none-any.whl", hash = "sha256:c3119520447d68ef3eb8187a55a4f44fa455f30eb1b4238fa5691ba094f2b05b"},
{file = "tzdata-2022.2.tar.gz", hash = "sha256:21f4f0d7241572efa7f7a4fdabb052e61b55dc48274e6842697ccdf5253e5451"},
]
tzlocal = [
{file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"},
{file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"},
]
unidecode = [ unidecode = [
{file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"}, {file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"},
{file = "Unidecode-1.3.4.tar.gz", hash = "sha256:8e4352fb93d5a735c788110d2e7ac8e8031eb06ccbfe8d324ab71735015f9342"}, {file = "Unidecode-1.3.4.tar.gz", hash = "sha256:8e4352fb93d5a735c788110d2e7ac8e8031eb06ccbfe8d324ab71735015f9342"},

View File

@ -30,13 +30,14 @@ werkzeug = "*"
spiffworkflow = "*" spiffworkflow = "*"
sentry-sdk = "*" sentry-sdk = "*"
sphinx-autoapi = "^2.0.0" sphinx-autoapi = "^2.0.0"
greenlet = "^2.0.1"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = "^6.2.5" pytest = "^6.2.5"
coverage = {extras = ["toml"], version = "^6.5"} coverage = {extras = ["toml"], version = "^6.5"}
safety = "^2.3.1" safety = "^2.3.1"
mypy = "^0.982" mypy = "^0.990"
typeguard = "^2.13.2" typeguard = "^2.13.2"
xdoctest = {extras = ["colors"], version = "^1.1.0"} xdoctest = {extras = ["colors"], version = "^1.1.0"}
sphinx = "^4.3.0" sphinx = "^4.3.0"

275
poetry.lock generated
View File

@ -80,8 +80,7 @@ python-versions = ">=3.7.2"
[package.dependencies] [package.dependencies]
lazy-object-proxy = ">=1.4.0" lazy-object-proxy = ">=1.4.0"
typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}
wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""}
[[package]] [[package]]
name = "attrs" name = "attrs"
@ -175,8 +174,6 @@ click = ">=8.0.0"
mypy-extensions = ">=0.4.3" mypy-extensions = ">=0.4.3"
pathspec = ">=0.9.0" pathspec = ">=0.9.0"
platformdirs = ">=2" platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras] [package.extras]
colorama = ["colorama (>=0.4.3)"] colorama = ["colorama (>=0.4.3)"]
@ -394,9 +391,6 @@ category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
[package.extras] [package.extras]
toml = ["tomli"] toml = ["tomli"]
@ -408,25 +402,6 @@ category = "dev"
optional = false optional = false
python-versions = ">=3.6,<4.0" python-versions = ">=3.6,<4.0"
[[package]]
name = "dateparser"
version = "1.1.2"
description = "Date parsing library designed to parse dates from HTML pages"
category = "main"
optional = false
python-versions = ">=3.5"
[package.dependencies]
python-dateutil = "*"
pytz = "*"
regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27,<2022.3.15"
tzlocal = "*"
[package.extras]
calendars = ["convertdate", "convertdate", "hijri-converter"]
fasttext = ["fasttext"]
langdetect = ["langdetect"]
[[package]] [[package]]
name = "distlib" name = "distlib"
version = "0.3.6" version = "0.3.6"
@ -474,17 +449,6 @@ six = ">=1.9.0"
gmpy = ["gmpy"] gmpy = ["gmpy"]
gmpy2 = ["gmpy2"] gmpy2 = ["gmpy2"]
[[package]]
name = "exceptiongroup"
version = "1.0.0"
description = "Backport of PEP 654 (exception groups)"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
test = ["pytest (>=6)"]
[[package]] [[package]]
name = "filelock" name = "filelock"
version = "3.8.0" version = "3.8.0"
@ -585,7 +549,6 @@ python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
click = ">=8.0" click = ">=8.0"
importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""}
itsdangerous = ">=2.0" itsdangerous = ">=2.0"
Jinja2 = ">=3.0" Jinja2 = ">=3.0"
Werkzeug = ">=2.2.2" Werkzeug = ">=2.2.2"
@ -650,7 +613,7 @@ werkzeug = "*"
type = "git" type = "git"
url = "https://github.com/sartography/flask-bpmn" url = "https://github.com/sartography/flask-bpmn"
reference = "main" reference = "main"
resolved_reference = "a8b90f2ca09ef1cbb24a491c36f1cc9437477325" resolved_reference = "17434e0907cc35914d013614bb79288eed1bd437"
[[package]] [[package]]
name = "flask-cors" name = "flask-cors"
@ -829,22 +792,6 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "importlib-metadata"
version = "5.0.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
perf = ["ipython"]
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
[[package]] [[package]]
name = "inflection" name = "inflection"
version = "0.5.1" version = "0.5.1"
@ -1078,7 +1025,6 @@ python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
mypy-extensions = ">=0.4.3" mypy-extensions = ">=0.4.3"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = ">=3.10" typing-extensions = ">=3.10"
[package.extras] [package.extras]
@ -1217,7 +1163,6 @@ python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
"ruamel.yaml" = ">=0.15" "ruamel.yaml" = ">=0.15"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[[package]] [[package]]
name = "prompt-toolkit" name = "prompt-toolkit"
@ -1339,11 +1284,9 @@ python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
attrs = ">=19.2.0" attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""} colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*" iniconfig = "*"
packaging = "*" packaging = "*"
pluggy = ">=0.12,<2.0" pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras] [package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
@ -1396,17 +1339,6 @@ pytest = ">=5.0"
[package.extras] [package.extras]
dev = ["pre-commit", "pytest-asyncio", "tox"] dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
[package.dependencies]
six = ">=1.5"
[[package]] [[package]]
name = "python-jose" name = "python-jose"
version = "3.3.0" version = "3.3.0"
@ -1480,14 +1412,6 @@ category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "regex"
version = "2022.3.2"
description = "Alternative regular expression module, to replace re."
category = "main"
optional = false
python-versions = ">=3.6"
[[package]] [[package]]
name = "reorder-python-imports" name = "reorder-python-imports"
version = "3.9.0" version = "3.9.0"
@ -1530,11 +1454,11 @@ requests = ">=2.0.1,<3.0.0"
[[package]] [[package]]
name = "restrictedpython" name = "restrictedpython"
version = "5.2" version = "6.0"
description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment." description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.11" python-versions = ">=3.6, <3.12"
[package.extras] [package.extras]
docs = ["Sphinx", "sphinx-rtd-theme"] docs = ["Sphinx", "sphinx-rtd-theme"]
@ -1570,21 +1494,10 @@ category = "dev"
optional = false optional = false
python-versions = ">=3" python-versions = ">=3"
[package.dependencies]
"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}
[package.extras] [package.extras]
docs = ["ryd"] docs = ["ryd"]
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
[[package]]
name = "ruamel-yaml-clib"
version = "0.2.7"
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
category = "dev"
optional = false
python-versions = ">=3.5"
[[package]] [[package]]
name = "safety" name = "safety"
version = "2.3.1" version = "2.3.1"
@ -1704,7 +1617,6 @@ babel = ">=2.9"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
docutils = ">=0.14,<0.20" docutils = ">=0.14,<0.20"
imagesize = ">=1.3" imagesize = ">=1.3"
importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
Jinja2 = ">=3.0" Jinja2 = ">=3.0"
packaging = ">=21.0" packaging = ">=21.0"
Pygments = ">=2.12" Pygments = ">=2.12"
@ -1868,15 +1780,13 @@ develop = false
[package.dependencies] [package.dependencies]
celery = "*" celery = "*"
configparser = "*" configparser = "*"
dateparser = "*"
lxml = "*" lxml = "*"
pytz = "*"
[package.source] [package.source]
type = "git" type = "git"
url = "https://github.com/sartography/SpiffWorkflow" url = "https://github.com/sartography/SpiffWorkflow"
reference = "main" reference = "main"
resolved_reference = "12f81480a5f9e848e64221b9287c6cfa6cb682b4" resolved_reference = "8d820dce1f439bb76bc07e39629832d998d6f634"
[[package]] [[package]]
name = "sqlalchemy" name = "sqlalchemy"
@ -1967,14 +1877,6 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "main"
optional = false
python-versions = ">=3.7"
[[package]] [[package]]
name = "tornado" name = "tornado"
version = "6.2" version = "6.2"
@ -2236,22 +2138,10 @@ runtime-strict = ["six (==1.11.0)"]
tests = ["cmake", "codecov", "ninja", "pybind11", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "scikit-build", "typing"] tests = ["cmake", "codecov", "ninja", "pybind11", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest", "pytest-cov", "pytest-cov", "pytest-cov", "pytest-cov", "scikit-build", "typing"]
tests-strict = ["cmake (==3.21.2)", "codecov (==2.0.15)", "ninja (==1.10.2)", "pybind11 (==2.7.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scikit-build (==0.11.1)", "typing (==3.7.4)"] tests-strict = ["cmake (==3.21.2)", "codecov (==2.0.15)", "ninja (==1.10.2)", "pybind11 (==2.7.1)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==2.8.1)", "pytest-cov (==2.8.1)", "pytest-cov (==2.9.0)", "pytest-cov (==3.0.0)", "scikit-build (==0.11.1)", "typing (==3.7.4)"]
[[package]]
name = "zipp"
version = "3.10.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.9,<3.11" python-versions = ">=3.11,<3.12"
content-hash = "bfb51ebc4ef76d4a74f670f44dc4d7ca7e91874b096f56521c2776f1837f6a63" content-hash = "2b730b9fd814bf805d68d2d7e3bc1caaf2e907c9f4bab4085f34322995670d27"
[metadata.files] [metadata.files]
alabaster = [ alabaster = [
@ -2456,10 +2346,6 @@ darglint = [
{file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"},
{file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
] ]
dateparser = [
{file = "dateparser-1.1.2-py2.py3-none-any.whl", hash = "sha256:d31659dc806a7d88e2b510b2c74f68b525ae531f145c62a57a99bd616b7f90cf"},
{file = "dateparser-1.1.2.tar.gz", hash = "sha256:3821bf191f95b2658c4abd91571c09821ce7a2bc179bf6cefd8b4515c3ccf9ef"},
]
distlib = [ distlib = [
{file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"},
{file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
@ -2476,10 +2362,6 @@ ecdsa = [
{file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"}, {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"},
{file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"}, {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"},
] ]
exceptiongroup = [
{file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"},
{file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"},
]
filelock = [ filelock = [
{file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"},
{file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"},
@ -2620,7 +2502,6 @@ greenlet = [
{file = "greenlet-1.1.3.post0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809"}, {file = "greenlet-1.1.3.post0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win32.whl", hash = "sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2"}, {file = "greenlet-1.1.3.post0-cp39-cp39-win32.whl", hash = "sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"}, {file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"},
{file = "greenlet-1.1.3.post0.tar.gz", hash = "sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c"},
] ]
gunicorn = [ gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
@ -2638,10 +2519,6 @@ imagesize = [
{file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
] ]
importlib-metadata = [
{file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"},
{file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"},
]
inflection = [ inflection = [
{file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
{file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"},
@ -3043,7 +2920,18 @@ psycopg2 = [
{file = "psycopg2-2.9.5.tar.gz", hash = "sha256:a5246d2e683a972e2187a8714b5c2cf8156c064629f9a9b1a873c1730d9e245a"}, {file = "psycopg2-2.9.5.tar.gz", hash = "sha256:a5246d2e683a972e2187a8714b5c2cf8156c064629f9a9b1a873c1730d9e245a"},
] ]
pyasn1 = [ pyasn1 = [
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
{file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"},
{file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"},
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
{file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"},
{file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"},
{file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"},
{file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"},
{file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"},
{file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"},
{file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"},
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
] ]
pycodestyle = [ pycodestyle = [
@ -3109,10 +2997,6 @@ pytest-mock = [
{file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"},
{file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"},
] ]
python-dateutil = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
python-jose = [ python-jose = [
{file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"},
{file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"},
@ -3175,82 +3059,6 @@ pyyaml = [
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
] ]
regex = [
{file = "regex-2022.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab69b4fe09e296261377d209068d52402fb85ef89dc78a9ac4a29a895f4e24a7"},
{file = "regex-2022.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5bc5f921be39ccb65fdda741e04b2555917a4bced24b4df14eddc7569be3b493"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43eba5c46208deedec833663201752e865feddc840433285fbadee07b84b464d"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c68d2c04f7701a418ec2e5631b7f3552efc32f6bcc1739369c6eeb1af55f62e0"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:caa2734ada16a44ae57b229d45091f06e30a9a52ace76d7574546ab23008c635"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef806f684f17dbd6263d72a54ad4073af42b42effa3eb42b877e750c24c76f86"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be319f4eb400ee567b722e9ea63d5b2bb31464e3cf1b016502e3ee2de4f86f5c"},
{file = "regex-2022.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:42bb37e2b2d25d958c25903f6125a41aaaa1ed49ca62c103331f24b8a459142f"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fbc88d3ba402b5d041d204ec2449c4078898f89c4a6e6f0ed1c1a510ef1e221d"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:91e0f7e7be77250b808a5f46d90bf0032527d3c032b2131b63dee54753a4d729"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:cb3652bbe6720786b9137862205986f3ae54a09dec8499a995ed58292bdf77c2"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:878c626cbca3b649e14e972c14539a01191d79e58934e3f3ef4a9e17f90277f8"},
{file = "regex-2022.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6df070a986fc064d865c381aecf0aaff914178fdf6874da2f2387e82d93cc5bd"},
{file = "regex-2022.3.2-cp310-cp310-win32.whl", hash = "sha256:b549d851f91a4efb3e65498bd4249b1447ab6035a9972f7fc215eb1f59328834"},
{file = "regex-2022.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:8babb2b5751105dc0aef2a2e539f4ba391e738c62038d8cb331c710f6b0f3da7"},
{file = "regex-2022.3.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1977bb64264815d3ef016625adc9df90e6d0e27e76260280c63eca993e3f455f"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e73652057473ad3e6934944af090852a02590c349357b79182c1b681da2c772"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b22ff939a8856a44f4822da38ef4868bd3a9ade22bb6d9062b36957c850e404f"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:878f5d649ba1db9f52cc4ef491f7dba2d061cdc48dd444c54260eebc0b1729b9"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0008650041531d0eadecc96a73d37c2dc4821cf51b0766e374cb4f1ddc4e1c14"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:06b1df01cf2aef3a9790858af524ae2588762c8a90e784ba00d003f045306204"},
{file = "regex-2022.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57484d39447f94967e83e56db1b1108c68918c44ab519b8ecfc34b790ca52bf7"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:74d86e8924835f863c34e646392ef39039405f6ce52956d8af16497af4064a30"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:ae17fc8103f3b63345709d3e9654a274eee1c6072592aec32b026efd401931d0"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5f92a7cdc6a0ae2abd184e8dfd6ef2279989d24c85d2c85d0423206284103ede"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:5dcc4168536c8f68654f014a3db49b6b4a26b226f735708be2054314ed4964f4"},
{file = "regex-2022.3.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:1e30762ddddb22f7f14c4f59c34d3addabc789216d813b0f3e2788d7bcf0cf29"},
{file = "regex-2022.3.2-cp36-cp36m-win32.whl", hash = "sha256:286ff9ec2709d56ae7517040be0d6c502642517ce9937ab6d89b1e7d0904f863"},
{file = "regex-2022.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d326ff80ed531bf2507cba93011c30fff2dd51454c85f55df0f59f2030b1687b"},
{file = "regex-2022.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9d828c5987d543d052b53c579a01a52d96b86f937b1777bbfe11ef2728929357"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87ac58b9baaf50b6c1b81a18d20eda7e2883aa9a4fb4f1ca70f2e443bfcdc57"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6c2441538e4fadd4291c8420853431a229fcbefc1bf521810fbc2629d8ae8c2"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f3356afbb301ec34a500b8ba8b47cba0b44ed4641c306e1dd981a08b416170b5"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d96eec8550fd2fd26f8e675f6d8b61b159482ad8ffa26991b894ed5ee19038b"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf668f26604e9f7aee9f8eaae4ca07a948168af90b96be97a4b7fa902a6d2ac1"},
{file = "regex-2022.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb0e2845e81bdea92b8281a3969632686502565abf4a0b9e4ab1471c863d8f3"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:87bc01226cd288f0bd9a4f9f07bf6827134dc97a96c22e2d28628e824c8de231"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:09b4b6ccc61d4119342b26246ddd5a04accdeebe36bdfe865ad87a0784efd77f"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:9557545c10d52c845f270b665b52a6a972884725aa5cf12777374e18f2ea8960"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:0be0c34a39e5d04a62fd5342f0886d0e57592a4f4993b3f9d257c1f688b19737"},
{file = "regex-2022.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7b103dffb9f6a47ed7ffdf352b78cfe058b1777617371226c1894e1be443afec"},
{file = "regex-2022.3.2-cp37-cp37m-win32.whl", hash = "sha256:f8169ec628880bdbca67082a9196e2106060a4a5cbd486ac51881a4df805a36f"},
{file = "regex-2022.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:4b9c16a807b17b17c4fa3a1d8c242467237be67ba92ad24ff51425329e7ae3d0"},
{file = "regex-2022.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:67250b36edfa714ba62dc62d3f238e86db1065fccb538278804790f578253640"},
{file = "regex-2022.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5510932596a0f33399b7fff1bd61c59c977f2b8ee987b36539ba97eb3513584a"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f7ee2289176cb1d2c59a24f50900f8b9580259fa9f1a739432242e7d254f93"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d7a68fa53688e1f612c3246044157117403c7ce19ebab7d02daf45bd63913e"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf5317c961d93c1a200b9370fb1c6b6836cc7144fef3e5a951326912bf1f5a3"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad397bc7d51d69cb07ef89e44243f971a04ce1dca9bf24c992c362406c0c6573"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:297c42ede2c81f0cb6f34ea60b5cf6dc965d97fa6936c11fc3286019231f0d66"},
{file = "regex-2022.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:af4d8cc28e4c7a2f6a9fed544228c567340f8258b6d7ea815b62a72817bbd178"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:452519bc4c973e961b1620c815ea6dd8944a12d68e71002be5a7aff0a8361571"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cb34c2d66355fb70ae47b5595aafd7218e59bb9c00ad8cc3abd1406ca5874f07"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d146e5591cb67c5e836229a04723a30af795ef9b70a0bbd913572e14b7b940f"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:03299b0bcaa7824eb7c0ebd7ef1e3663302d1b533653bfe9dc7e595d453e2ae9"},
{file = "regex-2022.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9ccb0a4ab926016867260c24c192d9df9586e834f5db83dfa2c8fffb3a6e5056"},
{file = "regex-2022.3.2-cp38-cp38-win32.whl", hash = "sha256:f7e8f1ee28e0a05831c92dc1c0c1c94af5289963b7cf09eca5b5e3ce4f8c91b0"},
{file = "regex-2022.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:35ed2f3c918a00b109157428abfc4e8d1ffabc37c8f9abc5939ebd1e95dabc47"},
{file = "regex-2022.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:55820bc631684172b9b56a991d217ec7c2e580d956591dc2144985113980f5a3"},
{file = "regex-2022.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:83f03f0bd88c12e63ca2d024adeee75234d69808b341e88343b0232329e1f1a1"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42d6007722d46bd2c95cce700181570b56edc0dcbadbfe7855ec26c3f2d7e008"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:320c2f4106962ecea0f33d8d31b985d3c185757c49c1fb735501515f963715ed"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbd3fe37353c62fd0eb19fb76f78aa693716262bcd5f9c14bb9e5aca4b3f0dc4"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17e51ad1e6131c496b58d317bc9abec71f44eb1957d32629d06013a21bc99cac"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72bc3a5effa5974be6d965ed8301ac1e869bc18425c8a8fac179fbe7876e3aee"},
{file = "regex-2022.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e5602a9b5074dcacc113bba4d2f011d2748f50e3201c8139ac5b68cf2a76bd8b"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:729aa8ca624c42f309397c5fc9e21db90bf7e2fdd872461aabdbada33de9063c"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d6ecfd1970b3380a569d7b3ecc5dd70dba295897418ed9e31ec3c16a5ab099a5"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:13bbf0c9453c6d16e5867bda7f6c0c7cff1decf96c5498318bb87f8136d2abd4"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:58ba41e462653eaf68fc4a84ec4d350b26a98d030be1ab24aba1adcc78ffe447"},
{file = "regex-2022.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c0446b2871335d5a5e9fcf1462f954586b09a845832263db95059dcd01442015"},
{file = "regex-2022.3.2-cp39-cp39-win32.whl", hash = "sha256:20e6a27959f162f979165e496add0d7d56d7038237092d1aba20b46de79158f1"},
{file = "regex-2022.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9efa41d1527b366c88f265a227b20bcec65bda879962e3fc8a2aee11e81266d7"},
{file = "regex-2022.3.2.tar.gz", hash = "sha256:79e5af1ff258bc0fe0bdd6f69bc4ae33935a898e3cbefbbccf22e88a27fa053b"},
]
reorder-python-imports = [ reorder-python-imports = [
{file = "reorder_python_imports-3.9.0-py2.py3-none-any.whl", hash = "sha256:3f9c16e8781f54c944756d0d1eb34a8c863554f7a4eb3693f574fe19b1a29b56"}, {file = "reorder_python_imports-3.9.0-py2.py3-none-any.whl", hash = "sha256:3f9c16e8781f54c944756d0d1eb34a8c863554f7a4eb3693f574fe19b1a29b56"},
{file = "reorder_python_imports-3.9.0.tar.gz", hash = "sha256:49292ed537829a6bece9fb3746fc1bbe98f52643be5de01a4e13680268a5b0ec"}, {file = "reorder_python_imports-3.9.0.tar.gz", hash = "sha256:49292ed537829a6bece9fb3746fc1bbe98f52643be5de01a4e13680268a5b0ec"},
@ -3264,8 +3072,8 @@ requests-toolbelt = [
{file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"},
] ]
restrictedpython = [ restrictedpython = [
{file = "RestrictedPython-5.2-py2.py3-none-any.whl", hash = "sha256:fdf8621034c5dcb990a2a198f232f66b2d48866dd16d848e00ac7d187ae452ba"}, {file = "RestrictedPython-6.0-py3-none-any.whl", hash = "sha256:3479303f7bff48a7dedad76f96e7704993c5e86c5adbd67f607295d5352f0fb8"},
{file = "RestrictedPython-5.2.tar.gz", hash = "sha256:634da1f6c5c122a262f433b083ee3d17a9a039f8f1b3778597efb47461cd361b"}, {file = "RestrictedPython-6.0.tar.gz", hash = "sha256:405cf0bd9eec2f19b1326b5f48228efe56d6590b4e91826b8cc3b2cd400a96ad"},
] ]
restructuredtext-lint = [ restructuredtext-lint = [
{file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"},
@ -3278,41 +3086,6 @@ ruamel-yaml = [
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
{file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
] ]
ruamel-yaml-clib = [
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"},
{file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"},
{file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"},
{file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"},
{file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"},
{file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"},
{file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"},
]
safety = [ safety = [
{file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"}, {file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"},
{file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"}, {file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"},
@ -3509,10 +3282,6 @@ toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
] ]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
tornado = [ tornado = [
{file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"}, {file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"},
{file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"}, {file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"},
@ -3680,7 +3449,3 @@ xdoctest = [
{file = "xdoctest-1.1.0-py3-none-any.whl", hash = "sha256:da330c4dacee51f3c785820bc743188fb6f7c64c5fa1c54bff8836b3cf23d69b"}, {file = "xdoctest-1.1.0-py3-none-any.whl", hash = "sha256:da330c4dacee51f3c785820bc743188fb6f7c64c5fa1c54bff8836b3cf23d69b"},
{file = "xdoctest-1.1.0.tar.gz", hash = "sha256:0fd4fad7932f0a2f082dfdfb857dd6ca41603757586c39b1e5b4d333fc389f8a"}, {file = "xdoctest-1.1.0.tar.gz", hash = "sha256:0fd4fad7932f0a2f082dfdfb857dd6ca41603757586c39b1e5b4d333fc389f8a"},
] ]
zipp = [
{file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"},
{file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"},
]

View File

@ -12,7 +12,7 @@ classifiers = [
] ]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.9,<3.11" python = ">=3.11,<3.12"
click = "^8.0.1" click = "^8.0.1"
flask = "2.2.2" flask = "2.2.2"
flask-admin = "*" flask-admin = "*"
@ -46,7 +46,7 @@ gunicorn = "^20.1.0"
python-keycloak = "^2.5.0" python-keycloak = "^2.5.0"
APScheduler = "^3.9.1" APScheduler = "^3.9.1"
Jinja2 = "^3.1.2" Jinja2 = "^3.1.2"
RestrictedPython = "^5.2" RestrictedPython = "^6.0"
Flask-SQLAlchemy = "^3" Flask-SQLAlchemy = "^3"
orjson = "^3.8.0" orjson = "^3.8.0"

View File

@ -12,22 +12,29 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { python: "3.10", os: "ubuntu-latest", session: "pre-commit" } - { python: "3.11", os: "ubuntu-latest", session: "pre-commit" }
- { python: "3.10", os: "ubuntu-latest", session: "safety" } - { python: "3.11", os: "ubuntu-latest", session: "safety" }
- { python: "3.11", os: "ubuntu-latest", session: "mypy" }
- { python: "3.10", os: "ubuntu-latest", session: "mypy" } - { python: "3.10", os: "ubuntu-latest", session: "mypy" }
- { python: "3.9", os: "ubuntu-latest", session: "mypy" } - { python: "3.9", os: "ubuntu-latest", session: "mypy" }
- { - {
python: "3.10", python: "3.11",
os: "ubuntu-latest", os: "ubuntu-latest",
session: "tests", session: "tests",
database: "mysql", database: "mysql",
} }
- { - {
python: "3.10", python: "3.11",
os: "ubuntu-latest", os: "ubuntu-latest",
session: "tests", session: "tests",
database: "postgres", database: "postgres",
} }
- {
python: "3.11",
os: "ubuntu-latest",
session: "tests",
database: "sqlite",
}
- { - {
python: "3.10", python: "3.10",
os: "ubuntu-latest", os: "ubuntu-latest",
@ -41,28 +48,28 @@ jobs:
database: "sqlite", database: "sqlite",
} }
- { - {
python: "3.10", python: "3.11",
os: "windows-latest", os: "windows-latest",
session: "tests", session: "tests",
database: "sqlite", database: "sqlite",
} }
- { - {
python: "3.10", python: "3.11",
os: "macos-latest", os: "macos-latest",
session: "tests", session: "tests",
database: "sqlite", database: "sqlite",
} }
- { - {
# typeguard 2.13.3 is broken with TypeDict in 3.10. # typeguard 2.13.3 is broken with TypeDict in 3.11.
# probably the next release fixes it. # probably the next release fixes it.
# https://github.com/agronholm/typeguard/issues/242 # https://github.com/agronholm/typeguard/issues/242
python: "3.9", python: "3.11",
os: "ubuntu-latest", os: "ubuntu-latest",
session: "typeguard", session: "typeguard",
database: "sqlite", database: "sqlite",
} }
- { python: "3.10", os: "ubuntu-latest", session: "xdoctest" } - { python: "3.11", os: "ubuntu-latest", session: "xdoctest" }
- { python: "3.10", os: "ubuntu-latest", session: "docs-build" } - { python: "3.11", os: "ubuntu-latest", session: "docs-build" }
env: env:
NOXSESSION: ${{ matrix.session }} NOXSESSION: ${{ matrix.session }}
@ -149,7 +156,7 @@ jobs:
- name: Upload coverage data - name: Upload coverage data
# pin to upload coverage from only one matrix entry, otherwise coverage gets confused later # pin to upload coverage from only one matrix entry, otherwise coverage gets confused later
if: always() && matrix.session == 'tests' && matrix.python == '3.10' && matrix.os == 'ubuntu-latest' if: always() && matrix.session == 'tests' && matrix.python == '3.11' && matrix.os == 'ubuntu-latest'
uses: "actions/upload-artifact@v3.0.0" uses: "actions/upload-artifact@v3.0.0"
with: with:
name: coverage-data name: coverage-data
@ -198,7 +205,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4.2.0 uses: actions/setup-python@v4.2.0
with: with:
python-version: "3.10" python-version: "3.11"
- name: Upgrade pip - name: Upgrade pip
run: | run: |

View File

@ -1 +1 @@
python 3.10.4 python 3.11.0

View File

@ -1,4 +1,4 @@
FROM ghcr.io/sartography/python:3.10 FROM ghcr.io/sartography/python:3.11
RUN pip install poetry RUN pip install poetry
RUN useradd _gunicorn --no-create-home --user-group RUN useradd _gunicorn --no-create-home --user-group
@ -11,7 +11,7 @@ RUN apt-get update && \
WORKDIR /app WORKDIR /app
COPY pyproject.toml poetry.lock /app/ COPY pyproject.toml poetry.lock /app/
RUN poetry install RUN poetry install --without dev
RUN set -xe \ RUN set -xe \
&& apt-get remove -y gcc python3-dev libssl-dev \ && apt-get remove -y gcc python3-dev libssl-dev \
@ -23,6 +23,6 @@ COPY . /app/
# run poetry install again AFTER copying the app into the image # run poetry install again AFTER copying the app into the image
# otherwise it does not know what the main app module is # otherwise it does not know what the main app module is
RUN poetry install RUN poetry install --without dev
CMD ./bin/boot_server_in_docker CMD ./bin/boot_server_in_docker

View File

@ -1,4 +1,4 @@
"""Updates all JSON files, based on the current state of BPMN_SPEC_ABSOLUTE_DIR""" """Updates all JSON files, based on the current state of BPMN_SPEC_ABSOLUTE_DIR."""
from spiffworkflow_backend import get_hacked_up_app_for_script from spiffworkflow_backend import get_hacked_up_app_for_script
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
@ -12,8 +12,8 @@ def main() -> None:
for group in groups: for group in groups:
for process_model in group.process_models: for process_model in group.process_models:
update_items = { update_items = {
'process_group_id': '', "process_group_id": "",
'id': f"{group.id}/{process_model.id}" "id": f"{group.id}/{process_model.id}",
} }
ProcessModelService().update_spec(process_model, update_items) ProcessModelService().update_spec(process_model, update_items)

View File

@ -8,7 +8,6 @@ from flask.testing import FlaskClient
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
@ -21,6 +20,8 @@ from spiffworkflow_backend.services.process_instance_service import (
) )
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
# from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
# We need to call this before importing spiffworkflow_backend # We need to call this before importing spiffworkflow_backend
# otherwise typeguard cannot work. hence the noqa: E402 # otherwise typeguard cannot work. hence the noqa: E402
@ -67,12 +68,14 @@ def with_super_admin_user() -> UserModel:
@pytest.fixture() @pytest.fixture()
def setup_process_instances_for_reports(client: FlaskClient, with_super_admin_user: UserModel) -> list[ProcessInstanceModel]: def setup_process_instances_for_reports(
client: FlaskClient, with_super_admin_user: UserModel
) -> list[ProcessInstanceModel]:
"""Setup_process_instances_for_reports.""" """Setup_process_instances_for_reports."""
user = with_super_admin_user user = with_super_admin_user
process_group_id = "runs_without_input" process_group_id = "runs_without_input"
process_model_id = "sample" process_model_id = "sample"
bpmn_file_name = "sample.bpmn" # bpmn_file_name = "sample.bpmn"
bpmn_file_location = "sample" bpmn_file_location = "sample"
process_model_identifier = BaseTest().basic_test_setup( process_model_identifier = BaseTest().basic_test_setup(
client, client,
@ -80,7 +83,7 @@ def setup_process_instances_for_reports(client: FlaskClient, with_super_admin_us
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
# bpmn_file_name=bpmn_file_name, # bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
# BaseTest().create_process_group( # BaseTest().create_process_group(

View File

@ -1,5 +1,3 @@
from __future__ import with_statement
import logging import logging
from logging.config import fileConfig from logging.config import fileConfig

View File

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: 50dd2e016d94 Revision ID: fd00c59e1f60
Revises: Revises:
Create Date: 2022-11-08 16:28:18.991635 Create Date: 2022-11-09 14:04:14.169379
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '50dd2e016d94' revision = 'fd00c59e1f60'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -45,6 +45,29 @@ def upgrade():
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('uri') sa.UniqueConstraint('uri')
) )
op.create_table('spiff_logging',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False),
sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=False),
sa.Column('bpmn_task_identifier', sa.String(length=255), nullable=False),
sa.Column('bpmn_task_name', sa.String(length=255), nullable=True),
sa.Column('bpmn_task_type', sa.String(length=255), nullable=True),
sa.Column('spiff_task_guid', sa.String(length=50), nullable=False),
sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False),
sa.Column('message', sa.String(length=255), nullable=True),
sa.Column('current_user_id', sa.Integer(), nullable=True),
sa.Column('spiff_step', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('spiff_step_details',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False),
sa.Column('spiff_step', sa.Integer(), nullable=False),
sa.Column('task_json', sa.JSON(), nullable=False),
sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False),
sa.Column('completed_by_user_id', sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('user', op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=255), nullable=False), sa.Column('username', sa.String(length=255), nullable=False),
@ -216,33 +239,6 @@ def upgrade():
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('principal_id', 'permission_target_id', 'permission', name='permission_assignment_uniq') sa.UniqueConstraint('principal_id', 'permission_target_id', 'permission', name='permission_assignment_uniq')
) )
op.create_table('spiff_logging',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False),
sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=False),
sa.Column('bpmn_task_identifier', sa.String(length=255), nullable=False),
sa.Column('bpmn_task_name', sa.String(length=255), nullable=True),
sa.Column('bpmn_task_type', sa.String(length=255), nullable=True),
sa.Column('spiff_task_guid', sa.String(length=50), nullable=False),
sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False),
sa.Column('message', sa.String(length=255), nullable=True),
sa.Column('current_user_id', sa.Integer(), nullable=True),
sa.Column('spiff_step', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['current_user_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('spiff_step_details',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False),
sa.Column('spiff_step', sa.Integer(), nullable=False),
sa.Column('task_json', sa.JSON(), nullable=False),
sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False),
sa.Column('completed_by_user_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['completed_by_user_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('active_task_user', op.create_table('active_task_user',
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('active_task_id', sa.Integer(), nullable=False), sa.Column('active_task_id', sa.Integer(), nullable=False),
@ -276,8 +272,6 @@ def downgrade():
op.drop_index(op.f('ix_active_task_user_user_id'), table_name='active_task_user') op.drop_index(op.f('ix_active_task_user_user_id'), table_name='active_task_user')
op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user') op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user')
op.drop_table('active_task_user') op.drop_table('active_task_user')
op.drop_table('spiff_step_details')
op.drop_table('spiff_logging')
op.drop_table('permission_assignment') op.drop_table('permission_assignment')
op.drop_table('message_instance') op.drop_table('message_instance')
op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation') op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation')
@ -302,6 +296,8 @@ def downgrade():
op.drop_index(op.f('ix_message_correlation_property_identifier'), table_name='message_correlation_property') op.drop_index(op.f('ix_message_correlation_property_identifier'), table_name='message_correlation_property')
op.drop_table('message_correlation_property') op.drop_table('message_correlation_property')
op.drop_table('user') op.drop_table('user')
op.drop_table('spiff_step_details')
op.drop_table('spiff_logging')
op.drop_table('permission_target') op.drop_table('permission_target')
op.drop_index(op.f('ix_message_model_name'), table_name='message_model') op.drop_index(op.f('ix_message_model_name'), table_name='message_model')
op.drop_index(op.f('ix_message_model_identifier'), table_name='message_model') op.drop_index(op.f('ix_message_model_identifier'), table_name='message_model')

View File

@ -21,7 +21,7 @@ except ImportError:
package = "spiffworkflow_backend" package = "spiffworkflow_backend"
python_versions = ["3.10", "3.9"] python_versions = ["3.11", "3.10", "3.9"]
nox.needs_version = ">= 2021.6.6" nox.needs_version = ">= 2021.6.6"
nox.options.sessions = ( nox.options.sessions = (
"pre-commit", "pre-commit",
@ -96,7 +96,7 @@ def activate_virtualenv_in_precommit_hooks(session: Session) -> None:
hook.write_text("\n".join(lines)) hook.write_text("\n".join(lines))
@session(name="pre-commit", python="3.10") @session(name="pre-commit", python="3.11")
def precommit(session: Session) -> None: def precommit(session: Session) -> None:
"""Lint using pre-commit.""" """Lint using pre-commit."""
args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"] args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"]
@ -119,7 +119,7 @@ def precommit(session: Session) -> None:
activate_virtualenv_in_precommit_hooks(session) activate_virtualenv_in_precommit_hooks(session)
@session(python="3.10") @session(python="3.11")
def safety(session: Session) -> None: def safety(session: Session) -> None:
"""Scan dependencies for insecure packages.""" """Scan dependencies for insecure packages."""
requirements = session.poetry.export_requirements() requirements = session.poetry.export_requirements()
@ -189,7 +189,7 @@ def xdoctest(session: Session) -> None:
session.run("python", "-m", "xdoctest", *args) session.run("python", "-m", "xdoctest", *args)
@session(name="docs-build", python="3.10") @session(name="docs-build", python="3.11")
def docs_build(session: Session) -> None: def docs_build(session: Session) -> None:
"""Build the documentation.""" """Build the documentation."""
args = session.posargs or ["docs", "docs/_build"] args = session.posargs or ["docs", "docs/_build"]
@ -206,7 +206,7 @@ def docs_build(session: Session) -> None:
session.run("sphinx-build", *args) session.run("sphinx-build", *args)
@session(python="3.10") @session(python="3.11")
def docs(session: Session) -> None: def docs(session: Session) -> None:
"""Build and serve the documentation with live reloading on file changes.""" """Build and serve the documentation with live reloading on file changes."""
args = session.posargs or ["--open-browser", "docs", "docs/_build"] args = session.posargs or ["--open-browser", "docs", "docs/_build"]

View File

@ -81,7 +81,10 @@ python-versions = ">=3.7.2"
[package.dependencies] [package.dependencies]
lazy-object-proxy = ">=1.4.0" lazy-object-proxy = ">=1.4.0"
typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""}
wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} wrapt = [
{version = ">=1.11,<2", markers = "python_version < \"3.11\""},
{version = ">=1.14,<2", markers = "python_version >= \"3.11\""},
]
[[package]] [[package]]
name = "attrs" name = "attrs"
@ -95,7 +98,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]] [[package]]
name = "Babel" name = "Babel"
@ -268,7 +271,7 @@ optional = false
python-versions = ">=3.6.0" python-versions = ">=3.6.0"
[package.extras] [package.extras]
unicode_backport = ["unicodedata2"] unicode-backport = ["unicodedata2"]
[[package]] [[package]]
name = "classify-imports" name = "classify-imports"
@ -630,6 +633,7 @@ flask-mail = "*"
flask-marshmallow = "*" flask-marshmallow = "*"
flask-migrate = "*" flask-migrate = "*"
flask-restful = "*" flask-restful = "*"
greenlet = "^2.0.1"
sentry-sdk = "*" sentry-sdk = "*"
sphinx-autoapi = "^2.0.0" sphinx-autoapi = "^2.0.0"
spiffworkflow = "*" spiffworkflow = "*"
@ -639,7 +643,7 @@ werkzeug = "*"
type = "git" type = "git"
url = "https://github.com/sartography/flask-bpmn" url = "https://github.com/sartography/flask-bpmn"
reference = "main" reference = "main"
resolved_reference = "191f0f32798720c9ce1e5307732c90ac26433298" resolved_reference = "b9d4077955e0d45406946ef07440176fb9fd12e5"
[[package]] [[package]]
name = "Flask-Cors" name = "Flask-Cors"
@ -765,14 +769,15 @@ gitdb = ">=4.0.1,<5"
[[package]] [[package]]
name = "greenlet" name = "greenlet"
version = "1.1.3.post0" version = "2.0.1"
description = "Lightweight in-process concurrent programming" description = "Lightweight in-process concurrent programming"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
[package.extras] [package.extras]
docs = ["Sphinx"] docs = ["Sphinx", "docutils (<0.18)"]
test = ["faulthandler", "objgraph", "psutil"]
[[package]] [[package]]
name = "gunicorn" name = "gunicorn"
@ -820,7 +825,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "4.13.0" version = "5.0.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
@ -1512,7 +1517,7 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras] [package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]] [[package]]
name = "requests-toolbelt" name = "requests-toolbelt"
@ -1526,12 +1531,12 @@ python-versions = "*"
requests = ">=2.0.1,<3.0.0" requests = ">=2.0.1,<3.0.0"
[[package]] [[package]]
name = "RestrictedPython" name = "restrictedpython"
version = "5.2" version = "6.0"
description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment." description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.11" python-versions = ">=3.6, <3.12"
[package.extras] [package.extras]
docs = ["Sphinx", "sphinx-rtd-theme"] docs = ["Sphinx", "sphinx-rtd-theme"]
@ -1575,8 +1580,8 @@ docs = ["ryd"]
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
[[package]] [[package]]
name = "ruamel.yaml.clib" name = "ruamel-yaml-clib"
version = "0.2.6" version = "0.2.7"
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
category = "dev" category = "dev"
optional = false optional = false
@ -1625,7 +1630,7 @@ falcon = ["falcon (>=1.4)"]
fastapi = ["fastapi (>=0.79.0)"] fastapi = ["fastapi (>=0.79.0)"]
flask = ["blinker (>=1.1)", "flask (>=0.11)"] flask = ["blinker (>=1.1)", "flask (>=0.11)"]
httpx = ["httpx (>=0.16.0)"] httpx = ["httpx (>=0.16.0)"]
pure_eval = ["asttokens", "executing", "pure-eval"] pure-eval = ["asttokens", "executing", "pure-eval"]
pyspark = ["pyspark (>=2.4.4)"] pyspark = ["pyspark (>=2.4.4)"]
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
rq = ["rq (>=0.6)"] rq = ["rq (>=0.6)"]
@ -1871,7 +1876,7 @@ lxml = "*"
type = "git" type = "git"
url = "https://github.com/sartography/SpiffWorkflow" url = "https://github.com/sartography/SpiffWorkflow"
reference = "main" reference = "main"
resolved_reference = "8d820dce1f439bb76bc07e39629832d998d6f634" resolved_reference = "580939cc8cb0b7ade1571483bd1e28f554434ac4"
[[package]] [[package]]
name = "SQLAlchemy" name = "SQLAlchemy"
@ -1889,19 +1894,19 @@ aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"] asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"]
mariadb_connector = ["mariadb (>=1.0.1,!=1.1.2)"] mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"]
mssql = ["pyodbc"] mssql = ["pyodbc"]
mssql_pymssql = ["pymssql"] mssql-pymssql = ["pymssql"]
mssql_pyodbc = ["pyodbc"] mssql-pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"]
mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"]
mysql_connector = ["mysql-connector-python"] mysql-connector = ["mysql-connector-python"]
oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"] oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"]
postgresql = ["psycopg2 (>=2.7)"] postgresql = ["psycopg2 (>=2.7)"]
postgresql_asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql_pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"]
postgresql_psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql_psycopg2cffi = ["psycopg2cffi"] postgresql-psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"] pymysql = ["pymysql", "pymysql (<1)"]
sqlcipher = ["sqlcipher3_binary"] sqlcipher = ["sqlcipher3_binary"]
@ -2241,7 +2246,7 @@ tests-strict = ["cmake (==3.21.2)", "codecov (==2.0.15)", "ninja (==1.10.2)", "p
[[package]] [[package]]
name = "zipp" name = "zipp"
version = "3.9.0" version = "3.10.0"
description = "Backport of pathlib-compatible object wrapper for zip files" description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main" category = "main"
optional = false optional = false
@ -2253,8 +2258,8 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = ">=3.9,<3.11" python-versions = ">=3.9,<3.12"
content-hash = "995be3a9a60b515b281f017ff32ff27a52ca178b1980611b348dccac6afb6b89" content-hash = "a6d3882a3ab142b82201b83ee8a0552fd16112c4540e2a1dbcb5c38599b917c1"
[metadata.files] [metadata.files]
alabaster = [ alabaster = [
@ -2554,71 +2559,63 @@ GitPython = [
{file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"},
] ]
greenlet = [ greenlet = [
{file = "greenlet-1.1.3.post0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:949c9061b8c6d3e6e439466a9be1e787208dec6246f4ec5fffe9677b4c19fcc3"}, {file = "greenlet-2.0.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c"},
{file = "greenlet-1.1.3.post0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d7815e1519a8361c5ea2a7a5864945906f8e386fa1bc26797b4d443ab11a4589"}, {file = "greenlet-2.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515"},
{file = "greenlet-1.1.3.post0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9649891ab4153f217f319914455ccf0b86986b55fc0573ce803eb998ad7d6854"}, {file = "greenlet-2.0.1-cp27-cp27m-win32.whl", hash = "sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a"},
{file = "greenlet-1.1.3.post0-cp27-cp27m-win32.whl", hash = "sha256:11fc7692d95cc7a6a8447bb160d98671ab291e0a8ea90572d582d57361360f05"}, {file = "greenlet-2.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524"},
{file = "greenlet-1.1.3.post0-cp27-cp27m-win_amd64.whl", hash = "sha256:05ae7383f968bba4211b1fbfc90158f8e3da86804878442b4fb6c16ccbcaa519"}, {file = "greenlet-2.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243"},
{file = "greenlet-1.1.3.post0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ccbe7129a282ec5797df0451ca1802f11578be018a32979131065565da89b392"}, {file = "greenlet-2.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26"},
{file = "greenlet-1.1.3.post0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a8b58232f5b72973350c2b917ea3df0bebd07c3c82a0a0e34775fc2c1f857e9"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd"},
{file = "greenlet-1.1.3.post0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:f6661b58412879a2aa099abb26d3c93e91dedaba55a6394d1fb1512a77e85de9"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45"},
{file = "greenlet-1.1.3.post0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c6e942ca9835c0b97814d14f78da453241837419e0d26f7403058e8db3e38f8"}, {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da"},
{file = "greenlet-1.1.3.post0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a812df7282a8fc717eafd487fccc5ba40ea83bb5b13eb3c90c446d88dbdfd2be"}, {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d"},
{file = "greenlet-1.1.3.post0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83a7a6560df073ec9de2b7cb685b199dfd12519bc0020c62db9d1bb522f989fa"}, {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"},
{file = "greenlet-1.1.3.post0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17a69967561269b691747e7f436d75a4def47e5efcbc3c573180fc828e176d80"}, {file = "greenlet-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617"},
{file = "greenlet-1.1.3.post0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:60839ab4ea7de6139a3be35b77e22e0398c270020050458b3d25db4c7c394df5"}, {file = "greenlet-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9"},
{file = "greenlet-1.1.3.post0-cp310-cp310-win_amd64.whl", hash = "sha256:8926a78192b8b73c936f3e87929931455a6a6c6c385448a07b9f7d1072c19ff3"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94"},
{file = "greenlet-1.1.3.post0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:c6f90234e4438062d6d09f7d667f79edcc7c5e354ba3a145ff98176f974b8132"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a"},
{file = "greenlet-1.1.3.post0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814f26b864ed2230d3a7efe0336f5766ad012f94aad6ba43a7c54ca88dd77cba"}, {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce"},
{file = "greenlet-1.1.3.post0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fda1139d87ce5f7bd80e80e54f9f2c6fe2f47983f1a6f128c47bf310197deb6"}, {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72"},
{file = "greenlet-1.1.3.post0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0643250dd0756f4960633f5359884f609a234d4066686754e834073d84e9b51"}, {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82"},
{file = "greenlet-1.1.3.post0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cb863057bed786f6622982fb8b2c122c68e6e9eddccaa9fa98fd937e45ee6c4f"}, {file = "greenlet-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd"},
{file = "greenlet-1.1.3.post0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8c0581077cf2734569f3e500fab09c0ff6a2ab99b1afcacbad09b3c2843ae743"}, {file = "greenlet-2.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f"},
{file = "greenlet-1.1.3.post0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:695d0d8b5ae42c800f1763c9fce9d7b94ae3b878919379150ee5ba458a460d57"}, {file = "greenlet-2.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f"},
{file = "greenlet-1.1.3.post0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5662492df0588a51d5690f6578f3bbbd803e7f8d99a99f3bf6128a401be9c269"}, {file = "greenlet-2.0.1-cp35-cp35m-win32.whl", hash = "sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955"},
{file = "greenlet-1.1.3.post0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:bffba15cff4802ff493d6edcf20d7f94ab1c2aee7cfc1e1c7627c05f1102eee8"}, {file = "greenlet-2.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77"},
{file = "greenlet-1.1.3.post0-cp35-cp35m-win32.whl", hash = "sha256:7afa706510ab079fd6d039cc6e369d4535a48e202d042c32e2097f030a16450f"}, {file = "greenlet-2.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581"},
{file = "greenlet-1.1.3.post0-cp35-cp35m-win_amd64.whl", hash = "sha256:3a24f3213579dc8459e485e333330a921f579543a5214dbc935bc0763474ece3"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:64e10f303ea354500c927da5b59c3802196a07468332d292aef9ddaca08d03dd"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:eb6ac495dccb1520667cfea50d89e26f9ffb49fa28496dea2b95720d8b45eb54"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:88720794390002b0c8fa29e9602b395093a9a766b229a847e8d88349e418b28a"}, {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39464518a2abe9c505a727af7c0b4efff2cf242aa168be5f0daa47649f4d7ca8"}, {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0914f02fcaa8f84f13b2df4a81645d9e82de21ed95633765dd5cc4d3af9d7403"}, {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96656c5f7c95fc02c36d4f6ef32f4e94bb0b6b36e6a002c21c39785a4eec5f5d"}, {file = "greenlet-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4f74aa0092602da2069df0bc6553919a15169d77bcdab52a21f8c5242898f519"}, {file = "greenlet-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:3aeac044c324c1a4027dca0cde550bd83a0c0fbff7ef2c98df9e718a5086c194"}, {file = "greenlet-2.0.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-win32.whl", hash = "sha256:fe7c51f8a2ab616cb34bc33d810c887e89117771028e1e3d3b77ca25ddeace04"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5"},
{file = "greenlet-1.1.3.post0-cp36-cp36m-win_amd64.whl", hash = "sha256:70048d7b2c07c5eadf8393e6398595591df5f59a2f26abc2f81abca09610492f"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:66aa4e9a726b70bcbfcc446b7ba89c8cec40f405e51422c39f42dfa206a96a05"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:025b8de2273d2809f027d347aa2541651d2e15d593bbce0d5f502ca438c54136"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:82a38d7d2077128a017094aff334e67e26194f46bd709f9dcdacbf3835d47ef5"}, {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7d20c3267385236b4ce54575cc8e9f43e7673fc761b069c820097092e318e3b"}, {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8ece5d1a99a2adcb38f69af2f07d96fb615415d32820108cd340361f590d128"}, {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2794eef1b04b5ba8948c72cc606aab62ac4b0c538b14806d9c0d88afd0576d6b"}, {file = "greenlet-2.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a8d24eb5cb67996fb84633fdc96dbc04f2d8b12bfcb20ab3222d6be271616b67"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0120a879aa2b1ac5118bce959ea2492ba18783f65ea15821680a256dfad04754"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-win32.whl", hash = "sha256:bef49c07fcb411c942da6ee7d7ea37430f830c482bf6e4b72d92fd506dd3a427"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"},
{file = "greenlet-1.1.3.post0-cp37-cp37m-win_amd64.whl", hash = "sha256:62723e7eb85fa52e536e516ee2ac91433c7bb60d51099293671815ff49ed1c21"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"},
{file = "greenlet-1.1.3.post0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d25cdedd72aa2271b984af54294e9527306966ec18963fd032cc851a725ddc1b"}, {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"},
{file = "greenlet-1.1.3.post0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:924df1e7e5db27d19b1359dc7d052a917529c95ba5b8b62f4af611176da7c8ad"}, {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"},
{file = "greenlet-1.1.3.post0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ec615d2912b9ad807afd3be80bf32711c0ff9c2b00aa004a45fd5d5dde7853d9"}, {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"},
{file = "greenlet-1.1.3.post0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0971d37ae0eaf42344e8610d340aa0ad3d06cd2eee381891a10fe771879791f9"}, {file = "greenlet-2.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb"},
{file = "greenlet-1.1.3.post0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:325f272eb997916b4a3fc1fea7313a8adb760934c2140ce13a2117e1b0a8095d"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19"},
{file = "greenlet-1.1.3.post0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75afcbb214d429dacdf75e03a1d6d6c5bd1fa9c35e360df8ea5b6270fb2211c"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"},
{file = "greenlet-1.1.3.post0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5c2d21c2b768d8c86ad935e404cc78c30d53dea009609c3ef3a9d49970c864b5"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"},
{file = "greenlet-1.1.3.post0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:467b73ce5dcd89e381292fb4314aede9b12906c18fab903f995b86034d96d5c8"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"},
{file = "greenlet-1.1.3.post0-cp38-cp38-win32.whl", hash = "sha256:8149a6865b14c33be7ae760bcdb73548bb01e8e47ae15e013bf7ef9290ca309a"}, {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"},
{file = "greenlet-1.1.3.post0-cp38-cp38-win_amd64.whl", hash = "sha256:104f29dd822be678ef6b16bf0035dcd43206a8a48668a6cae4d2fe9c7a7abdeb"}, {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"},
{file = "greenlet-1.1.3.post0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:c8c9301e3274276d3d20ab6335aa7c5d9e5da2009cccb01127bddb5c951f8870"}, {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"},
{file = "greenlet-1.1.3.post0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:8415239c68b2ec9de10a5adf1130ee9cb0ebd3e19573c55ba160ff0ca809e012"}, {file = "greenlet-2.0.1.tar.gz", hash = "sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67"},
{file = "greenlet-1.1.3.post0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:3c22998bfef3fcc1b15694818fc9b1b87c6cc8398198b96b6d355a7bcb8c934e"},
{file = "greenlet-1.1.3.post0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aa1845944e62f358d63fcc911ad3b415f585612946b8edc824825929b40e59e"},
{file = "greenlet-1.1.3.post0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:890f633dc8cb307761ec566bc0b4e350a93ddd77dc172839be122be12bae3e10"},
{file = "greenlet-1.1.3.post0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cf37343e43404699d58808e51f347f57efd3010cc7cee134cdb9141bd1ad9ea"},
{file = "greenlet-1.1.3.post0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5edf75e7fcfa9725064ae0d8407c849456553a181ebefedb7606bac19aa1478b"},
{file = "greenlet-1.1.3.post0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win32.whl", hash = "sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2"},
{file = "greenlet-1.1.3.post0-cp39-cp39-win_amd64.whl", hash = "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7"},
] ]
gunicorn = [ gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
@ -2637,8 +2634,8 @@ imagesize = [
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
] ]
importlib-metadata = [ importlib-metadata = [
{file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"}, {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"},
{file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"}, {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"},
] ]
inflection = [ inflection = [
{file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"},
@ -2943,7 +2940,10 @@ orjson = [
{file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"}, {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"},
{file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"}, {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"},
{file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"}, {file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"},
{file = "orjson-3.8.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:200eae21c33f1f8b02a11f5d88d76950cd6fd986d88f1afe497a8ae2627c49aa"},
{file = "orjson-3.8.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9529990f3eab54b976d327360aa1ff244a4b12cb5e4c5b3712fcdd96e8fe56d4"},
{file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"}, {file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"},
{file = "orjson-3.8.0-cp311-none-win_amd64.whl", hash = "sha256:b21c7af0ff6228ca7105f54f0800636eb49201133e15ddb80ac20c1ce973ef07"},
{file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"},
{file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"},
{file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"}, {file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"},
@ -3056,18 +3056,7 @@ py = [
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
] ]
pyasn1 = [ pyasn1 = [
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
{file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"},
{file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"},
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
{file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"},
{file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"},
{file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"},
{file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"},
{file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"},
{file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"},
{file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"},
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
] ]
pycodestyle = [ pycodestyle = [
@ -3287,9 +3276,9 @@ requests-toolbelt = [
{file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"},
{file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"},
] ]
RestrictedPython = [ restrictedpython = [
{file = "RestrictedPython-5.2-py2.py3-none-any.whl", hash = "sha256:fdf8621034c5dcb990a2a198f232f66b2d48866dd16d848e00ac7d187ae452ba"}, {file = "RestrictedPython-6.0-py3-none-any.whl", hash = "sha256:3479303f7bff48a7dedad76f96e7704993c5e86c5adbd67f607295d5352f0fb8"},
{file = "RestrictedPython-5.2.tar.gz", hash = "sha256:634da1f6c5c122a262f433b083ee3d17a9a039f8f1b3778597efb47461cd361b"}, {file = "RestrictedPython-6.0.tar.gz", hash = "sha256:405cf0bd9eec2f19b1326b5f48228efe56d6590b4e91826b8cc3b2cd400a96ad"},
] ]
restructuredtext-lint = [ restructuredtext-lint = [
{file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"},
@ -3302,37 +3291,40 @@ rsa = [
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
{file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
] ]
"ruamel.yaml.clib" = [ ruamel-yaml-clib = [
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"},
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:066f886bc90cc2ce44df8b5f7acfc6a7e2b2e672713f027136464492b0c34d7c"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"},
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"},
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"},
{file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d3c620a54748a3d4cf0bcfe623e388407c8e85a4b06b8188e126302bcab93ea8"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:210c8fcfeff90514b7133010bf14e3bad652c8efde6b20e00c43854bf94fa5a6"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:61bc5e5ca632d95925907c569daa559ea194a4d16084ba86084be98ab1cec1c6"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1b4139a6ffbca8ef60fdaf9b33dec05143ba746a6f0ae0f9d11d38239211d335"}, {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"},
{file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"},
{file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"},
{file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"},
] ]
safety = [ safety = [
{file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"}, {file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"},
@ -3706,6 +3698,6 @@ xdoctest = [
{file = "xdoctest-1.1.0.tar.gz", hash = "sha256:0fd4fad7932f0a2f082dfdfb857dd6ca41603757586c39b1e5b4d333fc389f8a"}, {file = "xdoctest-1.1.0.tar.gz", hash = "sha256:0fd4fad7932f0a2f082dfdfb857dd6ca41603757586c39b1e5b4d333fc389f8a"},
] ]
zipp = [ zipp = [
{file = "zipp-3.9.0-py3-none-any.whl", hash = "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980"}, {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"},
{file = "zipp-3.9.0.tar.gz", hash = "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb"}, {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"},
] ]

View File

@ -16,7 +16,7 @@ classifiers = [
Changelog = "https://github.com/sartography/spiffworkflow-backend/releases" Changelog = "https://github.com/sartography/spiffworkflow-backend/releases"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.9,<3.11" python = ">=3.9,<3.12"
click = "^8.0.1" click = "^8.0.1"
flask = "2.2.2" flask = "2.2.2"
flask-admin = "*" flask-admin = "*"
@ -47,7 +47,7 @@ gunicorn = "^20.1.0"
python-keycloak = "^2.5.0" python-keycloak = "^2.5.0"
APScheduler = "^3.9.1" APScheduler = "^3.9.1"
Jinja2 = "^3.1.2" Jinja2 = "^3.1.2"
RestrictedPython = "^5.2" RestrictedPython = "^6.0"
Flask-SQLAlchemy = "^3" Flask-SQLAlchemy = "^3"
orjson = "^3.8.0" orjson = "^3.8.0"

View File

@ -1,7 +1,7 @@
sonar.organization=sartography sonar.organization=sartography
sonar.projectKey=sartography_spiffworkflow-backend sonar.projectKey=sartography_spiffworkflow-backend
sonar.host.url=https://sonarcloud.io sonar.host.url=https://sonarcloud.io
sonar.python.version=3.9,3.10 sonar.python.version=3.9,3.10,3.11
sonar.python.coverage.reportPaths=coverage.xml sonar.python.coverage.reportPaths=coverage.xml
sonar.test.inclusions=tests sonar.test.inclusions=tests

View File

@ -72,16 +72,16 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
__tablename__ = "process_instance" __tablename__ = "process_instance"
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
process_model_identifier: str = db.Column(db.String(255), nullable=False, index=True) process_model_identifier: str = db.Column(
db.String(255), nullable=False, index=True
)
process_group_identifier: str = db.Column(db.String(50), nullable=False, index=True) process_group_identifier: str = db.Column(db.String(50), nullable=False, index=True)
process_initiator_id: int = db.Column(ForeignKey(UserModel.id), nullable=False) process_initiator_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
process_initiator = relationship("UserModel") process_initiator = relationship("UserModel")
active_tasks = relationship("ActiveTaskModel", cascade="delete") # type: ignore active_tasks = relationship("ActiveTaskModel", cascade="delete") # type: ignore
spiff_logs = relationship("SpiffLoggingModel", cascade="delete") # type: ignore
message_instances = relationship("MessageInstanceModel", cascade="delete") # type: ignore message_instances = relationship("MessageInstanceModel", cascade="delete") # type: ignore
message_correlations = relationship("MessageCorrelationModel", cascade="delete") # type: ignore message_correlations = relationship("MessageCorrelationModel", cascade="delete") # type: ignore
spiff_step_details = relationship("SpiffStepDetailsModel", cascade="delete") # type: ignore
bpmn_json: str | None = deferred(db.Column(db.JSON)) # type: ignore bpmn_json: str | None = deferred(db.Column(db.JSON)) # type: ignore
start_in_seconds: int | None = db.Column(db.Integer) start_in_seconds: int | None = db.Column(db.Integer)
@ -265,7 +265,7 @@ class ProcessInstanceMetadata:
id=process_instance.id, id=process_instance.id,
display_name=process_model.display_name, display_name=process_model.display_name,
description=process_model.description, description=process_model.description,
process_group_id=process_model.process_group_id, process_group_id=process_model.process_group,
state_message=process_instance.state_message, state_message=process_instance.state_message,
status=process_instance.status, status=process_instance.status,
completed_tasks=process_instance.completed_tasks, completed_tasks=process_instance.completed_tasks,

View File

@ -238,18 +238,18 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
user: UserModel, user: UserModel,
) -> ProcessInstanceReportModel: ) -> ProcessInstanceReportModel:
"""Create_with_attributes.""" """Create_with_attributes."""
# <<<<<<< HEAD # <<<<<<< HEAD
# process_model = ProcessModelService().get_process_model( # process_model = ProcessModelService().get_process_model(
# process_model_id=f"{process_model_identifier}" # process_model_id=f"{process_model_identifier}"
# ) # )
# process_instance_report = cls( # process_instance_report = cls(
# identifier=identifier, # identifier=identifier,
# process_group_identifier="process_model.process_group_id", # process_group_identifier="process_model.process_group_id",
# process_model_identifier=process_model.id, # process_model_identifier=process_model.id,
# ======= # =======
process_instance_report = cls( process_instance_report = cls(
identifier=identifier, identifier=identifier,
# >>>>>>> main # >>>>>>> main
created_by_id=user.id, created_by_id=user.id,
report_metadata=report_metadata, report_metadata=report_metadata,
) )

View File

@ -4,10 +4,6 @@ from typing import Optional
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel
@dataclass @dataclass
@ -16,7 +12,7 @@ class SpiffLoggingModel(SpiffworkflowBaseDBModel):
__tablename__ = "spiff_logging" __tablename__ = "spiff_logging"
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
process_instance_id: int = db.Column(ForeignKey(ProcessInstanceModel.id), nullable=False) # type: ignore process_instance_id: int = db.Column(db.Integer, nullable=False)
bpmn_process_identifier: str = db.Column(db.String(255), nullable=False) bpmn_process_identifier: str = db.Column(db.String(255), nullable=False)
bpmn_task_identifier: str = db.Column(db.String(255), nullable=False) bpmn_task_identifier: str = db.Column(db.String(255), nullable=False)
bpmn_task_name: str = db.Column(db.String(255), nullable=True) bpmn_task_name: str = db.Column(db.String(255), nullable=True)
@ -24,5 +20,5 @@ class SpiffLoggingModel(SpiffworkflowBaseDBModel):
spiff_task_guid: str = db.Column(db.String(50), nullable=False) spiff_task_guid: str = db.Column(db.String(50), nullable=False)
timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False) timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False)
message: Optional[str] = db.Column(db.String(255), nullable=True) message: Optional[str] = db.Column(db.String(255), nullable=True)
current_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=True) current_user_id: int = db.Column(db.Integer, nullable=True)
spiff_step: int = db.Column(db.Integer, nullable=False) spiff_step: int = db.Column(db.Integer, nullable=False)

View File

@ -3,12 +3,8 @@ from dataclasses import dataclass
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey
from sqlalchemy.orm import deferred from sqlalchemy.orm import deferred
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel
@dataclass @dataclass
class SpiffStepDetailsModel(SpiffworkflowBaseDBModel): class SpiffStepDetailsModel(SpiffworkflowBaseDBModel):
@ -16,8 +12,8 @@ class SpiffStepDetailsModel(SpiffworkflowBaseDBModel):
__tablename__ = "spiff_step_details" __tablename__ = "spiff_step_details"
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
process_instance_id: int = db.Column(ForeignKey(ProcessInstanceModel.id), nullable=False) # type: ignore process_instance_id: int = db.Column(db.Integer, nullable=False)
spiff_step: int = db.Column(db.Integer, nullable=False) spiff_step: int = db.Column(db.Integer, nullable=False)
task_json: str | None = deferred(db.Column(db.JSON, nullable=False)) # type: ignore task_json: str | None = deferred(db.Column(db.JSON, nullable=False)) # type: ignore
timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False) timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False)
completed_by_user_id: int = db.Column(ForeignKey(UserModel.id), nullable=True) completed_by_user_id: int = db.Column(db.Integer, nullable=True)

View File

@ -138,11 +138,13 @@ def permissions_check(body: Dict[str, Dict[str, list[str]]]) -> flask.wrappers.R
def modify_process_model_id(process_model_id: str) -> str: def modify_process_model_id(process_model_id: str) -> str:
return process_model_id.replace('/', ':') """Modify_process_model_id."""
return process_model_id.replace("/", ":")
def un_modify_modified_process_model_id(modified_process_model_id: str) -> str: def un_modify_modified_process_model_id(modified_process_model_id: str) -> str:
return modified_process_model_id.replace(':', '/') """Un_modify_modified_process_model_id."""
return modified_process_model_id.replace(":", "/")
def process_group_add(body: dict) -> flask.wrappers.Response: def process_group_add(body: dict) -> flask.wrappers.Response:
@ -251,7 +253,7 @@ def process_model_add(
def process_model_delete( def process_model_delete(
modified_process_model_identifier: str modified_process_model_identifier: str,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_model_delete.""" """Process_model_delete."""
process_model_identifier = modified_process_model_identifier.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
@ -265,7 +267,12 @@ def process_model_update(
) -> Any: ) -> Any:
"""Process_model_update.""" """Process_model_update."""
process_model_identifier = modified_process_model_identifier.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
body_include_list = ["display_name", "primary_file_name", "primary_process_id", "description"] body_include_list = [
"display_name",
"primary_file_name",
"primary_process_id",
"description",
]
body_filtered = { body_filtered = {
include_item: body[include_item] include_item: body[include_item]
for include_item in body_include_list for include_item in body_include_list
@ -415,11 +422,11 @@ def add_file(modified_process_model_id: str) -> flask.wrappers.Response:
) )
def process_instance_create( def process_instance_create(modified_process_model_id: str) -> flask.wrappers.Response:
modified_process_model_id: str
) -> flask.wrappers.Response:
"""Create_process_instance.""" """Create_process_instance."""
process_model_identifier = un_modify_modified_process_model_id(modified_process_model_id) process_model_identifier = un_modify_modified_process_model_id(
modified_process_model_id
)
process_instance = ProcessInstanceService.create_process_instance( process_instance = ProcessInstanceService.create_process_instance(
process_model_identifier, g.user process_model_identifier, g.user
) )
@ -522,7 +529,7 @@ def process_instance_log_list(
) )
.order_by(SpiffLoggingModel.timestamp.desc()) # type: ignore .order_by(SpiffLoggingModel.timestamp.desc()) # type: ignore
.join( .join(
UserModel, isouter=True UserModel, UserModel.id == SpiffLoggingModel.current_user_id, isouter=True
) # isouter since if we don't have a user, we still want the log ) # isouter since if we don't have a user, we still want the log
.add_columns( .add_columns(
UserModel.username, UserModel.username,
@ -785,14 +792,18 @@ def process_instance_show(
return make_response(jsonify(process_instance), 200) return make_response(jsonify(process_instance), 200)
def process_instance_delete( def process_instance_delete(process_instance_id: int) -> flask.wrappers.Response:
process_instance_id: int
) -> flask.wrappers.Response:
"""Create_process_instance.""" """Create_process_instance."""
process_instance = find_process_instance_by_id_or_raise(process_instance_id) process_instance = find_process_instance_by_id_or_raise(process_instance_id)
# (Pdb) db.session.delete # (Pdb) db.session.delete
# <bound method delete of <sqlalchemy.orm.scoping.scoped_session object at 0x103eaab30>> # <bound method delete of <sqlalchemy.orm.scoping.scoped_session object at 0x103eaab30>>
db.session.query(SpiffLoggingModel).filter_by(
process_instance_id=process_instance.id
).delete()
db.session.query(SpiffStepDetailsModel).filter_by(
process_instance_id=process_instance.id
).delete()
db.session.delete(process_instance) db.session.delete(process_instance)
db.session.commit() db.session.commit()
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
@ -906,7 +917,6 @@ def process_instance_report_show(
per_page: int = 100, per_page: int = 100,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_list.""" """Process_instance_list."""
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id) process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
).paginate( ).paginate(
@ -1302,9 +1312,7 @@ def get_process_model(process_model_id: str) -> ProcessModelInfo:
"""Get_process_model.""" """Get_process_model."""
process_model = None process_model = None
try: try:
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(process_model_id)
process_model_id
)
except ProcessEntityNotFoundError as exception: except ProcessEntityNotFoundError as exception:
raise ( raise (
ApiError( ApiError(

View File

@ -105,7 +105,7 @@ def verify_token(
raise ApiError( raise ApiError(
error_code="fail_get_user_info", error_code="fail_get_user_info",
message="Cannot get user info from token", message="Cannot get user info from token",
status_code=401 status_code=401,
) from e ) from e
if ( if (

View File

@ -13,8 +13,8 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]:
"""Load_fixtures.""" """Load_fixtures."""
current_app.logger.debug("load_acceptance_test_fixtures() start") current_app.logger.debug("load_acceptance_test_fixtures() start")
test_process_group_id = "acceptance-tests-group-one" test_process_group_id = ""
test_process_model_id = "acceptance-tests-model-1" test_process_model_id = "acceptance-tests-group-one/acceptance-tests-model-1"
user = BaseTest.find_or_create_user() user = BaseTest.find_or_create_user()
statuses = ProcessInstanceStatus.list() statuses = ProcessInstanceStatus.list()
current_time = round(time.time()) current_time = round(time.time())

View File

@ -48,7 +48,7 @@ class DataSetupService:
except Exception as ex: except Exception as ex:
failing_process_models.append( failing_process_models.append(
( (
f"{process_model.process_group_id}/{process_model.id}/{process_model_file.name}", f"{process_model.process_group}/{process_model.id}/{process_model_file.name}",
str(ex), str(ex),
) )
) )
@ -87,7 +87,7 @@ class DataSetupService:
else: else:
failing_process_models.append( failing_process_models.append(
( (
f"{process_model.process_group_id}/{process_model.id}", f"{process_model.process_group}/{process_model.id}",
"primary_file_name not set", "primary_file_name not set",
) )
) )

View File

@ -67,7 +67,9 @@ class FileSystemService:
@staticmethod @staticmethod
def full_path_to_process_model_file(spec: ProcessModelInfo) -> str: def full_path_to_process_model_file(spec: ProcessModelInfo) -> str:
"""Full_path_to_process_model_file.""" """Full_path_to_process_model_file."""
return os.path.join(FileSystemService.workflow_path(spec), spec.primary_file_name) return os.path.join(
FileSystemService.workflow_path(spec), spec.primary_file_name # type: ignore
)
def next_display_order(self, spec: ProcessModelInfo) -> int: def next_display_order(self, spec: ProcessModelInfo) -> int:
"""Next_display_order.""" """Next_display_order."""

View File

@ -193,6 +193,17 @@ def setup_logger(app: Flask) -> None:
class DBHandler(logging.Handler): class DBHandler(logging.Handler):
"""DBHandler.""" """DBHandler."""
def __init__(self) -> None:
"""__init__."""
self.logs: list[dict] = []
super().__init__()
def bulk_insert_logs(self) -> None:
"""Bulk_insert_logs."""
db.session.bulk_insert_mappings(SpiffLoggingModel, self.logs)
db.session.commit()
self.logs = []
def emit(self, record: logging.LogRecord) -> None: def emit(self, record: logging.LogRecord) -> None:
"""Emit.""" """Emit."""
# if we do not have a process instance id then do not log and assume we are running a script unit test # if we do not have a process instance id then do not log and assume we are running a script unit test
@ -211,17 +222,19 @@ class DBHandler(logging.Handler):
if hasattr(record, "spiff_step") and record.spiff_step is not None # type: ignore if hasattr(record, "spiff_step") and record.spiff_step is not None # type: ignore
else 1 else 1
) )
spiff_log = SpiffLoggingModel( self.logs.append(
process_instance_id=record.process_instance_id, # type: ignore {
bpmn_process_identifier=bpmn_process_identifier, "process_instance_id": record.process_instance_id, # type: ignore
spiff_task_guid=spiff_task_guid, "bpmn_process_identifier": bpmn_process_identifier,
bpmn_task_name=bpmn_task_name, "spiff_task_guid": spiff_task_guid,
bpmn_task_identifier=bpmn_task_identifier, "bpmn_task_name": bpmn_task_name,
bpmn_task_type=bpmn_task_type, "bpmn_task_identifier": bpmn_task_identifier,
message=message, "bpmn_task_type": bpmn_task_type,
timestamp=timestamp, "message": message,
current_user_id=current_user_id, "timestamp": timestamp,
spiff_step=spiff_step, "current_user_id": current_user_id,
"spiff_step": spiff_step,
}
) )
db.session.add(spiff_log) if len(self.logs) % 1000 == 0:
db.session.commit() self.bulk_insert_logs()

View File

@ -293,8 +293,9 @@ class ProcessInstanceProcessor:
tld.spiff_step = process_instance_model.spiff_step tld.spiff_step = process_instance_model.spiff_step
# we want this to be the fully qualified path to the process model including all group subcomponents # 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 = ( current_app.config[
f"{process_instance_model.process_group_identifier}/" "THREAD_LOCAL_DATA"
].process_model_identifier = (
f"{process_instance_model.process_model_identifier}" f"{process_instance_model.process_model_identifier}"
) )
@ -558,7 +559,7 @@ class ProcessInstanceProcessor:
"lane_assignment_id": lane_assignment_id, "lane_assignment_id": lane_assignment_id,
} }
def save_spiff_step_details(self) -> None: def spiff_step_details_mapping(self) -> dict:
"""SaveSpiffStepDetails.""" """SaveSpiffStepDetails."""
bpmn_json = self.serialize() bpmn_json = self.serialize()
wf_json = json.loads(bpmn_json) wf_json = json.loads(bpmn_json)
@ -569,13 +570,29 @@ class ProcessInstanceProcessor:
# TODO want to just save the tasks, something wasn't immediately working # TODO want to just save the tasks, something wasn't immediately working
# so after the flow works with the full wf_json revisit this # so after the flow works with the full wf_json revisit this
task_json = wf_json task_json = wf_json
return {
"process_instance_id": self.process_instance_model.id,
"spiff_step": self.process_instance_model.spiff_step or 1,
"task_json": task_json,
"timestamp": round(time.time()),
"completed_by_user_id": self.current_user().id,
}
def spiff_step_details(self) -> SpiffStepDetailsModel:
"""SaveSpiffStepDetails."""
details_mapping = self.spiff_step_details_mapping()
details_model = SpiffStepDetailsModel( details_model = SpiffStepDetailsModel(
process_instance_id=self.process_instance_model.id, process_instance_id=details_mapping["process_instance_id"],
spiff_step=self.process_instance_model.spiff_step or 1, spiff_step=details_mapping["spiff_step"],
task_json=task_json, task_json=details_mapping["task_json"],
timestamp=round(time.time()), timestamp=details_mapping["timestamp"],
completed_by_user_id=self.current_user().id, completed_by_user_id=details_mapping["completed_by_user_id"],
) )
return details_model
def save_spiff_step_details(self) -> None:
"""SaveSpiffStepDetails."""
details_model = self.spiff_step_details()
db.session.add(details_model) db.session.add(details_model)
db.session.commit() db.session.commit()
@ -988,25 +1005,47 @@ class ProcessInstanceProcessor:
self.process_instance_model.spiff_step = spiff_step self.process_instance_model.spiff_step = spiff_step
current_app.config["THREAD_LOCAL_DATA"].spiff_step = spiff_step current_app.config["THREAD_LOCAL_DATA"].spiff_step = spiff_step
db.session.add(self.process_instance_model) db.session.add(self.process_instance_model)
db.session.commit()
# TODO remove after done with the performance improvements
# to use delete the _ prefix here and add it to the real def below
def _do_engine_steps(self, exit_at: None = None, save: bool = False) -> None:
"""__do_engine_steps."""
import cProfile
from pstats import SortKey
with cProfile.Profile() as pr:
self._do_engine_steps(exit_at=exit_at, save=save)
pr.print_stats(sort=SortKey.CUMULATIVE)
def do_engine_steps(self, exit_at: None = None, save: bool = False) -> None: def do_engine_steps(self, exit_at: None = None, save: bool = False) -> None:
"""Do_engine_steps.""" """Do_engine_steps."""
step_details = []
try: try:
self.bpmn_process_instance.refresh_waiting_tasks( self.bpmn_process_instance.refresh_waiting_tasks(
will_refresh_task=lambda t: self.increment_spiff_step(), will_refresh_task=lambda t: self.increment_spiff_step(),
did_refresh_task=lambda t: self.save_spiff_step_details(), did_refresh_task=lambda t: step_details.append(
self.spiff_step_details_mapping()
),
) )
self.bpmn_process_instance.do_engine_steps( self.bpmn_process_instance.do_engine_steps(
exit_at=exit_at, exit_at=exit_at,
will_complete_task=lambda t: self.increment_spiff_step(), will_complete_task=lambda t: self.increment_spiff_step(),
did_complete_task=lambda t: self.save_spiff_step_details(), did_complete_task=lambda t: step_details.append(
self.spiff_step_details_mapping()
),
) )
self.process_bpmn_messages() self.process_bpmn_messages()
self.queue_waiting_receive_messages() self.queue_waiting_receive_messages()
db.session.bulk_insert_mappings(SpiffStepDetailsModel, step_details)
spiff_logger = logging.getLogger("spiff")
for handler in spiff_logger.handlers:
if hasattr(handler, "bulk_insert_logs"):
handler.bulk_insert_logs() # type: ignore
db.session.commit()
except WorkflowTaskExecException as we: except WorkflowTaskExecException as we:
raise ApiError.from_workflow_exception("task_error", str(we), we) from we raise ApiError.from_workflow_exception("task_error", str(we), we) from we

View File

@ -2,12 +2,10 @@
import time import time
from typing import Any from typing import Any
from typing import List from typing import List
from typing import Optional
from flask import current_app from flask import current_app
from flask_bpmn.api.api_error import ApiError from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore
from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceApi

View File

@ -34,13 +34,15 @@ class ProcessModelService(FileSystemService):
GROUP_SCHEMA = ProcessGroupSchema() GROUP_SCHEMA = ProcessGroupSchema()
WF_SCHEMA = ProcessModelInfoSchema() WF_SCHEMA = ProcessModelInfoSchema()
def is_group(self, path): def is_group(self, path: str) -> bool:
"""Is_group."""
group_json_path = os.path.join(path, self.CAT_JSON_FILE) group_json_path = os.path.join(path, self.CAT_JSON_FILE)
if os.path.exists(group_json_path): if os.path.exists(group_json_path):
return True return True
return False return False
def is_model(self, path): def is_model(self, path: str) -> bool:
"""Is_model."""
model_json_path = os.path.join(path, self.WF_JSON_FILE) model_json_path = os.path.join(path, self.WF_JSON_FILE)
if os.path.exists(model_json_path): if os.path.exists(model_json_path):
return True return True
@ -92,7 +94,7 @@ class ProcessModelService(FileSystemService):
error_code="existing_instances", error_code="existing_instances",
message=f"We cannot delete the model `{process_model_id}`, there are existing instances that depend on it.", message=f"We cannot delete the model `{process_model_id}`, there are existing instances that depend on it.",
) )
process_model = self.get_process_model(process_model_id) self.get_process_model(process_model_id)
# path = self.workflow_path(process_model) # path = self.workflow_path(process_model)
path = f"{FileSystemService.root_path()}/{process_model_id}" path = f"{FileSystemService.root_path()}/{process_model_id}"
shutil.rmtree(path) shutil.rmtree(path)
@ -107,11 +109,11 @@ class ProcessModelService(FileSystemService):
path = os.path.join(FileSystemService.root_path(), relative_path) path = os.path.join(FileSystemService.root_path(), relative_path)
return cls().__scan_spec(path, process_group=process_group) return cls().__scan_spec(path, process_group=process_group)
def get_process_model( def get_process_model(self, process_model_id: str) -> ProcessModelInfo:
self, process_model_id: str
) -> ProcessModelInfo:
"""Get a process model from a model and group id. """Get a process model from a model and group id.
process_model_id is the full path to the model--including groups"""
process_model_id is the full path to the model--including groups.
"""
if not os.path.exists(FileSystemService.root_path()): if not os.path.exists(FileSystemService.root_path()):
raise ProcessEntityNotFoundError("process_model_root_not_found") raise ProcessEntityNotFoundError("process_model_root_not_found")
@ -168,8 +170,9 @@ class ProcessModelService(FileSystemService):
def get_process_group(self, process_group_id: str) -> ProcessGroup: def get_process_group(self, process_group_id: str) -> ProcessGroup:
"""Look for a given process_group, and return it.""" """Look for a given process_group, and return it."""
if os.path.exists(FileSystemService.root_path()): if os.path.exists(FileSystemService.root_path()):
process_group_path = os.path.join(
process_group_path = os.path.join(FileSystemService.root_path(), process_group_id) FileSystemService.root_path(), process_group_id
)
if self.is_group(process_group_path): if self.is_group(process_group_path):
return self.__scan_process_group(process_group_path) return self.__scan_process_group(process_group_path)
# nested_groups = [] # nested_groups = []
@ -236,7 +239,7 @@ class ProcessModelService(FileSystemService):
process_groups = [] process_groups = []
for item in directory_items: for item in directory_items:
# if item.is_dir() and not item.name[0] == ".": # if item.is_dir() and not item.name[0] == ".":
if item.is_dir() and self.is_group(item): if item.is_dir() and self.is_group(item): # type: ignore
scanned_process_group = self.__scan_process_group(item.path) scanned_process_group = self.__scan_process_group(item.path)
process_groups.append(scanned_process_group) process_groups.append(scanned_process_group)
return process_groups return process_groups
@ -254,7 +257,7 @@ class ProcessModelService(FileSystemService):
message=f"We could not load the process_group from disk from: {dir_path}", message=f"We could not load the process_group from disk from: {dir_path}",
) )
else: else:
process_group_id = dir_path.replace(FileSystemService.root_path(), '') process_group_id = dir_path.replace(FileSystemService.root_path(), "")
process_group = ProcessGroup( process_group = ProcessGroup(
id=process_group_id, id=process_group_id,
display_name=process_group_id, display_name=process_group_id,
@ -279,7 +282,9 @@ class ProcessModelService(FileSystemService):
elif self.is_model(nested_item.path): elif self.is_model(nested_item.path):
process_group.process_models.append( process_group.process_models.append(
self.__scan_spec( self.__scan_spec(
nested_item.path, nested_item.name, process_group=process_group nested_item.path,
nested_item.name,
process_group=process_group,
) )
) )
process_group.process_models.sort() process_group.process_models.sort()
@ -323,5 +328,5 @@ class ProcessModelService(FileSystemService):
with open(spec_path, "w") as wf_json: with open(spec_path, "w") as wf_json:
json.dump(self.WF_SCHEMA.dump(spec), wf_json, indent=4) json.dump(self.WF_SCHEMA.dump(spec), wf_json, indent=4)
if process_group: if process_group:
spec.process_group_id = process_group.id spec.process_group = process_group.id
return spec return spec

View File

@ -107,7 +107,9 @@ class SpecFileService(FileSystemService):
"""Update_file.""" """Update_file."""
SpecFileService.assert_valid_file_name(file_name) SpecFileService.assert_valid_file_name(file_name)
# file_path = SpecFileService.file_path(process_model_info, file_name) # file_path = SpecFileService.file_path(process_model_info, file_name)
file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name) file_path = os.path.join(
FileSystemService.root_path(), process_model_info.id, file_name
)
SpecFileService.write_file_data_to_system(file_path, binary_data) SpecFileService.write_file_data_to_system(file_path, binary_data)
file = SpecFileService.to_file_object(file_name, file_path) file = SpecFileService.to_file_object(file_name, file_path)
@ -132,7 +134,9 @@ class SpecFileService(FileSystemService):
def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes: def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes:
"""Get_data.""" """Get_data."""
# file_path = SpecFileService.file_path(process_model_info, file_name) # file_path = SpecFileService.file_path(process_model_info, file_name)
file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name) file_path = os.path.join(
FileSystemService.root_path(), process_model_info.id, file_name
)
if not os.path.exists(file_path): if not os.path.exists(file_path):
raise ProcessModelFileNotFoundError( raise ProcessModelFileNotFoundError(
f"No file found with name {file_name} in {process_model_info.display_name}" f"No file found with name {file_name} in {process_model_info.display_name}"
@ -465,10 +469,12 @@ class SpecFileService(FileSystemService):
) )
if message_triggerable_process_model is None: if message_triggerable_process_model is None:
message_triggerable_process_model = MessageTriggerableProcessModel( message_triggerable_process_model = (
message_model_id=message_model.id, MessageTriggerableProcessModel(
process_model_identifier=process_model_info.id, message_model_id=message_model.id,
process_group_identifier="process_group_identifier", process_model_identifier=process_model_info.id,
process_group_identifier="process_group_identifier",
)
) )
db.session.add(message_triggerable_process_model) db.session.add(message_triggerable_process_model)
db.session.commit() db.session.commit()
@ -480,8 +486,7 @@ class SpecFileService(FileSystemService):
# != process_model_info.process_group_id # != process_model_info.process_group_id
): ):
raise ValidationException( raise ValidationException(
"Message model is already used to start process model" f"Message model is already used to start process model {process_model_info.id}"
f"'{process_model_info.process_group_id}/{process_model_info.id}'"
) )
for child in et_root: for child in et_root:

View File

@ -12,10 +12,6 @@ from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from flask_bpmn.api.api_error import ApiError from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from spiffworkflow_backend.services.file_system_service import FileSystemService
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from werkzeug.test import TestResponse # type: ignore from werkzeug.test import TestResponse # type: ignore
@ -29,6 +25,7 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.file_system_service import FileSystemService
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
from spiffworkflow_backend.services.user_service import UserService from spiffworkflow_backend.services.user_service import UserService
@ -45,19 +42,22 @@ class BaseTest:
process_group_id: Optional[str] = "test_group", process_group_id: Optional[str] = "test_group",
process_model_id: Optional[str] = "random_fact", process_model_id: Optional[str] = "random_fact",
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
bpmn_file_location: Optional[str] = None bpmn_file_location: Optional[str] = None,
) -> str: ) -> str:
"""Creates a process group """Creates a process group.
Creates a process model
Adds a bpmn file to the model"""
process_group_display_name = process_group_id Creates a process model
process_group_description = process_group_id Adds a bpmn file to the model.
"""
process_group_display_name = process_group_id or ""
process_group_description = process_group_id or ""
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
if bpmn_file_location is None: if bpmn_file_location is None:
bpmn_file_location = process_model_id bpmn_file_location = process_model_id
self.create_process_group(client, user, process_group_id, process_group_display_name) self.create_process_group(
client, user, process_group_description, process_group_display_name
)
self.create_process_model_with_api( self.create_process_model_with_api(
client, client,
@ -70,7 +70,7 @@ class BaseTest:
load_test_spec( load_test_spec(
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
process_model_source_directory=bpmn_file_location process_model_source_directory=bpmn_file_location,
) )
return process_model_identifier return process_model_identifier
@ -115,8 +115,9 @@ class BaseTest:
headers: Dict[str, str], headers: Dict[str, str],
) -> TestResponse: ) -> TestResponse:
"""Create_process_instance. """Create_process_instance.
There must be an existing process model to instantiate."""
There must be an existing process model to instantiate.
"""
modified_process_model_id = test_process_model_id.replace("/", ":") modified_process_model_id = test_process_model_id.replace("/", ":")
response = client.post( response = client.post(
f"/v1.0/process-models/{modified_process_model_id}/process-instances", f"/v1.0/process-models/{modified_process_model_id}/process-instances",
@ -138,7 +139,6 @@ class BaseTest:
user: Optional[UserModel] = None, user: Optional[UserModel] = None,
) -> TestResponse: ) -> TestResponse:
"""Create_process_model.""" """Create_process_model."""
if process_model_id is not None: if process_model_id is not None:
# make sure we have a group # make sure we have a group
@ -174,7 +174,9 @@ class BaseTest:
else: else:
raise Exception("You must create the group first") raise Exception("You must create the group first")
else: else:
raise Exception("You must include the process_model_id, which must be a path to the model") raise Exception(
"You must include the process_model_id, which must be a path to the model"
)
def create_spec_file( def create_spec_file(
self, self,
@ -187,18 +189,20 @@ class BaseTest:
user: Optional[UserModel] = None, user: Optional[UserModel] = None,
) -> Any: ) -> Any:
"""Test_create_spec_file. """Test_create_spec_file.
Adds a bpmn file to the model. Adds a bpmn file to the model.
process_model_id is the destination path process_model_id is the destination path
process_model_location is the source path process_model_location is the source path
because of permissions, user might be required now..., not sure yet""" because of permissions, user might be required now..., not sure yet.
"""
if process_model_location is None: if process_model_location is None:
process_model_location = file_name.split(".")[0] process_model_location = file_name.split(".")[0]
if process_model is None: if process_model is None:
process_model = load_test_spec( process_model = load_test_spec(
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=file_name, bpmn_file_name=file_name,
process_model_source_directory=process_model_location process_model_source_directory=process_model_location,
) )
data = {"file": (io.BytesIO(file_data), file_name)} data = {"file": (io.BytesIO(file_data), file_name)}
if user is None: if user is None:

View File

@ -21,7 +21,7 @@ class ExampleDataLoader:
display_order: int = 0, display_order: int = 0,
# from_tests: bool = False, # from_tests: bool = False,
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
process_model_source_directory: str = None, process_model_source_directory: Optional[str] = None,
) -> ProcessModelInfo: ) -> ProcessModelInfo:
"""Assumes that process_model_source_directory exists in static/bpmn and contains bpmn_file_name. """Assumes that process_model_source_directory exists in static/bpmn and contains bpmn_file_name.

View File

@ -38,10 +38,9 @@ def assure_process_group_exists(process_group_id: Optional[str] = None) -> Proce
def load_test_spec( def load_test_spec(
process_model_id: str, process_model_id: str,
bpmn_file_name: Optional[str] = None, bpmn_file_name: Optional[str] = None,
process_model_source_directory: str = None, process_model_source_directory: Optional[str] = None,
) -> ProcessModelInfo: ) -> ProcessModelInfo:
"""Loads a bpmn file into the process model dir based on a directory in tests/data.""" """Loads a bpmn file into the process model dir based on a directory in tests/data."""
if process_model_source_directory is None: if process_model_source_directory is None:
raise Exception("You must inclode a `process_model_source_directory`.") raise Exception("You must inclode a `process_model_source_directory`.")

View File

@ -19,15 +19,17 @@ class TestLoggingService(BaseTest):
"""Test_process_instance_run.""" """Test_process_instance_run."""
process_group_id = "test_logging_spiff_logger" process_group_id = "test_logging_spiff_logger"
process_model_id = "simple_script" process_model_id = "simple_script"
self.create_process_group(client=client, user=with_super_admin_user, process_group_id=process_group_id) self.create_process_group(
client=client, user=with_super_admin_user, process_group_id=process_group_id
)
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
# create the model # create the model
process_model_info = self.create_process_model_with_api( self.create_process_model_with_api(
client=client, client=client,
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
process_model_display_name="Simple Script", process_model_display_name="Simple Script",
process_model_description="Simple Script", process_model_description="Simple Script",
user=with_super_admin_user user=with_super_admin_user,
) )
bpmn_file_name = "simple_script.bpmn" bpmn_file_name = "simple_script.bpmn"
@ -40,7 +42,7 @@ class TestLoggingService(BaseTest):
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
file_name=bpmn_file_name, file_name=bpmn_file_name,
file_data=bpmn_file_data_bytes, file_data=bpmn_file_data_bytes,
user=with_super_admin_user user=with_super_admin_user,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
response = self.create_process_instance( response = self.create_process_instance(

View File

@ -1,41 +1,46 @@
"""Test_nested_groups."""
import json import json
from spiffworkflow_backend.models.process_group import ProcessGroup, ProcessGroupSchema
from spiffworkflow_backend.models.process_model import ProcessModelInfo, ProcessModelInfoSchema
from spiffworkflow_backend.models.user import UserModel
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.process_group import ProcessGroup
from spiffworkflow_backend.models.process_group import ProcessGroupSchema
from spiffworkflow_backend.models.process_model import ProcessModelInfo
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
from spiffworkflow_backend.models.user import UserModel
class TestNestedGroups(BaseTest): class TestNestedGroups(BaseTest):
"""TestNestedGroups."""
def test_nested_groups( def test_nested_groups(
self, self,
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
) -> None: ) -> None:
"""Test_nested_groups."""
# /process-groups/{process_group_path}/show # /process-groups/{process_group_path}/show
target_uri = "/v1.0/process-groups/group_a,group_b" target_uri = "/v1.0/process-groups/group_a,group_b"
user = self.find_or_create_user() user = self.find_or_create_user()
self.add_permissions_to_user( self.add_permissions_to_user(
user, target_uri=target_uri, permission_names=["read"] user, target_uri=target_uri, permission_names=["read"]
) )
response = client.get( response = client.get( # noqa: F841
target_uri, target_uri, headers=self.logged_in_headers(user)
headers=self.logged_in_headers(user)
) )
print("test_nested_groups") print("test_nested_groups")
def test_add_nested_group( def test_add_nested_group(
self, self,
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
target_uri = "/process-groups" """Test_add_nested_group."""
# user = self.find_or_create_user() # user = self.find_or_create_user()
# self.add_permissions_to_user( # self.add_permissions_to_user(
# user, target_uri=target_uri, permission_names=["read", "create"] # user, target_uri=target_uri, permission_names=["read", "create"]
@ -46,33 +51,31 @@ class TestNestedGroups(BaseTest):
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_a = client.post( response_a = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
data=json.dumps(ProcessGroupSchema().dump(process_group_a)), data=json.dumps(ProcessGroupSchema().dump(process_group_a)),
) )
process_group_b = ProcessGroup( process_group_b = ProcessGroup(
id="group_a/group_b", id="group_a/group_b",
display_name="Group B", display_name="Group B",
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_b = client.post( response_b = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
data=json.dumps(ProcessGroupSchema().dump(process_group_b)), data=json.dumps(ProcessGroupSchema().dump(process_group_b)),
) )
process_group_c = ProcessGroup( process_group_c = ProcessGroup(
id="group_a/group_b/group_c", id="group_a/group_b/group_c",
display_name="Group C", display_name="Group C",
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_c = client.post( response_c = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
@ -82,32 +85,32 @@ class TestNestedGroups(BaseTest):
print("test_add_nested_group") print("test_add_nested_group")
def test_process_model_add( def test_process_model_add(
self, self,
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
): ) -> None:
"""Test_process_model_add."""
process_group_a = ProcessGroup( process_group_a = ProcessGroup(
id="group_a", id="group_a",
display_name="Group A", display_name="Group A",
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_a = client.post( response_a = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
data=json.dumps(ProcessGroupSchema().dump(process_group_a)), data=json.dumps(ProcessGroupSchema().dump(process_group_a)),
) )
process_group_b = ProcessGroup( process_group_b = ProcessGroup(
id="group_a/group_b", id="group_a/group_b",
display_name="Group B", display_name="Group B",
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_b = client.post( response_b = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
@ -119,24 +122,24 @@ class TestNestedGroups(BaseTest):
description="Process Model", description="Process Model",
primary_file_name="primary_file.bpmn", primary_file_name="primary_file.bpmn",
primary_process_id="primary_process_id", primary_process_id="primary_process_id",
display_order=0 display_order=0,
) )
model_response = client.post( model_response = client.post( # noqa: F841
"v1.0/process-models", "v1.0/process-models",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
data=json.dumps(ProcessModelInfoSchema().dump(process_model)) data=json.dumps(ProcessModelInfoSchema().dump(process_model)),
) )
print("test_process_model_add") print("test_process_model_add")
def test_process_group_show( def test_process_group_show(
self, self,
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_process_group_show."""
# target_uri = "/process-groups/{process_group_id}" # target_uri = "/process-groups/{process_group_id}"
# user = self.find_or_create_user("testadmin1") # user = self.find_or_create_user("testadmin1")
# self.add_permissions_to_user( # self.add_permissions_to_user(
@ -152,7 +155,7 @@ class TestNestedGroups(BaseTest):
display_order=0, display_order=0,
admin=False, admin=False,
) )
response_create_a = client.post( response_create_a = client.post( # noqa: F841
"/v1.0/process-groups", "/v1.0/process-groups",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
@ -164,9 +167,8 @@ class TestNestedGroups(BaseTest):
self.add_permissions_to_user( self.add_permissions_to_user(
user, target_uri=target_uri, permission_names=["read"] user, target_uri=target_uri, permission_names=["read"]
) )
response = client.get( response = client.get( # noqa: F841
target_uri, target_uri, headers=self.logged_in_headers(user)
headers=self.logged_in_headers(user)
) )
print("test_process_group_show: ") print("test_process_group_show: ")

View File

@ -9,8 +9,6 @@ import pytest
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
@ -33,6 +31,9 @@ from spiffworkflow_backend.services.file_system_service import FileSystemService
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,
) )
from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.process_model_service import ProcessModelService
# from spiffworkflow_backend.services.git_service import GitService # from spiffworkflow_backend.services.git_service import GitService
@ -114,7 +115,9 @@ class TestProcessApi(BaseTest):
process_group_id = "test_process_group" process_group_id = "test_process_group"
process_group_display_name = "Test Process Group" process_group_display_name = "Test Process Group"
# creates the group directory, and the json file # creates the group directory, and the json file
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_display_name) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_display_name
)
process_model_id = "sample" process_model_id = "sample"
model_display_name = "Sample" model_display_name = "Sample"
@ -170,14 +173,16 @@ class TestProcessApi(BaseTest):
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
initial_primary_process_id = "sample" initial_primary_process_id = "sample"
terminal_primary_process_id = "new_process_id" terminal_primary_process_id = "new_process_id"
self.create_process_group(client=client, user=with_super_admin_user, process_group_id=process_group_id) self.create_process_group(
client=client, user=with_super_admin_user, process_group_id=process_group_id
)
bpmn_file_name = f"{process_model_id}.bpmn" bpmn_file_name = f"{process_model_id}.bpmn"
bpmn_file_source_directory = process_model_id bpmn_file_source_directory = process_model_id
process_model = load_test_spec( process_model = load_test_spec(
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
process_model_source_directory=process_model_id process_model_source_directory=process_model_id,
) )
assert process_model.primary_process_id == initial_primary_process_id assert process_model.primary_process_id == initial_primary_process_id
@ -220,7 +225,9 @@ class TestProcessApi(BaseTest):
process_group_description = "Test Process Group" process_group_description = "Test Process Group"
process_model_id = "sample" process_model_id = "sample"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_description) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_description
)
self.create_process_model_with_api( self.create_process_model_with_api(
client, client,
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
@ -228,7 +235,9 @@ class TestProcessApi(BaseTest):
) )
# assert we have a model # assert we have a model
process_model = ProcessModelService().get_process_model(process_model_identifier) process_model = ProcessModelService().get_process_model(
process_model_identifier
)
assert process_model is not None assert process_model is not None
assert process_model.id == process_model_identifier assert process_model.id == process_model_identifier
@ -261,7 +270,9 @@ class TestProcessApi(BaseTest):
process_model_identifier = f"{test_process_group_id}/{test_process_model_id}" process_model_identifier = f"{test_process_group_id}/{test_process_model_id}"
modified_process_model_identifier = process_model_identifier.replace("/", ":") modified_process_model_identifier = process_model_identifier.replace("/", ":")
self.create_process_group(client, with_super_admin_user, test_process_group_id) self.create_process_group(client, with_super_admin_user, test_process_group_id)
self.create_process_model_with_api(client, process_model_identifier, user=with_super_admin_user) self.create_process_model_with_api(
client, process_model_identifier, user=with_super_admin_user
)
bpmn_file_data_bytes = self.get_test_data_file_contents( bpmn_file_data_bytes = self.get_test_data_file_contents(
bpmn_file_name, bpmn_file_location bpmn_file_name, bpmn_file_location
) )
@ -271,7 +282,7 @@ class TestProcessApi(BaseTest):
process_model_location=test_process_model_id, process_model_location=test_process_model_id,
file_name=bpmn_file_name, file_name=bpmn_file_name,
file_data=bpmn_file_data_bytes, file_data=bpmn_file_data_bytes,
user=with_super_admin_user user=with_super_admin_user,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
# create an instance from a model # create an instance from a model
@ -306,14 +317,18 @@ class TestProcessApi(BaseTest):
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_process_model_update.""" """Test_process_model_update."""
self.create_process_group(client, with_super_admin_user, "test_process_group", "Test Process Group") self.create_process_group(
client, with_super_admin_user, "test_process_group", "Test Process Group"
)
process_model_identifier = "test_process_group/make_cookies" process_model_identifier = "test_process_group/make_cookies"
self.create_process_model_with_api( self.create_process_model_with_api(
client, client,
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
user=with_super_admin_user, user=with_super_admin_user,
) )
process_model = ProcessModelService().get_process_model(process_model_identifier) process_model = ProcessModelService().get_process_model(
process_model_identifier
)
assert process_model.id == process_model_identifier assert process_model.id == process_model_identifier
assert process_model.display_name == "Cooooookies" assert process_model.display_name == "Cooooookies"
assert process_model.is_review is False assert process_model.is_review is False
@ -608,7 +623,6 @@ class TestProcessApi(BaseTest):
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_process_model_file_update.""" """Test_process_model_file_update."""
process_model_identifier = self.basic_test_setup(client, with_super_admin_user) process_model_identifier = self.basic_test_setup(client, with_super_admin_user)
modified_process_model_id = process_model_identifier.replace("/", ":") modified_process_model_id = process_model_identifier.replace("/", ":")
@ -661,7 +675,9 @@ class TestProcessApi(BaseTest):
process_group_description = "Test Group" process_group_description = "Test Group"
process_model_id = "random_fact" process_model_id = "random_fact"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_description) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_description
)
self.create_process_model_with_api( self.create_process_model_with_api(
client, client,
process_model_id=process_model_identifier, process_model_id=process_model_identifier,
@ -672,7 +688,7 @@ class TestProcessApi(BaseTest):
original_file = load_test_spec( original_file = load_test_spec(
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
process_model_source_directory="random_fact" process_model_source_directory="random_fact",
) )
modified_process_model_id = process_model_identifier.replace("/", ":") modified_process_model_id = process_model_identifier.replace("/", ":")
@ -712,7 +728,9 @@ class TestProcessApi(BaseTest):
# process_model = load_test_spec("random_fact") # process_model = load_test_spec("random_fact")
bad_process_model_identifier = f"x{process_model_identifier}" bad_process_model_identifier = f"x{process_model_identifier}"
modified_bad_process_model_identifier = bad_process_model_identifier.replace("/", ":") modified_bad_process_model_identifier = bad_process_model_identifier.replace(
"/", ":"
)
response = client.delete( response = client.delete(
f"/v1.0/process-models/{modified_bad_process_model_identifier}/files/random_fact.svg", f"/v1.0/process-models/{modified_bad_process_model_identifier}/files/random_fact.svg",
follow_redirects=True, follow_redirects=True,
@ -920,9 +938,7 @@ class TestProcessApi(BaseTest):
"""Test_process_instance_create.""" """Test_process_instance_create."""
test_process_model_id = "runs_without_input/sample" test_process_model_id = "runs_without_input/sample"
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
response = self.create_process_instance( response = self.create_process_instance(client, test_process_model_id, headers)
client, test_process_model_id, headers
)
assert response.json is not None assert response.json is not None
assert response.json["updated_at_in_seconds"] is not None assert response.json["updated_at_in_seconds"] is not None
assert response.json["status"] == "not_started" assert response.json["status"] == "not_started"
@ -946,7 +962,7 @@ class TestProcessApi(BaseTest):
process_group_id="runs_without_input", process_group_id="runs_without_input",
process_model_id="sample", process_model_id="sample",
bpmn_file_name=None, bpmn_file_name=None,
bpmn_file_location="sample" bpmn_file_location="sample",
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
@ -955,7 +971,6 @@ class TestProcessApi(BaseTest):
) )
assert response.json is not None assert response.json is not None
process_instance_id = response.json["id"] process_instance_id = response.json["id"]
modified_process_model_identifier = process_model_identifier.replace("/", ":")
response = client.post( response = client.post(
f"/v1.0/process-instances/{process_instance_id}/run", f"/v1.0/process-instances/{process_instance_id}/run",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
@ -987,7 +1002,7 @@ class TestProcessApi(BaseTest):
client, client,
with_super_admin_user, with_super_admin_user,
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id process_model_id=process_model_id,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":") modified_process_model_identifier = process_model_identifier.replace("/", ":")
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
@ -1006,7 +1021,9 @@ class TestProcessApi(BaseTest):
) )
assert show_response.json is not None assert show_response.json is not None
file_system_root = FileSystemService.root_path() file_system_root = FileSystemService.root_path()
file_path = f"{file_system_root}/{process_model_identifier}/{process_model_id}.bpmn" file_path = (
f"{file_system_root}/{process_model_identifier}/{process_model_id}.bpmn"
)
with open(file_path) as f_open: with open(file_path) as f_open:
xml_file_contents = f_open.read() xml_file_contents = f_open.read()
assert show_response.json["bpmn_xml_file_contents"] == xml_file_contents assert show_response.json["bpmn_xml_file_contents"] == xml_file_contents
@ -1030,7 +1047,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
message_model_identifier = "message_send" message_model_identifier = "message_send"
@ -1078,9 +1095,8 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":")
message_model_identifier = "message_response" message_model_identifier = "message_response"
payload = { payload = {
@ -1147,9 +1163,8 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":")
response = self.create_process_instance( response = self.create_process_instance(
client, client,
@ -1197,9 +1212,8 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":")
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
response = self.create_process_instance( response = self.create_process_instance(
@ -1230,7 +1244,6 @@ class TestProcessApi(BaseTest):
"""Test_process_instance_run_user_task.""" """Test_process_instance_run_user_task."""
process_group_id = "my_process_group" process_group_id = "my_process_group"
process_model_id = "dynamic_enum_select_fields" process_model_id = "dynamic_enum_select_fields"
bpmn_file_name = "dynamic_enums_ask_for_color.bpmn"
bpmn_file_location = "dynamic_enum_select_fields" bpmn_file_location = "dynamic_enum_select_fields"
process_model_identifier = self.basic_test_setup( process_model_identifier = self.basic_test_setup(
client, client,
@ -1238,9 +1251,8 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
# bpmn_file_name=bpmn_file_name, # bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":")
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
response = self.create_process_instance( response = self.create_process_instance(
@ -1255,7 +1267,7 @@ class TestProcessApi(BaseTest):
) )
assert response.json is not None assert response.json is not None
assert response.json['next_task'] is not None assert response.json["next_task"] is not None
active_tasks = ( active_tasks = (
db.session.query(ActiveTaskModel) db.session.query(ActiveTaskModel)
@ -1290,13 +1302,11 @@ class TestProcessApi(BaseTest):
with_super_admin_user, with_super_admin_user,
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
self.create_process_instance( self.create_process_instance(client, process_model_identifier, headers)
client, process_model_identifier, headers
)
response = client.get( response = client.get(
"/v1.0/process-instances", "/v1.0/process-instances",
@ -1312,7 +1322,8 @@ class TestProcessApi(BaseTest):
process_instance_dict = response.json["results"][0] process_instance_dict = response.json["results"][0]
assert type(process_instance_dict["id"]) is int assert type(process_instance_dict["id"]) is int
assert ( assert (
process_instance_dict["process_model_identifier"] == process_model_identifier process_instance_dict["process_model_identifier"]
== process_model_identifier
) )
assert type(process_instance_dict["start_in_seconds"]) is int assert type(process_instance_dict["start_in_seconds"]) is int
assert process_instance_dict["start_in_seconds"] > 0 assert process_instance_dict["start_in_seconds"] > 0
@ -1337,24 +1348,14 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
self.create_process_instance( self.create_process_instance(client, process_model_identifier, headers)
client, process_model_identifier, headers self.create_process_instance(client, process_model_identifier, headers)
) self.create_process_instance(client, process_model_identifier, headers)
self.create_process_instance( self.create_process_instance(client, process_model_identifier, headers)
client, process_model_identifier, headers self.create_process_instance(client, process_model_identifier, headers)
)
self.create_process_instance(
client, process_model_identifier, headers
)
self.create_process_instance(
client, process_model_identifier, headers
)
self.create_process_instance(
client, process_model_identifier, headers
)
response = client.get( response = client.get(
"/v1.0/process-instances?per_page=2&page=3", "/v1.0/process-instances?per_page=2&page=3",
@ -1396,7 +1397,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
statuses = [status.value for status in ProcessInstanceStatus] statuses = [status.value for status in ProcessInstanceStatus]
@ -1503,15 +1504,14 @@ class TestProcessApi(BaseTest):
process_model_id = "sample" process_model_id = "sample"
bpmn_file_name = "sample.bpmn" bpmn_file_name = "sample.bpmn"
bpmn_file_location = "sample" bpmn_file_location = "sample"
process_model_identifier = self.basic_test_setup( process_model_identifier = self.basic_test_setup( # noqa: F841
client, client,
with_super_admin_user, with_super_admin_user,
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
modified_process_model_identifier = process_model_identifier.replace("/", ":")
self.logged_in_headers(with_super_admin_user) self.logged_in_headers(with_super_admin_user)
report_identifier = "testreport" report_identifier = "testreport"
@ -1553,7 +1553,6 @@ class TestProcessApi(BaseTest):
# bpmn_file_location=bpmn_file_location # bpmn_file_location=bpmn_file_location
# ) # )
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
modified_process_model_identifier = process_model_identifier.replace("/", ":")
report_metadata = { report_metadata = {
"columns": [ "columns": [
@ -1594,7 +1593,8 @@ class TestProcessApi(BaseTest):
process_instance_dict = response.json["results"][0] process_instance_dict = response.json["results"][0]
assert type(process_instance_dict["id"]) is int assert type(process_instance_dict["id"]) is int
assert ( assert (
process_instance_dict["process_model_identifier"] == process_model_identifier process_instance_dict["process_model_identifier"]
== process_model_identifier
) )
assert type(process_instance_dict["start_in_seconds"]) is int assert type(process_instance_dict["start_in_seconds"]) is int
assert process_instance_dict["start_in_seconds"] > 0 assert process_instance_dict["start_in_seconds"] > 0
@ -1609,7 +1609,6 @@ class TestProcessApi(BaseTest):
setup_process_instances_for_reports: list[ProcessInstanceModel], setup_process_instances_for_reports: list[ProcessInstanceModel],
) -> None: ) -> None:
"""Test_process_instance_report_show_with_default_list.""" """Test_process_instance_report_show_with_default_list."""
report_metadata = { report_metadata = {
"filter_by": [ "filter_by": [
{ {
@ -1659,9 +1658,7 @@ class TestProcessApi(BaseTest):
) -> Any: ) -> Any:
"""Setup_testing_instance.""" """Setup_testing_instance."""
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
response = self.create_process_instance( response = self.create_process_instance(client, process_model_id, headers)
client, process_model_id, headers
)
process_instance = response.json process_instance = response.json
assert isinstance(process_instance, dict) assert isinstance(process_instance, dict)
process_instance_id = process_instance["id"] process_instance_id = process_instance["id"]
@ -1685,7 +1682,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
process_instance_id = self.setup_testing_instance( process_instance_id = self.setup_testing_instance(
@ -1739,7 +1736,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
process_instance_id = self.setup_testing_instance( process_instance_id = self.setup_testing_instance(
@ -1793,7 +1790,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
process_instance_id = self.setup_testing_instance( process_instance_id = self.setup_testing_instance(
@ -1852,7 +1849,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
result = self.create_spec_file( result = self.create_spec_file(
@ -1885,7 +1882,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
# load_test_spec( # load_test_spec(
# "message_receiver", # "message_receiver",
@ -1977,7 +1974,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
# process_model = load_test_spec( # process_model = load_test_spec(
@ -2171,6 +2168,7 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_process_instance_suspend."""
bpmn_file_name = "manual_task.bpmn" bpmn_file_name = "manual_task.bpmn"
bpmn_file_location = "manual_task" bpmn_file_location = "manual_task"
process_model_identifier = self.basic_test_setup( process_model_identifier = self.basic_test_setup(
@ -2178,7 +2176,7 @@ class TestProcessApi(BaseTest):
user=with_super_admin_user, user=with_super_admin_user,
process_model_id="manual_task", process_model_id="manual_task",
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
bpmn_file_data_bytes = self.get_test_data_file_contents( bpmn_file_data_bytes = self.get_test_data_file_contents(
@ -2190,7 +2188,7 @@ class TestProcessApi(BaseTest):
process_model_location=process_model_identifier, process_model_location=process_model_identifier,
file_name=bpmn_file_name, file_name=bpmn_file_name,
file_data=bpmn_file_data_bytes, file_data=bpmn_file_data_bytes,
user=with_super_admin_user user=with_super_admin_user,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
@ -2205,14 +2203,18 @@ class TestProcessApi(BaseTest):
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
process_instance = ProcessInstanceService().get_process_instance(process_instance_id) process_instance = ProcessInstanceService().get_process_instance(
process_instance_id
)
assert process_instance.status == "user_input_required" assert process_instance.status == "user_input_required"
client.post( client.post(
f"/v1.0/process-instances/{process_instance_id}/suspend", f"/v1.0/process-instances/{process_instance_id}/suspend",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
process_instance = ProcessInstanceService().get_process_instance(process_instance_id) process_instance = ProcessInstanceService().get_process_instance(
process_instance_id
)
assert process_instance.status == "suspended" assert process_instance.status == "suspended"
# TODO: Why can I run a suspended process instance? # TODO: Why can I run a suspended process instance?
@ -2232,6 +2234,7 @@ class TestProcessApi(BaseTest):
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel, with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_script_unit_test_run."""
process_group_id = "test_group" process_group_id = "test_group"
process_model_id = "simple_script" process_model_id = "simple_script"
bpmn_file_name = "simple_script.bpmn" bpmn_file_name = "simple_script.bpmn"
@ -2242,7 +2245,7 @@ class TestProcessApi(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
bpmn_file_data_bytes = self.get_test_data_file_contents( bpmn_file_data_bytes = self.get_test_data_file_contents(
@ -2254,7 +2257,7 @@ class TestProcessApi(BaseTest):
process_model_location=process_model_identifier, process_model_location=process_model_identifier,
file_name=bpmn_file_name, file_name=bpmn_file_name,
file_data=bpmn_file_data_bytes, file_data=bpmn_file_data_bytes,
user=with_super_admin_user user=with_super_admin_user,
) )
# python_script = _get_required_parameter_or_raise("python_script", body) # python_script = _get_required_parameter_or_raise("python_script", body)
@ -2263,22 +2266,21 @@ class TestProcessApi(BaseTest):
# "expected_output_json", body # "expected_output_json", body
# ) # )
python_script = "c = a + b" python_script = "c = a + b"
input_json = {'a': 1, 'b': 2} input_json = {"a": 1, "b": 2}
expected_output_json = {'a': 1, 'b': 2, 'c': 3} expected_output_json = {"a": 1, "b": 2, "c": 3}
# bpmn_task_identifier = "Activity_CalculateNewData" # bpmn_task_identifier = "Activity_CalculateNewData"
data = { data = {
'python_script': python_script, "python_script": python_script,
'input_json': input_json, "input_json": input_json,
'expected_output_json': expected_output_json, "expected_output_json": expected_output_json,
} }
response = client.post( response = client.post( # noqa: F841
f"/v1.0/process-models/{process_group_id}/{process_model_id}/script-unit-tests/run", f"/v1.0/process-models/{process_group_id}/{process_model_id}/script-unit-tests/run",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
content_type="application/json", content_type="application/json",
data=json.dumps(data), data=json.dumps(data),
) )
print("test_script_unit_test_run") print("test_script_unit_test_run")

View File

@ -42,7 +42,9 @@ class SecretServiceTestHelpers(BaseTest):
self.test_process_group_id, self.test_process_group_id,
display_name=self.test_process_group_display_name, display_name=self.test_process_group_display_name,
) )
process_model_identifier = f"{self.test_process_group_id}/{self.test_process_model_id}" process_model_identifier = (
f"{self.test_process_group_id}/{self.test_process_model_id}"
)
self.create_process_model_with_api( self.create_process_model_with_api(
client, client,
process_model_id=process_model_identifier, process_model_id=process_model_identifier,

View File

@ -21,7 +21,7 @@ class TestGetGroupMembers(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_get_members_of_a_group.""" """Test_can_get_members_of_a_group."""
initiator_user = self.find_or_create_user("initiator_user") initiator_user = self.find_or_create_user("initiator_user")
@ -38,11 +38,13 @@ class TestGetGroupMembers(BaseTest):
UserService.add_user_to_group(testuser2, group_a) UserService.add_user_to_group(testuser2, group_a)
UserService.add_user_to_group(testuser3, group_b) UserService.add_user_to_group(testuser3, group_b)
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
process_model_id="test_group/get_group_members", process_model_id="test_group/get_group_members",
bpmn_file_name="get_group_members.bpmn", bpmn_file_name="get_group_members.bpmn",
process_model_source_directory="get_group_members" process_model_source_directory="get_group_members",
) )
process_instance = self.create_process_instance_from_process_model( process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=initiator_user process_model=process_model, user=initiator_user

View File

@ -50,13 +50,17 @@ class TestGetLocaltime(BaseTest):
"""Test_process_instance_run.""" """Test_process_instance_run."""
initiator_user = self.find_or_create_user("initiator_user") initiator_user = self.find_or_create_user("initiator_user")
self.add_permissions_to_user( self.add_permissions_to_user(
initiator_user, target_uri="/v1.0/process-groups", permission_names=["read", "create"] initiator_user,
target_uri="/v1.0/process-groups",
permission_names=["read", "create"],
)
self.create_process_group(
client=client, user=initiator_user, process_group_id="test_group"
) )
self.create_process_group(client=client, user=initiator_user, process_group_id="test_group")
process_model = load_test_spec( process_model = load_test_spec(
process_model_id="test_group/get_localtime", process_model_id="test_group/get_localtime",
bpmn_file_name="get_localtime.bpmn", bpmn_file_name="get_localtime.bpmn",
process_model_source_directory="get_localtime" process_model_source_directory="get_localtime",
) )
process_instance = self.create_process_instance_from_process_model( process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=initiator_user process_model=process_model, user=initiator_user

View File

@ -2,12 +2,10 @@
import pytest import pytest
from flask import Flask from flask import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.services.process_model_service import ProcessModelService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.user import UserModel, UserNotFoundError from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user import UserNotFoundError
from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.authorization_service import AuthorizationService
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,
@ -15,6 +13,7 @@ from spiffworkflow_backend.services.process_instance_processor import (
from spiffworkflow_backend.services.process_instance_service import ( from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService, ProcessInstanceService,
) )
from spiffworkflow_backend.services.process_model_service import ProcessModelService
class TestAuthorizationService(BaseTest): class TestAuthorizationService(BaseTest):
@ -96,7 +95,7 @@ class TestAuthorizationService(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_user_can_be_added_to_active_task_on_first_login.""" """Test_user_can_be_added_to_active_task_on_first_login."""
initiator_user = self.find_or_create_user("initiator_user") initiator_user = self.find_or_create_user("initiator_user")
@ -111,7 +110,7 @@ class TestAuthorizationService(BaseTest):
process_group_id="test_group", process_group_id="test_group",
process_model_id="model_with_lanes", process_model_id="model_with_lanes",
bpmn_file_name="lanes.bpmn", bpmn_file_name="lanes.bpmn",
bpmn_file_location="model_with_lanes" bpmn_file_location="model_with_lanes",
) )
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(

View File

@ -1,10 +1,7 @@
"""Test_various_bpmn_constructs.""" """Test_various_bpmn_constructs."""
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.services.authorization_service import AuthorizationService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
@ -19,7 +16,11 @@ class TestDotNotation(BaseTest):
"""TestVariousBpmnConstructs.""" """TestVariousBpmnConstructs."""
def test_dot_notation( def test_dot_notation(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_form_data_conversion_to_dot_dict.""" """Test_form_data_conversion_to_dot_dict."""
process_group_id = "dot_notation_group" process_group_id = "dot_notation_group"
@ -32,7 +33,7 @@ class TestDotNotation(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
headers = self.logged_in_headers(with_super_admin_user) headers = self.logged_in_headers(with_super_admin_user)
@ -40,7 +41,9 @@ class TestDotNotation(BaseTest):
client, process_model_identifier, headers client, process_model_identifier, headers
) )
process_instance_id = response.json["id"] process_instance_id = response.json["id"]
process_instance = ProcessInstanceService().get_process_instance(process_instance_id) process_instance = ProcessInstanceService().get_process_instance(
process_instance_id
)
processor = ProcessInstanceProcessor(process_instance) processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps(save=True) processor.do_engine_steps(save=True)

View File

@ -3,19 +3,19 @@ import pytest
from flask import Flask from flask import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from spiffworkflow_backend.services.process_model_service import ProcessModelService
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel
from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.message_model import MessageModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_model_service import ProcessModelService
class TestMessageInstance(BaseTest): class TestMessageInstance(BaseTest):
"""TestMessageInstance.""" """TestMessageInstance."""
def setup_message_tests(self, client: FlaskClient, user: UserModel) -> str: def setup_message_tests(self, client: FlaskClient, user: UserModel) -> str:
"""Setup_message_tests."""
process_group_id = "test_group" process_group_id = "test_group"
process_model_id = "hello_world" process_model_id = "hello_world"
bpmn_file_name = "hello_world.bpmn" bpmn_file_name = "hello_world.bpmn"
@ -26,17 +26,23 @@ class TestMessageInstance(BaseTest):
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
bpmn_file_name=bpmn_file_name, bpmn_file_name=bpmn_file_name,
bpmn_file_location=bpmn_file_location bpmn_file_location=bpmn_file_location,
) )
return process_model_identifier return process_model_identifier
def test_can_create_message_instance( def test_can_create_message_instance(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_create_message_instance.""" """Test_can_create_message_instance."""
message_model_identifier = "message_model_one" message_model_identifier = "message_model_one"
message_model = self.create_message_model(message_model_identifier) message_model = self.create_message_model(message_model_identifier)
process_model_identifier = self.setup_message_tests(client, with_super_admin_user) process_model_identifier = self.setup_message_tests(
client, with_super_admin_user
)
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(
process_model_id=process_model_identifier process_model_id=process_model_identifier
@ -62,12 +68,18 @@ class TestMessageInstance(BaseTest):
assert queued_message_from_query is not None assert queued_message_from_query is not None
def test_cannot_set_invalid_status( def test_cannot_set_invalid_status(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_cannot_set_invalid_status.""" """Test_cannot_set_invalid_status."""
message_model_identifier = "message_model_one" message_model_identifier = "message_model_one"
message_model = self.create_message_model(message_model_identifier) message_model = self.create_message_model(message_model_identifier)
process_model_identifier = self.setup_message_tests(client, with_super_admin_user) process_model_identifier = self.setup_message_tests(
client, with_super_admin_user
)
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(
process_model_id=process_model_identifier process_model_id=process_model_identifier
@ -102,12 +114,18 @@ class TestMessageInstance(BaseTest):
) )
def test_cannot_set_invalid_message_type( def test_cannot_set_invalid_message_type(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_cannot_set_invalid_message_type.""" """Test_cannot_set_invalid_message_type."""
message_model_identifier = "message_model_one" message_model_identifier = "message_model_one"
message_model = self.create_message_model(message_model_identifier) message_model = self.create_message_model(message_model_identifier)
process_model_identifier = self.setup_message_tests(client, with_super_admin_user) process_model_identifier = self.setup_message_tests(
client, with_super_admin_user
)
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(
process_model_id=process_model_identifier process_model_id=process_model_identifier
@ -143,12 +161,18 @@ class TestMessageInstance(BaseTest):
) )
def test_force_failure_cause_if_status_is_failure( def test_force_failure_cause_if_status_is_failure(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_force_failure_cause_if_status_is_failure.""" """Test_force_failure_cause_if_status_is_failure."""
message_model_identifier = "message_model_one" message_model_identifier = "message_model_one"
message_model = self.create_message_model(message_model_identifier) message_model = self.create_message_model(message_model_identifier)
process_model_identifier = self.setup_message_tests(client, with_super_admin_user) process_model_identifier = self.setup_message_tests(
client, with_super_admin_user
)
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(
process_model_id=process_model_identifier process_model_id=process_model_identifier

View File

@ -24,16 +24,22 @@ class TestMessageService(BaseTest):
"""TestMessageService.""" """TestMessageService."""
def test_can_send_message_to_waiting_message( def test_can_send_message_to_waiting_message(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_send_message_to_waiting_message.""" """Test_can_send_message_to_waiting_message."""
process_group_id = "test_group" process_group_id = "test_group"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
load_test_spec( load_test_spec(
"test_group/message_receiver", "test_group/message_receiver",
process_model_source_directory="message_send_one_conversation", process_model_source_directory="message_send_one_conversation",
bpmn_file_name="message_receiver.bpmn" bpmn_file_name="message_receiver.bpmn",
) )
process_model_sender = load_test_spec( process_model_sender = load_test_spec(
"test_group/message_sender", "test_group/message_sender",
@ -118,12 +124,17 @@ class TestMessageService(BaseTest):
assert process_instance.status == "complete" assert process_instance.status == "complete"
def test_can_send_message_to_multiple_process_models( def test_can_send_message_to_multiple_process_models(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_send_message_to_multiple_process_models.""" """Test_can_send_message_to_multiple_process_models."""
process_group_id = "test_group" process_group_id = "test_group"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
process_model_sender = load_test_spec( process_model_sender = load_test_spec(
"test_group/message_sender", "test_group/message_sender",

View File

@ -24,15 +24,21 @@ class TestPermissions(BaseTest):
"""TestPermissions.""" """TestPermissions."""
def test_user_can_be_given_permission_to_administer_process_group( def test_user_can_be_given_permission_to_administer_process_group(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_user_can_be_given_permission_to_administer_process_group.""" """Test_user_can_be_given_permission_to_administer_process_group."""
process_group_id = "group-a" process_group_id = "group-a"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
load_test_spec( load_test_spec(
"group-a/timers_intermediate_catch_event", "group-a/timers_intermediate_catch_event",
bpmn_file_name="timers_intermediate_catch_event.bpmn", bpmn_file_name="timers_intermediate_catch_event.bpmn",
process_model_source_directory="timers_intermediate_catch_event" process_model_source_directory="timers_intermediate_catch_event",
) )
dan = self.find_or_create_user() dan = self.find_or_create_user()
principal = dan.principal principal = dan.principal
@ -61,7 +67,7 @@ class TestPermissions(BaseTest):
load_test_spec( load_test_spec(
f"{process_group_id}/timers_intermediate_catch_event", f"{process_group_id}/timers_intermediate_catch_event",
bpmn_file_name="timers_intermediate_catch_event", bpmn_file_name="timers_intermediate_catch_event",
process_model_source_directory="timers_intermediate_catch_event" process_model_source_directory="timers_intermediate_catch_event",
) )
group_a_admin = self.find_or_create_user() group_a_admin = self.find_or_create_user()
@ -95,7 +101,7 @@ class TestPermissions(BaseTest):
load_test_spec( load_test_spec(
f"{process_group_id}/timers_intermediate_catch_event", f"{process_group_id}/timers_intermediate_catch_event",
bpmn_file_name="timers_intermediate_catch_event.bpmn", bpmn_file_name="timers_intermediate_catch_event.bpmn",
process_model_source_directory="timers_intermediate_catch_event" process_model_source_directory="timers_intermediate_catch_event",
) )
user = self.find_or_create_user() user = self.find_or_create_user()
group = GroupModel(identifier="groupA") group = GroupModel(identifier="groupA")
@ -134,7 +140,7 @@ class TestPermissions(BaseTest):
load_test_spec( load_test_spec(
f"{process_group_id}/timers_intermediate_catch_event", f"{process_group_id}/timers_intermediate_catch_event",
bpmn_file_name="timers_intermediate_catch_event.bpmn", bpmn_file_name="timers_intermediate_catch_event.bpmn",
process_model_source_directory="timers_intermediate_catch_event" process_model_source_directory="timers_intermediate_catch_event",
) )
group_a_admin = self.find_or_create_user() group_a_admin = self.find_or_create_user()

View File

@ -54,10 +54,12 @@ class TestProcessInstanceProcessor(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_sets_permission_correctly_on_active_task.""" """Test_sets_permission_correctly_on_active_task."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
initiator_user = self.find_or_create_user("initiator_user") initiator_user = self.find_or_create_user("initiator_user")
finance_user = self.find_or_create_user("testuser2") finance_user = self.find_or_create_user("testuser2")
assert initiator_user.principal is not None assert initiator_user.principal is not None
@ -70,7 +72,7 @@ class TestProcessInstanceProcessor(BaseTest):
process_model = load_test_spec( process_model = load_test_spec(
process_model_id="test_group/model_with_lanes", process_model_id="test_group/model_with_lanes",
bpmn_file_name="lanes.bpmn", bpmn_file_name="lanes.bpmn",
process_model_source_directory="model_with_lanes" process_model_source_directory="model_with_lanes",
) )
process_instance = self.create_process_instance_from_process_model( process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=initiator_user process_model=process_model, user=initiator_user
@ -132,10 +134,12 @@ class TestProcessInstanceProcessor(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_sets_permission_correctly_on_active_task_when_using_dict.""" """Test_sets_permission_correctly_on_active_task_when_using_dict."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
initiator_user = self.find_or_create_user("initiator_user") initiator_user = self.find_or_create_user("initiator_user")
finance_user_three = self.find_or_create_user("testuser3") finance_user_three = self.find_or_create_user("testuser3")
finance_user_four = self.find_or_create_user("testuser4") finance_user_four = self.find_or_create_user("testuser4")
@ -150,7 +154,7 @@ class TestProcessInstanceProcessor(BaseTest):
process_model = load_test_spec( process_model = load_test_spec(
process_model_id="test_group/model_with_lanes", process_model_id="test_group/model_with_lanes",
bpmn_file_name="lanes_with_owner_dict.bpmn", bpmn_file_name="lanes_with_owner_dict.bpmn",
process_model_source_directory="model_with_lanes" process_model_source_directory="model_with_lanes",
) )
process_instance = self.create_process_instance_from_process_model( process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=initiator_user process_model=process_model, user=initiator_user

View File

@ -24,10 +24,16 @@ class TestProcessModel(BaseTest):
assert process_model_one.files == [] assert process_model_one.files == []
def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory( def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_run_process_model_with_call_activities.""" """Test_can_run_process_model_with_call_activities."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/call_activity_test", "test_group/call_activity_test",
# bpmn_file_name="call_activity_test.bpmn", # bpmn_file_name="call_activity_test.bpmn",
@ -42,10 +48,16 @@ class TestProcessModel(BaseTest):
assert process_instance.status == "complete" assert process_instance.status == "complete"
def test_can_run_process_model_with_call_activities_when_not_in_same_directory( def test_can_run_process_model_with_call_activities_when_not_in_same_directory(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_run_process_model_with_call_activities.""" """Test_can_run_process_model_with_call_activities."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/call_activity_nested", "test_group/call_activity_nested",
process_model_source_directory="call_activity_nested", process_model_source_directory="call_activity_nested",
@ -71,10 +83,16 @@ class TestProcessModel(BaseTest):
assert process_instance.status == "complete" assert process_instance.status == "complete"
def test_can_run_process_model_with_call_activities_when_process_identifier_is_not_in_database( def test_can_run_process_model_with_call_activities_when_process_identifier_is_not_in_database(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_run_process_model_with_call_activities.""" """Test_can_run_process_model_with_call_activities."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/call_activity_nested", "test_group/call_activity_nested",
process_model_source_directory="call_activity_nested", process_model_source_directory="call_activity_nested",

View File

@ -12,14 +12,20 @@ class TestProcessModelService(BaseTest):
"""TestProcessModelService.""" """TestProcessModelService."""
def test_can_update_specified_attributes( def test_can_update_specified_attributes(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_update_specified_attributes.""" """Test_can_update_specified_attributes."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/hello_world", "test_group/hello_world",
bpmn_file_name="hello_world.bpmn", bpmn_file_name="hello_world.bpmn",
process_model_source_directory="hello_world" process_model_source_directory="hello_world",
) )
assert process_model.display_name == "test_group/hello_world" assert process_model.display_name == "test_group/hello_world"

View File

@ -16,10 +16,16 @@ class TestOpenFile(BaseTest):
"""TestVariousBpmnConstructs.""" """TestVariousBpmnConstructs."""
def test_dot_notation( def test_dot_notation(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_form_data_conversion_to_dot_dict.""" """Test_form_data_conversion_to_dot_dict."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/dangerous", "test_group/dangerous",
bpmn_file_name="read_etc_passwd.bpmn", bpmn_file_name="read_etc_passwd.bpmn",
@ -41,10 +47,16 @@ class TestImportModule(BaseTest):
"""TestVariousBpmnConstructs.""" """TestVariousBpmnConstructs."""
def test_dot_notation( def test_dot_notation(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_form_data_conversion_to_dot_dict.""" """Test_form_data_conversion_to_dot_dict."""
self.create_process_group(client, with_super_admin_user, "test_group", "test_group") self.create_process_group(
client, with_super_admin_user, "test_group", "test_group"
)
process_model = load_test_spec( process_model = load_test_spec(
"test_group/dangerous", "test_group/dangerous",
bpmn_file_name="read_env.bpmn", bpmn_file_name="read_env.bpmn",

View File

@ -20,19 +20,21 @@ class TestScriptUnitTestRunner(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_takes_data_and_returns_expected_result.""" """Test_takes_data_and_returns_expected_result."""
app.config["THREAD_LOCAL_DATA"].process_instance_id = None app.config["THREAD_LOCAL_DATA"].process_instance_id = None
process_group_id = "test_logging_spiff_logger" process_group_id = "test_logging_spiff_logger"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
process_model_id = "simple_script" process_model_id = "simple_script"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
load_test_spec( load_test_spec(
process_model_identifier, process_model_identifier,
bpmn_file_name=process_model_id, bpmn_file_name=process_model_id,
process_model_source_directory=process_model_id process_model_source_directory=process_model_id,
) )
bpmn_process_instance = ( bpmn_process_instance = (
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
@ -60,20 +62,22 @@ class TestScriptUnitTestRunner(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_fails_when_expected_output_does_not_match_actual_output.""" """Test_fails_when_expected_output_does_not_match_actual_output."""
app.config["THREAD_LOCAL_DATA"].process_instance_id = None app.config["THREAD_LOCAL_DATA"].process_instance_id = None
process_group_id = "test_logging_spiff_logger" process_group_id = "test_logging_spiff_logger"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
process_model_id = "simple_script" process_model_id = "simple_script"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
load_test_spec( load_test_spec(
process_model_identifier, process_model_identifier,
bpmn_file_name=process_model_id, bpmn_file_name=process_model_id,
process_model_source_directory=process_model_id process_model_source_directory=process_model_id,
) )
bpmn_process_instance = ( bpmn_process_instance = (
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
@ -101,20 +105,22 @@ class TestScriptUnitTestRunner(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_script_with_unit_tests_when_hey_is_passed_in.""" """Test_script_with_unit_tests_when_hey_is_passed_in."""
app.config["THREAD_LOCAL_DATA"].process_instance_id = None app.config["THREAD_LOCAL_DATA"].process_instance_id = None
process_group_id = "script_with_unit_tests" process_group_id = "script_with_unit_tests"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
process_model_id = "script_with_unit_tests" process_model_id = "script_with_unit_tests"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
load_test_spec( load_test_spec(
process_model_identifier, process_model_identifier,
bpmn_file_name=process_model_id, bpmn_file_name=process_model_id,
process_model_source_directory=process_model_id process_model_source_directory=process_model_id,
) )
bpmn_process_instance = ( bpmn_process_instance = (
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
@ -140,13 +146,15 @@ class TestScriptUnitTestRunner(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_script_with_unit_tests_when_hey_is_not_passed_in.""" """Test_script_with_unit_tests_when_hey_is_not_passed_in."""
app.config["THREAD_LOCAL_DATA"].process_instance_id = None app.config["THREAD_LOCAL_DATA"].process_instance_id = None
process_group_id = "script_with_unit_tests" process_group_id = "script_with_unit_tests"
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) self.create_process_group(
client, with_super_admin_user, process_group_id, process_group_id
)
process_model_id = "script_with_unit_tests" process_model_id = "script_with_unit_tests"
process_model_identifier = f"{process_group_id}/{process_model_id}" process_model_identifier = f"{process_group_id}/{process_model_id}"
@ -154,7 +162,7 @@ class TestScriptUnitTestRunner(BaseTest):
load_test_spec( load_test_spec(
process_model_identifier, process_model_identifier,
bpmn_file_name=process_model_id, bpmn_file_name=process_model_id,
process_model_source_directory=process_model_id process_model_source_directory=process_model_id,
) )
bpmn_process_instance = ( bpmn_process_instance = (
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(

View File

@ -28,7 +28,11 @@ class TestSpecFileService(BaseTest):
) )
def test_can_store_process_ids_for_lookup( def test_can_store_process_ids_for_lookup(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_can_store_process_ids_for_lookup.""" """Test_can_store_process_ids_for_lookup."""
self.basic_test_setup( self.basic_test_setup(
@ -37,7 +41,7 @@ class TestSpecFileService(BaseTest):
process_group_id=self.process_group_id, process_group_id=self.process_group_id,
process_model_id=self.process_model_id, process_model_id=self.process_model_id,
bpmn_file_name=self.bpmn_file_name, bpmn_file_name=self.bpmn_file_name,
bpmn_file_location="call_activity_nested" bpmn_file_location="call_activity_nested",
) )
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
assert len(bpmn_process_id_lookups) == 1 assert len(bpmn_process_id_lookups) == 1
@ -48,7 +52,11 @@ class TestSpecFileService(BaseTest):
) )
def test_fails_to_save_duplicate_process_id( def test_fails_to_save_duplicate_process_id(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_fails_to_save_duplicate_process_id.""" """Test_fails_to_save_duplicate_process_id."""
bpmn_process_identifier = "Level1" bpmn_process_identifier = "Level1"
@ -58,7 +66,7 @@ class TestSpecFileService(BaseTest):
process_group_id=self.process_group_id, process_group_id=self.process_group_id,
process_model_id=self.process_model_id, process_model_id=self.process_model_id,
bpmn_file_name=self.bpmn_file_name, bpmn_file_name=self.bpmn_file_name,
bpmn_file_location=self.process_model_id bpmn_file_location=self.process_model_id,
) )
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
assert len(bpmn_process_id_lookups) == 1 assert len(bpmn_process_id_lookups) == 1
@ -81,7 +89,11 @@ class TestSpecFileService(BaseTest):
) )
def test_updates_relative_file_path_when_appropriate( def test_updates_relative_file_path_when_appropriate(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_updates_relative_file_path_when_appropriate.""" """Test_updates_relative_file_path_when_appropriate."""
bpmn_process_identifier = "Level1" bpmn_process_identifier = "Level1"
@ -98,7 +110,7 @@ class TestSpecFileService(BaseTest):
process_group_id=self.process_group_id, process_group_id=self.process_group_id,
process_model_id=self.process_model_id, process_model_id=self.process_model_id,
bpmn_file_name=self.bpmn_file_name, bpmn_file_name=self.bpmn_file_name,
bpmn_file_location=self.process_model_id bpmn_file_location=self.process_model_id,
) )
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
@ -113,7 +125,11 @@ class TestSpecFileService(BaseTest):
) )
def test_load_reference_information( def test_load_reference_information(
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_load_reference_information. """Test_load_reference_information.
@ -128,14 +144,13 @@ class TestSpecFileService(BaseTest):
""" """
process_group_id = "test_group" process_group_id = "test_group"
process_model_id = "call_activity_nested" process_model_id = "call_activity_nested"
bpmn_file_name = "call_activity_nested.bpmn"
process_model_identifier = self.basic_test_setup( process_model_identifier = self.basic_test_setup(
client=client, client=client,
user=with_super_admin_user, user=with_super_admin_user,
process_group_id=process_group_id, process_group_id=process_group_id,
process_model_id=process_model_id, process_model_id=process_model_id,
# bpmn_file_name=bpmn_file_name, # bpmn_file_name=bpmn_file_name,
bpmn_file_location=process_model_id bpmn_file_location=process_model_id,
) )
# load_test_spec( # load_test_spec(
# , # ,

View File

@ -1,11 +1,14 @@
"""Test_various_bpmn_constructs.""" """Test_various_bpmn_constructs."""
from flask.app import Flask from flask.app import Flask
from flask.testing import FlaskClient from flask.testing import FlaskClient
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_model_service import ProcessModelService
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.base_test import BaseTest
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
from spiffworkflow_backend.services.process_model_service import ProcessModelService
class TestVariousBpmnConstructs(BaseTest): class TestVariousBpmnConstructs(BaseTest):
"""TestVariousBpmnConstructs.""" """TestVariousBpmnConstructs."""
@ -15,14 +18,14 @@ class TestVariousBpmnConstructs(BaseTest):
app: Flask, app: Flask,
client: FlaskClient, client: FlaskClient,
with_db_and_bpmn_file_cleanup: None, with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel with_super_admin_user: UserModel,
) -> None: ) -> None:
"""Test_running_process_with_timer_intermediate_catch_event.""" """Test_running_process_with_timer_intermediate_catch_event."""
process_model_identifier = self.basic_test_setup( process_model_identifier = self.basic_test_setup(
client, client,
with_super_admin_user, with_super_admin_user,
"test_group", "test_group",
"timer_intermediate_catch_event" "timer_intermediate_catch_event",
) )
process_model = ProcessModelService().get_process_model( process_model = ProcessModelService().get_process_model(

View File

@ -3,10 +3,10 @@ import { DATE_FORMAT, PROCESS_STATUSES } from '../../src/config';
const filterByDate = (fromDate) => { const filterByDate = (fromDate) => {
cy.get('#date-picker-start-from').clear().type(format(fromDate, DATE_FORMAT)); cy.get('#date-picker-start-from').clear().type(format(fromDate, DATE_FORMAT));
cy.contains('Start Range').click(); cy.contains('Start date from').click();
cy.get('#date-picker-end-from').clear().type(format(fromDate, DATE_FORMAT)); cy.get('#date-picker-end-from').clear().type(format(fromDate, DATE_FORMAT));
cy.contains('Start Range').click(); cy.contains('End date from').click();
cy.contains('Filter').click(); cy.getBySel('filter-button').click();
}; };
const updateDmnText = (oldText, newText, elementId = 'wonderful_process') => { const updateDmnText = (oldText, newText, elementId = 'wonderful_process') => {
@ -165,23 +165,25 @@ describe('process-instances', () => {
cy.basicPaginationTest(); cy.basicPaginationTest();
}); });
it('can filter', () => { it.only('can filter', () => {
cy.getBySel('process-instance-list-link').click(); cy.getBySel('process-instance-list-link').click();
cy.assertAtLeastOneItemInPaginatedResults(); cy.assertAtLeastOneItemInPaginatedResults();
PROCESS_STATUSES.forEach((processStatus) => { PROCESS_STATUSES.forEach((processStatus) => {
if (!['all', 'waiting'].includes(processStatus)) { if (!['all', 'waiting'].includes(processStatus)) {
cy.get('[name=process-status-selection]').click(); cy.get('#process-instance-status-select').click();
cy.get('[name=process-status-selection]').type(processStatus); cy.get('#process-instance-status-select')
cy.get(`[aria-label=${processStatus}]`).click(); .contains(processStatus)
cy.contains('Process Status').click(); .click();
cy.contains('Filter').click(); // close the dropdown again
cy.get('#process-instance-status-select').click();
cy.getBySel('filter-button').click();
cy.assertAtLeastOneItemInPaginatedResults(); cy.assertAtLeastOneItemInPaginatedResults();
cy.getBySel(`process-instance-status-${processStatus}`).contains( cy.getBySel(`process-instance-status-${processStatus}`).contains(
processStatus processStatus
); );
// there should really only be one, but in CI there are sometimes more // there should really only be one, but in CI there are sometimes more
cy.get('button[aria-label=Remove]:first').click(); cy.get('div[aria-label="Clear all selected items"]:first').click();
} }
}); });
@ -190,7 +192,7 @@ describe('process-instances', () => {
filterByDate(date); filterByDate(date);
cy.assertAtLeastOneItemInPaginatedResults(); cy.assertAtLeastOneItemInPaginatedResults();
date.setHours(date.getHours() + 2); date.setHours(date.getHours() + 26);
filterByDate(date); filterByDate(date);
cy.assertNoItemInPaginatedResults(); cy.assertNoItemInPaginatedResults();
}); });

View File

@ -16,20 +16,14 @@ describe('process-models', () => {
const modelId = `test-model-2-${id}`; const modelId = `test-model-2-${id}`;
cy.contains(groupDisplayName).click(); cy.contains(groupDisplayName).click();
cy.createModel(groupId, modelId, modelDisplayName); cy.createModel(groupId, modelId, modelDisplayName);
cy.contains(`Process Group: ${groupId}`).click(); cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.contains(modelId); cy.contains(`Process Model: ${modelDisplayName}`);
cy.contains(modelId).click();
cy.url().should('include', `process-models/${groupId}/${modelId}`);
cy.contains(`Process Model: ${modelId}`);
cy.contains('Edit process model').click(); cy.contains('Edit process model').click();
cy.get('input[name=display_name]').clear().type(newModelDisplayName); cy.get('input[name=display_name]').clear().type(newModelDisplayName);
cy.contains('Submit').click(); cy.contains('Submit').click();
const modifiedModelId = cy.modifyProcessModelPath(modelId); cy.contains(`Process Model: ${groupId}/${modelId}`);
cy.contains(`Process Model: ${modifiedModelId}`); cy.contains('Submit').click();
cy.contains('Edit process model').click();
cy.get('input[name=display_name]').should( cy.get('input[name=display_name]').should(
'have.value', 'have.value',
newModelDisplayName newModelDisplayName
@ -37,7 +31,7 @@ describe('process-models', () => {
cy.contains('Delete').click(); cy.contains('Delete').click();
cy.contains('Are you sure'); cy.contains('Are you sure');
cy.contains('OK').click(); cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`); cy.url().should('include', `process-groups/${groupId}`);
cy.contains(modelId).should('not.exist'); cy.contains(modelId).should('not.exist');
}); });
@ -57,8 +51,6 @@ describe('process-models', () => {
cy.contains(groupDisplayName).click(); cy.contains(groupDisplayName).click();
cy.createModel(groupId, modelId, modelDisplayName); cy.createModel(groupId, modelId, modelDisplayName);
cy.contains(groupId).click(); cy.contains(groupId).click();
cy.contains(modelId);
cy.contains(modelId).click(); cy.contains(modelId).click();
cy.url().should('include', `process-models/${groupId}:${modelId}`); cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.contains(`Process Model: ${modelDisplayName}`); cy.contains(`Process Model: ${modelDisplayName}`);
@ -117,7 +109,7 @@ describe('process-models', () => {
cy.contains('Edit process model').click(); cy.contains('Edit process model').click();
cy.contains('Delete').click(); cy.contains('Delete').click();
cy.contains('Are you sure'); cy.contains('Are you sure');
cy.contains('OK').click(); cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`); cy.url().should('include', `process-groups/${groupId}`);
cy.contains(modelId).should('not.exist'); cy.contains(modelId).should('not.exist');
}); });
@ -133,36 +125,35 @@ describe('process-models', () => {
cy.contains(groupDisplayName).click(); cy.contains(groupDisplayName).click();
cy.createModel(groupId, modelId, modelDisplayName); cy.createModel(groupId, modelId, modelDisplayName);
// seeing if getBySel works better, because we are seeing tests fail in CI cy.contains(`${groupId}`).click();
// when looking for the "Add a process model" link, so it seems like the
// click on the breadcrumb element must have failed.
cy.getBySel('process-group-breadcrumb-link').click();
// cy.contains(`Process Group: ${groupId}`).click();
cy.contains('Add a process model'); cy.contains('Add a process model');
cy.contains(modelId).click(); cy.contains(modelId).click();
cy.url().should('include', `process-models/${groupId}/${modelId}`); cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.contains(`Process Model: ${modelId}`); cy.contains(`Process Model: ${modelDisplayName}`);
cy.get('input[type=file]').selectFile( cy.getBySel('files-accordion').click();
cy.getBySel('upload-file-button').click();
cy.contains('Add file').selectFile(
'cypress/fixtures/test_bpmn_file_upload.bpmn' 'cypress/fixtures/test_bpmn_file_upload.bpmn'
); );
cy.contains('Submit').click(); cy.getBySel('modal-upload-file-dialog')
.find('.cds--btn--primary')
.contains('Upload')
.click();
cy.runPrimaryBpmnFile(); cy.runPrimaryBpmnFile();
cy.getBySel('process-instance-list-link').click(); cy.getBySel('process-instance-list-link').click();
cy.getBySel('process-instance-show-link').click(); cy.getBySel('process-instance-show-link').click();
cy.contains('Delete').click(); cy.contains('Delete').click();
cy.contains('Are you sure'); cy.contains('Are you sure');
cy.contains('OK').click(); cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.contains(`Process Instances for: ${groupId}/${modelId}`); cy.contains(`Process Instances for: ${groupId}/${modelId}`);
cy.contains(modelId).click(); cy.contains(modelId).click();
cy.contains('Edit process model').click(); cy.contains('Edit process model').click();
cy.contains('Delete').click(); cy.contains('Delete').click();
cy.contains('Are you sure'); cy.contains('Are you sure');
cy.contains('OK').click(); cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`); cy.url().should('include', `process-groups/${groupId}`);
cy.contains(modelId).should('not.exist'); cy.contains(modelId).should('not.exist');
}); });

View File

@ -118,9 +118,15 @@ Cypress.Commands.add('assertAtLeastOneItemInPaginatedResults', () => {
}); });
Cypress.Commands.add('assertNoItemInPaginatedResults', () => { Cypress.Commands.add('assertNoItemInPaginatedResults', () => {
cy.getBySel('total-paginated-items').contains('0'); cy.contains(/\b00 of 0 items/);
}); });
Cypress.Commands.add('modifyProcessModelPath', (path) => { Cypress.Commands.add('modifyProcessModelPath', (path) => {
return path.replace('/', ':') || ''; path.replace('/', ':');
return path;
});
Cypress.Commands.add('modifyProcessModelPath', (path) => {
path.replace('/', ':');
return path;
}); });

View File

@ -31,7 +31,7 @@
"bootstrap": "^5.2.0", "bootstrap": "^5.2.0",
"bpmn-js": "^9.3.2", "bpmn-js": "^9.3.2",
"bpmn-js-properties-panel": "^1.10.0", "bpmn-js-properties-panel": "^1.10.0",
"bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#feature/more_launch_buttons_and_dropdowns", "bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#main",
"craco": "^0.0.3", "craco": "^0.0.3",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"diagram-js": "^8.5.0", "diagram-js": "^8.5.0",
@ -7485,7 +7485,7 @@
}, },
"node_modules/bpmn-js-spiffworkflow": { "node_modules/bpmn-js-spiffworkflow": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#84593aee1ead7328efdc7da03ab3c9cd34364496", "resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#24c2cc36067adf8fed75990c6bf4a1a67bc9122b",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"inherits": "^2.0.4", "inherits": "^2.0.4",
@ -35755,8 +35755,8 @@
} }
}, },
"bpmn-js-spiffworkflow": { "bpmn-js-spiffworkflow": {
"version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#84593aee1ead7328efdc7da03ab3c9cd34364496", "version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#24c2cc36067adf8fed75990c6bf4a1a67bc9122b",
"from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#feature/more_launch_buttons_and_dropdowns", "from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#main",
"requires": { "requires": {
"inherits": "^2.0.4", "inherits": "^2.0.4",
"inherits-browser": "^0.0.1", "inherits-browser": "^0.0.1",

View File

@ -26,7 +26,7 @@
"bootstrap": "^5.2.0", "bootstrap": "^5.2.0",
"bpmn-js": "^9.3.2", "bpmn-js": "^9.3.2",
"bpmn-js-properties-panel": "^1.10.0", "bpmn-js-properties-panel": "^1.10.0",
"bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#feature/more_launch_buttons_and_dropdowns", "bpmn-js-spiffworkflow": "sartography/bpmn-js-spiffworkflow#main",
"craco": "^0.0.3", "craco": "^0.0.3",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"diagram-js": "^8.5.0", "diagram-js": "^8.5.0",

View File

@ -14,14 +14,14 @@ import ButtonWithConfirmation from './ButtonWithConfirmation';
type OwnProps = { type OwnProps = {
mode: string; mode: string;
processModel: ProcessModel; processModel: ProcessModel;
process_group_id?: string; processGroupId?: string;
setProcessModel: (..._args: any[]) => any; setProcessModel: (..._args: any[]) => any;
}; };
export default function ProcessModelForm({ export default function ProcessModelForm({
mode, mode,
processModel, processModel,
process_group_id, processGroupId,
setProcessModel, setProcessModel,
}: OwnProps) { }: OwnProps) {
const [identifierInvalid, setIdentifierInvalid] = useState<boolean>(false); const [identifierInvalid, setIdentifierInvalid] = useState<boolean>(false);
@ -88,7 +88,7 @@ export default function ProcessModelForm({
}; };
if (mode === 'new') { if (mode === 'new') {
Object.assign(postBody, { Object.assign(postBody, {
id: `${process_group_id}:${processModel.id}`, id: `${processGroupId}:${processModel.id}`,
}); });
} }

View File

@ -1,7 +1,12 @@
import { slugifyString } from './helpers'; import { convertSecondsToFormattedDate, slugifyString } from './helpers';
test('it can slugify a string', () => { test('it can slugify a string', () => {
expect(slugifyString('hello---world_ and then Some such-')).toEqual( expect(slugifyString('hello---world_ and then Some such-')).toEqual(
'hello-world-and-then-some-such' 'hello-world-and-then-some-such'
); );
}); });
test('it can keep the correct date when converting seconds to date', () => {
const dateString = convertSecondsToFormattedDate(1666325400);
expect(dateString).toEqual('2022-10-21');
});

View File

@ -44,7 +44,9 @@ export const convertDateToSeconds = (
export const convertStringToDate = (dateString: string) => { export const convertStringToDate = (dateString: string) => {
if (dateString) { if (dateString) {
return new Date(dateString); // add midnight time to the date so it c uses the correct date
// after converting to timezone
return new Date(`${dateString}T00:10:00`);
} }
return null; return null;
}; };
@ -95,13 +97,10 @@ export const getProcessModelFullIdentifierFromSearchParams = (
searchParams: any searchParams: any
) => { ) => {
let processModelFullIdentifier = null; let processModelFullIdentifier = null;
if ( if (searchParams.get('process_model_identifier')) {
searchParams.get('process_model_identifier') &&
searchParams.get('process_group_identifier')
) {
processModelFullIdentifier = `${searchParams.get( processModelFullIdentifier = `${searchParams.get(
'process_group_identifier' 'process_model_identifier'
)}/${searchParams.get('process_model_identifier')}`; )}`;
} }
return processModelFullIdentifier; return processModelFullIdentifier;
}; };
@ -116,19 +115,19 @@ export const truncateString = (text: string, len: number) => {
// Because of limitations in the way openapi defines parameters, we have to modify process models ids // Because of limitations in the way openapi defines parameters, we have to modify process models ids
// which are basically paths to the models // which are basically paths to the models
export const modifyProcessModelPath = (path: String) => { export const modifyProcessModelPath = (path: string) => {
return path.replace(/\//g, ':') || ''; return path.replace(/\//g, ':') || '';
}; };
export const unModifyProcessModelPath = (path: String) => { export const unModifyProcessModelPath = (path: string) => {
return path.replace(/:/g, '/') || ''; return path.replace(/:/g, '/') || '';
}; };
export const getGroupFromModifiedModelId = (modifiedId: String) => { export const getGroupFromModifiedModelId = (modifiedId: string) => {
const finalSplitIndex = modifiedId.lastIndexOf(':'); const finalSplitIndex = modifiedId.lastIndexOf(':');
return modifiedId.slice(0, finalSplitIndex); return modifiedId.slice(0, finalSplitIndex);
}; };
export const splitProcessModelId = (processModelId: String) => { export const splitProcessModelId = (processModelId: string) => {
return processModelId.split('/'); return processModelId.split('/');
}; };

View File

@ -17,11 +17,9 @@ import {
Grid, Grid,
Column, Column,
MultiSelect, MultiSelect,
// TableHeader, TableHeader,
// TableHead, TableHead,
// TableRow, TableRow,
// TableBody,
// TableCell,
// @ts-ignore // @ts-ignore
} from '@carbon/react'; } from '@carbon/react';
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config'; import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
@ -113,6 +111,7 @@ export default function ProcessInstanceList() {
searchParamValue as any searchParamValue as any
); );
functionToCall(dateString); functionToCall(dateString);
setShowFilterOptions(true);
} }
}); });
@ -125,6 +124,7 @@ export default function ProcessInstanceList() {
if (functionToCall !== null) { if (functionToCall !== null) {
functionToCall(searchParams.get(paramName) || ''); functionToCall(searchParams.get(paramName) || '');
} }
setShowFilterOptions(true);
} }
} }
); );
@ -162,6 +162,7 @@ export default function ProcessInstanceList() {
getProcessInstances(); getProcessInstances();
} }
// populate process model selection
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-models?per_page=1000`, path: `/process-models?per_page=1000`,
successCallback: processResultForProcessModels, successCallback: processResultForProcessModels,
@ -298,6 +299,7 @@ export default function ProcessInstanceList() {
return ( return (
<MultiSelect <MultiSelect
label="Choose Status" label="Choose Status"
className="our-class"
id="process-instance-status-select" id="process-instance-status-select"
titleText="Status" titleText="Status"
items={processStatusAllOptions} items={processStatusAllOptions}
@ -369,7 +371,11 @@ export default function ProcessInstanceList() {
> >
Clear Clear
</Button> </Button>
<Button kind="secondary" onClick={applyFilter}> <Button
kind="secondary"
onClick={applyFilter}
data-qa="filter-button"
>
Filter Filter
</Button> </Button>
</ButtonSet> </ButtonSet>
@ -392,12 +398,13 @@ export default function ProcessInstanceList() {
return headerLabels[header] ?? header; return headerLabels[header] ?? header;
}; };
const headers = (reportMetadata as any).columns.map((column: any) => { const headers = (reportMetadata as any).columns.map((column: any) => {
return <th>{getHeaderLabel((column as any).Header)}</th>; // return <th>{getHeaderLabel((column as any).Header)}</th>;
return getHeaderLabel((column as any).Header);
}); });
const formatProcessInstanceId = (row: any, id: any) => { const formatProcessInstanceId = (row: any, id: any) => {
const modifiedProcessModelId: String = modifyProcessModelPath( const modifiedProcessModelId: String = modifyProcessModelPath(
(row as any).process_model_identifier row.process_model_identifier
); );
return ( return (
<Link <Link
@ -408,7 +415,7 @@ export default function ProcessInstanceList() {
</Link> </Link>
); );
}; };
const formatProcessModelIdentifier = (row: any, identifier: any) => { const formatProcessModelIdentifier = (_row: any, identifier: any) => {
return ( return (
<Link <Link
to={`/admin/process-models/${modifyProcessModelPath(identifier)}`} to={`/admin/process-models/${modifyProcessModelPath(identifier)}`}
@ -417,10 +424,10 @@ export default function ProcessInstanceList() {
</Link> </Link>
); );
}; };
const formatSecondsForDisplay = (row: any, seconds: any) => { const formatSecondsForDisplay = (_row: any, seconds: any) => {
return convertSecondsToFormattedDate(seconds) || '-'; return convertSecondsToFormattedDate(seconds) || '-';
}; };
const defaultFormatter = (row: any, value: any) => { const defaultFormatter = (_row: any, value: any) => {
return value; return value;
}; };
@ -433,20 +440,32 @@ export default function ProcessInstanceList() {
const formattedColumn = (row: any, column: any) => { const formattedColumn = (row: any, column: any) => {
const formatter = columnFormatters[column.accessor] ?? defaultFormatter; const formatter = columnFormatters[column.accessor] ?? defaultFormatter;
const value = row[column.accessor]; const value = row[column.accessor];
if (column.accessor === 'status') {
return (
<td data-qa={`process-instance-status-${value}`}>
{formatter(row, value)}
</td>
);
}
return <td>{formatter(row, value)}</td>; return <td>{formatter(row, value)}</td>;
}; };
const rows = processInstances.map((row) => { const rows = processInstances.map((row: any) => {
const currentRow = (reportMetadata as any).columns.map((column: any) => { const currentRow = (reportMetadata as any).columns.map((column: any) => {
return formattedColumn(row, column); return formattedColumn(row, column);
}); });
return <tr key={(row as any).id}>{currentRow}</tr>; return <tr key={row.id}>{currentRow}</tr>;
}); });
return ( return (
<Table size="lg"> <Table size="lg">
<thead> <TableHead>
<tr>{headers}</tr> <TableRow>
</thead> {headers.map((header: any) => (
<TableHeader key={header}>{header}</TableHeader>
))}
</TableRow>
</TableHead>
<tbody>{rows}</tbody> <tbody>{rows}</tbody>
</Table> </Table>
); );
@ -461,7 +480,11 @@ export default function ProcessInstanceList() {
return ( return (
<h2> <h2>
Process Instances for:{' '} Process Instances for:{' '}
<Link to={`/admin/process-models/${processModelFullIdentifier}`}> <Link
to={`/admin/process-models/${modifyProcessModelPath(
processModelFullIdentifier
)}`}
>
{processModelFullIdentifier} {processModelFullIdentifier}
</Link> </Link>
</h2> </h2>
@ -478,9 +501,13 @@ export default function ProcessInstanceList() {
<> <>
{processInstanceTitleElement()} {processInstanceTitleElement()}
<Grid fullWidth> <Grid fullWidth>
<Column lg={15} /> <Column
<Column lg={1}> sm={{ span: 1, offset: 3 }}
md={{ span: 1, offset: 7 }}
lg={{ span: 1, offset: 15 }}
>
<Button <Button
data-qa="filter-section-expand-toggle"
kind="ghost" kind="ghost"
renderIcon={Filter} renderIcon={Filter}
iconDescription="Filter Options" iconDescription="Filter Options"
@ -492,18 +519,14 @@ export default function ProcessInstanceList() {
</Grid> </Grid>
{filterOptions()} {filterOptions()}
<br /> <br />
<Grid fullWidth> <PaginationForTable
<Column lg={16}> page={page}
<PaginationForTable perPage={perPage}
page={page} pagination={pagination}
perPage={perPage} tableToDisplay={buildTable()}
pagination={pagination} queryParamString={getSearchParamsAsQueryString()}
tableToDisplay={buildTable()} path="/admin/process-instances"
queryParamString={getSearchParamsAsQueryString()} />
path="/admin/process-instances"
/>
</Column>
</Grid>
</> </>
); );
} }

View File

@ -88,7 +88,7 @@ export default function ProcessInstanceLogList() {
perPage={perPage} perPage={perPage}
pagination={pagination} pagination={pagination}
tableToDisplay={buildTable()} tableToDisplay={buildTable()}
path={`/admin/process-instances/${params.process_instance_id}/logs`} path={`/admin/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}/logs`}
/> />
</main> </main>
); );

View File

@ -443,9 +443,14 @@ export default function ProcessInstanceShow() {
return ( return (
<> <>
<ProcessBreadcrumb <ProcessBreadcrumb
processModelId={processModelId} hotCrumbs={[
processGroupId={params.process_group_id} ['Process Groups', '/admin'],
linkProcessModel [
`Process Model: ${processModelId}`,
`process_model:${processModelId}:link`,
],
[`Process Instance: ${params.process_instance_id}`],
]}
/> />
<Stack orientation="horizontal" gap={3}> <Stack orientation="horizontal" gap={3}>
<h2>Process Instance Id: {processInstanceToUse.id}</h2> <h2>Process Instance Id: {processInstanceToUse.id}</h2>

View File

@ -24,7 +24,7 @@ export default function ProcessModelEdit() {
<h2>Edit Process Model: {(processModel as any).id}</h2> <h2>Edit Process Model: {(processModel as any).id}</h2>
<ProcessModelForm <ProcessModelForm
mode="edit" mode="edit"
process_group_id={params.process_group_id} processGroupId={params.process_group_id}
processModel={processModel} processModel={processModel}
setProcessModel={setProcessModel} setProcessModel={setProcessModel}
/> />

View File

@ -107,7 +107,6 @@ export default function ProcessModelEditDiagram() {
}; };
if (params.file_name) { if (params.file_name) {
console.log(`processModelPath: ${processModelPath}`);
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/${processModelPath}/files/${params.file_name}`, path: `/${processModelPath}/files/${params.file_name}`,
successCallback: fileResult, successCallback: fileResult,
@ -685,42 +684,34 @@ export default function ProcessModelEditDiagram() {
* fixme: Not currently in use. This would only work for bpmn files within the process model. Which is right for DMN and json, but not right here. Need to merge in work on the nested process groups before tackling this. * fixme: Not currently in use. This would only work for bpmn files within the process model. Which is right for DMN and json, but not right here. Need to merge in work on the nested process groups before tackling this.
* @param processId * @param processId
*/ */
const fileNameTemplatePath =
'/admin/process-models/:process_model_id/files/:file_name';
const onLaunchBpmnEditor = (processId: string) => { const onLaunchBpmnEditor = (processId: string) => {
const file = findFileNameForReferenceId(processId, 'bpmn'); const file = findFileNameForReferenceId(processId, 'bpmn');
if (file) { if (file) {
const path = generatePath( const path = generatePath(fileNameTemplatePath, {
'/admin/process-models/:process_group_id/:process_model_id/files/:file_name', process_model_id: params.process_model_id,
{ file_name: file.name,
process_group_id: params.process_group_id, });
process_model_id: params.process_model_id,
file_name: file.name,
}
);
window.open(path); window.open(path);
} }
}; };
const onLaunchJsonEditor = (fileName: string) => { const onLaunchJsonEditor = (fileName: string) => {
const path = generatePath( const path = generatePath(fileNameTemplatePath, {
'/admin/process-models/:process_group_id/:process_model_id/form/:file_name', process_model_id: params.process_model_id,
{ file_name: fileName,
process_group_id: params.process_group_id, });
process_model_id: params.process_model_id,
file_name: fileName,
}
);
window.open(path); window.open(path);
}; };
const onLaunchDmnEditor = (processId: string) => { const onLaunchDmnEditor = (processId: string) => {
const file = findFileNameForReferenceId(processId, 'dmn'); const file = findFileNameForReferenceId(processId, 'dmn');
if (file) { if (file) {
const path = generatePath( const path = generatePath(fileNameTemplatePath, {
'/admin/process-models/:process_group_id/:process_model_id/files/:file_name', process_model_id: params.process_model_id,
{ file_name: file.name,
process_group_id: params.process_group_id, });
process_model_id: params.process_model_id,
file_name: file.name,
}
);
window.open(path); window.open(path);
} }
}; };
@ -776,9 +767,7 @@ export default function ProcessModelEditDiagram() {
// if a file name is not given then this is a new model and the ReactDiagramEditor component will handle it // if a file name is not given then this is a new model and the ReactDiagramEditor component will handle it
if ((bpmnXmlForDiagramRendering || !params.file_name) && processModel) { if ((bpmnXmlForDiagramRendering || !params.file_name) && processModel) {
const processModelFileName = processModelFile const processModelFileName = processModelFile ? processModelFile.name : '';
? `: ${processModelFile.name}`
: '';
return ( return (
<> <>
<ProcessBreadcrumb <ProcessBreadcrumb
@ -792,7 +781,7 @@ export default function ProcessModelEditDiagram() {
]} ]}
/> />
<h2> <h2>
Process Model File Process Model File{processModelFile ? ': ' : ''}
{processModelFileName} {processModelFileName}
</h2> </h2>
{appropriateEditor()} {appropriateEditor()}

View File

@ -20,7 +20,7 @@ export default function ProcessModelNew() {
<h2>Add Process Model</h2> <h2>Add Process Model</h2>
<ProcessModelForm <ProcessModelForm
mode="new" mode="new"
process_group_id={params.process_group_id} processGroupId={params.process_group_id}
processModel={processModel} processModel={processModel}
setProcessModel={setProcessModel} setProcessModel={setProcessModel}
/> />

View File

@ -400,13 +400,14 @@ export default function ProcessModelShow() {
httpMethod: 'POST', httpMethod: 'POST',
postBody: formData, postBody: formData,
}); });
setShowFileUploadModal(false);
} }
setShowFileUploadModal(false);
}; };
const fileUploadModal = () => { const fileUploadModal = () => {
return ( return (
<Modal <Modal
data-qa="modal-upload-file-dialog"
open={showFileUploadModal} open={showFileUploadModal}
modalHeading="Upload File" modalHeading="Upload File"
primaryButtonText="Upload" primaryButtonText="Upload"
@ -455,6 +456,7 @@ export default function ProcessModelShow() {
<ButtonSet> <ButtonSet>
<Button <Button
renderIcon={Upload} renderIcon={Upload}
data-qa="upload-file-button"
onClick={() => setShowFileUploadModal(true)} onClick={() => setShowFileUploadModal(true)}
size="sm" size="sm"
kind="" kind=""

View File

@ -6,7 +6,8 @@ import { Button, Modal } from '@carbon/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import HttpService from '../services/HttpService'; import HttpService from '../services/HttpService';
import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
import { modifyProcessModelPath } from '../helpers'; import { modifyProcessModelPath, unModifyProcessModelPath } from '../helpers';
import { ProcessFile } from '../interfaces';
// NOTE: This is mostly the same as ProcessModelEditDiagram and if we go this route could // NOTE: This is mostly the same as ProcessModelEditDiagram and if we go this route could
// possibly be merged into it. I'm leaving as a separate file now in case it does // possibly be merged into it. I'm leaving as a separate file now in case it does
@ -19,7 +20,9 @@ export default function ReactFormEditor() {
const handleShowFileNameEditor = () => setShowFileNameEditor(true); const handleShowFileNameEditor = () => setShowFileNameEditor(true);
const navigate = useNavigate(); const navigate = useNavigate();
const [processModelFile, setProcessModelFile] = useState(null); const [processModelFile, setProcessModelFile] = useState<ProcessFile | null>(
null
);
const [processModelFileContents, setProcessModelFileContents] = useState(''); const [processModelFileContents, setProcessModelFileContents] = useState('');
const fileExtension = (() => { const fileExtension = (() => {
@ -146,6 +149,7 @@ export default function ReactFormEditor() {
}; };
if (processModelFile || !params.file_name) { if (processModelFile || !params.file_name) {
const processModelFileName = processModelFile ? processModelFile.name : '';
return ( return (
<main> <main>
<ProcessBreadcrumb <ProcessBreadcrumb
@ -155,15 +159,19 @@ export default function ReactFormEditor() {
hotCrumbs={[ hotCrumbs={[
['Process Groups', '/admin'], ['Process Groups', '/admin'],
[ [
`Process Model: ${params.process_model_id}`, `Process Model: ${unModifyProcessModelPath(
`process_model:${params.process_model_id}:link`, params.process_model_id || ''
)}`,
`process_model:${unModifyProcessModelPath(
params.process_model_id || ''
)}:link`,
], ],
[(processModelFile as any).name || ''], [processModelFileName],
]} ]}
/> />
<h2> <h2>
Process Model File Process Model File{processModelFile ? ': ' : ''}
{processModelFile ? `: ${(processModelFile as any).name}` : ''} {processModelFileName}
</h2> </h2>
{newFileNameBox()} {newFileNameBox()}
<Button onClick={saveFile} variant="danger" data-qa="file-save-button"> <Button onClick={saveFile} variant="danger" data-qa="file-save-button">