From a023e4f7d24fad8c352ce1775341e1264082ca68 Mon Sep 17 00:00:00 2001 From: Jonatan Martens <40060128+JonatanMartens@users.noreply.github.com> Date: Tue, 29 Sep 2020 12:32:01 +0300 Subject: [PATCH 01/37] Create codeql-analysis.yml --- .github/workflows/codeql-analysis.yml | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..405d19a4 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,66 @@ +name: "CodeQL" + +on: + push: + branches: [master, development] + pull_request: + # The branches below must be a subset of the branches above + branches: [master, development] + schedule: + - cron: '0 13 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['python'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 From 67710c9227a27e3be5c9fc4473a8d92d1934de13 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 14:44:11 +0300 Subject: [PATCH 02/37] [ADDED] Basic documentation structure --- Pipfile | 1 + Pipfile.lock | 270 +++++++++++++++++++++++++++++++++++++++--- docs/Makefile | 20 ++++ docs/make.bat | 35 ++++++ docs/source/conf.py | 55 +++++++++ docs/source/index.rst | 21 ++++ 6 files changed, 388 insertions(+), 14 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst diff --git a/Pipfile b/Pipfile index 643a2d46..f13d3075 100644 --- a/Pipfile +++ b/Pipfile @@ -13,6 +13,7 @@ mypy = "~=0.782" coveralls = "~=2.1.2" importlib-metadata = "~=1.7.0" pyzeebe = {editable = true, path = "."} +sphinx = "~=3.2.1" [packages] grpcio = "~=1.31.0" diff --git a/Pipfile.lock b/Pipfile.lock index 9ff6ffd1..621a3fee 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "bb3161b065590548ccc64d0de401cba6480c58d221583f5929d79fdf509b529c" + "sha256": "47d93a76534c451b2a976519c2f8b4394af69c80c97cc8c78bb44cdae17bdc83" }, "pipfile-spec": 6, "requires": {}, @@ -148,6 +148,13 @@ } }, "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, "astroid": { "hashes": [ "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703", @@ -166,11 +173,11 @@ }, "attrs": { "hashes": [ - "sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a", - "sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff" + "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594", + "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.1.0" + "version": "==20.2.0" }, "autopep8": { "hashes": [ @@ -179,6 +186,14 @@ "index": "pypi", "version": "==1.5.4" }, + "babel": { + "hashes": [ + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.0" + }, "certifi": { "hashes": [ "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", @@ -198,7 +213,7 @@ "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" ], - "markers": "sys_platform == 'win32' and sys_platform == 'win32'", + "markers": "sys_platform == 'win32' and sys_platform == 'win32' and sys_platform == 'win32'", "version": "==0.4.3" }, "coverage": { @@ -255,6 +270,59 @@ ], "version": "==0.6.2" }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "grpcio": { + "hashes": [ + "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151", + "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a", + "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304", + "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482", + "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6", + "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df", + "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9", + "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c", + "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9", + "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6", + "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796", + "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39", + "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637", + "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e", + "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd", + "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2", + "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff", + "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1", + "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352", + "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f", + "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a", + "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069", + "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a", + "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642", + "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510", + "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71", + "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc", + "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf", + "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e", + "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b", + "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408", + "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590", + "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552", + "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b", + "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084", + "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770", + "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225", + "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7", + "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d" + ], + "index": "pypi", + "version": "==1.31.0" + }, "idna": { "hashes": [ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", @@ -263,6 +331,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.10" }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.0" + }, "importlib-metadata": { "hashes": [ "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", @@ -280,11 +356,19 @@ }, "isort": { "hashes": [ - "sha256:92533892058de0306e51c88f22ece002a209dc8e80288aa3cec6d443060d584f", - "sha256:a200d47b7ee8b7f7d0a9646650160c4a51b6a91a9413fd31b1da2c4de789f5d3" + "sha256:6187a9f1ce8784cbc6d1b88790a43e6083a6302f03e9ae482acc0f232a98c843", + "sha256:c16eaa7432a1c004c585d79b12ad080c6c421dd18fe27982ca11f95e6898e432" ], "markers": "python_version >= '3.6' and python_version < '4.0'", - "version": "==5.5.1" + "version": "==5.5.3" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" }, "lazy-object-proxy": { "hashes": [ @@ -313,6 +397,45 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.4.3" }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -355,6 +478,14 @@ ], "version": "==0.4.3" }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "index": "pypi", + "version": "==3.1.0" + }, "packaging": { "hashes": [ "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", @@ -371,6 +502,30 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.1" }, + "protobuf": { + "hashes": [ + "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33", + "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463", + "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c", + "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a", + "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f", + "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7", + "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b", + "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5", + "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4", + "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec", + "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c", + "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630", + "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7", + "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e", + "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a", + "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060", + "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9", + "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb" + ], + "index": "pypi", + "version": "==3.13.0" + }, "py": { "hashes": [ "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", @@ -387,6 +542,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.6.0" }, + "pygments": { + "hashes": [ + "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998", + "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7" + ], + "markers": "python_version >= '3.5'", + "version": "==2.7.1" + }, "pylint": { "hashes": [ "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210", @@ -405,11 +568,11 @@ }, "pytest": { "hashes": [ - "sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4", - "sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad" + "sha256:0e37f61339c4578776e090c3b8f6b16ce4db333889d65d0efb305243ec544b40", + "sha256:c8f57c2a30983f469bf03e68cdfa74dc474ce56b8f280ddcb080dfd91df01043" ], "index": "pypi", - "version": "==6.0.1" + "version": "==6.0.2" }, "pytest-grpc": { "hashes": [ @@ -419,6 +582,13 @@ "index": "pypi", "version": "==0.8.0" }, + "pytz": { + "hashes": [ + "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", + "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" + ], + "version": "==2020.1" + }, "pyzeebe": { "editable": true, "path": "." @@ -431,6 +601,15 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.24.0" }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "index": "pypi", + "version": "==1.3.0" + }, "six": { "hashes": [ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", @@ -439,6 +618,69 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.15.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + ], + "version": "==2.0.0" + }, + "sphinx": { + "hashes": [ + "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8", + "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.4" + }, "toml": { "hashes": [ "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", @@ -496,11 +738,11 @@ }, "zipp": { "hashes": [ - "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", - "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" + "sha256:43f4fa8d8bb313e65d8323a3952ef8756bf40f9a5c3ea7334be23ee4ec8278b6", + "sha256:b52f22895f4cfce194bc8172f3819ee8de7540aa6d873535a8668b730b8b411f" ], "markers": "python_version >= '3.6'", - "version": "==3.1.0" + "version": "==3.2.0" } } } diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d0c3cbf1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..9534b018 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..29719dcc --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,55 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'pyzeebe' +copyright = '2020, Jonatan Martens' +author = 'Jonatan Martens' + +# The full version, including alpha/beta/rc tags +release = '2.1.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'classic' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..e4477c38 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,21 @@ +.. pyzeebe documentation master file, created by + sphinx-quickstart on Tue Sep 29 12:49:24 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to pyzeebe's documentation! +=================================== +Python client for Zeebe workflow engine + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` From ad931c592aa22c591a43fbfdc72c24797e7a949a Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:34:08 +0300 Subject: [PATCH 03/37] [ADDED] Client quickstart --- docs/source/client.rst | 14 +++++ docs/source/client_quickstart.rst | 79 +++++++++++++++++++++++++++++ docs/source/client_run_workflow.rst | 0 docs/source/conf.py | 7 +-- docs/source/index.rst | 68 ++++++++++++++++++++----- 5 files changed, 153 insertions(+), 15 deletions(-) create mode 100644 docs/source/client.rst create mode 100644 docs/source/client_quickstart.rst create mode 100644 docs/source/client_run_workflow.rst diff --git a/docs/source/client.rst b/docs/source/client.rst new file mode 100644 index 00000000..89c20b92 --- /dev/null +++ b/docs/source/client.rst @@ -0,0 +1,14 @@ +.. _aiohttp-client: + +====== +Client +====== + +The page contains all information about the `ZeebeClient` class: + + +.. toctree:: + :name: client + + Quickstart + Running workflows diff --git a/docs/source/client_quickstart.rst b/docs/source/client_quickstart.rst new file mode 100644 index 00000000..79721ba1 --- /dev/null +++ b/docs/source/client_quickstart.rst @@ -0,0 +1,79 @@ +================= +Client Quickstart +================= + +Create a client +--------------- + +To create a client with default configuration: + +.. code-block:: python + + from pyzeebe import ZeebeClient + + client = ZeebeClient() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 + + +To create a client with custom hostname and port: + +.. code-block:: python + + client = ZeebeClient(hostname="zeebe_gateway", port=26500) + +To create a client with a secure connection: + +.. code-block:: python + + client = ZeebeClient(secure_connection=True) + +To create a client with OAuth 2.0 authentication: + +.. code-block:: python + + from pyzeebe import ZeebeClient, OAuthCredentials + + credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", + audience="audience") + client = ZeebeClient() + +To create a client for a Camunda Cloud instance: + +.. code-block:: python + + from pyzeebe import ZeebeClient, CamundaCloudCredentials + + credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", + cluster_id="cluster_id") + client = ZeebeClient() + + +Run a workflow +-------------- + +.. code-block:: python + + workflow_instance_key = client.run_workflow("bpmn_process_id") + + +Run a workflow with result +-------------------------- + +.. code-block:: python + + result_as_dict = client.run_workflow_with_result("bpmn_process_id") + + +Deploy a workflow +----------------- + +.. code-block:: python + + client.deploy_workflow("workflow_file.bpmn") + + +Publish a message +----------------- + +.. code-block:: python + + client.publish_message(name="message_name", correlation_key="correlation_key") diff --git a/docs/source/client_run_workflow.rst b/docs/source/client_run_workflow.rst new file mode 100644 index 00000000..e69de29b diff --git a/docs/source/conf.py b/docs/source/conf.py index 29719dcc..9b07317c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,7 +24,6 @@ # The full version, including alpha/beta/rc tags release = '2.1.0' - # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -47,9 +46,11 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'classic' +html_theme = 'alabaster' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] \ No newline at end of file +html_static_path = ['_static'] + +version = "2.1.0" diff --git a/docs/source/index.rst b/docs/source/index.rst index e4477c38..1feb1169 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,21 +1,65 @@ -.. pyzeebe documentation master file, created by - sphinx-quickstart on Tue Sep 29 12:49:24 2020. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +.. pyzeebe documentation master file, created by Jonatan Martens. sphinx-quickstart on Tue Sep 29 12:49:24 2020. Welcome to pyzeebe's documentation! =================================== Python client for Zeebe workflow engine -.. toctree:: - :maxdepth: 2 - :caption: Contents: +Current version is |version|. + + +Library installation +==================== + +.. code-block:: bash + + $ pip install pyzeebe + +Getting Started +=============== + +Creating a worker + +.. code-block:: python + + from pyzeebe import ZeebeWorker + + worker = ZeebeWorker() + + @worker.task(task_type="my_task") + def my_task(x: int): + return {"y": x + 1} + worker.work() +Creating a client -Indices and tables -================== +.. code-block:: python + + from pyzeebe import ZeebeClient + + client = ZeebeClient() + + client.run_workflow("my_workflow") + + # Run workflow with variables: + client.run_workflow("my_workflow", variables={"x": 0}) + + +Dependencies +============ + +* python 3.5+ +* grpcio +* protobuf +* oauthlib +* requests-oauthlib + + +Table Of Contents +================= +.. toctree:: + :maxdepth: 2 + :caption: Contents: -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + client + worker From 92ce0ad83f6d17b44679d8555e6d1d646efb9b6e Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:44:08 +0300 Subject: [PATCH 04/37] [REMOVED] Contents file --- docs/source/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 1feb1169..49975c75 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -59,7 +59,6 @@ Table Of Contents ================= .. toctree:: :maxdepth: 2 - :caption: Contents: client worker From 45570a5e579a2db594bfdb357fa1595d225df526 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:48:57 +0300 Subject: [PATCH 05/37] [ADDED] Read the docs config --- .readthedocs.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .readthedocs.yml diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..4799edfa --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,12 @@ +version: 2 + +build: + image: latest +python: + version: 3.8 + pip_install: false + +sphinx: + builder: html + configuration: docs/conf.py + #fail_on_warning: true From f3404e60159501969a0df040b44d951e54c9c5b5 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:49:58 +0300 Subject: [PATCH 06/37] [REMOVED] no pip install --- .readthedocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 4799edfa..e35d1fa6 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,7 +4,6 @@ build: image: latest python: version: 3.8 - pip_install: false sphinx: builder: html From 94f24f9e096c67e97ea0a49f36fb24674c7f66ff Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:54:17 +0300 Subject: [PATCH 07/37] [ADDED] master_doc=index --- docs/source/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 9b07317c..4e95d840 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -54,3 +54,5 @@ html_static_path = ['_static'] version = "2.1.0" + +master_doc = 'index' From 350f76b7e7d495fca91d5520088bc924ba68bc20 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 15:56:52 +0300 Subject: [PATCH 08/37] [FIXED] conf.py location --- .readthedocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index e35d1fa6..51b24220 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,5 +7,5 @@ python: sphinx: builder: html - configuration: docs/conf.py + configuration: docs/source/conf.py #fail_on_warning: true From 69a3926a1d64d1296a6743f364297b4416094e71 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Tue, 29 Sep 2020 16:40:59 +0300 Subject: [PATCH 09/37] [ADDED] Some parts of the worker documentation --- docs/source/client.rst | 2 - docs/source/client_quickstart.rst | 6 +- docs/source/conf.py | 2 +- docs/source/index.rst | 4 +- docs/source/worker.rst | 12 ++++ docs/source/worker_quickstart.rst | 79 +++++++++++++++++++++++ docs/source/worker_tasks.rst | 101 ++++++++++++++++++++++++++++++ 7 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 docs/source/worker.rst create mode 100644 docs/source/worker_quickstart.rst create mode 100644 docs/source/worker_tasks.rst diff --git a/docs/source/client.rst b/docs/source/client.rst index 89c20b92..8cc5f80e 100644 --- a/docs/source/client.rst +++ b/docs/source/client.rst @@ -1,5 +1,3 @@ -.. _aiohttp-client: - ====== Client ====== diff --git a/docs/source/client_quickstart.rst b/docs/source/client_quickstart.rst index 79721ba1..a8609ac0 100644 --- a/docs/source/client_quickstart.rst +++ b/docs/source/client_quickstart.rst @@ -58,9 +58,13 @@ Run a workflow Run a workflow with result -------------------------- +To run a workflow and receive the result directly: + .. code-block:: python - result_as_dict = client.run_workflow_with_result("bpmn_process_id") + result = client.run_workflow_with_result("bpmn_process_id") + + # result will be a dict Deploy a workflow diff --git a/docs/source/conf.py b/docs/source/conf.py index 4e95d840..d8fb86ca 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -46,7 +46,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'classic' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/source/index.rst b/docs/source/index.rst index 49975c75..08bc10cd 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -60,5 +60,5 @@ Table Of Contents .. toctree:: :maxdepth: 2 - client - worker + Client + Worker diff --git a/docs/source/worker.rst b/docs/source/worker.rst new file mode 100644 index 00000000..0246fd22 --- /dev/null +++ b/docs/source/worker.rst @@ -0,0 +1,12 @@ +====== +Worker +====== + +The page contains all information about the :class:`ZeebeWorker` class: + + +.. toctree:: + :name: worker + + Quickstart + Tasks diff --git a/docs/source/worker_quickstart.rst b/docs/source/worker_quickstart.rst new file mode 100644 index 00000000..a9994c51 --- /dev/null +++ b/docs/source/worker_quickstart.rst @@ -0,0 +1,79 @@ +================= +Worker Quickstart +================= + +Create and start a worker +------------------------- + +.. code-block:: python + + from pyzeebe import ZeebeWorker + + + worker = ZeebeWorker() + + + @worker.task(task_type="my_task") + def my_task(x: int): + return {"y": x + 1} + + worker.work() + + +Worker connection options +------------------------- + +To create a worker with default configuration: + +.. code-block:: python + + from pyzeebe import ZeebeWorker + + worker = ZeebeWorker() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 + + +To create a worker with custom hostname and port: + +.. code-block:: python + + worker = ZeebeWorker(hostname="zeebe_gateway", port=26500) + +To create a worker with a secure connection: + +.. code-block:: python + + worker = ZeebeWorker(secure_connection=True) + +To create a worker with OAuth 2.0 authentication: + +.. code-block:: python + + from pyzeebe import ZeebeWorker, OAuthCredentials + + credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", + audience="audience") + worker = ZeebeWorker() + +To create a worker for a Camunda Cloud instance: + +.. code-block:: python + + from pyzeebe import ZeebeWorker, CamundaCloudCredentials + + credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", + cluster_id="cluster_id") + worker = ZeebeWorker() + + +Add a task +---------- + + +To add a task to the worker: + +.. code-block:: python + + @worker.task(task_type="my_task") + def my_task(x: int): + return {"y": x + 1} + diff --git a/docs/source/worker_tasks.rst b/docs/source/worker_tasks.rst new file mode 100644 index 00000000..034397f6 --- /dev/null +++ b/docs/source/worker_tasks.rst @@ -0,0 +1,101 @@ +===== +Tasks +===== + +Tasks are the building blocks of workflows + +Most basic Task +--------------- + +To create a task you must first create a :class:`ZeebeWorker` instance. + +.. code-block:: python + + @worker.task(task_type="my_task") + def my_task(): + return {} + +This is a task that does nothing. It receives no parameters and also doesn't return any. + + + + + +Task Exception Handler +---------------------- + +An exception handler's signature: + +.. code-block:: python + + Callable[[Exception, Job], None] + +In other words: an exception handler is a function that receives an :class:`Exception` and :class:`Job` instance (a pyzeebe class). + +The exception handler is called when the task has failed. + +To add an exception handler to a task: + +.. code-block:: python + + from pyzeebe import Job + + + def my_exception_handler(exception: Exception, job: Job) -> None: + print(exception) + job.set_failure_status(message=str(exception)) + + + @worker.task(task_type="my_task", exception_handler=my_exception_handler) + def my_task(): + raise Exception() + +Now every time ``my_task`` is called (and then fails), ``my_exception_handler`` is called. + +*What does job.set_failure_status do?* + +This tells Zeebe that the job failed. The job will then be retried (if configured in workflow definition). + +Task timeout +------------ +When creating a task one of the parameters we can specify is ``timeout``. + +.. code-block:: python + + @worker.task(task_type="my_task", timeout=20000) + def my_task(input: str): + return {"output": f"Hello World, {input}!"} + +Here we specify a timeout of 20000 milliseconds (20 seconds). +If the job is not completed within this timeout, Zeebe will reactivate the job and another worker will take over. + +The default value is 10000 milliseconds or 10 seconds. + +**Be sure to test your task's time and adjust the timeout accordingly.** + +Tasks that don't return a dictionary +------------------------------------ + +Sometimes we want a task to return a singular JSON value (not a dictionary). +To do this we can set the ``single_value`` parameter to ``True``. + +.. code-block:: python + + @worker.task(task_type="my_task", single_value=True, variable_name="y") + def my_task(x: int) -> int: + return x + 1 + +This will create a task that receives parameter ``x`` and returns an integer called ``y``. + +So the above task is in fact equal to: + +.. code-block:: python + + @worker.task(task_type="my_task") + def my_task(x: int) -> dict: + return {"y": x + 1} + + +This can be helpful when we don't want to read return values from a dictionary each time we call the task (in tests for example). + + From 84357ede7a514ee78d24d98e3b7b59e5c867608d Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 11:48:40 +0300 Subject: [PATCH 10/37] [ADDED] Decorator documentation --- docs/source/decorators.rst | 95 ++++++++++++++++++++++++++++++++++++ docs/source/index.rst | 1 + docs/source/worker_tasks.rst | 10 +++- 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 docs/source/decorators.rst diff --git a/docs/source/decorators.rst b/docs/source/decorators.rst new file mode 100644 index 00000000..da6e3625 --- /dev/null +++ b/docs/source/decorators.rst @@ -0,0 +1,95 @@ +========== +Decorators +========== + +A ``pyzeebe`` decorator is a function that receives a :class:`Job` instance and returns a :class:`Job`. + +.. code-block:: python + + Callable[[Job], Job] + +An example decorator: + +.. code-block:: python + + def logging_decorator(job: Job) -> Job: + logging.info(job) + return job +If a decorator raises an :class:`Exception` ``pyzeebe`` will just ignore it and continue the task/other decorators. + +Task Decorators +--------------- + +To add a decorator to a :class:`Task`: + +.. code-block:: python + + from pyzeebe import Job + + + def my_decorator(job: Job) -> Job: + print(job) + return job + + + @worker.task(task_type="my_task", before=[my_decorator], after=[my_decorator]) + def my_task(): + return {} + +Now before and after a job is performed ``my_decorator`` will be called. + +TaskRouter Decorators +--------------------- + +You can also add a decorator to a :class:`ZeebeTaskRouter`. All tasks registered under the router will then have the decorator. + + +.. code-block:: python + + from pyzeebe import ZeebeTaskRouter, Job + + router = ZeebeTaskRouter() + + def my_decorator(job: Job) -> Job: + print(job) + return job + + + router.before(my_decorator) + router.after(my_decorator) + +Now all tasks registered to the router will have ``my_decorator``. + +Worker Decorators +----------------- + +You can also add a decorator to a :class:`ZeebeWorker`. All tasks registered under the worker will then have the decorator. + + +.. code-block:: python + + from pyzeebe import ZeebeWorker, Job + + worker = ZeebeWorker() + + def my_decorator(job: Job) -> Job: + print(job) + return job + + + worker.before(my_decorator) + worker.after(my_decorator) + +Now all tasks registered to the worker will have ``my_decorator``. + + +Decorator order +--------------- + +``Worker`` -> ``Router`` -> ``Task`` -> Actual task function -> ``Task`` -> ``Router`` -> ``Worker`` + +``Worker`` - Decorators registered via the :class:`ZeebeWorker` class. + +``Router`` - Decorators registered via the :class:`ZeebeTaskRouter` class and included in the worker with ``include_router``. + +``Task`` - Decorators registered to the :class:`Task` class (with the worker/router ``task`` decorator). diff --git a/docs/source/index.rst b/docs/source/index.rst index 08bc10cd..d44925aa 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -62,3 +62,4 @@ Table Of Contents Client Worker + Decorators diff --git a/docs/source/worker_tasks.rst b/docs/source/worker_tasks.rst index 034397f6..c7b2b235 100644 --- a/docs/source/worker_tasks.rst +++ b/docs/source/worker_tasks.rst @@ -4,10 +4,10 @@ Tasks Tasks are the building blocks of workflows -Most basic Task +Creating a Task --------------- -To create a task you must first create a :class:`ZeebeWorker` instance. +To create a task you must first create a :class:`ZeebeWorker` or :class:`ZeebeTaskRouter` instance. .. code-block:: python @@ -18,7 +18,9 @@ To create a task you must first create a :class:`ZeebeWorker` instance. This is a task that does nothing. It receives no parameters and also doesn't return any. +.. note:: + While this task indeed returns a python dictionary, it doesn't return anything to Zeebe. Do do that we have to fill the dictionary. Task Exception Handler @@ -56,6 +58,7 @@ Now every time ``my_task`` is called (and then fails), ``my_exception_handler`` This tells Zeebe that the job failed. The job will then be retried (if configured in workflow definition). + Task timeout ------------ When creating a task one of the parameters we can specify is ``timeout``. @@ -98,4 +101,7 @@ So the above task is in fact equal to: This can be helpful when we don't want to read return values from a dictionary each time we call the task (in tests for example). +.. note:: + + The parameter ``variable_name`` must be supplied if ``single_value`` is true. If not given a :class:`NoVariableNameGiven` will be raised. From b6f197a2a2cd0bc50c59d8ab8251892706a8565e Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 11:56:09 +0300 Subject: [PATCH 11/37] [CHANGED] Client docs are one page --- docs/source/client.rst | 81 ++++++++++++++++++++++++++-- docs/source/client_quickstart.rst | 83 ----------------------------- docs/source/client_run_workflow.rst | 0 3 files changed, 76 insertions(+), 88 deletions(-) delete mode 100644 docs/source/client_quickstart.rst delete mode 100644 docs/source/client_run_workflow.rst diff --git a/docs/source/client.rst b/docs/source/client.rst index 8cc5f80e..63948c37 100644 --- a/docs/source/client.rst +++ b/docs/source/client.rst @@ -2,11 +2,82 @@ Client ====== -The page contains all information about the `ZeebeClient` class: +Create a client +--------------- +To create a client with default configuration: -.. toctree:: - :name: client +.. code-block:: python - Quickstart - Running workflows + from pyzeebe import ZeebeClient + + client = ZeebeClient() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 + + +To create a client with custom hostname and port: + +.. code-block:: python + + client = ZeebeClient(hostname="zeebe_gateway", port=26500) + +To create a client with a secure connection: + +.. code-block:: python + + client = ZeebeClient(secure_connection=True) + +To create a client with OAuth 2.0 authentication: + +.. code-block:: python + + from pyzeebe import ZeebeClient, OAuthCredentials + + credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", + audience="audience") + client = ZeebeClient() + +To create a client for a Camunda Cloud instance: + +.. code-block:: python + + from pyzeebe import ZeebeClient, CamundaCloudCredentials + + credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", + cluster_id="cluster_id") + client = ZeebeClient() + + +Run a workflow +-------------- + +.. code-block:: python + + workflow_instance_key = client.run_workflow("bpmn_process_id") + + +Run a workflow with result +-------------------------- + +To run a workflow and receive the result directly: + +.. code-block:: python + + result = client.run_workflow_with_result("bpmn_process_id") + + # result will be a dict + + +Deploy a workflow +----------------- + +.. code-block:: python + + client.deploy_workflow("workflow_file.bpmn") + + +Publish a message +----------------- + +.. code-block:: python + + client.publish_message(name="message_name", correlation_key="correlation_key") diff --git a/docs/source/client_quickstart.rst b/docs/source/client_quickstart.rst deleted file mode 100644 index a8609ac0..00000000 --- a/docs/source/client_quickstart.rst +++ /dev/null @@ -1,83 +0,0 @@ -================= -Client Quickstart -================= - -Create a client ---------------- - -To create a client with default configuration: - -.. code-block:: python - - from pyzeebe import ZeebeClient - - client = ZeebeClient() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 - - -To create a client with custom hostname and port: - -.. code-block:: python - - client = ZeebeClient(hostname="zeebe_gateway", port=26500) - -To create a client with a secure connection: - -.. code-block:: python - - client = ZeebeClient(secure_connection=True) - -To create a client with OAuth 2.0 authentication: - -.. code-block:: python - - from pyzeebe import ZeebeClient, OAuthCredentials - - credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", - audience="audience") - client = ZeebeClient() - -To create a client for a Camunda Cloud instance: - -.. code-block:: python - - from pyzeebe import ZeebeClient, CamundaCloudCredentials - - credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", - cluster_id="cluster_id") - client = ZeebeClient() - - -Run a workflow --------------- - -.. code-block:: python - - workflow_instance_key = client.run_workflow("bpmn_process_id") - - -Run a workflow with result --------------------------- - -To run a workflow and receive the result directly: - -.. code-block:: python - - result = client.run_workflow_with_result("bpmn_process_id") - - # result will be a dict - - -Deploy a workflow ------------------ - -.. code-block:: python - - client.deploy_workflow("workflow_file.bpmn") - - -Publish a message ------------------ - -.. code-block:: python - - client.publish_message(name="message_name", correlation_key="correlation_key") diff --git a/docs/source/client_run_workflow.rst b/docs/source/client_run_workflow.rst deleted file mode 100644 index e69de29b..00000000 From b06109a81fdad5295bfb6c3df3252247a75bba89 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 12:52:36 +0300 Subject: [PATCH 12/37] [ADDED] theme, auto docs --- Pipfile | 1 + Pipfile.lock | 16 ++++++++++++---- docs/source/conf.py | 16 +++++++++++----- docs/source/decorators.rst | 1 + docs/source/index.rst | 2 -- docs/source/worker.rst | 4 +++- docs/source/worker_reference.rst | 27 +++++++++++++++++++++++++++ docs/source/worker_taskrouter.rst | 7 +++++++ pyzeebe/worker/task_handler.py | 22 ++++++++++++++-------- pyzeebe/worker/worker.py | 2 +- 10 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 docs/source/worker_reference.rst create mode 100644 docs/source/worker_taskrouter.rst diff --git a/Pipfile b/Pipfile index f13d3075..7fcb35ed 100644 --- a/Pipfile +++ b/Pipfile @@ -14,6 +14,7 @@ coveralls = "~=2.1.2" importlib-metadata = "~=1.7.0" pyzeebe = {editable = true, path = "."} sphinx = "~=3.2.1" +sphinx-rtd-theme = "*" [packages] grpcio = "~=1.31.0" diff --git a/Pipfile.lock b/Pipfile.lock index 621a3fee..e0ea8fdb 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "47d93a76534c451b2a976519c2f8b4394af69c80c97cc8c78bb44cdae17bdc83" + "sha256": "149fa7a9f59eed05549f84ebf0107445089952897347f0bb678be8e9cba074fb" }, "pipfile-spec": 6, "requires": {}, @@ -356,11 +356,11 @@ }, "isort": { "hashes": [ - "sha256:6187a9f1ce8784cbc6d1b88790a43e6083a6302f03e9ae482acc0f232a98c843", - "sha256:c16eaa7432a1c004c585d79b12ad080c6c421dd18fe27982ca11f95e6898e432" + "sha256:36f0c6659b9000597e92618d05b72d4181104cf59472b1c6a039e3783f930c95", + "sha256:ba040c24d20aa302f78f4747df549573ae1eaf8e1084269199154da9c483f07f" ], "markers": "python_version >= '3.6' and python_version < '4.0'", - "version": "==5.5.3" + "version": "==5.5.4" }, "jinja2": { "hashes": [ @@ -633,6 +633,14 @@ "index": "pypi", "version": "==3.2.1" }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d", + "sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82" + ], + "index": "pypi", + "version": "==0.5.0" + }, "sphinxcontrib-applehelp": { "hashes": [ "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", diff --git a/docs/source/conf.py b/docs/source/conf.py index d8fb86ca..9031d222 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,13 +10,17 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) +import os +import sys +sys.path.insert(0, os.path.abspath('...')) # -- Project information ----------------------------------------------------- +import sphinx_rtd_theme + +sphinx_rtd_theme # So optimize imports doens't erase it + project = 'pyzeebe' copyright = '2020, Jonatan Martens' author = 'Jonatan Martens' @@ -30,6 +34,9 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + "sphinx_rtd_theme", + "sphinx.ext.autodoc", + "sphinx.ext.napoleon" ] # Add any paths that contain templates here, relative to this directory. @@ -40,13 +47,12 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] - # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'classic' +html_theme = "sphinx_rtd_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/source/decorators.rst b/docs/source/decorators.rst index da6e3625..964e07a3 100644 --- a/docs/source/decorators.rst +++ b/docs/source/decorators.rst @@ -15,6 +15,7 @@ An example decorator: def logging_decorator(job: Job) -> Job: logging.info(job) return job + If a decorator raises an :class:`Exception` ``pyzeebe`` will just ignore it and continue the task/other decorators. Task Decorators diff --git a/docs/source/index.rst b/docs/source/index.rst index d44925aa..de3f5106 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,3 @@ -.. pyzeebe documentation master file, created by Jonatan Martens. sphinx-quickstart on Tue Sep 29 12:49:24 2020. - Welcome to pyzeebe's documentation! =================================== Python client for Zeebe workflow engine diff --git a/docs/source/worker.rst b/docs/source/worker.rst index 0246fd22..338002dc 100644 --- a/docs/source/worker.rst +++ b/docs/source/worker.rst @@ -2,7 +2,7 @@ Worker ====== -The page contains all information about the :class:`ZeebeWorker` class: +The page contains all information about the :py:class:`ZeebeWorker` class: .. toctree:: @@ -10,3 +10,5 @@ The page contains all information about the :class:`ZeebeWorker` class: Quickstart Tasks + TaskRouter + Reference diff --git a/docs/source/worker_reference.rst b/docs/source/worker_reference.rst new file mode 100644 index 00000000..8ac5e46a --- /dev/null +++ b/docs/source/worker_reference.rst @@ -0,0 +1,27 @@ +================ +Worker Reference +================ + +The :py:class:`ZeebeTaskHandler` class from which both :py:class:`ZeebeWorker` and :py:class:`ZeebeTaskRouter` inherit. + +.. autoclass:: pyzeebe.worker.task_handler.ZeebeTaskHandler + :members: + :undoc-members: + + +.. autoclass:: pyzeebe.ZeebeWorker + :members: + :undoc-members: + +.. autoclass:: pyzeebe.ZeebeTaskRouter + :members: + :undoc-members: + +.. autoclass:: pyzeebe.Job + :members: + :undoc-members: + + +.. autoclass:: pyzeebe.JobStatus + :members: + :undoc-members: diff --git a/docs/source/worker_taskrouter.rst b/docs/source/worker_taskrouter.rst new file mode 100644 index 00000000..49a80f93 --- /dev/null +++ b/docs/source/worker_taskrouter.rst @@ -0,0 +1,7 @@ +=========== +Task Router +=========== + +.. py:class:: ZeebeTaskRouter + + ... diff --git a/pyzeebe/worker/task_handler.py b/pyzeebe/worker/task_handler.py index 13424203..976af334 100644 --- a/pyzeebe/worker/task_handler.py +++ b/pyzeebe/worker/task_handler.py @@ -29,14 +29,20 @@ def task(self, task_type: str, exception_handler: ExceptionHandler = default_exc variables_to_fetch: List[str] = None, timeout: int = 10000, max_jobs_to_activate: int = 32, before: List[TaskDecorator] = None, after: List[TaskDecorator] = None, single_value: bool = False, variable_name: str = None): - """Decorator to create a task - single_value (bool): If the function returns a single value (int, string, list) and not a dictionary set this to - True. Default: False - variable_name (str): If single_value then this will be the variable name given to zeebe: - { : } - timeout (int): Maximum duration of the task in milliseconds. If the timeout is surpasses Zeebe will give up - on the job and retry it. Default: 10000 - max_jobs_to_activate (int): Maximum jobs the worker will execute in parallel (of this task). Default: 32 + """ + Decorator to create a task + + Args: + before (List[TaskDecorator]): All decorators which should be performed before the task. + after (List[TaskDecorator]): All decorators which should be performed after the task. + timeout (int): How long Zeebe should wait before the job is retried. Default: 10000 milliseconds + single_value (bool): If the function returns a single value (int, string, list) and not a dictionary set + this to True. Default: False + variable_name (str): If single_value then this will be the variable name given to zeebe: + { : } + timeout (int): Maximum duration of the task in milliseconds. If the timeout is surpasses Zeebe will give up + on the job and retry it. Default: 10000 + max_jobs_to_activate (int): Maximum jobs the worker will execute in parallel (of this task). Default: 32 """ if single_value and not variable_name: raise NoVariableNameGiven(task_type=task_type) diff --git a/pyzeebe/worker/worker.py b/pyzeebe/worker/worker.py index 447209c1..2fbec272 100644 --- a/pyzeebe/worker/worker.py +++ b/pyzeebe/worker/worker.py @@ -44,7 +44,7 @@ def work(self) -> None: task_thread = Thread(target=self._handle_task, args=(task,)) task_thread.start() - def stop(self): + def stop(self) -> None: """ Stop the worker. This will wait for all tasks to complete before stopping """ From fecc08309946805735dfae3333e9217987ddd88d Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 12:54:30 +0300 Subject: [PATCH 13/37] [CHANGED] :class: to :py:class: --- docs/source/decorators.rst | 14 +++++++------- docs/source/worker_tasks.rst | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/decorators.rst b/docs/source/decorators.rst index 964e07a3..2c299932 100644 --- a/docs/source/decorators.rst +++ b/docs/source/decorators.rst @@ -2,7 +2,7 @@ Decorators ========== -A ``pyzeebe`` decorator is a function that receives a :class:`Job` instance and returns a :class:`Job`. +A ``pyzeebe`` decorator is a function that receives a :py:class:`Job` instance and returns a :py:class:`Job`. .. code-block:: python @@ -21,7 +21,7 @@ If a decorator raises an :class:`Exception` ``pyzeebe`` will just ignore it and Task Decorators --------------- -To add a decorator to a :class:`Task`: +To add a decorator to a :py:class:`Task`: .. code-block:: python @@ -42,7 +42,7 @@ Now before and after a job is performed ``my_decorator`` will be called. TaskRouter Decorators --------------------- -You can also add a decorator to a :class:`ZeebeTaskRouter`. All tasks registered under the router will then have the decorator. +You can also add a decorator to a :py:class:`ZeebeTaskRouter`. All tasks registered under the router will then have the decorator. .. code-block:: python @@ -64,7 +64,7 @@ Now all tasks registered to the router will have ``my_decorator``. Worker Decorators ----------------- -You can also add a decorator to a :class:`ZeebeWorker`. All tasks registered under the worker will then have the decorator. +You can also add a decorator to a :py:class:`ZeebeWorker`. All tasks registered under the worker will then have the decorator. .. code-block:: python @@ -89,8 +89,8 @@ Decorator order ``Worker`` -> ``Router`` -> ``Task`` -> Actual task function -> ``Task`` -> ``Router`` -> ``Worker`` -``Worker`` - Decorators registered via the :class:`ZeebeWorker` class. +``Worker`` - Decorators registered via the :py:class:`ZeebeWorker` class. -``Router`` - Decorators registered via the :class:`ZeebeTaskRouter` class and included in the worker with ``include_router``. +``Router`` - Decorators registered via the :py:class:`ZeebeTaskRouter` class and included in the worker with ``include_router``. -``Task`` - Decorators registered to the :class:`Task` class (with the worker/router ``task`` decorator). +``Task`` - Decorators registered to the :py:class:`Task` class (with the worker/router ``task`` decorator). diff --git a/docs/source/worker_tasks.rst b/docs/source/worker_tasks.rst index c7b2b235..9372a11e 100644 --- a/docs/source/worker_tasks.rst +++ b/docs/source/worker_tasks.rst @@ -7,7 +7,7 @@ Tasks are the building blocks of workflows Creating a Task --------------- -To create a task you must first create a :class:`ZeebeWorker` or :class:`ZeebeTaskRouter` instance. +To create a task you must first create a :py:class:`ZeebeWorker` or :py:class:`ZeebeTaskRouter` instance. .. code-block:: python @@ -32,7 +32,7 @@ An exception handler's signature: Callable[[Exception, Job], None] -In other words: an exception handler is a function that receives an :class:`Exception` and :class:`Job` instance (a pyzeebe class). +In other words: an exception handler is a function that receives an :class:`Exception` and :py:class:`Job` instance (a pyzeebe class). The exception handler is called when the task has failed. From a008db7819b66f9d507a58a6169b345cf230268d Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 13:07:41 +0300 Subject: [PATCH 14/37] [ADDED] ZeebeTaskRouter documentation --- docs/source/worker_taskrouter.rst | 41 ++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/source/worker_taskrouter.rst b/docs/source/worker_taskrouter.rst index 49a80f93..28515d8d 100644 --- a/docs/source/worker_taskrouter.rst +++ b/docs/source/worker_taskrouter.rst @@ -2,6 +2,45 @@ Task Router =========== -.. py:class:: ZeebeTaskRouter +The :py:class:`ZeebeTaskRouter` class is responsible for routing tasks to a :py:class:`ZeebeWorker` instance. +This helps with organization of large projects, where you can't import the worker in each file. + +Create a Router +--------------- + +.. code-block:: python + + from pyzeebe import ZeebeTaskRouter + + router = ZeebeTaskRouter() + +Create a task with a Router +--------------------------- + +Creating a task with a router is the exact same process as wiht a :py:class:`ZeebeWorker` instance. + +.. code-block:: python + + @router.task(task_type="my_task") + def my_task(x: int): + return {"y": x + 1} + + +.. note:: + + The :py:class:`ZeebeTaskRouter` :py:func:`task` decorator has all the capabities of the :py:class:`ZeebeWorker` class. + +Merge Router tasks to a worker +------------------------------ + +To add the router tasks to the worker we use the :py:func:`include_router` method on the worker. + +.. code-block:: python + + from my_task import router + + worker.include_router(router) ... + +That's it! From e9733d2a3c1a4ec083ef9335baef6275081224da Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 14:22:34 +0300 Subject: [PATCH 15/37] [ADDED] Client reference --- docs/source/client.rst | 82 ++------------------------------ docs/source/client_reference.rst | 7 +++ pyzeebe/client/client.py | 54 ++++++++++++++++++++- 3 files changed, 64 insertions(+), 79 deletions(-) create mode 100644 docs/source/client_reference.rst diff --git a/docs/source/client.rst b/docs/source/client.rst index 63948c37..a82a7db0 100644 --- a/docs/source/client.rst +++ b/docs/source/client.rst @@ -2,82 +2,8 @@ Client ====== -Create a client ---------------- +.. toctree:: + :name: client -To create a client with default configuration: - -.. code-block:: python - - from pyzeebe import ZeebeClient - - client = ZeebeClient() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 - - -To create a client with custom hostname and port: - -.. code-block:: python - - client = ZeebeClient(hostname="zeebe_gateway", port=26500) - -To create a client with a secure connection: - -.. code-block:: python - - client = ZeebeClient(secure_connection=True) - -To create a client with OAuth 2.0 authentication: - -.. code-block:: python - - from pyzeebe import ZeebeClient, OAuthCredentials - - credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", - audience="audience") - client = ZeebeClient() - -To create a client for a Camunda Cloud instance: - -.. code-block:: python - - from pyzeebe import ZeebeClient, CamundaCloudCredentials - - credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", - cluster_id="cluster_id") - client = ZeebeClient() - - -Run a workflow --------------- - -.. code-block:: python - - workflow_instance_key = client.run_workflow("bpmn_process_id") - - -Run a workflow with result --------------------------- - -To run a workflow and receive the result directly: - -.. code-block:: python - - result = client.run_workflow_with_result("bpmn_process_id") - - # result will be a dict - - -Deploy a workflow ------------------ - -.. code-block:: python - - client.deploy_workflow("workflow_file.bpmn") - - -Publish a message ------------------ - -.. code-block:: python - - client.publish_message(name="message_name", correlation_key="correlation_key") + Quickstart + Reference diff --git a/docs/source/client_reference.rst b/docs/source/client_reference.rst new file mode 100644 index 00000000..0addf6bf --- /dev/null +++ b/docs/source/client_reference.rst @@ -0,0 +1,7 @@ +================ +Client Reference +================ + +.. autoclass:: pyzeebe.ZeebeClient + :members: + :undoc-members: diff --git a/pyzeebe/client/client.py b/pyzeebe/client/client.py index 902fcd1f..a8c4cc82 100644 --- a/pyzeebe/client/client.py +++ b/pyzeebe/client/client.py @@ -13,25 +13,77 @@ def __init__(self, hostname: str = None, port: int = None, credentials: BaseCred secure_connection=secure_connection) def run_workflow(self, bpmn_process_id: str, variables: Dict = None, version: int = -1) -> int: + """ + Run workflow + + Args: + bpmn_process_id (str): The unique process id of the workflow. + variables (dict): A dictionary containing all the starting variables the workflow needs. Must be JSONable. + version (int): The version of the workflow. Default: -1 (latest) + + Returns: + int: workflow_instance_key, the unique id of the running workflow generated by Zeebe. + """ return self.zeebe_adapter.create_workflow_instance(bpmn_process_id=bpmn_process_id, variables=variables or {}, version=version) def run_workflow_with_result(self, bpmn_process_id: str, variables: Dict = None, version: int = -1, timeout: int = 0, variables_to_fetch: List[str] = None) -> Dict: + """ + Run workflow and wait for the result. + + Args: + bpmn_process_id (str): The unique process id of the workflow. + variables (dict): A dictionary containing all the starting variables the workflow needs. Must be JSONable. + version (int): The version of the workflow. Default: -1 (latest) + timeout (int): How long to wait until a timeout occurs. Default: 0 (Zeebe default timeout) + variables_to_fetch (List[str]): Which variables to get from the finished workflow + + Returns: + dict: A dictionary of the end state of the workflow instance + """ return self.zeebe_adapter.create_workflow_instance_with_result(bpmn_process_id=bpmn_process_id, variables=variables or {}, version=version, timeout=timeout, variables_to_fetch=variables_to_fetch or []) def cancel_workflow_instance(self, workflow_instance_key: int) -> int: + """ + Cancel a running workflow instance + + Args: + workflow_instance_key (int): The key of the running workflow to cancel + + Returns: + int: The workflow_instance_key + """ self.zeebe_adapter.cancel_workflow_instance(workflow_instance_key=workflow_instance_key) return workflow_instance_key - def deploy_workflow(self, *workflow_file_path: str): + def deploy_workflow(self, *workflow_file_path: str) -> None: + """ + Deploy one or more workflows + + Args: + workflow_file_path (str): The file path to a workflow definition file (bpmn/yaml) + + """ self.zeebe_adapter.deploy_workflow(*workflow_file_path) def publish_message(self, name: str, correlation_key: str, variables: Dict = None, time_to_live_in_milliseconds: int = 60000, message_id: str = None) -> None: + """ + Publish a message + + Args: + name (str): The message name + correlation_key (str): The correlation key. For more info: https://docs.zeebe.io/glossary.html?highlight=correlation#correlation-key + variables (dict): The variables the message should contain. + time_to_live_in_milliseconds (int): How long this message should stay active. Default: 60000 ms (60 seconds) + message_id (str): A unique message id. Useful for avoiding duplication. If a message with this id is still + active, a MessageAlreadyExists will be raised. + + """ self.zeebe_adapter.publish_message(name=name, correlation_key=correlation_key, time_to_live_in_milliseconds=time_to_live_in_milliseconds, variables=variables or {}, message_id=message_id) From 062cbdb39018672af1dbee03df734af507a06145 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 14:43:17 +0300 Subject: [PATCH 16/37] [ADDED] Client reference --- docs/source/client_quickstart.rst | 83 +++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 docs/source/client_quickstart.rst diff --git a/docs/source/client_quickstart.rst b/docs/source/client_quickstart.rst new file mode 100644 index 00000000..3cafb0fc --- /dev/null +++ b/docs/source/client_quickstart.rst @@ -0,0 +1,83 @@ +================= +Client QuickStart +================= + +Create a client +--------------- + +To create a client with default configuration: + +.. code-block:: python + + from pyzeebe import ZeebeClient + + client = ZeebeClient() # Will use ZEEBE_ADDRESS environment variable or localhost:26500 + + +To create a client with custom hostname and port: + +.. code-block:: python + + client = ZeebeClient(hostname="zeebe_gateway", port=26500) + +To create a client with a secure connection: + +.. code-block:: python + + client = ZeebeClient(secure_connection=True) + +To create a client with OAuth 2.0 authentication: + +.. code-block:: python + + from pyzeebe import ZeebeClient, OAuthCredentials + + credentials = OAuthCredentials(url="oauth_token_url", client_id="client_id", client_secret="client_secret", + audience="audience") + client = ZeebeClient() + +To create a client for a Camunda Cloud instance: + +.. code-block:: python + + from pyzeebe import ZeebeClient, CamundaCloudCredentials + + credentials = CamundaCloudCredentials(client_id="client_id", client_secret="client_secret", + cluster_id="cluster_id") + client = ZeebeClient() + + +Run a workflow +-------------- + +.. code-block:: python + + workflow_instance_key = client.run_workflow("bpmn_process_id") + + +Run a workflow with result +-------------------------- + +To run a workflow and receive the result directly: + +.. code-block:: python + + result = client.run_workflow_with_result("bpmn_process_id") + + # result will be a dict + + +Deploy a workflow +----------------- + +.. code-block:: python + + client.deploy_workflow("workflow_file.bpmn") + + +Publish a message +----------------- + +.. code-block:: python + + client.publish_message(name="message_name", correlation_key="correlation_key") From 1fc6fd40587612b8597b4aecdee90b6db654bd34 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 14:45:07 +0300 Subject: [PATCH 17/37] [MOVED] Documentation conf and rst files to docs/ from docs/source --- .readthedocs.yml | 2 +- docs/{source => }/client.rst | 0 docs/{source => }/client_quickstart.rst | 0 docs/{source => }/client_reference.rst | 0 docs/{source => }/conf.py | 0 docs/{source => }/decorators.rst | 0 docs/{source => }/index.rst | 0 docs/{source => }/worker.rst | 0 docs/{source => }/worker_quickstart.rst | 0 docs/{source => }/worker_reference.rst | 0 docs/{source => }/worker_taskrouter.rst | 0 docs/{source => }/worker_tasks.rst | 0 12 files changed, 1 insertion(+), 1 deletion(-) rename docs/{source => }/client.rst (100%) rename docs/{source => }/client_quickstart.rst (100%) rename docs/{source => }/client_reference.rst (100%) rename docs/{source => }/conf.py (100%) rename docs/{source => }/decorators.rst (100%) rename docs/{source => }/index.rst (100%) rename docs/{source => }/worker.rst (100%) rename docs/{source => }/worker_quickstart.rst (100%) rename docs/{source => }/worker_reference.rst (100%) rename docs/{source => }/worker_taskrouter.rst (100%) rename docs/{source => }/worker_tasks.rst (100%) diff --git a/.readthedocs.yml b/.readthedocs.yml index 51b24220..e35d1fa6 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,5 +7,5 @@ python: sphinx: builder: html - configuration: docs/source/conf.py + configuration: docs/conf.py #fail_on_warning: true diff --git a/docs/source/client.rst b/docs/client.rst similarity index 100% rename from docs/source/client.rst rename to docs/client.rst diff --git a/docs/source/client_quickstart.rst b/docs/client_quickstart.rst similarity index 100% rename from docs/source/client_quickstart.rst rename to docs/client_quickstart.rst diff --git a/docs/source/client_reference.rst b/docs/client_reference.rst similarity index 100% rename from docs/source/client_reference.rst rename to docs/client_reference.rst diff --git a/docs/source/conf.py b/docs/conf.py similarity index 100% rename from docs/source/conf.py rename to docs/conf.py diff --git a/docs/source/decorators.rst b/docs/decorators.rst similarity index 100% rename from docs/source/decorators.rst rename to docs/decorators.rst diff --git a/docs/source/index.rst b/docs/index.rst similarity index 100% rename from docs/source/index.rst rename to docs/index.rst diff --git a/docs/source/worker.rst b/docs/worker.rst similarity index 100% rename from docs/source/worker.rst rename to docs/worker.rst diff --git a/docs/source/worker_quickstart.rst b/docs/worker_quickstart.rst similarity index 100% rename from docs/source/worker_quickstart.rst rename to docs/worker_quickstart.rst diff --git a/docs/source/worker_reference.rst b/docs/worker_reference.rst similarity index 100% rename from docs/source/worker_reference.rst rename to docs/worker_reference.rst diff --git a/docs/source/worker_taskrouter.rst b/docs/worker_taskrouter.rst similarity index 100% rename from docs/source/worker_taskrouter.rst rename to docs/worker_taskrouter.rst diff --git a/docs/source/worker_tasks.rst b/docs/worker_tasks.rst similarity index 100% rename from docs/source/worker_tasks.rst rename to docs/worker_tasks.rst From 20021f65c2b7fd0c09de4e2bca43a8520fd818fc Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 14:50:03 +0300 Subject: [PATCH 18/37] Revert "[MOVED] Documentation conf and rst files to docs/ from docs/source" This reverts commit 1fc6fd40 --- .readthedocs.yml | 2 +- docs/{ => source}/client.rst | 0 docs/{ => source}/client_quickstart.rst | 0 docs/{ => source}/client_reference.rst | 0 docs/{ => source}/conf.py | 0 docs/{ => source}/decorators.rst | 0 docs/{ => source}/index.rst | 0 docs/{ => source}/worker.rst | 0 docs/{ => source}/worker_quickstart.rst | 0 docs/{ => source}/worker_reference.rst | 0 docs/{ => source}/worker_taskrouter.rst | 0 docs/{ => source}/worker_tasks.rst | 0 12 files changed, 1 insertion(+), 1 deletion(-) rename docs/{ => source}/client.rst (100%) rename docs/{ => source}/client_quickstart.rst (100%) rename docs/{ => source}/client_reference.rst (100%) rename docs/{ => source}/conf.py (100%) rename docs/{ => source}/decorators.rst (100%) rename docs/{ => source}/index.rst (100%) rename docs/{ => source}/worker.rst (100%) rename docs/{ => source}/worker_quickstart.rst (100%) rename docs/{ => source}/worker_reference.rst (100%) rename docs/{ => source}/worker_taskrouter.rst (100%) rename docs/{ => source}/worker_tasks.rst (100%) diff --git a/.readthedocs.yml b/.readthedocs.yml index e35d1fa6..51b24220 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,5 +7,5 @@ python: sphinx: builder: html - configuration: docs/conf.py + configuration: docs/source/conf.py #fail_on_warning: true diff --git a/docs/client.rst b/docs/source/client.rst similarity index 100% rename from docs/client.rst rename to docs/source/client.rst diff --git a/docs/client_quickstart.rst b/docs/source/client_quickstart.rst similarity index 100% rename from docs/client_quickstart.rst rename to docs/source/client_quickstart.rst diff --git a/docs/client_reference.rst b/docs/source/client_reference.rst similarity index 100% rename from docs/client_reference.rst rename to docs/source/client_reference.rst diff --git a/docs/conf.py b/docs/source/conf.py similarity index 100% rename from docs/conf.py rename to docs/source/conf.py diff --git a/docs/decorators.rst b/docs/source/decorators.rst similarity index 100% rename from docs/decorators.rst rename to docs/source/decorators.rst diff --git a/docs/index.rst b/docs/source/index.rst similarity index 100% rename from docs/index.rst rename to docs/source/index.rst diff --git a/docs/worker.rst b/docs/source/worker.rst similarity index 100% rename from docs/worker.rst rename to docs/source/worker.rst diff --git a/docs/worker_quickstart.rst b/docs/source/worker_quickstart.rst similarity index 100% rename from docs/worker_quickstart.rst rename to docs/source/worker_quickstart.rst diff --git a/docs/worker_reference.rst b/docs/source/worker_reference.rst similarity index 100% rename from docs/worker_reference.rst rename to docs/source/worker_reference.rst diff --git a/docs/worker_taskrouter.rst b/docs/source/worker_taskrouter.rst similarity index 100% rename from docs/worker_taskrouter.rst rename to docs/source/worker_taskrouter.rst diff --git a/docs/worker_tasks.rst b/docs/source/worker_tasks.rst similarity index 100% rename from docs/worker_tasks.rst rename to docs/source/worker_tasks.rst From ebf4da89f221ae43a82a2551a50c36b5a252a4fa Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 14:59:32 +0300 Subject: [PATCH 19/37] [TRYING] once again moved to /docs/ --- docs/{source => }/client.rst | 0 docs/{source => }/client_quickstart.rst | 0 docs/{source => }/client_reference.rst | 0 docs/{source => }/conf.py | 2 +- docs/{source => }/decorators.rst | 0 docs/{source => }/index.rst | 0 docs/{source => }/worker.rst | 0 docs/{source => }/worker_quickstart.rst | 0 docs/{source => }/worker_reference.rst | 0 docs/{source => }/worker_taskrouter.rst | 0 docs/{source => }/worker_tasks.rst | 0 11 files changed, 1 insertion(+), 1 deletion(-) rename docs/{source => }/client.rst (100%) rename docs/{source => }/client_quickstart.rst (100%) rename docs/{source => }/client_reference.rst (100%) rename docs/{source => }/conf.py (97%) rename docs/{source => }/decorators.rst (100%) rename docs/{source => }/index.rst (100%) rename docs/{source => }/worker.rst (100%) rename docs/{source => }/worker_quickstart.rst (100%) rename docs/{source => }/worker_reference.rst (100%) rename docs/{source => }/worker_taskrouter.rst (100%) rename docs/{source => }/worker_tasks.rst (100%) diff --git a/docs/source/client.rst b/docs/client.rst similarity index 100% rename from docs/source/client.rst rename to docs/client.rst diff --git a/docs/source/client_quickstart.rst b/docs/client_quickstart.rst similarity index 100% rename from docs/source/client_quickstart.rst rename to docs/client_quickstart.rst diff --git a/docs/source/client_reference.rst b/docs/client_reference.rst similarity index 100% rename from docs/source/client_reference.rst rename to docs/client_reference.rst diff --git a/docs/source/conf.py b/docs/conf.py similarity index 97% rename from docs/source/conf.py rename to docs/conf.py index 9031d222..5cf75fee 100644 --- a/docs/source/conf.py +++ b/docs/conf.py @@ -13,7 +13,7 @@ import os import sys -sys.path.insert(0, os.path.abspath('...')) +sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- diff --git a/docs/source/decorators.rst b/docs/decorators.rst similarity index 100% rename from docs/source/decorators.rst rename to docs/decorators.rst diff --git a/docs/source/index.rst b/docs/index.rst similarity index 100% rename from docs/source/index.rst rename to docs/index.rst diff --git a/docs/source/worker.rst b/docs/worker.rst similarity index 100% rename from docs/source/worker.rst rename to docs/worker.rst diff --git a/docs/source/worker_quickstart.rst b/docs/worker_quickstart.rst similarity index 100% rename from docs/source/worker_quickstart.rst rename to docs/worker_quickstart.rst diff --git a/docs/source/worker_reference.rst b/docs/worker_reference.rst similarity index 100% rename from docs/source/worker_reference.rst rename to docs/worker_reference.rst diff --git a/docs/source/worker_taskrouter.rst b/docs/worker_taskrouter.rst similarity index 100% rename from docs/source/worker_taskrouter.rst rename to docs/worker_taskrouter.rst diff --git a/docs/source/worker_tasks.rst b/docs/worker_tasks.rst similarity index 100% rename from docs/source/worker_tasks.rst rename to docs/worker_tasks.rst From 1d2aef2c4cde77c8ad109dbb2edc5588329b61dd Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:01:21 +0300 Subject: [PATCH 20/37] [FIXED] config location --- .readthedocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 51b24220..e35d1fa6 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,5 +7,5 @@ python: sphinx: builder: html - configuration: docs/source/conf.py + configuration: docs/conf.py #fail_on_warning: true From e35da651b2c22566a47a3f0e27f185840501ff8d Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:25:08 +0300 Subject: [PATCH 21/37] Using requirements.txt instead of pipenv --- .github/workflows/test-python-package.yml | 11 +- .github/workflows/test-zeebe-integration.yml | 9 +- Pipfile | 23 - Pipfile.lock | 756 ------------------- requirements.txt | 14 + 5 files changed, 23 insertions(+), 790 deletions(-) delete mode 100644 Pipfile delete mode 100644 Pipfile.lock create mode 100644 requirements.txt diff --git a/.github/workflows/test-python-package.yml b/.github/workflows/test-python-package.yml index 7c22af61..e969bbd5 100644 --- a/.github/workflows/test-python-package.yml +++ b/.github/workflows/test-python-package.yml @@ -2,9 +2,9 @@ name: Test pyzeebe on: push: - branches: [ master, development, feature/*, bugfix/*, maintenance/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] pull_request: - branches: [ master, development, feature/*, bugfix/*, maintenance/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] jobs: build: @@ -19,13 +19,12 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies run: | - pip install pipenv - pipenv install --dev + pip install -r requirements.txt - name: Test with pytest run: | - pipenv run coverage run --source=pyzeebe -m py.test tests/unit + coverage run --source=pyzeebe -m py.test tests/unit - name: Upload to coveralls run: | - pipenv run coveralls + coveralls env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-zeebe-integration.yml b/.github/workflows/test-zeebe-integration.yml index 464f1502..538a6bdf 100644 --- a/.github/workflows/test-zeebe-integration.yml +++ b/.github/workflows/test-zeebe-integration.yml @@ -2,9 +2,9 @@ name: Integration test pyzeebe on: push: - branches: [ master, development, feature/*, bugfix/*, maintenance/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] pull_request: - branches: [ master, development, feature/*, bugfix/*, maintenance/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] jobs: test: @@ -28,9 +28,8 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies run: | - pip install pipenv - pipenv install --dev + pip install -r requirements.txt - name: Run integration tests run: | - pipenv run pytest tests/integration + pytest tests/integration diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 7fcb35ed..00000000 --- a/Pipfile +++ /dev/null @@ -1,23 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -autopep8 = "~=1.5.4" -pylint = "~=2.6.0" -coverage = "~=5.2.1" -pytest = "~=6.0.1" -pytest-grpc = "~=0.8.0" -mypy = "~=0.782" -coveralls = "~=2.1.2" -importlib-metadata = "~=1.7.0" -pyzeebe = {editable = true, path = "."} -sphinx = "~=3.2.1" -sphinx-rtd-theme = "*" - -[packages] -grpcio = "~=1.31.0" -protobuf = "~=3.13.0" -oauthlib = "~=3.1.0" -requests-oauthlib = "~=1.3.0" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index e0ea8fdb..00000000 --- a/Pipfile.lock +++ /dev/null @@ -1,756 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "149fa7a9f59eed05549f84ebf0107445089952897347f0bb678be8e9cba074fb" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "certifi": { - "hashes": [ - "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", - "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" - ], - "version": "==2020.6.20" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "grpcio": { - "hashes": [ - "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151", - "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a", - "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304", - "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482", - "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6", - "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df", - "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9", - "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c", - "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9", - "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6", - "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796", - "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39", - "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637", - "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e", - "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd", - "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2", - "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff", - "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1", - "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352", - "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f", - "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a", - "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069", - "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a", - "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642", - "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510", - "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71", - "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc", - "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf", - "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e", - "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b", - "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408", - "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590", - "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552", - "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b", - "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084", - "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770", - "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225", - "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7", - "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d" - ], - "index": "pypi", - "version": "==1.31.0" - }, - "idna": { - "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" - }, - "oauthlib": { - "hashes": [ - "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", - "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" - ], - "index": "pypi", - "version": "==3.1.0" - }, - "protobuf": { - "hashes": [ - "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33", - "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463", - "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c", - "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a", - "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f", - "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7", - "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b", - "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5", - "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4", - "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec", - "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c", - "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630", - "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7", - "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e", - "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a", - "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060", - "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9", - "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb" - ], - "index": "pypi", - "version": "==3.13.0" - }, - "requests": { - "hashes": [ - "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", - "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.24.0" - }, - "requests-oauthlib": { - "hashes": [ - "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", - "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", - "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" - ], - "index": "pypi", - "version": "==1.3.0" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.15.0" - }, - "urllib3": { - "hashes": [ - "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a", - "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.25.10" - } - }, - "develop": { - "alabaster": { - "hashes": [ - "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", - "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" - ], - "version": "==0.7.12" - }, - "astroid": { - "hashes": [ - "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703", - "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386" - ], - "markers": "python_version >= '3.5'", - "version": "==2.4.2" - }, - "atomicwrites": { - "hashes": [ - "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", - "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" - ], - "markers": "sys_platform == 'win32'", - "version": "==1.4.0" - }, - "attrs": { - "hashes": [ - "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594", - "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.2.0" - }, - "autopep8": { - "hashes": [ - "sha256:d21d3901cb0da6ebd1e83fc9b0dfbde8b46afc2ede4fe32fbda0c7c6118ca094" - ], - "index": "pypi", - "version": "==1.5.4" - }, - "babel": { - "hashes": [ - "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", - "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.0" - }, - "certifi": { - "hashes": [ - "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", - "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" - ], - "version": "==2020.6.20" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "colorama": { - "hashes": [ - "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", - "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" - ], - "markers": "sys_platform == 'win32' and sys_platform == 'win32' and sys_platform == 'win32'", - "version": "==0.4.3" - }, - "coverage": { - "hashes": [ - "sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb", - "sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3", - "sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716", - "sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034", - "sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3", - "sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8", - "sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0", - "sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f", - "sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4", - "sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962", - "sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d", - "sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b", - "sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4", - "sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3", - "sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258", - "sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59", - "sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01", - "sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd", - "sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b", - "sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d", - "sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89", - "sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd", - "sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b", - "sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d", - "sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46", - "sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546", - "sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082", - "sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b", - "sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4", - "sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8", - "sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811", - "sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd", - "sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651", - "sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0" - ], - "index": "pypi", - "version": "==5.2.1" - }, - "coveralls": { - "hashes": [ - "sha256:4430b862baabb3cf090d36d84d331966615e4288d8a8c5957e0fd456d0dd8bd6", - "sha256:b3b60c17b03a0dee61952a91aed6f131e0b2ac8bd5da909389c53137811409e1" - ], - "index": "pypi", - "version": "==2.1.2" - }, - "docopt": { - "hashes": [ - "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" - ], - "version": "==0.6.2" - }, - "docutils": { - "hashes": [ - "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", - "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.16" - }, - "grpcio": { - "hashes": [ - "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151", - "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a", - "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304", - "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482", - "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6", - "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df", - "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9", - "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c", - "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9", - "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6", - "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796", - "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39", - "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637", - "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e", - "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd", - "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2", - "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff", - "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1", - "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352", - "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f", - "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a", - "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069", - "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a", - "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642", - "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510", - "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71", - "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc", - "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf", - "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e", - "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b", - "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408", - "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590", - "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552", - "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b", - "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084", - "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770", - "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225", - "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7", - "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d" - ], - "index": "pypi", - "version": "==1.31.0" - }, - "idna": { - "hashes": [ - "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", - "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.10" - }, - "imagesize": { - "hashes": [ - "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", - "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.2.0" - }, - "importlib-metadata": { - "hashes": [ - "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", - "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" - ], - "index": "pypi", - "version": "==1.7.0" - }, - "iniconfig": { - "hashes": [ - "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437", - "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69" - ], - "version": "==1.0.1" - }, - "isort": { - "hashes": [ - "sha256:36f0c6659b9000597e92618d05b72d4181104cf59472b1c6a039e3783f930c95", - "sha256:ba040c24d20aa302f78f4747df549573ae1eaf8e1084269199154da9c483f07f" - ], - "markers": "python_version >= '3.6' and python_version < '4.0'", - "version": "==5.5.4" - }, - "jinja2": { - "hashes": [ - "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", - "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.11.2" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d", - "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449", - "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08", - "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a", - "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50", - "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd", - "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239", - "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb", - "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea", - "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e", - "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156", - "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142", - "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442", - "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62", - "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db", - "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531", - "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383", - "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a", - "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357", - "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4", - "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.4.3" - }, - "markupsafe": { - "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", - "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", - "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", - "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", - "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", - "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", - "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", - "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", - "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", - "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", - "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", - "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", - "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", - "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", - "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", - "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", - "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.1.1" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "more-itertools": { - "hashes": [ - "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20", - "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c" - ], - "markers": "python_version >= '3.5'", - "version": "==8.5.0" - }, - "mypy": { - "hashes": [ - "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c", - "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86", - "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b", - "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd", - "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc", - "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea", - "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e", - "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308", - "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406", - "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d", - "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707", - "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d", - "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c", - "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a" - ], - "index": "pypi", - "version": "==0.782" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "oauthlib": { - "hashes": [ - "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", - "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" - ], - "index": "pypi", - "version": "==3.1.0" - }, - "packaging": { - "hashes": [ - "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", - "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.4" - }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.13.1" - }, - "protobuf": { - "hashes": [ - "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33", - "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463", - "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c", - "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a", - "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f", - "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7", - "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b", - "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5", - "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4", - "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec", - "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c", - "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630", - "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7", - "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e", - "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a", - "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060", - "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9", - "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb" - ], - "index": "pypi", - "version": "==3.13.0" - }, - "py": { - "hashes": [ - "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", - "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.9.0" - }, - "pycodestyle": { - "hashes": [ - "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", - "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.6.0" - }, - "pygments": { - "hashes": [ - "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998", - "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7" - ], - "markers": "python_version >= '3.5'", - "version": "==2.7.1" - }, - "pylint": { - "hashes": [ - "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210", - "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f" - ], - "index": "pypi", - "version": "==2.6.0" - }, - "pyparsing": { - "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.4.7" - }, - "pytest": { - "hashes": [ - "sha256:0e37f61339c4578776e090c3b8f6b16ce4db333889d65d0efb305243ec544b40", - "sha256:c8f57c2a30983f469bf03e68cdfa74dc474ce56b8f280ddcb080dfd91df01043" - ], - "index": "pypi", - "version": "==6.0.2" - }, - "pytest-grpc": { - "hashes": [ - "sha256:0bd2683ffd34199444d707c0ab01970b22e0afbba6cb1ddb6d578c85ebfe09bd", - "sha256:5b062cf498e59995e84b3051da76f7bcff8cfe307927869f7bdc27ab967eee35" - ], - "index": "pypi", - "version": "==0.8.0" - }, - "pytz": { - "hashes": [ - "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", - "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" - ], - "version": "==2020.1" - }, - "pyzeebe": { - "editable": true, - "path": "." - }, - "requests": { - "hashes": [ - "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", - "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.24.0" - }, - "requests-oauthlib": { - "hashes": [ - "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", - "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", - "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" - ], - "index": "pypi", - "version": "==1.3.0" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.15.0" - }, - "snowballstemmer": { - "hashes": [ - "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", - "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" - ], - "version": "==2.0.0" - }, - "sphinx": { - "hashes": [ - "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8", - "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0" - ], - "index": "pypi", - "version": "==3.2.1" - }, - "sphinx-rtd-theme": { - "hashes": [ - "sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d", - "sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82" - ], - "index": "pypi", - "version": "==0.5.0" - }, - "sphinxcontrib-applehelp": { - "hashes": [ - "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", - "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.2" - }, - "sphinxcontrib-devhelp": { - "hashes": [ - "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", - "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.2" - }, - "sphinxcontrib-htmlhelp": { - "hashes": [ - "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", - "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.3" - }, - "sphinxcontrib-jsmath": { - "hashes": [ - "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", - "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.1" - }, - "sphinxcontrib-qthelp": { - "hashes": [ - "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", - "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.3" - }, - "sphinxcontrib-serializinghtml": { - "hashes": [ - "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", - "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" - ], - "markers": "python_version >= '3.5'", - "version": "==1.1.4" - }, - "toml": { - "hashes": [ - "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", - "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88" - ], - "version": "==0.10.1" - }, - "typed-ast": { - "hashes": [ - "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", - "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", - "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", - "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", - "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", - "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", - "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", - "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", - "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", - "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", - "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", - "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", - "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", - "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", - "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", - "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", - "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", - "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", - "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", - "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", - "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" - ], - "version": "==1.4.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", - "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", - "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" - ], - "version": "==3.7.4.3" - }, - "urllib3": { - "hashes": [ - "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a", - "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.25.10" - }, - "wrapt": { - "hashes": [ - "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" - ], - "version": "==1.12.1" - }, - "zipp": { - "hashes": [ - "sha256:43f4fa8d8bb313e65d8323a3952ef8756bf40f9a5c3ea7334be23ee4ec8278b6", - "sha256:b52f22895f4cfce194bc8172f3819ee8de7540aa6d873535a8668b730b8b411f" - ], - "markers": "python_version >= '3.6'", - "version": "==3.2.0" - } - } -} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..fc3a3c4a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +autopep8~=1.5.4 +pylint~=2.6.0 +coverage~=5.2.1 +pytest~=6.0.2 +pytest-grpc~=0.8.0 +mypy~=0.782 +coveralls~=2.1.2 +importlib-metadata~=1.7.0 +sphinx~=3.2.1 +sphinx-rtd-theme +grpcio~=1.31.0 +protobuf~=3.13.0 +oauthlib~=3.1.0 +requests-oauthlib~=1.3.0 From 23b9bf1ca65cc7892f38e4e26544501f85ce64f5 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:29:47 +0300 Subject: [PATCH 22/37] Revert "Using requirements.txt instead of pipenv" This reverts commit e35da651 --- .github/workflows/test-python-package.yml | 11 +- .github/workflows/test-zeebe-integration.yml | 9 +- Pipfile | 23 + Pipfile.lock | 756 +++++++++++++++++++ requirements.txt | 14 - 5 files changed, 790 insertions(+), 23 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock delete mode 100644 requirements.txt diff --git a/.github/workflows/test-python-package.yml b/.github/workflows/test-python-package.yml index e969bbd5..7c22af61 100644 --- a/.github/workflows/test-python-package.yml +++ b/.github/workflows/test-python-package.yml @@ -2,9 +2,9 @@ name: Test pyzeebe on: push: - branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/* ] pull_request: - branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/* ] jobs: build: @@ -19,12 +19,13 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies run: | - pip install -r requirements.txt + pip install pipenv + pipenv install --dev - name: Test with pytest run: | - coverage run --source=pyzeebe -m py.test tests/unit + pipenv run coverage run --source=pyzeebe -m py.test tests/unit - name: Upload to coveralls run: | - coveralls + pipenv run coveralls env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-zeebe-integration.yml b/.github/workflows/test-zeebe-integration.yml index 538a6bdf..464f1502 100644 --- a/.github/workflows/test-zeebe-integration.yml +++ b/.github/workflows/test-zeebe-integration.yml @@ -2,9 +2,9 @@ name: Integration test pyzeebe on: push: - branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/* ] pull_request: - branches: [ master, development, feature/*, bugfix/*, maintenance/*, enhancement/* ] + branches: [ master, development, feature/*, bugfix/*, maintenance/* ] jobs: test: @@ -28,8 +28,9 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies run: | - pip install -r requirements.txt + pip install pipenv + pipenv install --dev - name: Run integration tests run: | - pytest tests/integration + pipenv run pytest tests/integration diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..7fcb35ed --- /dev/null +++ b/Pipfile @@ -0,0 +1,23 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +autopep8 = "~=1.5.4" +pylint = "~=2.6.0" +coverage = "~=5.2.1" +pytest = "~=6.0.1" +pytest-grpc = "~=0.8.0" +mypy = "~=0.782" +coveralls = "~=2.1.2" +importlib-metadata = "~=1.7.0" +pyzeebe = {editable = true, path = "."} +sphinx = "~=3.2.1" +sphinx-rtd-theme = "*" + +[packages] +grpcio = "~=1.31.0" +protobuf = "~=3.13.0" +oauthlib = "~=3.1.0" +requests-oauthlib = "~=1.3.0" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 00000000..e0ea8fdb --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,756 @@ +{ + "_meta": { + "hash": { + "sha256": "149fa7a9f59eed05549f84ebf0107445089952897347f0bb678be8e9cba074fb" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" + ], + "version": "==2020.6.20" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "grpcio": { + "hashes": [ + "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151", + "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a", + "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304", + "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482", + "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6", + "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df", + "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9", + "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c", + "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9", + "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6", + "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796", + "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39", + "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637", + "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e", + "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd", + "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2", + "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff", + "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1", + "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352", + "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f", + "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a", + "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069", + "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a", + "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642", + "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510", + "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71", + "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc", + "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf", + "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e", + "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b", + "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408", + "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590", + "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552", + "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b", + "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084", + "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770", + "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225", + "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7", + "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d" + ], + "index": "pypi", + "version": "==1.31.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "index": "pypi", + "version": "==3.1.0" + }, + "protobuf": { + "hashes": [ + "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33", + "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463", + "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c", + "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a", + "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f", + "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7", + "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b", + "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5", + "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4", + "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec", + "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c", + "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630", + "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7", + "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e", + "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a", + "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060", + "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9", + "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb" + ], + "index": "pypi", + "version": "==3.13.0" + }, + "requests": { + "hashes": [ + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.24.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "index": "pypi", + "version": "==1.3.0" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" + }, + "urllib3": { + "hashes": [ + "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a", + "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.25.10" + } + }, + "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "astroid": { + "hashes": [ + "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703", + "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386" + ], + "markers": "python_version >= '3.5'", + "version": "==2.4.2" + }, + "atomicwrites": { + "hashes": [ + "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", + "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" + ], + "markers": "sys_platform == 'win32'", + "version": "==1.4.0" + }, + "attrs": { + "hashes": [ + "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594", + "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.2.0" + }, + "autopep8": { + "hashes": [ + "sha256:d21d3901cb0da6ebd1e83fc9b0dfbde8b46afc2ede4fe32fbda0c7c6118ca094" + ], + "index": "pypi", + "version": "==1.5.4" + }, + "babel": { + "hashes": [ + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.0" + }, + "certifi": { + "hashes": [ + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" + ], + "version": "==2020.6.20" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "colorama": { + "hashes": [ + "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", + "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" + ], + "markers": "sys_platform == 'win32' and sys_platform == 'win32' and sys_platform == 'win32'", + "version": "==0.4.3" + }, + "coverage": { + "hashes": [ + "sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb", + "sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3", + "sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716", + "sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034", + "sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3", + "sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8", + "sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0", + "sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f", + "sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4", + "sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962", + "sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d", + "sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b", + "sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4", + "sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3", + "sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258", + "sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59", + "sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01", + "sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd", + "sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b", + "sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d", + "sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89", + "sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd", + "sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b", + "sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d", + "sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46", + "sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546", + "sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082", + "sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b", + "sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4", + "sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8", + "sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811", + "sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd", + "sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651", + "sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0" + ], + "index": "pypi", + "version": "==5.2.1" + }, + "coveralls": { + "hashes": [ + "sha256:4430b862baabb3cf090d36d84d331966615e4288d8a8c5957e0fd456d0dd8bd6", + "sha256:b3b60c17b03a0dee61952a91aed6f131e0b2ac8bd5da909389c53137811409e1" + ], + "index": "pypi", + "version": "==2.1.2" + }, + "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], + "version": "==0.6.2" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "grpcio": { + "hashes": [ + "sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151", + "sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a", + "sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304", + "sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482", + "sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6", + "sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df", + "sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9", + "sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c", + "sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9", + "sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6", + "sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796", + "sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39", + "sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637", + "sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e", + "sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd", + "sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2", + "sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff", + "sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1", + "sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352", + "sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f", + "sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a", + "sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069", + "sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a", + "sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642", + "sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510", + "sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71", + "sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc", + "sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf", + "sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e", + "sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b", + "sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408", + "sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590", + "sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552", + "sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b", + "sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084", + "sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770", + "sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225", + "sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7", + "sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d" + ], + "index": "pypi", + "version": "==1.31.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.0" + }, + "importlib-metadata": { + "hashes": [ + "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83", + "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070" + ], + "index": "pypi", + "version": "==1.7.0" + }, + "iniconfig": { + "hashes": [ + "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437", + "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69" + ], + "version": "==1.0.1" + }, + "isort": { + "hashes": [ + "sha256:36f0c6659b9000597e92618d05b72d4181104cf59472b1c6a039e3783f930c95", + "sha256:ba040c24d20aa302f78f4747df549573ae1eaf8e1084269199154da9c483f07f" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==5.5.4" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d", + "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449", + "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08", + "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a", + "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50", + "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd", + "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239", + "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb", + "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea", + "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e", + "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156", + "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142", + "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442", + "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62", + "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db", + "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531", + "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383", + "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a", + "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357", + "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4", + "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.4.3" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20", + "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c" + ], + "markers": "python_version >= '3.5'", + "version": "==8.5.0" + }, + "mypy": { + "hashes": [ + "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c", + "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86", + "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b", + "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd", + "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc", + "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea", + "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e", + "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308", + "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406", + "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d", + "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707", + "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d", + "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c", + "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a" + ], + "index": "pypi", + "version": "==0.782" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "index": "pypi", + "version": "==3.1.0" + }, + "packaging": { + "hashes": [ + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.4" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.13.1" + }, + "protobuf": { + "hashes": [ + "sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33", + "sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463", + "sha256:339c3a003e3c797bc84499fa32e0aac83c768e67b3de4a5d7a5a9aa3b0da634c", + "sha256:361acd76f0ad38c6e38f14d08775514fbd241316cce08deb2ce914c7dfa1184a", + "sha256:3dee442884a18c16d023e52e32dd34a8930a889e511af493f6dc7d4d9bf12e4f", + "sha256:4d1174c9ed303070ad59553f435846a2f877598f59f9afc1b89757bdf846f2a7", + "sha256:5db9d3e12b6ede5e601b8d8684a7f9d90581882925c96acf8495957b4f1b204b", + "sha256:6a82e0c8bb2bf58f606040cc5814e07715b2094caeba281e2e7d0b0e2e397db5", + "sha256:8c35bcbed1c0d29b127c886790e9d37e845ffc2725cc1db4bd06d70f4e8359f4", + "sha256:91c2d897da84c62816e2f473ece60ebfeab024a16c1751aaf31100127ccd93ec", + "sha256:9c2e63c1743cba12737169c447374fab3dfeb18111a460a8c1a000e35836b18c", + "sha256:9edfdc679a3669988ec55a989ff62449f670dfa7018df6ad7f04e8dbacb10630", + "sha256:c0c5ab9c4b1eac0a9b838f1e46038c3175a95b0f2d944385884af72876bd6bc7", + "sha256:c8abd7605185836f6f11f97b21200f8a864f9cb078a193fe3c9e235711d3ff1e", + "sha256:d69697acac76d9f250ab745b46c725edf3e98ac24763990b24d58c16c642947a", + "sha256:df3932e1834a64b46ebc262e951cd82c3cf0fa936a154f0a42231140d8237060", + "sha256:e7662437ca1e0c51b93cadb988f9b353fa6b8013c0385d63a70c8a77d84da5f9", + "sha256:f68eb9d03c7d84bd01c790948320b768de8559761897763731294e3bc316decb" + ], + "index": "pypi", + "version": "==3.13.0" + }, + "py": { + "hashes": [ + "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2", + "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.9.0" + }, + "pycodestyle": { + "hashes": [ + "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", + "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.6.0" + }, + "pygments": { + "hashes": [ + "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998", + "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7" + ], + "markers": "python_version >= '3.5'", + "version": "==2.7.1" + }, + "pylint": { + "hashes": [ + "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210", + "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f" + ], + "index": "pypi", + "version": "==2.6.0" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pytest": { + "hashes": [ + "sha256:0e37f61339c4578776e090c3b8f6b16ce4db333889d65d0efb305243ec544b40", + "sha256:c8f57c2a30983f469bf03e68cdfa74dc474ce56b8f280ddcb080dfd91df01043" + ], + "index": "pypi", + "version": "==6.0.2" + }, + "pytest-grpc": { + "hashes": [ + "sha256:0bd2683ffd34199444d707c0ab01970b22e0afbba6cb1ddb6d578c85ebfe09bd", + "sha256:5b062cf498e59995e84b3051da76f7bcff8cfe307927869f7bdc27ab967eee35" + ], + "index": "pypi", + "version": "==0.8.0" + }, + "pytz": { + "hashes": [ + "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", + "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" + ], + "version": "==2020.1" + }, + "pyzeebe": { + "editable": true, + "path": "." + }, + "requests": { + "hashes": [ + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.24.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "index": "pypi", + "version": "==1.3.0" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + ], + "version": "==2.0.0" + }, + "sphinx": { + "hashes": [ + "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8", + "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d", + "sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82" + ], + "index": "pypi", + "version": "==0.5.0" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.4" + }, + "toml": { + "hashes": [ + "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", + "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88" + ], + "version": "==0.10.1" + }, + "typed-ast": { + "hashes": [ + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" + ], + "version": "==1.4.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "version": "==3.7.4.3" + }, + "urllib3": { + "hashes": [ + "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a", + "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.25.10" + }, + "wrapt": { + "hashes": [ + "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" + ], + "version": "==1.12.1" + }, + "zipp": { + "hashes": [ + "sha256:43f4fa8d8bb313e65d8323a3952ef8756bf40f9a5c3ea7334be23ee4ec8278b6", + "sha256:b52f22895f4cfce194bc8172f3819ee8de7540aa6d873535a8668b730b8b411f" + ], + "markers": "python_version >= '3.6'", + "version": "==3.2.0" + } + } +} diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index fc3a3c4a..00000000 --- a/requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -autopep8~=1.5.4 -pylint~=2.6.0 -coverage~=5.2.1 -pytest~=6.0.2 -pytest-grpc~=0.8.0 -mypy~=0.782 -coveralls~=2.1.2 -importlib-metadata~=1.7.0 -sphinx~=3.2.1 -sphinx-rtd-theme -grpcio~=1.31.0 -protobuf~=3.13.0 -oauthlib~=3.1.0 -requests-oauthlib~=1.3.0 From 150809316b21525015d16c701079dcc7e9f4bbef Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:33:37 +0300 Subject: [PATCH 23/37] [ADDED] mock imports to autodoc --- docs/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 5cf75fee..ccc36742 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -62,3 +62,5 @@ version = "2.1.0" master_doc = 'index' + +autodoc_mock_imports = ["grpc", "oauthlib", "requests-oauthlib"] From 08f3090ba4220208efd0cbf5e9c7710fc43ced9c Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:36:31 +0300 Subject: [PATCH 24/37] [ADDED] google mock doc --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index ccc36742..9546ef28 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,4 +63,4 @@ master_doc = 'index' -autodoc_mock_imports = ["grpc", "oauthlib", "requests-oauthlib"] +autodoc_mock_imports = ["grpc", "oauthlib", "requests-oauthlib", "google"] From b41947643c9b654d2cd3e1d1c5ffad72b60114d3 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:43:28 +0300 Subject: [PATCH 25/37] [USING] pip install . in config --- .readthedocs.yml | 3 +++ docs/conf.py | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index e35d1fa6..0d4f8430 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,6 +4,9 @@ build: image: latest python: version: 3.8 + install: + - method: pip + path: . sphinx: builder: html diff --git a/docs/conf.py b/docs/conf.py index 9546ef28..5cf75fee 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -62,5 +62,3 @@ version = "2.1.0" master_doc = 'index' - -autodoc_mock_imports = ["grpc", "oauthlib", "requests-oauthlib", "google"] From 2cc2f15fd24878adb897d9ff8a395a654a3a615b Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 15:53:19 +0300 Subject: [PATCH 26/37] [ADDED] Client Raises documentation --- docs/Makefile | 2 +- docs/make.bat | 2 +- pyzeebe/client/client.py | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index d0c3cbf1..ed880990 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build -SOURCEDIR = source +SOURCEDIR = . BUILDDIR = build # Put it first so that "make" without argument is like "make help". diff --git a/docs/make.bat b/docs/make.bat index 9534b018..3d64bb3a 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -7,7 +7,7 @@ REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) -set SOURCEDIR=source +set SOURCEDIR=. set BUILDDIR=build if "%1" == "" goto help diff --git a/pyzeebe/client/client.py b/pyzeebe/client/client.py index a8c4cc82..7d7ce432 100644 --- a/pyzeebe/client/client.py +++ b/pyzeebe/client/client.py @@ -23,6 +23,12 @@ def run_workflow(self, bpmn_process_id: str, variables: Dict = None, version: in Returns: int: workflow_instance_key, the unique id of the running workflow generated by Zeebe. + + Raises: + WorkflowNotFound: No workflow with bpmn_process_id exists + InvalidJSON: variables is not JSONable + WorkflowHasNoStartEvent: The specified workflow does not have a start event + """ return self.zeebe_adapter.create_workflow_instance(bpmn_process_id=bpmn_process_id, variables=variables or {}, version=version) @@ -41,6 +47,12 @@ def run_workflow_with_result(self, bpmn_process_id: str, variables: Dict = None, Returns: dict: A dictionary of the end state of the workflow instance + + Raises: + WorkflowNotFound: No workflow with bpmn_process_id exists + InvalidJSON: variables is not JSONable + WorkflowHasNoStartEvent: The specified workflow does not have a start event + """ return self.zeebe_adapter.create_workflow_instance_with_result(bpmn_process_id=bpmn_process_id, variables=variables or {}, version=version, @@ -56,6 +68,10 @@ def cancel_workflow_instance(self, workflow_instance_key: int) -> int: Returns: int: The workflow_instance_key + + Raises: + WorkflowInstanceNotFound: If no workflow instance with workflow_instance_key exists + """ self.zeebe_adapter.cancel_workflow_instance(workflow_instance_key=workflow_instance_key) return workflow_instance_key @@ -67,6 +83,9 @@ def deploy_workflow(self, *workflow_file_path: str) -> None: Args: workflow_file_path (str): The file path to a workflow definition file (bpmn/yaml) + Raises: + WorkflowInvalid: If one of the workflow file definitions is invalid + """ self.zeebe_adapter.deploy_workflow(*workflow_file_path) @@ -83,6 +102,9 @@ def publish_message(self, name: str, correlation_key: str, variables: Dict = Non message_id (str): A unique message id. Useful for avoiding duplication. If a message with this id is still active, a MessageAlreadyExists will be raised. + Raises: + MessageAlreadyExist: If a message with message_id already exists + """ self.zeebe_adapter.publish_message(name=name, correlation_key=correlation_key, time_to_live_in_milliseconds=time_to_live_in_milliseconds, From c929ebbe03cf9884a72d4da78e3614b203c25487 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:07:15 +0300 Subject: [PATCH 27/37] [ADDED] Worker docstring, DuplicateTaskType --- pyzeebe/client/client.py | 15 ++++++++++++ pyzeebe/exceptions/pyzeebe_exceptions.py | 6 +++++ pyzeebe/worker/task_handler.py | 30 ++++++++++++++++++++++++ pyzeebe/worker/worker.py | 22 +++++++++++++---- tests/unit/worker/worker_test.py | 14 +++++++++++ 5 files changed, 83 insertions(+), 4 deletions(-) diff --git a/pyzeebe/client/client.py b/pyzeebe/client/client.py index 7d7ce432..5338068e 100644 --- a/pyzeebe/client/client.py +++ b/pyzeebe/client/client.py @@ -28,6 +28,9 @@ def run_workflow(self, bpmn_process_id: str, variables: Dict = None, version: in WorkflowNotFound: No workflow with bpmn_process_id exists InvalidJSON: variables is not JSONable WorkflowHasNoStartEvent: The specified workflow does not have a start event + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error """ return self.zeebe_adapter.create_workflow_instance(bpmn_process_id=bpmn_process_id, variables=variables or {}, @@ -52,6 +55,9 @@ def run_workflow_with_result(self, bpmn_process_id: str, variables: Dict = None, WorkflowNotFound: No workflow with bpmn_process_id exists InvalidJSON: variables is not JSONable WorkflowHasNoStartEvent: The specified workflow does not have a start event + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error """ return self.zeebe_adapter.create_workflow_instance_with_result(bpmn_process_id=bpmn_process_id, @@ -71,6 +77,9 @@ def cancel_workflow_instance(self, workflow_instance_key: int) -> int: Raises: WorkflowInstanceNotFound: If no workflow instance with workflow_instance_key exists + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error """ self.zeebe_adapter.cancel_workflow_instance(workflow_instance_key=workflow_instance_key) @@ -85,6 +94,9 @@ def deploy_workflow(self, *workflow_file_path: str) -> None: Raises: WorkflowInvalid: If one of the workflow file definitions is invalid + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error """ self.zeebe_adapter.deploy_workflow(*workflow_file_path) @@ -104,6 +116,9 @@ def publish_message(self, name: str, correlation_key: str, variables: Dict = Non Raises: MessageAlreadyExist: If a message with message_id already exists + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error """ self.zeebe_adapter.publish_message(name=name, correlation_key=correlation_key, diff --git a/pyzeebe/exceptions/pyzeebe_exceptions.py b/pyzeebe/exceptions/pyzeebe_exceptions.py index 9ac453a6..bf027432 100644 --- a/pyzeebe/exceptions/pyzeebe_exceptions.py +++ b/pyzeebe/exceptions/pyzeebe_exceptions.py @@ -14,3 +14,9 @@ def __init__(self, task_type: str): class NoZeebeAdapter(PyZeebeException): pass + + +class DuplicateTaskType(PyZeebeException): + def __init__(self, task_type: str): + super().__init__(f"Task with type {task_type} already exists") + self.task_type = task_type diff --git a/pyzeebe/worker/task_handler.py b/pyzeebe/worker/task_handler.py index 976af334..77efe6bf 100644 --- a/pyzeebe/worker/task_handler.py +++ b/pyzeebe/worker/task_handler.py @@ -43,6 +43,10 @@ def task(self, task_type: str, exception_handler: ExceptionHandler = default_exc timeout (int): Maximum duration of the task in milliseconds. If the timeout is surpasses Zeebe will give up on the job and retry it. Default: 10000 max_jobs_to_activate (int): Maximum jobs the worker will execute in parallel (of this task). Default: 32 + + Raises: + DuplicateTaskType: If a task from the router already exists in the worker + """ if single_value and not variable_name: raise NoVariableNameGiven(task_type=task_type) @@ -88,10 +92,36 @@ def _get_parameters_from_function(fn: Callable) -> List[str]: return list(parameters) def remove_task(self, task_type: str) -> Task: + """ + Remove a task + + Args: + task_type (str): The type of the wanted task + + Returns: + Task: The task that was removed + + Raises: + TaskNotFound: If no task with specified type exists + + """ task_index = self._get_task_index(task_type) return self.tasks.pop(task_index) def get_task(self, task_type: str) -> Task: + """ + Get a task by its type + + Args: + task_type (str): The type of the wanted task + + Returns: + Task: The wanted task + + Raises: + TaskNotFound: If no task with specified type exists + + """ return self._get_task_and_index(task_type)[0] def _get_task_index(self, task_type: str) -> int: diff --git a/pyzeebe/worker/worker.py b/pyzeebe/worker/worker.py index 2fbec272..c46b1077 100644 --- a/pyzeebe/worker/worker.py +++ b/pyzeebe/worker/worker.py @@ -4,6 +4,7 @@ from typing import List, Callable, Generator, Tuple, Dict from pyzeebe.credentials.base_credentials import BaseCredentials +from pyzeebe.exceptions import TaskNotFound, DuplicateTaskType from pyzeebe.grpc_internals.zeebe_adapter import ZeebeAdapter from pyzeebe.job.job import Job from pyzeebe.task.exception_handler import ExceptionHandler @@ -39,6 +40,13 @@ def __init__(self, name: str = None, request_timeout: int = 0, hostname: str = N def work(self) -> None: """ Start the worker. The worker will poll zeebe for jobs of each task in a different thread. + + Raises: + ActivateJobsRequestInvalid: If one of the worker's task has invalid types + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error + """ for task in self.tasks: task_thread = Thread(target=self._handle_task, args=(task,)) @@ -109,8 +117,12 @@ def wrapper(fn: Callable[..., Dict]): return wrapper def _add_task(self, task: Task) -> None: - task.handler = self._create_task_handler(task) - self.tasks.append(task) + try: + self.get_task(task.type) + raise DuplicateTaskType(task.type) + except TaskNotFound: + task.handler = self._create_task_handler(task) + self.tasks.append(task) def _create_task_handler(self, task: Task) -> Callable[[Job], Job]: before_decorator_runner = self._create_before_decorator_runner(task) @@ -175,8 +187,10 @@ def _run_decorator(decorator: TaskDecorator, job: Job) -> Job: def include_router(self, router: ZeebeTaskRouter) -> None: """ Adds all router's tasks to the worker. - Decorator order: - Worker -> Router -> Task -> fn -> Task -> Router -> Worker + + Raises: + DuplicateTaskType: If a task from the router already exists in the worker + """ for task in router.tasks: self._add_task(task) diff --git a/tests/unit/worker/worker_test.py b/tests/unit/worker/worker_test.py index 64cd6505..4d9909b7 100644 --- a/tests/unit/worker/worker_test.py +++ b/tests/unit/worker/worker_test.py @@ -3,6 +3,7 @@ from unittest.mock import patch, MagicMock from uuid import uuid4 +from pyzeebe.exceptions import DuplicateTaskType from pyzeebe.job.job import Job from pyzeebe.task.task import Task from pyzeebe.worker.task_router import ZeebeTaskRouter @@ -28,6 +29,19 @@ def run_around_tests(): task = Task(str(uuid4()), lambda x: {"x": x}, lambda x, y, z: x) +def test_add_task(): + zeebe_worker._add_task(task) + + assert len(zeebe_worker.tasks) == 1 + assert zeebe_worker.get_task(task.type) == task + + +def test_add_duplicate_task(): + zeebe_worker._add_task(task) + with pytest.raises(DuplicateTaskType): + zeebe_worker._add_task(task) + + def test_add_task_through_decorator(): task_type = str(uuid4()) timeout = randint(0, 10000) From 49d99418cddd0fc4106450b958bfa08ef4a44f1e Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:17:22 +0300 Subject: [PATCH 28/37] [CHANGED] version to v2.2.0, Duplicate task --- pyzeebe/worker/task_handler.py | 15 ++++++++++++--- pyzeebe/worker/worker.py | 10 +++------- setup.py | 2 +- tests/unit/worker/task_handler_test.py | 12 +++++++++++- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/pyzeebe/worker/task_handler.py b/pyzeebe/worker/task_handler.py index 77efe6bf..fc7a62b1 100644 --- a/pyzeebe/worker/task_handler.py +++ b/pyzeebe/worker/task_handler.py @@ -1,9 +1,9 @@ import logging from abc import abstractmethod -from typing import Tuple, List, Callable +from typing import Tuple, List, Callable, Dict from pyzeebe.decorators.zeebe_decorator_base import ZeebeDecoratorBase -from pyzeebe.exceptions import NoVariableNameGiven, TaskNotFound +from pyzeebe.exceptions import NoVariableNameGiven, TaskNotFound, DuplicateTaskType from pyzeebe.job.job import Job from pyzeebe.task.exception_handler import ExceptionHandler from pyzeebe.task.task import Task @@ -48,6 +48,8 @@ def task(self, task_type: str, exception_handler: ExceptionHandler = default_exc DuplicateTaskType: If a task from the router already exists in the worker """ + self._is_task_duplicate(task_type) + if single_value and not variable_name: raise NoVariableNameGiven(task_type=task_type) @@ -75,7 +77,7 @@ def _non_dict_task(self, task_type: str, variable_name: str, raise NotImplemented() @staticmethod - def _single_value_function_to_dict(variable_name: str, fn: Callable): + def _single_value_function_to_dict(variable_name: str, fn: Callable) -> Callable[..., Dict]: def inner_fn(*args, **kwargs): return {variable_name: fn(*args, **kwargs)} @@ -91,6 +93,13 @@ def _get_parameters_from_function(fn: Callable) -> List[str]: else: return list(parameters) + def _is_task_duplicate(self, task_type: str) -> None: + try: + self.get_task(task_type) + raise DuplicateTaskType(task_type) + except TaskNotFound: + return + def remove_task(self, task_type: str) -> Task: """ Remove a task diff --git a/pyzeebe/worker/worker.py b/pyzeebe/worker/worker.py index c46b1077..87083f53 100644 --- a/pyzeebe/worker/worker.py +++ b/pyzeebe/worker/worker.py @@ -4,7 +4,6 @@ from typing import List, Callable, Generator, Tuple, Dict from pyzeebe.credentials.base_credentials import BaseCredentials -from pyzeebe.exceptions import TaskNotFound, DuplicateTaskType from pyzeebe.grpc_internals.zeebe_adapter import ZeebeAdapter from pyzeebe.job.job import Job from pyzeebe.task.exception_handler import ExceptionHandler @@ -117,12 +116,9 @@ def wrapper(fn: Callable[..., Dict]): return wrapper def _add_task(self, task: Task) -> None: - try: - self.get_task(task.type) - raise DuplicateTaskType(task.type) - except TaskNotFound: - task.handler = self._create_task_handler(task) - self.tasks.append(task) + self._is_task_duplicate(task.type) + task.handler = self._create_task_handler(task) + self.tasks.append(task) def _create_task_handler(self, task: Task) -> Callable[[Job], Job]: before_decorator_runner = self._create_before_decorator_runner(task) diff --git a/setup.py b/setup.py index ad32d26a..ee0d07b7 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="pyzeebe", - version="2.1.0", + version="2.2.0", author="Jonatan Martens", author_email="jonatanmartenstav@gmail.com", description="Zeebe client api", diff --git a/tests/unit/worker/task_handler_test.py b/tests/unit/worker/task_handler_test.py index 4f42ecc5..b5a8b24a 100644 --- a/tests/unit/worker/task_handler_test.py +++ b/tests/unit/worker/task_handler_test.py @@ -3,7 +3,7 @@ import pytest -from pyzeebe.exceptions import NoVariableNameGiven, TaskNotFound +from pyzeebe.exceptions import NoVariableNameGiven, TaskNotFound, DuplicateTaskType from pyzeebe.task.task import Task from pyzeebe.worker.task_handler import ZeebeTaskHandler, default_exception_handler from tests.unit.utils.random_utils import randint, random_job @@ -178,3 +178,13 @@ def test_get_parameters_from_function_lambda(): my_func = lambda x: x assert zeebe_task_handler._get_parameters_from_function(my_func) == ["x"] + + +def test_check_is_task_duplicate_with_duplicate(): + zeebe_task_handler.tasks.append(task) + with pytest.raises(DuplicateTaskType): + zeebe_task_handler._is_task_duplicate(task.type) + + +def test_check_is_task_duplicate_no_duplicate(): + zeebe_task_handler.tasks.append(task) From 61ffe49eb07f3c25fb63ac54d25bc87677a11605 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:29:34 +0300 Subject: [PATCH 29/37] [ADDED] Exceptions to documentation --- .readthedocs.yml | 2 +- docs/_static/.gitkeep | 0 docs/exceptions.rst | 39 +++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + pyzeebe/job/job.py | 27 +++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/_static/.gitkeep create mode 100644 docs/exceptions.rst diff --git a/.readthedocs.yml b/.readthedocs.yml index 0d4f8430..8dfef72e 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -11,4 +11,4 @@ python: sphinx: builder: html configuration: docs/conf.py - #fail_on_warning: true + fail_on_warning: true diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/exceptions.rst b/docs/exceptions.rst new file mode 100644 index 00000000..c4e672f2 --- /dev/null +++ b/docs/exceptions.rst @@ -0,0 +1,39 @@ +========== +Exceptions +========== + +All ``pyzeebe`` exceptions inherit from :py:class:`PyZeebeException` + +.. autoexception:: pyzeebe.exceptions.PyZeebeException + +.. autoexception:: pyzeebe.exceptions.TaskNotFound + +.. autoexception:: pyzeebe.exceptions.NoVariableNameGiven + +.. autoexception:: pyzeebe.exceptions.NoZeebeAdapter + +.. autoexception:: pyzeebe.exceptions.DuplicateTaskType + +.. autoexception:: pyzeebe.exceptions.ActivateJobsRequestInvalid + +.. autoexception:: pyzeebe.exceptions.JobAlreadyDeactivated + +.. autoexception:: pyzeebe.exceptions.JobNotFound + +.. autoexception:: pyzeebe.exceptions.MessageAlreadyExists + +.. autoexception:: pyzeebe.exceptions.WorkflowNotFound + +.. autoexception:: pyzeebe.exceptions.WorkflowInstanceNotFound + +.. autoexception:: pyzeebe.exceptions.WorkflowHasNoStartEvent + +.. autoexception:: pyzeebe.exceptions.WorkflowInvalid + +.. autoexception:: pyzeebe.exceptions.InvalidJSON + +.. autoexception:: pyzeebe.exceptions.ZeebeBackPressure + +.. autoexception:: pyzeebe.exceptions.ZeebeGatewayUnavailable + +.. autoexception:: pyzeebe.exceptions.ZeebeInternalError diff --git a/docs/index.rst b/docs/index.rst index de3f5106..d046ea75 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,3 +61,4 @@ Table Of Contents Client Worker Decorators + Exceptions diff --git a/pyzeebe/job/job.py b/pyzeebe/job/job.py index 9eb3e6e0..741eddd1 100644 --- a/pyzeebe/job/job.py +++ b/pyzeebe/job/job.py @@ -28,6 +28,13 @@ def __init__(self, key: int, _type: str, workflow_instance_key: int, bpmn_proces def set_success_status(self) -> None: """ Success status means that the job has been completed as intended. + + Raises: + NoZeebeAdapter: If the job does not have a configured ZeebeAdapter + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error + """ if self.zeebe_adapter: self.zeebe_adapter.complete_job(job_key=self.key, variables=self.variables) @@ -38,6 +45,16 @@ def set_failure_status(self, message: str) -> None: """ Failure status means a technical error has occurred. If retried the job may succeed. For example: connection to DB lost + + Args: + message (str): The failure message that Zeebe will receive + + Raises: + NoZeebeAdapter: If the job does not have a configured ZeebeAdapter + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error + """ if self.zeebe_adapter: self.zeebe_adapter.fail_job(job_key=self.key, message=message) @@ -48,6 +65,16 @@ def set_error_status(self, message: str) -> None: """ Error status means that the job could not be completed because of a business error and won't ever be able to be completed. For example: a required parameter was not given + + Args: + message (str): The error message that Zeebe will receive + + Raises: + NoZeebeAdapter: If the job does not have a configured ZeebeAdapter + ZeebeBackPressure: If Zeebe is currently in back pressure (too many requests) + ZeebeGatewayUnavailable: If the Zeebe gateway is unavailable + ZeebeInternalError: If Zeebe experiences an internal error + """ if self.zeebe_adapter: self.zeebe_adapter.throw_error(job_key=self.key, message=message) From 77107af33d97496850a157971c3fe5b1d7ccc4b9 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:36:37 +0300 Subject: [PATCH 30/37] [ADDED] __version__ for standard versioning in docs + pypi --- README.md | 2 ++ docs/conf.py | 6 ++++-- pyzeebe/__init__.py | 2 ++ setup.py | 4 +++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4d816721..640480bf 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ To install: `pip install pyzeebe` +For full documentation please visit: https://pyzeebe.readthedocs.io/en/latest/ + ## Usage ### Worker diff --git a/docs/conf.py b/docs/conf.py index 5cf75fee..0fd6d73c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,11 +13,13 @@ import os import sys +import sphinx_rtd_theme + sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- -import sphinx_rtd_theme +import pyzeebe sphinx_rtd_theme # So optimize imports doens't erase it @@ -59,6 +61,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -version = "2.1.0" +version = pyzeebe.__version__ master_doc = 'index' diff --git a/pyzeebe/__init__.py b/pyzeebe/__init__.py index be126098..4fb92c9a 100644 --- a/pyzeebe/__init__.py +++ b/pyzeebe/__init__.py @@ -1,3 +1,5 @@ +__version__ = "2.2.0" + from pyzeebe import exceptions from pyzeebe.client.client import ZeebeClient from pyzeebe.credentials.camunda_cloud_credentials import CamundaCloudCredentials diff --git a/setup.py b/setup.py index ee0d07b7..c331904f 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,13 @@ import setuptools +import pyzeebe + with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name="pyzeebe", - version="2.2.0", + version=pyzeebe.__version__, author="Jonatan Martens", author_email="jonatanmartenstav@gmail.com", description="Zeebe client api", From cc8b846650668f9eb710e4dfbc402d556b702b74 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:37:53 +0300 Subject: [PATCH 31/37] [CHANGED] Documentation url to stable --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 640480bf..8bb5d7c7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To install: `pip install pyzeebe` -For full documentation please visit: https://pyzeebe.readthedocs.io/en/latest/ +For full documentation please visit: https://pyzeebe.readthedocs.io/en/stable/ ## Usage From fadf01235d0b9f2fd91b0b739c7c29ea3bf2d214 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:39:23 +0300 Subject: [PATCH 32/37] [TRYING] using from import --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0fd6d73c..5a7c49ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,7 +19,7 @@ # -- Project information ----------------------------------------------------- -import pyzeebe +from pyzeebe import __version__ sphinx_rtd_theme # So optimize imports doens't erase it @@ -61,6 +61,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -version = pyzeebe.__version__ +version = __version__ master_doc = 'index' From ad7df63b577477d3528804394d7c9e80c0ba7c95 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:41:39 +0300 Subject: [PATCH 33/37] [FIXED] no pyzeebe import in conf.py --- docs/conf.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5a7c49ba..ab3549e0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,8 +19,6 @@ # -- Project information ----------------------------------------------------- -from pyzeebe import __version__ - sphinx_rtd_theme # So optimize imports doens't erase it project = 'pyzeebe' @@ -61,6 +59,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -version = __version__ +version = "2.2.0" master_doc = 'index' From 87c190ed157b8a90dbc7100afb359f3fd5146bd0 Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:54:10 +0300 Subject: [PATCH 34/37] [TRYING] Single source in __version__.py --- docs/conf.py | 5 ++++- pyzeebe/__init__.py | 3 +-- pyzeebe/__version__.py | 1 + setup.py | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 pyzeebe/__version__.py diff --git a/docs/conf.py b/docs/conf.py index ab3549e0..07e18ba8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,10 +15,13 @@ import sphinx_rtd_theme +from pyzeebe.__version__ import __version__ + sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- + sphinx_rtd_theme # So optimize imports doens't erase it project = 'pyzeebe' @@ -59,6 +62,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -version = "2.2.0" +version = __version__ master_doc = 'index' diff --git a/pyzeebe/__init__.py b/pyzeebe/__init__.py index 4fb92c9a..003bf593 100644 --- a/pyzeebe/__init__.py +++ b/pyzeebe/__init__.py @@ -1,6 +1,5 @@ -__version__ = "2.2.0" - from pyzeebe import exceptions +from pyzeebe.__version__ import __version__ from pyzeebe.client.client import ZeebeClient from pyzeebe.credentials.camunda_cloud_credentials import CamundaCloudCredentials from pyzeebe.credentials.oauth_credentials import OAuthCredentials diff --git a/pyzeebe/__version__.py b/pyzeebe/__version__.py new file mode 100644 index 00000000..8a124bf6 --- /dev/null +++ b/pyzeebe/__version__.py @@ -0,0 +1 @@ +__version__ = "2.2.0" diff --git a/setup.py b/setup.py index c331904f..21d53bf8 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ import setuptools -import pyzeebe +from pyzeebe.__version__ import __version__ with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name="pyzeebe", - version=pyzeebe.__version__, + version=__version__, author="Jonatan Martens", author_email="jonatanmartenstav@gmail.com", description="Zeebe client api", From 6fdd211f1749848454d1c981946ab5c6ab222c9e Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:55:33 +0300 Subject: [PATCH 35/37] Revert "[TRYING] Single source in __version__.py" This reverts commit 87c190ed --- docs/conf.py | 5 +---- pyzeebe/__init__.py | 3 ++- pyzeebe/__version__.py | 1 - setup.py | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) delete mode 100644 pyzeebe/__version__.py diff --git a/docs/conf.py b/docs/conf.py index 07e18ba8..ab3549e0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,13 +15,10 @@ import sphinx_rtd_theme -from pyzeebe.__version__ import __version__ - sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- - sphinx_rtd_theme # So optimize imports doens't erase it project = 'pyzeebe' @@ -62,6 +59,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -version = __version__ +version = "2.2.0" master_doc = 'index' diff --git a/pyzeebe/__init__.py b/pyzeebe/__init__.py index 003bf593..4fb92c9a 100644 --- a/pyzeebe/__init__.py +++ b/pyzeebe/__init__.py @@ -1,5 +1,6 @@ +__version__ = "2.2.0" + from pyzeebe import exceptions -from pyzeebe.__version__ import __version__ from pyzeebe.client.client import ZeebeClient from pyzeebe.credentials.camunda_cloud_credentials import CamundaCloudCredentials from pyzeebe.credentials.oauth_credentials import OAuthCredentials diff --git a/pyzeebe/__version__.py b/pyzeebe/__version__.py deleted file mode 100644 index 8a124bf6..00000000 --- a/pyzeebe/__version__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "2.2.0" diff --git a/setup.py b/setup.py index 21d53bf8..c331904f 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ import setuptools -from pyzeebe.__version__ import __version__ +import pyzeebe with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name="pyzeebe", - version=__version__, + version=pyzeebe.__version__, author="Jonatan Martens", author_email="jonatanmartenstav@gmail.com", description="Zeebe client api", From c771cfffb01cd6e4df0525309eef7e440b464a1f Mon Sep 17 00:00:00 2001 From: Jonatan Martens Date: Wed, 30 Sep 2020 16:56:11 +0300 Subject: [PATCH 36/37] [FIXED] Not single sourcing the version anymore --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index c331904f..ee0d07b7 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,11 @@ import setuptools -import pyzeebe - with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name="pyzeebe", - version=pyzeebe.__version__, + version="2.2.0", author="Jonatan Martens", author_email="jonatanmartenstav@gmail.com", description="Zeebe client api", From 6adda0ef1c064c89d5c0089b9d1485543d066007 Mon Sep 17 00:00:00 2001 From: Jonatan Martens <40060128+JonatanMartens@users.noreply.github.com> Date: Wed, 30 Sep 2020 17:29:35 +0300 Subject: [PATCH 37/37] [FIXED] JSONDecodeError with invalid oauth/camunda_cloud credentials (#49) --- docs/exceptions.rst | 4 +++ .../credentials/camunda_cloud_credentials.py | 8 ++++-- pyzeebe/credentials/oauth_credentials.py | 25 ++++++++++++------- pyzeebe/exceptions/__init__.py | 1 + pyzeebe/exceptions/credentials_exceptions.py | 12 +++++++++ .../camunda_cloud_credentials_test.py | 13 +++++++++- .../credentials/oauth_credentials_test.py | 13 ++++++++++ .../grpc_internals/zeebe_adapter_base_test.py | 13 ++++++---- 8 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 pyzeebe/exceptions/credentials_exceptions.py diff --git a/docs/exceptions.rst b/docs/exceptions.rst index c4e672f2..eb4cbfc4 100644 --- a/docs/exceptions.rst +++ b/docs/exceptions.rst @@ -37,3 +37,7 @@ All ``pyzeebe`` exceptions inherit from :py:class:`PyZeebeException` .. autoexception:: pyzeebe.exceptions.ZeebeGatewayUnavailable .. autoexception:: pyzeebe.exceptions.ZeebeInternalError + +.. autoexception:: pyzeebe.exceptions.InvalidOAuthCredentials + +.. autoexception:: pyzeebe.exceptions.InvalidCamundaCloudCredentials diff --git a/pyzeebe/credentials/camunda_cloud_credentials.py b/pyzeebe/credentials/camunda_cloud_credentials.py index 22dce6e6..3758b2c8 100644 --- a/pyzeebe/credentials/camunda_cloud_credentials.py +++ b/pyzeebe/credentials/camunda_cloud_credentials.py @@ -1,10 +1,14 @@ from pyzeebe.credentials.oauth_credentials import OAuthCredentials +from pyzeebe.exceptions import InvalidOAuthCredentials, InvalidCamundaCloudCredentials class CamundaCloudCredentials(OAuthCredentials): def __init__(self, client_id: str, client_secret: str, cluster_id: str): - super().__init__(url="https://login.cloud.camunda.io/oauth/token", client_id=client_id, - client_secret=client_secret, audience=f"{cluster_id}.zeebe.camunda.io") + try: + super().__init__(url="https://login.cloud.camunda.io/oauth/token", client_id=client_id, + client_secret=client_secret, audience=f"{cluster_id}.zeebe.camunda.io") + except InvalidOAuthCredentials: + raise InvalidCamundaCloudCredentials(client_id=client_id, cluster_id=cluster_id) def get_connection_uri(self) -> str: return f"{self.audience}:443" diff --git a/pyzeebe/credentials/oauth_credentials.py b/pyzeebe/credentials/oauth_credentials.py index efe0d223..48374635 100644 --- a/pyzeebe/credentials/oauth_credentials.py +++ b/pyzeebe/credentials/oauth_credentials.py @@ -1,8 +1,10 @@ import grpc from oauthlib import oauth2 +from requests import HTTPError from requests_oauthlib import OAuth2Session from pyzeebe.credentials.base_credentials import BaseCredentials +from pyzeebe.exceptions import InvalidOAuthCredentials class OAuthCredentials(BaseCredentials): @@ -19,15 +21,20 @@ def __init__(self, url: str, client_id: str, client_secret: str, audience: str): @staticmethod def get_access_token(url: str, client_id: str, client_secret: str, audience: str) -> str: - client = oauth2.BackendApplicationClient(client_id) - client.prepare_request_body(include_client_id=True) - with OAuth2Session(client=client) as session: - return session.post(url, - data={ - "client_id": client_id, - "client_secret": client_secret, - "audience": audience - }).json()["access_token"] + try: + client = oauth2.BackendApplicationClient(client_id) + client.prepare_request_body(include_client_id=True) + with OAuth2Session(client=client) as session: + response = session.post(url, + data={ + "client_id": client_id, + "client_secret": client_secret, + "audience": audience + }) + response.raise_for_status() + return response.json()["access_token"] + except HTTPError: + raise InvalidOAuthCredentials(url=url, client_id=client_id, audience=audience) def get_connection_uri(self) -> str: return None diff --git a/pyzeebe/exceptions/__init__.py b/pyzeebe/exceptions/__init__.py index 6de5300f..7e2ff3a4 100644 --- a/pyzeebe/exceptions/__init__.py +++ b/pyzeebe/exceptions/__init__.py @@ -1,3 +1,4 @@ +from .credentials_exceptions import * from .job_exceptions import * from .message_exceptions import * from .pyzeebe_exceptions import * diff --git a/pyzeebe/exceptions/credentials_exceptions.py b/pyzeebe/exceptions/credentials_exceptions.py new file mode 100644 index 00000000..5fe5a1ab --- /dev/null +++ b/pyzeebe/exceptions/credentials_exceptions.py @@ -0,0 +1,12 @@ +from pyzeebe.exceptions.pyzeebe_exceptions import PyZeebeException + + +class InvalidOAuthCredentials(PyZeebeException): + def __init__(self, url: str, client_id: str, audience: str): + super().__init__( + f"Invalid OAuth credentials supplied for {url} with audience {audience} and client id {client_id}") + + +class InvalidCamundaCloudCredentials(PyZeebeException): + def __init__(self, client_id: str, cluster_id: str): + super().__init__(f"Invalid credentials supplied for cluster {cluster_id} with client {client_id}") diff --git a/tests/unit/credentials/camunda_cloud_credentials_test.py b/tests/unit/credentials/camunda_cloud_credentials_test.py index 0e45eb94..51d104c5 100644 --- a/tests/unit/credentials/camunda_cloud_credentials_test.py +++ b/tests/unit/credentials/camunda_cloud_credentials_test.py @@ -1,7 +1,10 @@ -from unittest.mock import patch +from unittest.mock import patch, MagicMock from uuid import uuid4 +import pytest + from pyzeebe.credentials.camunda_cloud_credentials import CamundaCloudCredentials +from pyzeebe.exceptions import InvalidOAuthCredentials, InvalidCamundaCloudCredentials def test_init(): @@ -13,3 +16,11 @@ def test_init(): CamundaCloudCredentials(client_id, client_secret, cluster_id) init.assert_called_with(url=f"https://login.cloud.camunda.io/oauth/token", client_id=client_id, client_secret=client_secret, audience=f"{cluster_id}.zeebe.camunda.io") + + +def test_invalid_credentials(): + CamundaCloudCredentials.get_access_token = MagicMock( + side_effect=InvalidOAuthCredentials(str(uuid4()), str(uuid4()), str(uuid4()))) + + with pytest.raises(InvalidCamundaCloudCredentials): + CamundaCloudCredentials(str(uuid4()), str(uuid4()), str(uuid4())) diff --git a/tests/unit/credentials/oauth_credentials_test.py b/tests/unit/credentials/oauth_credentials_test.py index bf8c6e38..23b33bfb 100644 --- a/tests/unit/credentials/oauth_credentials_test.py +++ b/tests/unit/credentials/oauth_credentials_test.py @@ -1,7 +1,11 @@ from unittest.mock import patch from uuid import uuid4 +import pytest +from requests import HTTPError + from pyzeebe.credentials.oauth_credentials import OAuthCredentials +from pyzeebe.exceptions import InvalidOAuthCredentials def test_get_access_token(): @@ -17,3 +21,12 @@ def test_get_access_token(): "client_secret": client_secret, "audience": audience }) + + +def test_get_invalid_access_token(): + with patch("requests_oauthlib.OAuth2Session.post") as post_mock: + post_mock.side_effect = HTTPError() + + with pytest.raises(InvalidOAuthCredentials): + OAuthCredentials.get_access_token(url=f"https://{str(uuid4())}/oauth/token", client_id=str(uuid4()), + client_secret=str(uuid4()), audience=str(uuid4())) diff --git a/tests/unit/grpc_internals/zeebe_adapter_base_test.py b/tests/unit/grpc_internals/zeebe_adapter_base_test.py index d417bcad..0f312ce0 100644 --- a/tests/unit/grpc_internals/zeebe_adapter_base_test.py +++ b/tests/unit/grpc_internals/zeebe_adapter_base_test.py @@ -1,5 +1,5 @@ from random import randint -from unittest.mock import patch +from unittest.mock import patch, MagicMock from uuid import uuid4 from pyzeebe.credentials.camunda_cloud_credentials import CamundaCloudCredentials @@ -75,8 +75,10 @@ def test_with_secure_connection(): def test_with_camunda_cloud_credentials(): - with patch("requests_oauthlib.OAuth2Session.post"): - credentials = CamundaCloudCredentials(str(uuid4()), str(uuid4()), str(uuid4())) + CamundaCloudCredentials.get_access_token = MagicMock() + CamundaCloudCredentials.get_access_token.return_value = str(uuid4()) + credentials = CamundaCloudCredentials(str(uuid4()), str(uuid4()), str(uuid4())) + with patch("grpc.secure_channel") as grpc_secure_channel_mock: ZeebeAdapterBase(credentials=credentials) grpc_secure_channel_mock.assert_called() @@ -86,8 +88,9 @@ def test_credentials_connection_uri_gotten(): client_id = str(uuid4()) client_secret = str(uuid4()) cluster_id = str(uuid4()) - with patch("requests_oauthlib.OAuth2Session.post"): - credentials = CamundaCloudCredentials(client_id, client_secret, cluster_id) + CamundaCloudCredentials.get_access_token = MagicMock() + CamundaCloudCredentials.get_access_token.return_value = str(uuid4()) + credentials = CamundaCloudCredentials(client_id, client_secret, cluster_id) zeebe_adapter = ZeebeAdapterBase(credentials=credentials) assert zeebe_adapter.connection_uri == f"{cluster_id}.zeebe.camunda.io:443"