From bc56b8be751f6ee376d2d27fd72473f8a31d4676 Mon Sep 17 00:00:00 2001 From: Ralf Grubenmann Date: Thu, 9 Jun 2022 19:49:13 +0200 Subject: [PATCH] feat(cli): add renku template validate command (#2936) --- .pre-commit-config.yaml | 88 +++-- poetry.lock | 520 ++++++++++++++-------------- pyproject.toml | 4 +- renku/command/template.py | 7 +- renku/core/management/git.py | 11 +- renku/core/management/repository.py | 2 +- renku/core/template/template.py | 6 +- renku/core/template/usecase.py | 57 ++- renku/domain_model/template.py | 153 +++++--- renku/infrastructure/git_merger.py | 2 +- renku/infrastructure/repository.py | 27 +- renku/ui/cli/__init__.py | 2 +- renku/ui/cli/dataset.py | 27 +- renku/ui/cli/exception_handler.py | 3 +- renku/ui/cli/service.py | 6 +- renku/ui/cli/template.py | 62 ++++ renku/ui/cli/workflow.py | 3 +- renku/version.py | 2 +- tests/cli/test_save.py | 6 +- tests/cli/test_template.py | 115 +++++- tests/core/models/test_template.py | 20 +- 21 files changed, 742 insertions(+), 381 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3f72757cc..b408c9c816 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,36 +1,54 @@ +default_language_version: + python: python3.8 repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 - hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace -- repo: https://github.com/psf/black - rev: 22.3.0 - hooks: - - id: black - additional_dependencies: ['click==8.0.4'] -- repo: https://github.com/pycqa/isort - rev: 5.10.1 - hooks: - - id: isort - name: isort (python) -- repo: https://github.com/pycqa/flake8 - rev: '3.9.2' - hooks: - - id: flake8 - exclude: ^docs/ - args: - - "--max-line-length=120" - - "--show-source" - - "--ignore=E121,E126,E203,E226,E231,W503,W504" -- repo: https://github.com/pycqa/pydocstyle - rev: 4.0.1 - hooks: - - id: pydocstyle - args: - - --ignore=D105,D107,D202,D203,D212,D213,D401,D406,D407,D410,D411,D413 -- repo: https://github.com/koalaman/shellcheck-precommit - rev: v0.8.0 - hooks: - - id: shellcheck + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + additional_dependencies: ["click==8.0.4"] + - repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: isort (python) + - repo: https://github.com/pycqa/flake8 + rev: "3.9.2" + hooks: + - id: flake8 + exclude: ^docs/ + args: + - "--max-line-length=120" + - "--show-source" + - "--ignore=E121,E126,E203,E226,E231,W503,W504" + - repo: https://github.com/pycqa/pydocstyle + rev: 4.0.1 + hooks: + - id: pydocstyle + args: + - --ignore=D105,D107,D202,D203,D212,D213,D401,D406,D407,D410,D411,D413 + - repo: https://github.com/koalaman/shellcheck-precommit + rev: v0.8.0 + hooks: + - id: shellcheck + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v0.961" + hooks: + - id: mypy + language_version: '3.8' + args: + - --no-strict-optional + - --ignore-missing-imports + additional_dependencies: + - types-python-dateutil>=2.8.10 + - types-PyYAML<6.1.0,>=5.4 + - types-redis>=3.5.3,<4.1.0 + - types-requests<2.27.2,>=2.23.0 + - types-tabulate<0.8.10,>=0.7.7 + - attrs<21.5.0,>=21.4.0 + - filelock>=3.3.0,<3.6.1 diff --git a/poetry.lock b/poetry.lock index b8268a9ade..54fbffe603 100644 --- a/poetry.lock +++ b/poetry.lock @@ -167,11 +167,11 @@ python-versions = "*" [[package]] name = "bracex" -version = "2.2.1" +version = "2.3.post1" description = "Bash style brace expander." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "btrees" @@ -192,8 +192,8 @@ test = ["persistent (>=4.4.3)", "transaction", "zope.testrunner"] [[package]] name = "build" -version = "0.7.0" -description = "A simple, correct PEP517 package builder" +version = "0.8.0" +description = "A simple, correct PEP 517 build frontend" category = "main" optional = true python-versions = ">=3.6" @@ -203,12 +203,12 @@ colorama = {version = "*", markers = "os_name == \"nt\""} importlib-metadata = {version = ">=0.22", markers = "python_version < \"3.8\""} packaging = ">=19.0" pep517 = ">=0.9.1" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2020.11.19b18)", "sphinx (>=3.0,<4.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] -test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"] -typing = ["importlib-metadata (>=4.6.4)", "mypy (==0.910)", "typing-extensions (>=3.7.4.3)"] +docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] +test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "toml (>=0.10.0)", "wheel (>=0.36.0)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)"] +typing = ["importlib-metadata (>=4.6.4)", "mypy (==0.950)", "typing-extensions (>=3.7.4.3)"] virtualenv = ["virtualenv (>=20.0.35)"] [[package]] @@ -229,7 +229,7 @@ redis = ["redis (>=2.10.5)"] [[package]] name = "cachetools" -version = "5.1.0" +version = "5.2.0" description = "Extensible memoizing collections and decorators" category = "main" optional = false @@ -254,11 +254,11 @@ docs = ["sphinx (>=3.0.3,<4.0.0)", "sphinx-rtd-theme (>=0.4.3,<0.5.0)", "sphinxc [[package]] name = "certifi" -version = "2021.10.8" +version = "2022.5.18.1" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "cffi" @@ -525,11 +525,11 @@ dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "im [[package]] name = "dill" -version = "0.3.4" +version = "0.3.5.1" description = "serialize all of python" category = "main" optional = true -python-versions = ">=2.7, !=3.0.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" [package.extras] graph = ["objgraph (>=1.7.2)"] @@ -832,7 +832,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.11.3" +version = "4.11.4" description = "Read metadata from Python packages" category = "main" optional = false @@ -954,7 +954,7 @@ python-versions = "*" [[package]] name = "lxml" -version = "4.8.0" +version = "4.9.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." category = "main" optional = false @@ -1009,8 +1009,8 @@ python-versions = "*" [[package]] name = "msgpack" -version = "1.0.3" -description = "MessagePack (de)serializer." +version = "1.0.4" +description = "MessagePack serializer" category = "main" optional = false python-versions = "*" @@ -1025,7 +1025,7 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.950" +version = "0.961" description = "Optional static typing for Python" category = "main" optional = true @@ -1770,7 +1770,7 @@ python-versions = ">=3.6" [[package]] name = "pyzmq" -version = "22.3.0" +version = "23.1.0" description = "Python bindings for 0MQ" category = "main" optional = true @@ -1942,11 +1942,11 @@ python-versions = ">=3.5" [[package]] name = "schema-salad" -version = "8.2.20220204150214" +version = "8.3.20220525163636" description = "Schema Annotations for Linked Avro Data (SALAD)" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" [package.dependencies] CacheControl = ">=0.11.7,<0.13" @@ -1957,7 +1957,7 @@ requests = ">=1.0" "ruamel.yaml" = ">=0.12.4,<0.16.6 || >0.16.6,<0.18" [package.extras] -docs = ["sphinx (>=2.2)", "sphinx-rtd-theme", "pytest (<7)"] +docs = ["sphinx (>=2.2)", "sphinx-rtd-theme", "pytest (<8)"] pycodegen = ["black"] [[package]] @@ -2177,7 +2177,7 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-spelling" -version = "7.3.3" +version = "7.5.0" description = "Sphinx spelling extension" category = "main" optional = true @@ -2260,7 +2260,7 @@ python-versions = ">=3.7" [[package]] name = "tomlkit" -version = "0.10.2" +version = "0.11.0" description = "Style preserving TOML library" category = "main" optional = true @@ -2308,7 +2308,7 @@ testing = ["nose", "coverage", "mock"] [[package]] name = "typed-ast" -version = "1.5.3" +version = "1.5.4" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "main" optional = true @@ -2316,7 +2316,7 @@ python-versions = ">=3.6" [[package]] name = "types-python-dateutil" -version = "2.8.15" +version = "2.8.17" description = "Typing stubs for python-dateutil" category = "main" optional = true @@ -2324,7 +2324,7 @@ python-versions = "*" [[package]] name = "types-pyyaml" -version = "6.0.7" +version = "6.0.8" description = "Typing stubs for PyYAML" category = "main" optional = true @@ -2676,7 +2676,7 @@ toil = ["toil"] [metadata] lock-version = "1.1" python-versions = "^3.7.1" -content-hash = "b60483b22459939dd0939e82715000c9bf0682a6976a44d70c117b8b60d19933" +content-hash = "6abf84a65f4a28ee5a7a87d81654df2bb44a91cf88bcdf3dd68d04eb150c5bd3" [metadata.files] addict = [ @@ -2756,8 +2756,8 @@ blinker = [ {file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"}, ] bracex = [ - {file = "bracex-2.2.1-py3-none-any.whl", hash = "sha256:096c4b788bf492f7af4e90ef8b5bcbfb99759ae3415ea1b83c9d29a5ed8f9a94"}, - {file = "bracex-2.2.1.tar.gz", hash = "sha256:1c8d1296e00ad9a91030ccb4c291f9e4dc7c054f12c707ba3c5ff3e9a81bcd21"}, + {file = "bracex-2.3.post1-py3-none-any.whl", hash = "sha256:351b7f20d56fb9ea91f9b9e9e7664db466eb234188c175fd943f8f755c807e73"}, + {file = "bracex-2.3.post1.tar.gz", hash = "sha256:e7b23fc8b2cd06d3dec0692baabecb249dda94e06a617901ff03a6c56fd71693"}, ] btrees = [ {file = "BTrees-4.10.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c349a416e7e4f3d6a2858d605b9fa0b92fad268714134dd0e2f7e0b631c03eef"}, @@ -2798,24 +2798,24 @@ btrees = [ {file = "BTrees-4.10.0.tar.gz", hash = "sha256:d6ab0e3410d074d7154245d6dc6493ae86f1b50bd6080d1310ebb3ecdea5deb6"}, ] build = [ - {file = "build-0.7.0-py3-none-any.whl", hash = "sha256:21b7ebbd1b22499c4dac536abc7606696ea4d909fd755e00f09f3c0f2c05e3c8"}, - {file = "build-0.7.0.tar.gz", hash = "sha256:1aaadcd69338252ade4f7ec1265e1a19184bf916d84c9b7df095f423948cb89f"}, + {file = "build-0.8.0-py3-none-any.whl", hash = "sha256:19b0ed489f92ace6947698c3ca8436cb0556a66e2aa2d34cd70e2a5d27cd0437"}, + {file = "build-0.8.0.tar.gz", hash = "sha256:887a6d471c901b1a6e6574ebaeeebb45e5269a79d095fe9a8f88d6614ed2e5f0"}, ] cachecontrol = [ {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"}, {file = "CacheControl-0.12.11.tar.gz", hash = "sha256:a5b9fcc986b184db101aa280b42ecdcdfc524892596f606858e0b7a8b4d9e144"}, ] cachetools = [ - {file = "cachetools-5.1.0-py3-none-any.whl", hash = "sha256:4ebbd38701cdfd3603d1f751d851ed248ab4570929f2d8a7ce69e30c420b141c"}, - {file = "cachetools-5.1.0.tar.gz", hash = "sha256:8b3b8fa53f564762e5b221e9896798951e7f915513abf2ba072ce0f07f3f5a98"}, + {file = "cachetools-5.2.0-py3-none-any.whl", hash = "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db"}, + {file = "cachetools-5.2.0.tar.gz", hash = "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757"}, ] calamus = [ {file = "calamus-0.3.14-py3-none-any.whl", hash = "sha256:d614c4b489f12933363abc2c46d45a58b1a53946f22ce1417047b7c9f33f45e4"}, {file = "calamus-0.3.14.tar.gz", hash = "sha256:114b6e4461561aab7c8f44c52ea988f0718ae505242c613487727c3724d68fe3"}, ] certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, + {file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"}, + {file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"}, ] cffi = [ {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, @@ -2999,8 +2999,8 @@ deprecated = [ {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, ] dill = [ - {file = "dill-0.3.4-py2.py3-none-any.whl", hash = "sha256:7e40e4a70304fd9ceab3535d36e58791d9c4a776b38ec7f7ec9afc8d3dca4d4f"}, - {file = "dill-0.3.4.zip", hash = "sha256:9f9734205146b2b353ab3fec9af0070237b6ddae78452af83d2fca84d739e675"}, + {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, + {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, ] docker = [ {file = "docker-5.0.3-py2.py3-none-any.whl", hash = "sha256:7a79bb439e3df59d0a72621775d600bc8bc8b422d285824cb37103eab91d1ce0"}, @@ -3112,8 +3112,8 @@ imagesize = [ {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"}, - {file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"}, + {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"}, + {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"}, ] importlib-resources = [ {file = "importlib_resources-5.7.1-py3-none-any.whl", hash = "sha256:e447dc01619b1e951286f3929be820029d48c75eb25d265c28b92a16548212b8"}, @@ -3190,67 +3190,69 @@ lockfile = [ {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] lxml = [ - {file = "lxml-4.8.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e1ab2fac607842ac36864e358c42feb0960ae62c34aa4caaf12ada0a1fb5d99b"}, - {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28d1af847786f68bec57961f31221125c29d6f52d9187c01cd34dc14e2b29430"}, - {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b92d40121dcbd74831b690a75533da703750f7041b4bf951befc657c37e5695a"}, - {file = "lxml-4.8.0-cp27-cp27m-win32.whl", hash = "sha256:e01f9531ba5420838c801c21c1b0f45dbc9607cb22ea2cf132844453bec863a5"}, - {file = "lxml-4.8.0-cp27-cp27m-win_amd64.whl", hash = "sha256:6259b511b0f2527e6d55ad87acc1c07b3cbffc3d5e050d7e7bcfa151b8202df9"}, - {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1010042bfcac2b2dc6098260a2ed022968dbdfaf285fc65a3acf8e4eb1ffd1bc"}, - {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa56bb08b3dd8eac3a8c5b7d075c94e74f755fd9d8a04543ae8d37b1612dd170"}, - {file = "lxml-4.8.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:31ba2cbc64516dcdd6c24418daa7abff989ddf3ba6d3ea6f6ce6f2ed6e754ec9"}, - {file = "lxml-4.8.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:31499847fc5f73ee17dbe1b8e24c6dafc4e8d5b48803d17d22988976b0171f03"}, - {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5f7d7d9afc7b293147e2d506a4596641d60181a35279ef3aa5778d0d9d9123fe"}, - {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a3c5f1a719aa11866ffc530d54ad965063a8cbbecae6515acbd5f0fae8f48eaa"}, - {file = "lxml-4.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6268e27873a3d191849204d00d03f65c0e343b3bcb518a6eaae05677c95621d1"}, - {file = "lxml-4.8.0-cp310-cp310-win32.whl", hash = "sha256:330bff92c26d4aee79c5bc4d9967858bdbe73fdbdbacb5daf623a03a914fe05b"}, - {file = "lxml-4.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:b2582b238e1658c4061ebe1b4df53c435190d22457642377fd0cb30685cdfb76"}, - {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a2bfc7e2a0601b475477c954bf167dee6d0f55cb167e3f3e7cefad906e7759f6"}, - {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a1547ff4b8a833511eeaceacbcd17b043214fcdb385148f9c1bc5556ca9623e2"}, - {file = "lxml-4.8.0-cp35-cp35m-win32.whl", hash = "sha256:a9f1c3489736ff8e1c7652e9dc39f80cff820f23624f23d9eab6e122ac99b150"}, - {file = "lxml-4.8.0-cp35-cp35m-win_amd64.whl", hash = "sha256:530f278849031b0eb12f46cca0e5db01cfe5177ab13bd6878c6e739319bae654"}, - {file = "lxml-4.8.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:078306d19a33920004addeb5f4630781aaeabb6a8d01398045fcde085091a169"}, - {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:86545e351e879d0b72b620db6a3b96346921fa87b3d366d6c074e5a9a0b8dadb"}, - {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24f5c5ae618395ed871b3d8ebfcbb36e3f1091fd847bf54c4de623f9107942f3"}, - {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bbab6faf6568484707acc052f4dfc3802bdb0cafe079383fbaa23f1cdae9ecd4"}, - {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7993232bd4044392c47779a3c7e8889fea6883be46281d45a81451acfd704d7e"}, - {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d6483b1229470e1d8835e52e0ff3c6973b9b97b24cd1c116dca90b57a2cc613"}, - {file = "lxml-4.8.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ad4332a532e2d5acb231a2e5d33f943750091ee435daffca3fec0a53224e7e33"}, - {file = "lxml-4.8.0-cp36-cp36m-win32.whl", hash = "sha256:db3535733f59e5605a88a706824dfcb9bd06725e709ecb017e165fc1d6e7d429"}, - {file = "lxml-4.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5f148b0c6133fb928503cfcdfdba395010f997aa44bcf6474fcdd0c5398d9b63"}, - {file = "lxml-4.8.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8a31f24e2a0b6317f33aafbb2f0895c0bce772980ae60c2c640d82caac49628a"}, - {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:719544565c2937c21a6f76d520e6e52b726d132815adb3447ccffbe9f44203c4"}, - {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:c0b88ed1ae66777a798dc54f627e32d3b81c8009967c63993c450ee4cbcbec15"}, - {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fa9b7c450be85bfc6cd39f6df8c5b8cbd76b5d6fc1f69efec80203f9894b885f"}, - {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9f84ed9f4d50b74fbc77298ee5c870f67cb7e91dcdc1a6915cb1ff6a317476c"}, - {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1d650812b52d98679ed6c6b3b55cbb8fe5a5460a0aef29aeb08dc0b44577df85"}, - {file = "lxml-4.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:80bbaddf2baab7e6de4bc47405e34948e694a9efe0861c61cdc23aa774fcb141"}, - {file = "lxml-4.8.0-cp37-cp37m-win32.whl", hash = "sha256:6f7b82934c08e28a2d537d870293236b1000d94d0b4583825ab9649aef7ddf63"}, - {file = "lxml-4.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e1fd7d2fe11f1cb63d3336d147c852f6d07de0d0020d704c6031b46a30b02ca8"}, - {file = "lxml-4.8.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5045ee1ccd45a89c4daec1160217d363fcd23811e26734688007c26f28c9e9e7"}, - {file = "lxml-4.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0c1978ff1fd81ed9dcbba4f91cf09faf1f8082c9d72eb122e92294716c605428"}, - {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cbf2ff155b19dc4d4100f7442f6a697938bf4493f8d3b0c51d45568d5666b5"}, - {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ce13d6291a5f47c1c8dbd375baa78551053bc6b5e5c0e9bb8e39c0a8359fd52f"}, - {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11527dc23d5ef44d76fef11213215c34f36af1608074561fcc561d983aeb870"}, - {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:60d2f60bd5a2a979df28ab309352cdcf8181bda0cca4529769a945f09aba06f9"}, - {file = "lxml-4.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:62f93eac69ec0f4be98d1b96f4d6b964855b8255c345c17ff12c20b93f247b68"}, - {file = "lxml-4.8.0-cp38-cp38-win32.whl", hash = "sha256:20b8a746a026017acf07da39fdb10aa80ad9877046c9182442bf80c84a1c4696"}, - {file = "lxml-4.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:891dc8f522d7059ff0024cd3ae79fd224752676447f9c678f2a5c14b84d9a939"}, - {file = "lxml-4.8.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b6fc2e2fb6f532cf48b5fed57567ef286addcef38c28874458a41b7837a57807"}, - {file = "lxml-4.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:74eb65ec61e3c7c019d7169387d1b6ffcfea1b9ec5894d116a9a903636e4a0b1"}, - {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:627e79894770783c129cc5e89b947e52aa26e8e0557c7e205368a809da4b7939"}, - {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:545bd39c9481f2e3f2727c78c169425efbfb3fbba6e7db4f46a80ebb249819ca"}, - {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5a58d0b12f5053e270510bf12f753a76aaf3d74c453c00942ed7d2c804ca845c"}, - {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec4b4e75fc68da9dc0ed73dcdb431c25c57775383fec325d23a770a64e7ebc87"}, - {file = "lxml-4.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5804e04feb4e61babf3911c2a974a5b86f66ee227cc5006230b00ac6d285b3a9"}, - {file = "lxml-4.8.0-cp39-cp39-win32.whl", hash = "sha256:aa0cf4922da7a3c905d000b35065df6184c0dc1d866dd3b86fd961905bbad2ea"}, - {file = "lxml-4.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:dd10383f1d6b7edf247d0960a3db274c07e96cf3a3fc7c41c8448f93eac3fb1c"}, - {file = "lxml-4.8.0-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:2403a6d6fb61c285969b71f4a3527873fe93fd0abe0832d858a17fe68c8fa507"}, - {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:986b7a96228c9b4942ec420eff37556c5777bfba6758edcb95421e4a614b57f9"}, - {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6fe4ef4402df0250b75ba876c3795510d782def5c1e63890bde02d622570d39e"}, - {file = "lxml-4.8.0-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:f10ce66fcdeb3543df51d423ede7e238be98412232fca5daec3e54bcd16b8da0"}, - {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:730766072fd5dcb219dd2b95c4c49752a54f00157f322bc6d71f7d2a31fecd79"}, - {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8b99ec73073b37f9ebe8caf399001848fced9c08064effdbfc4da2b5a8d07b93"}, - {file = "lxml-4.8.0.tar.gz", hash = "sha256:f63f62fc60e6228a4ca9abae28228f35e1bd3ce675013d1dfb828688d50c6e23"}, + {file = "lxml-4.9.0-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b5031d151d6147eac53366d6ec87da84cd4d8c5e80b1d9948a667a7164116e39"}, + {file = "lxml-4.9.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5d52e1173f52020392f593f87a6af2d4055dd800574a5cb0af4ea3878801d307"}, + {file = "lxml-4.9.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3af00ee88376022589ceeb8170eb67dacf5f7cd625ea59fa0977d719777d4ae8"}, + {file = "lxml-4.9.0-cp27-cp27m-win32.whl", hash = "sha256:1057356b808d149bc14eb8f37bb89129f237df488661c1e0fc0376ca90e1d2c3"}, + {file = "lxml-4.9.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f6d23a01921b741774f35e924d418a43cf03eca1444f3fdfd7978d35a5aaab8b"}, + {file = "lxml-4.9.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56e19fb6e4b8bd07fb20028d03d3bc67bcc0621347fbde64f248e44839771756"}, + {file = "lxml-4.9.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4cd69bca464e892ea4ed544ba6a7850aaff6f8d792f8055a10638db60acbac18"}, + {file = "lxml-4.9.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:94b181dd2777890139e49a5336bf3a9a3378ce66132c665fe8db4e8b7683cde2"}, + {file = "lxml-4.9.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:607224ffae9a0cf0a2f6e14f5f6bce43e83a6fbdaa647891729c103bdd6a5593"}, + {file = "lxml-4.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:11d62c97ceff9bab94b6b29c010ea5fb6831743459bb759c917f49ba75601cd0"}, + {file = "lxml-4.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:70a198030d26f5e569367f0f04509b63256faa76a22886280eea69a4f535dd40"}, + {file = "lxml-4.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3cf816aed8125cfc9e6e5c6c31ff94278320d591bd7970c4a0233bee0d1c8790"}, + {file = "lxml-4.9.0-cp310-cp310-win32.whl", hash = "sha256:65b3b5f12c6fb5611e79157214f3cd533083f9b058bf2fc8a1c5cc5ee40fdc5a"}, + {file = "lxml-4.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:0aa4cce579512c33373ca4c5e23c21e40c1aa1a33533a75e51b654834fd0e4f2"}, + {file = "lxml-4.9.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63419db39df8dc5564f6f103102c4665f7e4d9cb64030e98cf7a74eae5d5760d"}, + {file = "lxml-4.9.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d8e5021e770b0a3084c30dda5901d5fce6d4474feaf0ced8f8e5a82702502fbb"}, + {file = "lxml-4.9.0-cp35-cp35m-win32.whl", hash = "sha256:f17b9df97c5ecdfb56c5e85b3c9df9831246df698f8581c6e111ac664c7c656e"}, + {file = "lxml-4.9.0-cp35-cp35m-win_amd64.whl", hash = "sha256:75da29a0752c8f2395df0115ac1681cefbdd4418676015be8178b733704cbff2"}, + {file = "lxml-4.9.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:e4d020ecf3740b7312bacab2cb966bb720fd4d3490562d373b4ad91dd1857c0d"}, + {file = "lxml-4.9.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b71c52d69b91af7d18c13aef1b0cc3baee36b78607c711eb14a52bf3aa7c815e"}, + {file = "lxml-4.9.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cf04a1a38e961d4a764d2940af9b941b66263ed5584392ef875ee9c1e360a3"}, + {file = "lxml-4.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:915ecf7d486df17cc65aeefdb680d5ad4390cc8c857cf8db3fe241ed234f856a"}, + {file = "lxml-4.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e564d5a771b4015f34166a05ea2165b7e283635c41b1347696117f780084b46d"}, + {file = "lxml-4.9.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c2a57755e366e0ac7ebdb3e9207f159c3bf1afed02392ab18453ce81f5ee92ee"}, + {file = "lxml-4.9.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:00f3a6f88fd5f4357844dd91a1abac5f466c6799f1b7f1da2df6665253845b11"}, + {file = "lxml-4.9.0-cp36-cp36m-win32.whl", hash = "sha256:9093a359a86650a3dbd6532c3e4d21a6f58ba2cb60d0e72db0848115d24c10ba"}, + {file = "lxml-4.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d1690c4d37674a5f0cdafbc5ed7e360800afcf06928c2a024c779c046891bf09"}, + {file = "lxml-4.9.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:6af7f51a6010748fc1bb71917318d953c9673e4ae3f6d285aaf93ef5b2eb11c1"}, + {file = "lxml-4.9.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:eabdbe04ee0a7e760fa6cd9e799d2b020d098c580ba99107d52e1e5e538b1ecb"}, + {file = "lxml-4.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b1e22f3ee4d75ca261b6bffbf64f6f178cb194b1be3191065a09f8d98828daa9"}, + {file = "lxml-4.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:53b0410b220766321759f7f9066da67b1d0d4a7f6636a477984cbb1d98483955"}, + {file = "lxml-4.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d76da27f5e3e9bc40eba6ed7a9e985f57547e98cf20521d91215707f2fb57e0f"}, + {file = "lxml-4.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:686565ac77ff94a8965c11829af253d9e2ce3bf0d9225b1d2eb5c4d4666d0dca"}, + {file = "lxml-4.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b62d1431b4c40cda43cc986f19b8c86b1d2ae8918cfc00f4776fdf070b65c0c4"}, + {file = "lxml-4.9.0-cp37-cp37m-win32.whl", hash = "sha256:4becd16750ca5c2a1b1588269322b2cebd10c07738f336c922b658dbab96a61c"}, + {file = "lxml-4.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e35a298691b9e10e5a5631f8f0ba605b30ebe19208dc8f58b670462f53753641"}, + {file = "lxml-4.9.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:aa7447bf7c1a15ef24e2b86a277b585dd3f055e8890ac7f97374d170187daa97"}, + {file = "lxml-4.9.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:612ef8f2795a89ba3a1d4c8c1af84d8453fd53ee611aa5ad460fdd2cab426fc2"}, + {file = "lxml-4.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1bfb791a8fcdbf55d1d41b8be940393687bec0e9b12733f0796668086d1a23ff"}, + {file = "lxml-4.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:024684e0c5cfa121c22140d3a0898a3a9b2ea0f0fd2c229b6658af4bdf1155e5"}, + {file = "lxml-4.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:81c29c8741fa07ecec8ec7417c3d8d1e2f18cf5a10a280f4e1c3f8c3590228b2"}, + {file = "lxml-4.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6467626fa74f96f4d80fc6ec2555799e97fff8f36e0bfc7f67769f83e59cff40"}, + {file = "lxml-4.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9cae837b988f44925d14d048fa6a8c54f197c8b1223fd9ee9c27084f84606143"}, + {file = "lxml-4.9.0-cp38-cp38-win32.whl", hash = "sha256:5a49ad78543925e1a4196e20c9c54492afa4f1502c2a563f73097e2044c75190"}, + {file = "lxml-4.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:bb7c1b029e54e26e01b1d1d912fc21abb65650d16ea9a191d026def4ed0859ed"}, + {file = "lxml-4.9.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d0d03b9636f1326772e6854459728676354d4c7731dae9902b180e2065ba3da6"}, + {file = "lxml-4.9.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:9af19eb789d674b59a9bee5005779757aab857c40bf9cc313cb01eafac55ce55"}, + {file = "lxml-4.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:dd00d28d1ab5fa7627f5abc957f29a6338a7395b724571a8cbff8fbed83aaa82"}, + {file = "lxml-4.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:754a1dd04bff8a509a31146bd8f3a5dc8191a8694d582dd5fb71ff09f0722c22"}, + {file = "lxml-4.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7679344f2270840dc5babc9ccbedbc04f7473c1f66d4676bb01680c0db85bcc"}, + {file = "lxml-4.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d882c2f3345261e898b9f604be76b61c901fbfa4ac32e3f51d5dc1edc89da3cb"}, + {file = "lxml-4.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e97c8fc761ad63909198acc892f34c20f37f3baa2c50a62d5ec5d7f1efc68a1"}, + {file = "lxml-4.9.0-cp39-cp39-win32.whl", hash = "sha256:cf9ec915857d260511399ab87e1e70fa13d6b2972258f8e620a3959468edfc32"}, + {file = "lxml-4.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:1254a79f8a67a3908de725caf59eae62d86738f6387b0a34b32e02abd6ae73db"}, + {file = "lxml-4.9.0-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:03370ec37fe562238d385e2c53089076dee53aabf8325cab964fdb04a9130fa0"}, + {file = "lxml-4.9.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f386def57742aacc3d864169dfce644a8c396f95aa35b41b69df53f558d56dd0"}, + {file = "lxml-4.9.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ea3f2e9eb41f973f73619e88bf7bd950b16b4c2ce73d15f24a11800ce1eaf276"}, + {file = "lxml-4.9.0-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d10659e6e5c53298e6d718fd126e793285bff904bb71d7239a17218f6a197b7"}, + {file = "lxml-4.9.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fcdf70191f0d1761d190a436db06a46f05af60e1410e1507935f0332280c9268"}, + {file = "lxml-4.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:2b9c2341d96926b0d0e132e5c49ef85eb53fa92ae1c3a70f9072f3db0d32bc07"}, + {file = "lxml-4.9.0-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:615886ee84b6f42f1bdf1852a9669b5fe3b96b6ff27f1a7a330b67ad9911200a"}, + {file = "lxml-4.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:94f2e45b054dd759bed137b6e14ae8625495f7d90ddd23cf62c7a68f72b62656"}, + {file = "lxml-4.9.0.tar.gz", hash = "sha256:520461c36727268a989790aef08884347cd41f2d8ae855489ccf40b50321d8d7"}, ] markupsafe = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, @@ -3307,40 +3309,58 @@ mistune = [ {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] msgpack = [ - {file = "msgpack-1.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:96acc674bb9c9be63fa8b6dabc3248fdc575c4adc005c440ad02f87ca7edd079"}, - {file = "msgpack-1.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2c3ca57c96c8e69c1a0d2926a6acf2d9a522b41dc4253a8945c4c6cd4981a4e3"}, - {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0a792c091bac433dfe0a70ac17fc2087d4595ab835b47b89defc8bbabcf5c73"}, - {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c58cdec1cb5fcea8c2f1771d7b5fec79307d056874f746690bd2bdd609ab147"}, - {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f97c0f35b3b096a330bb4a1a9247d0bd7e1f3a2eba7ab69795501504b1c2c39"}, - {file = "msgpack-1.0.3-cp310-cp310-win32.whl", hash = "sha256:36a64a10b16c2ab31dcd5f32d9787ed41fe68ab23dd66957ca2826c7f10d0b85"}, - {file = "msgpack-1.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c1ba333b4024c17c7591f0f372e2daa3c31db495a9b2af3cf664aef3c14354f7"}, - {file = "msgpack-1.0.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c2140cf7a3ec475ef0938edb6eb363fa704159e0bf71dde15d953bacc1cf9d7d"}, - {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f4c22717c74d44bcd7af353024ce71c6b55346dad5e2cc1ddc17ce8c4507c6b"}, - {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d733a15ade190540c703de209ffbc42a3367600421b62ac0c09fde594da6ec"}, - {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e03b06f2982aa98d4ddd082a210c3db200471da523f9ac197f2828e80e7770"}, - {file = "msgpack-1.0.3-cp36-cp36m-win32.whl", hash = "sha256:3d875631ecab42f65f9dce6f55ce6d736696ced240f2634633188de2f5f21af9"}, - {file = "msgpack-1.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:40fb89b4625d12d6027a19f4df18a4de5c64f6f3314325049f219683e07e678a"}, - {file = "msgpack-1.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6eef0cf8db3857b2b556213d97dd82de76e28a6524853a9beb3264983391dc1a"}, - {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d8c332f53ffff01953ad25131272506500b14750c1d0ce8614b17d098252fbc"}, - {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0903bd93cbd34653dd63bbfcb99d7539c372795201f39d16fdfde4418de43a"}, - {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf1e6bfed4860d72106f4e0a1ab519546982b45689937b40257cfd820650b920"}, - {file = "msgpack-1.0.3-cp37-cp37m-win32.whl", hash = "sha256:d02cea2252abc3756b2ac31f781f7a98e89ff9759b2e7450a1c7a0d13302ff50"}, - {file = "msgpack-1.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f30dd0dc4dfe6231ad253b6f9f7128ac3202ae49edd3f10d311adc358772dba"}, - {file = "msgpack-1.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f201d34dc89342fabb2a10ed7c9a9aaaed9b7af0f16a5923f1ae562b31258dea"}, - {file = "msgpack-1.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bb87f23ae7d14b7b3c21009c4b1705ec107cb21ee71975992f6aca571fb4a42a"}, - {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a3a5c4b16e9d0edb823fe54b59b5660cc8d4782d7bf2c214cb4b91a1940a8ef"}, - {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74da1e5fcf20ade12c6bf1baa17a2dc3604958922de8dc83cbe3eff22e8b611"}, - {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73a80bd6eb6bcb338c1ec0da273f87420829c266379c8c82fa14c23fb586cfa1"}, - {file = "msgpack-1.0.3-cp38-cp38-win32.whl", hash = "sha256:9fce00156e79af37bb6db4e7587b30d11e7ac6a02cb5bac387f023808cd7d7f4"}, - {file = "msgpack-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:9b6f2d714c506e79cbead331de9aae6837c8dd36190d02da74cb409b36162e8a"}, - {file = "msgpack-1.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:89908aea5f46ee1474cc37fbc146677f8529ac99201bc2faf4ef8edc023c2bf3"}, - {file = "msgpack-1.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:973ad69fd7e31159eae8f580f3f707b718b61141838321c6fa4d891c4a2cca52"}, - {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da24375ab4c50e5b7486c115a3198d207954fe10aaa5708f7b65105df09109b2"}, - {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a598d0685e4ae07a0672b59792d2cc767d09d7a7f39fd9bd37ff84e060b1a996"}, - {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4c309a68cb5d6bbd0c50d5c71a25ae81f268c2dc675c6f4ea8ab2feec2ac4e2"}, - {file = "msgpack-1.0.3-cp39-cp39-win32.whl", hash = "sha256:494471d65b25a8751d19c83f1a482fd411d7ca7a3b9e17d25980a74075ba0e88"}, - {file = "msgpack-1.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:f01b26c2290cbd74316990ba84a14ac3d599af9cebefc543d241a66e785cf17d"}, - {file = "msgpack-1.0.3.tar.gz", hash = "sha256:51fdc7fb93615286428ee7758cecc2f374d5ff363bdd884c7ea622a7a327a81e"}, + {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"}, + {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"}, + {file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"}, + {file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"}, + {file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"}, + {file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"}, + {file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"}, + {file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"}, + {file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"}, + {file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"}, + {file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"}, + {file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"}, + {file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"}, + {file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"}, + {file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"}, + {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"}, ] multidict = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, @@ -3404,29 +3424,29 @@ multidict = [ {file = "multidict-6.0.2.tar.gz", hash = "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013"}, ] mypy = [ - {file = "mypy-0.950-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cf9c261958a769a3bd38c3e133801ebcd284ffb734ea12d01457cb09eacf7d7b"}, - {file = "mypy-0.950-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5b5bd0ffb11b4aba2bb6d31b8643902c48f990cc92fda4e21afac658044f0c0"}, - {file = "mypy-0.950-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e7647df0f8fc947388e6251d728189cfadb3b1e558407f93254e35abc026e22"}, - {file = "mypy-0.950-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eaff8156016487c1af5ffa5304c3e3fd183edcb412f3e9c72db349faf3f6e0eb"}, - {file = "mypy-0.950-cp310-cp310-win_amd64.whl", hash = "sha256:563514c7dc504698fb66bb1cf897657a173a496406f1866afae73ab5b3cdb334"}, - {file = "mypy-0.950-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dd4d670eee9610bf61c25c940e9ade2d0ed05eb44227275cce88701fee014b1f"}, - {file = "mypy-0.950-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca75ecf2783395ca3016a5e455cb322ba26b6d33b4b413fcdedfc632e67941dc"}, - {file = "mypy-0.950-cp36-cp36m-win_amd64.whl", hash = "sha256:6003de687c13196e8a1243a5e4bcce617d79b88f83ee6625437e335d89dfebe2"}, - {file = "mypy-0.950-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4c653e4846f287051599ed8f4b3c044b80e540e88feec76b11044ddc5612ffed"}, - {file = "mypy-0.950-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e19736af56947addedce4674c0971e5dceef1b5ec7d667fe86bcd2b07f8f9075"}, - {file = "mypy-0.950-cp37-cp37m-win_amd64.whl", hash = "sha256:ef7beb2a3582eb7a9f37beaf38a28acfd801988cde688760aea9e6cc4832b10b"}, - {file = "mypy-0.950-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0112752a6ff07230f9ec2f71b0d3d4e088a910fdce454fdb6553e83ed0eced7d"}, - {file = "mypy-0.950-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee0a36edd332ed2c5208565ae6e3a7afc0eabb53f5327e281f2ef03a6bc7687a"}, - {file = "mypy-0.950-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77423570c04aca807508a492037abbd72b12a1fb25a385847d191cd50b2c9605"}, - {file = "mypy-0.950-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ce6a09042b6da16d773d2110e44f169683d8cc8687e79ec6d1181a72cb028d2"}, - {file = "mypy-0.950-cp38-cp38-win_amd64.whl", hash = "sha256:5b231afd6a6e951381b9ef09a1223b1feabe13625388db48a8690f8daa9b71ff"}, - {file = "mypy-0.950-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0384d9f3af49837baa92f559d3fa673e6d2652a16550a9ee07fc08c736f5e6f8"}, - {file = "mypy-0.950-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1fdeb0a0f64f2a874a4c1f5271f06e40e1e9779bf55f9567f149466fc7a55038"}, - {file = "mypy-0.950-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:61504b9a5ae166ba5ecfed9e93357fd51aa693d3d434b582a925338a2ff57fd2"}, - {file = "mypy-0.950-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a952b8bc0ae278fc6316e6384f67bb9a396eb30aced6ad034d3a76120ebcc519"}, - {file = "mypy-0.950-cp39-cp39-win_amd64.whl", hash = "sha256:eaea21d150fb26d7b4856766e7addcf929119dd19fc832b22e71d942835201ef"}, - {file = "mypy-0.950-py3-none-any.whl", hash = "sha256:a4d9898f46446bfb6405383b57b96737dcfd0a7f25b748e78ef3e8c576bba3cb"}, - {file = "mypy-0.950.tar.gz", hash = "sha256:1b333cfbca1762ff15808a0ef4f71b5d3eed8528b23ea1c3fb50543c867d68de"}, + {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"}, + {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"}, + {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"}, + {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"}, + {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"}, + {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"}, + {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"}, + {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"}, + {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"}, + {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"}, + {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"}, + {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"}, + {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"}, + {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"}, + {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"}, + {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"}, + {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"}, + {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"}, + {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -3880,53 +3900,63 @@ pyyaml = [ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] pyzmq = [ - {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, - {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2841997a0d85b998cbafecb4183caf51fd19c4357075dfd33eb7efea57e4c149"}, - {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, - {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, - {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, - {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, - {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, - {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, - {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, - {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, - {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, - {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, - {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, - {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, - {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, - {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, - {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, - {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, - {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, - {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, - {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, - {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, - {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, - {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, - {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, - {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, - {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, - {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, - {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, - {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, - {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f43b4a2e6218371dd4f41e547bd919ceeb6ebf4abf31a7a0669cd11cd91ea973"}, - {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, - {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, - {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, - {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, - {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, - {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, - {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, - {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:80e043a89c6cadefd3a0712f8a1322038e819ebe9dbac7eca3bce1721bcb63bf"}, - {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1621e7a2af72cced1f6ec8ca8ca91d0f76ac236ab2e8828ac8fe909512d566cb"}, - {file = "pyzmq-22.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d6157793719de168b199194f6b6173f0ccd3bf3499e6870fac17086072e39115"}, - {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, + {file = "pyzmq-23.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6d346e551fa64b89d57a4ac74b9bc66703413f02f50093e089e861999ec5cccc"}, + {file = "pyzmq-23.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c7fb691fb07ec7ab99fd173bb0e7e0248d31bf83d484a87b917a342f63812c9"}, + {file = "pyzmq-23.1.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cd82cca9c489e441574804dbda2dd8e114cf3be7935b03de11dade2c9478aea6"}, + {file = "pyzmq-23.1.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28f9164fb2658b7b414fa0894c75b1a9c61375774cdc1bdb7298beb042a2cd87"}, + {file = "pyzmq-23.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53b2c1326c2e484d450932d2be739f064b7cb572faabec38386098a28516a529"}, + {file = "pyzmq-23.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425ba851a6f9892bde1da2024d82e2fe6796bd77e3391fb96665c50fe9d4c6a5"}, + {file = "pyzmq-23.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38f778a74e3889392e949326cfd0e9b2eb37dcbb2980d98fad2c51703d523db2"}, + {file = "pyzmq-23.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ddf4ad1d651e6c9234945061e1a31fe27a4be0dea21c498b87b186fadf8f5919"}, + {file = "pyzmq-23.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b08774057ae7ce8a2eb4e7d54db05358234440706ce43a85814500c5d7bd22e"}, + {file = "pyzmq-23.1.0-cp310-cp310-win32.whl", hash = "sha256:67ec63ae3c9c1fa2e077fcb42e77035e2121a04f987464bdf9945a28535d30ad"}, + {file = "pyzmq-23.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:f4c7d370badc60ac94a554bc571a46d03e39d8aacfba8006b334512e184aed59"}, + {file = "pyzmq-23.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f6c9d30888503f2f5f87d6d41f016301352dd98da4a861bd10663c3a2d99d3b5"}, + {file = "pyzmq-23.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16b832adb5d8716f46051da5533c480250bf126984ce86804db6137a3a7f931b"}, + {file = "pyzmq-23.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:da72a384a1d7e87490ca71182f3ab469ed21d847adc16b70c34faac5a3b12801"}, + {file = "pyzmq-23.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ab4b6108e69f63c917cd7ef7217c5727955b1ac90600e44a13ed5312019a014"}, + {file = "pyzmq-23.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7626e8384275a7dea6f3d1f749fb5e00299042e9c895fc3dbe24cb154909c242"}, + {file = "pyzmq-23.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:cbc1184349ca6e5112898aa7fc3efa1b1bbae24ab1edc774cfd09cbfd3b091d7"}, + {file = "pyzmq-23.1.0-cp36-cp36m-win32.whl", hash = "sha256:d977df6f7c4109ed1d96ffb6795f6af77114be606ae4556efbfc9cac725db65d"}, + {file = "pyzmq-23.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2951c29b8649f3672af9dca8ff61d86310d3664d9629788b1c66422fb13b1239"}, + {file = "pyzmq-23.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bd2a13a0f8367e50347cbac87ae230ae1953935443240238f956bf10668bead6"}, + {file = "pyzmq-23.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bd7f18bd4cf51ea8d7e54825902cf36f9d2f35cc51ef618373988d5398b8dd0"}, + {file = "pyzmq-23.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fab8a7877275060f7b303e1f91c218069a2814a616b6a5ee2d8a3737deb15915"}, + {file = "pyzmq-23.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:894be7d17228e7328cc188096c0162697211ec91761f6812fff12790cbe11c66"}, + {file = "pyzmq-23.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bba54f97578943f48f621b4a7afb8eb022370da26a88b88ccc9fee9f3ef7ce45"}, + {file = "pyzmq-23.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:eb0ae5dfda83bbce660179d7b41c1c38fd833a54d2e6d9b258c644f3b75ef94d"}, + {file = "pyzmq-23.1.0-cp37-cp37m-win32.whl", hash = "sha256:523ba7fd4d8fe75ad09c1e574a648892b75a97d0cfc8005727681053ac19555b"}, + {file = "pyzmq-23.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6cd53e861bccc0bdc4620f68fb4a91d5bcfe9f4213cf8e200fa498044d33a6dc"}, + {file = "pyzmq-23.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:81623c67cb71b93b5f7e06c9107f3781738ae86866db830c950223d87af2a235"}, + {file = "pyzmq-23.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:83f1c76068faf62c32a36dd62dc4db642c2027bbbd960f8f6345b59e9d4dc472"}, + {file = "pyzmq-23.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:312e56799410c34797417a4060a8bd37d4db1f06d1ec0c54f7c8fd81e0d90376"}, + {file = "pyzmq-23.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff8708fabc9f9bc2949f457d39b4088c9656c4c9ac15fbbbbaafce8f6d07833"}, + {file = "pyzmq-23.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8c3abf7eab5b76ae162c4fbb16d514a947fc57fd995b64e5ea8ef8ba3b888a69"}, + {file = "pyzmq-23.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4fbcd657cda75574fd1315a4c44bd322bc2e219039fb09f146bbe6f8aef039e9"}, + {file = "pyzmq-23.1.0-cp38-cp38-win32.whl", hash = "sha256:540d7146c3cdc9bbffab039ea067f494eba24d1abe5bd33eb9f963c01e3305d4"}, + {file = "pyzmq-23.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8679bb1dd723ecbea03b1f96c98972815775fd8ec756c440a14f289c436c472e"}, + {file = "pyzmq-23.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:cfee22e072a382b92ee0709dbb8203dabd52d54258051e770d9d2a81b162530b"}, + {file = "pyzmq-23.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:68e22c5d3be451e87d47f956b397a7823bfbde2176341bc902fba30f96831d7e"}, + {file = "pyzmq-23.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:97d6c676dc97d593625d9fc48154f2ffeabb619a1e6fe8d2a5b53f97e3e9bdee"}, + {file = "pyzmq-23.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3bc3cf200aab74f3d758586ac50295214eda496ac6a6636e0c881c5958d9123"}, + {file = "pyzmq-23.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48bbc2db041ab28eeee4a3e8ada0ed336640946dd5a8e53dbd3805f9dbdcf0dc"}, + {file = "pyzmq-23.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:67a049bcf967a39993858beed873ed3405536019820922d4efacfe35ab3da51a"}, + {file = "pyzmq-23.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3955dd5bbbe02f454655296ee36a66c334c7102a29b8458223d168c0380edfd5"}, + {file = "pyzmq-23.1.0-cp39-cp39-win32.whl", hash = "sha256:8a0f240bf43c29be1bd82d77e602a61c798e9de02e5f8bb7bb414cb814f43236"}, + {file = "pyzmq-23.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7e7346b2b33dcd4a2171dd8a9870ae283eec8f6231dcbcf237a0f41e74751a50"}, + {file = "pyzmq-23.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:99dd85f0ca1db8d17a01a25c2bbb7784d25a2d39497c6beddbe96bff74194e04"}, + {file = "pyzmq-23.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:563d4281c4dbdf647d93114420151d33f895afc4c46b7115a67a0aa5347e6624"}, + {file = "pyzmq-23.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:154de02b15422af28b53d29a02de72121ba503634955017255573fc1f995143d"}, + {file = "pyzmq-23.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8757c62f7960cd26122f7aaaf86eda1e016fa85734c3777b8054dd334d7dea4d"}, + {file = "pyzmq-23.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f6c378b435a26fda8996579c0e324b108d2ca0d01b4661503a75634e5155559f"}, + {file = "pyzmq-23.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2e2ac40f7a91c740ec68d6db07ae19ea9259c959333c68bee56ab2c799a67d66"}, + {file = "pyzmq-23.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ce8ba5ed8b0a7a203922d61cff45ee6001a41a9359f04f00d055a4e988755569"}, + {file = "pyzmq-23.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:93332c6972e4c91522c4810e907f3aea067424338071161b39cacded022559df"}, + {file = "pyzmq-23.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fc32e7d7f98cac3d8d5153ed2cb583158ae3d446a6efb8e28ccb1c54a09f4169"}, + {file = "pyzmq-23.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86fb683cb9a9c0bb7476988b7957393ecdd22777d87d804442c66e62c99197f9"}, + {file = "pyzmq-23.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:057176dd3f5ccf5aad4abd662d76b6a39bbf799baaf2f39cd4fdaf2eab326e43"}, + {file = "pyzmq-23.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05ec90a8da618f2398f9d1aa20b18a9ef332992c6ac23e8c866099faad6ef0d6"}, + {file = "pyzmq-23.1.0.tar.gz", hash = "sha256:1df26aa854bdd3a8341bf199064dd6aa6e240f2eaa3c9fa8d217e5d8b868c73e"}, ] rdflib = [ {file = "rdflib-6.0.2-py3-none-any.whl", hash = "sha256:b7642daac8cdad1ba157fecb236f5d1b2aa1de64e714dcee80d65e2b794d88a6"}, @@ -3996,20 +4026,8 @@ rq-scheduler = [ {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, ] schema-salad = [ - {file = "schema-salad-8.2.20220204150214.tar.gz", hash = "sha256:3e53dbfe7137796b9e5135920e96bb2713ded9e7be2859dae554d1dc8b029704"}, - {file = "schema_salad-8.2.20220204150214-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:609ba090fb40f493cedf64bb124c1d208af7388b6663af9d76a91a03ec7d8710"}, - {file = "schema_salad-8.2.20220204150214-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecf2c386cff04f7bc08b0ec4f3f3f0c6196043d746799c64a98ca4cb596e4c9f"}, - {file = "schema_salad-8.2.20220204150214-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ec4ad0f1fd56637ad3f935d647adceaebc28bbe7c204cf24165c231320c09b8"}, - {file = "schema_salad-8.2.20220204150214-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77ff2a0d76e490f5c39375ca4d3f625fffa51a93aa719966a5c06b5375f76fc8"}, - {file = "schema_salad-8.2.20220204150214-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86addbf36269646914c666035318ca38a5e84a4ae5732c013cde3f03550ca5f7"}, - {file = "schema_salad-8.2.20220204150214-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b72181040f4330decdad422130fac6d7953d0415843a6bb02d6e7835f20e10e7"}, - {file = "schema_salad-8.2.20220204150214-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b27300acf4d71547dae3c0f065789075c157391de74e71fdbf1daf318ef958dc"}, - {file = "schema_salad-8.2.20220204150214-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd1f72602c21fb4e201cecba36c60f896f0cc95edaeb49bb9b720ed9869af372"}, - {file = "schema_salad-8.2.20220204150214-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2de190abaccd39408e384982c0bbb871708502ebb81682cf0a6e522bcdf86dc3"}, - {file = "schema_salad-8.2.20220204150214-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c8d4b433f745e3c51fa8ea83ab319c45269af3003cb180d53e6eb719c1f8606"}, - {file = "schema_salad-8.2.20220204150214-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4976cbb5c4801b29295bdadb3e234e7b9572b1b9716b063f79806cb30820181"}, - {file = "schema_salad-8.2.20220204150214-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1627e1666e8f835d337926fac65d5484128ce5798fefa4bb1a0ae862e1f9ec82"}, - {file = "schema_salad-8.2.20220204150214-py3-none-any.whl", hash = "sha256:ce49adf0bc97fd44d99df98bf00d6bc66b38a2483b3cc721cbd200d010add3c5"}, + {file = "schema-salad-8.3.20220525163636.tar.gz", hash = "sha256:547bbb05c271d58e00d4e56540bf9e8908f3840eb87529ad9a4678b903f21edd"}, + {file = "schema_salad-8.3.20220525163636-py3-none-any.whl", hash = "sha256:ecd5c33f3b505a57fce6f4157f9f45f857e0575075bf7da32bfdec0aa6438ca1"}, ] sentry-sdk = [ {file = "sentry-sdk-1.5.11.tar.gz", hash = "sha256:6c01d9d0b65935fd275adc120194737d1df317dce811e642cbf0394d0d37a007"}, @@ -4076,8 +4094,8 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] sphinxcontrib-spelling = [ - {file = "sphinxcontrib-spelling-7.3.3.tar.gz", hash = "sha256:3819d12629d95e0c909224fa40b462a67e0adb321d50283d7fc0d11686c8ac7e"}, - {file = "sphinxcontrib_spelling-7.3.3-py3-none-any.whl", hash = "sha256:8809d5dc175f43f00628134a41ef9fec56db9f794f4eab701f9a5a87f8c69bb0"}, + {file = "sphinxcontrib-spelling-7.5.0.tar.gz", hash = "sha256:d92bdc1d63f361b6e0a171b9d68518101745485317f15861501e387f1b78f6ab"}, + {file = "sphinxcontrib_spelling-7.5.0-py3-none-any.whl", hash = "sha256:da64b9939eca553ebc6930ae82921c0d4aa7b6a7b5d46726b620b421c14b1f30"}, ] tabulate = [ {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, @@ -4100,8 +4118,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ - {file = "tomlkit-0.10.2-py3-none-any.whl", hash = "sha256:905cf92c2111ef80d355708f47ac24ad1b6fc2adc5107455940088c9bbecaedb"}, - {file = "tomlkit-0.10.2.tar.gz", hash = "sha256:30d54c0b914e595f3d10a87888599eab5321a2a69abc773bbefff51599b72db6"}, + {file = "tomlkit-0.11.0-py3-none-any.whl", hash = "sha256:0f4050db66fd445b885778900ce4dd9aea8c90c4721141fde0d6ade893820ef1"}, + {file = "tomlkit-0.11.0.tar.gz", hash = "sha256:71ceb10c0eefd8b8f11fe34e8a51ad07812cb1dc3de23247425fbc9ddc47b9dd"}, ] tornado = [ {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, @@ -4155,38 +4173,38 @@ transaction = [ {file = "transaction-3.0.1.tar.gz", hash = "sha256:0c15ef0b7ff3518357ceea75722a30d974c3f85e11aa5cec5d5a2b6a40cfcf68"}, ] typed-ast = [ - {file = "typed_ast-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ad3b48cf2b487be140072fb86feff36801487d4abb7382bb1929aaac80638ea"}, - {file = "typed_ast-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:542cd732351ba8235f20faa0fc7398946fe1a57f2cdb289e5497e1e7f48cfedb"}, - {file = "typed_ast-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc2c11ae59003d4a26dda637222d9ae924387f96acae9492df663843aefad55"}, - {file = "typed_ast-1.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd5df1313915dbd70eaaa88c19030b441742e8b05e6103c631c83b75e0435ccc"}, - {file = "typed_ast-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:e34f9b9e61333ecb0f7d79c21c28aa5cd63bec15cb7e1310d7d3da6ce886bc9b"}, - {file = "typed_ast-1.5.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f818c5b81966d4728fec14caa338e30a70dfc3da577984d38f97816c4b3071ec"}, - {file = "typed_ast-1.5.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3042bfc9ca118712c9809201f55355479cfcdc17449f9f8db5e744e9625c6805"}, - {file = "typed_ast-1.5.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4fff9fdcce59dc61ec1b317bdb319f8f4e6b69ebbe61193ae0a60c5f9333dc49"}, - {file = "typed_ast-1.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:8e0b8528838ffd426fea8d18bde4c73bcb4167218998cc8b9ee0a0f2bfe678a6"}, - {file = "typed_ast-1.5.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ef1d96ad05a291f5c36895d86d1375c0ee70595b90f6bb5f5fdbee749b146db"}, - {file = "typed_ast-1.5.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed44e81517364cb5ba367e4f68fca01fba42a7a4690d40c07886586ac267d9b9"}, - {file = "typed_ast-1.5.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f60d9de0d087454c91b3999a296d0c4558c1666771e3460621875021bf899af9"}, - {file = "typed_ast-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9e237e74fd321a55c90eee9bc5d44be976979ad38a29bbd734148295c1ce7617"}, - {file = "typed_ast-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee852185964744987609b40aee1d2eb81502ae63ee8eef614558f96a56c1902d"}, - {file = "typed_ast-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27e46cdd01d6c3a0dd8f728b6a938a6751f7bd324817501c15fb056307f918c6"}, - {file = "typed_ast-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d64dabc6336ddc10373922a146fa2256043b3b43e61f28961caec2a5207c56d5"}, - {file = "typed_ast-1.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8cdf91b0c466a6c43f36c1964772918a2c04cfa83df8001ff32a89e357f8eb06"}, - {file = "typed_ast-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:9cc9e1457e1feb06b075c8ef8aeb046a28ec351b1958b42c7c31c989c841403a"}, - {file = "typed_ast-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e20d196815eeffb3d76b75223e8ffed124e65ee62097e4e73afb5fec6b993e7a"}, - {file = "typed_ast-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:37e5349d1d5de2f4763d534ccb26809d1c24b180a477659a12c4bde9dd677d74"}, - {file = "typed_ast-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f1a27592fac87daa4e3f16538713d705599b0a27dfe25518b80b6b017f0a6d"}, - {file = "typed_ast-1.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8831479695eadc8b5ffed06fdfb3e424adc37962a75925668deeb503f446c0a3"}, - {file = "typed_ast-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:20d5118e494478ef2d3a2702d964dae830aedd7b4d3b626d003eea526be18718"}, - {file = "typed_ast-1.5.3.tar.gz", hash = "sha256:27f25232e2dd0edfe1f019d6bfaaf11e86e657d9bdb7b0956db95f560cceb2b3"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, + {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, + {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, + {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, + {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, + {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, + {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, + {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, + {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, ] types-python-dateutil = [ - {file = "types-python-dateutil-2.8.15.tar.gz", hash = "sha256:7db1e4ed4916bd128cbee3eecdee0e06cc5684da2a1cdfd57f98541cdfbe0861"}, - {file = "types_python_dateutil-2.8.15-py3-none-any.whl", hash = "sha256:9d6f01382d5ffe1977dc29f0782a01228dfaa36da148a7f4076cbd9beba26647"}, + {file = "types-python-dateutil-2.8.17.tar.gz", hash = "sha256:6c54265a221681dd87f61df6743bd5eab060cf1b4086ff65c1a8fd763ed6370e"}, + {file = "types_python_dateutil-2.8.17-py3-none-any.whl", hash = "sha256:0be7435b4d382d1cd00b8c55a8a90f4e515aaad8a96f8f0bc20c22df046792e5"}, ] types-pyyaml = [ - {file = "types-PyYAML-6.0.7.tar.gz", hash = "sha256:59480cf44595d836aaae050f35e3c39f197f3a833679ef3978d97aa9f2fb7def"}, - {file = "types_PyYAML-6.0.7-py3-none-any.whl", hash = "sha256:7b273a34f32af9910cf9405728c9d2ad3afc4be63e4048091a1a73d76681fe67"}, + {file = "types-PyYAML-6.0.8.tar.gz", hash = "sha256:d9495d377bb4f9c5387ac278776403eb3b4bb376851025d913eea4c22b4c6438"}, + {file = "types_PyYAML-6.0.8-py3-none-any.whl", hash = "sha256:56a7b0e8109602785f942a11ebfbd16e97d5d0e79f5fbb077ec4e6a0004837ff"}, ] types-redis = [ {file = "types-redis-4.0.6.tar.gz", hash = "sha256:3d870147794303077598343125727ee24a1a8961dca1a6870013152f2ba2a81b"}, diff --git a/pyproject.toml b/pyproject.toml index b13b12fb2b..873280eaa2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ deepmerge = "==1.0.1" docker = "<6,>=3.7.2" environ-config = ">=18.2.0,<22.2.0" fakeredis = { version = ">=1.4.1,<1.7.2", optional = true } -filelock = ">=3.0.0,<3.6.1" +filelock = ">=3.3.0,<3.6.1" flake8 = { version = "<4.0,>=3.8", optional = true } #wait for https://github.com/flakehell/flakehell/pull/23 to be merged before bumping flakehell = { version = ">=0.9.0,<1.0.*", optional = true } flaky = { version = "==3.7.0", optional = true } @@ -132,7 +132,7 @@ responses = { version = ">=0.7.0,<0.21.0", optional = true } rich = ">=9.3.0,<12.3.0" rq = { version = "==1.10.1", optional = true } rq-scheduler = { version = "==0.11.0", optional = true } -sentry-sdk = { version = ">=1.0.0,<1.5.12,!=1.5.10", extras = ["flask"], optional = true } +sentry-sdk = { version = ">=1.5.11,<1.5.12", extras = ["flask"], optional = true } shellingham = "1.4.0" sphinxcontrib-spelling = { version = "7.*", optional = true } sphinx-rtd-theme = { version = "<1.1,>=0.5.0", optional = true } diff --git a/renku/command/template.py b/renku/command/template.py index 940e4ac510..0e4fdafa20 100644 --- a/renku/command/template.py +++ b/renku/command/template.py @@ -18,7 +18,7 @@ """Template management commands.""" from renku.command.command_builder.command import Command -from renku.core.template.usecase import list_templates, set_template, show_template, update_template +from renku.core.template.usecase import list_templates, set_template, show_template, update_template, validate_templates def list_templates_command(): @@ -55,3 +55,8 @@ def update_template_command(): .with_database(write=True) .with_commit() ) + + +def validate_templates_command(): + """Command to validate a template repository.""" + return Command().command(validate_templates) diff --git a/renku/core/management/git.py b/renku/core/management/git.py index 7988745b77..11dc019e4b 100644 --- a/renku/core/management/git.py +++ b/renku/core/management/git.py @@ -150,16 +150,15 @@ def prepare_worktree( # TODO sys.argv if commit is NULL_TREE: - args = ["add", "--detach", path] - original_client.repository.run_git_command("worktree", *args) + original_client.repository.create_worktree(path, detach=True) client = attr.evolve(original_client, path=path) client.repository.run_git_command("checkout", "--orphan", branch_name) client.repository.remove("*", recursive=True, force=True) else: - args = ["add", "-b", branch_name, path] + revision = None if commit: - args.append(commit.hexsha) - original_client.repository.run_git_command("worktree", *args) + revision = commit.hexsha + original_client.repository.create_worktree(path, branch=branch_name, reference=revision) client = attr.evolve(original_client, path=path) client.repository.get_configuration = original_client.repository.get_configuration @@ -207,7 +206,7 @@ def finalize_worktree( raise errors.FailedMerge(client.repository, branch_name, merge_args) if delete: - client.repository.run_git_command("worktree", "remove", path) + client.repository.remove_worktree(path) if new_branch: # delete the created temporary branch diff --git a/renku/core/management/repository.py b/renku/core/management/repository.py index fb8e0b72f7..563a51bae8 100644 --- a/renku/core/management/repository.py +++ b/renku/core/management/repository.py @@ -58,7 +58,7 @@ def _path_converter(path) -> Path: class PathMixin: """Define a default path attribute.""" - path: Path = attr.ib(default=default_path, converter=_path_converter) + path: Path = attr.ib(default=default_path, converter=_path_converter) # type: ignore @path.validator def _check_path(self, _, value): diff --git a/renku/core/template/template.py b/renku/core/template/template.py index 7c0a59b8af..37e0ada7e0 100644 --- a/renku/core/template/template.py +++ b/renku/core/template/template.py @@ -407,8 +407,10 @@ class RepositoryTemplates(TemplatesSource): get available versions of templates. """ - def __init__(self, path, source, reference, version, repository: Repository): - super().__init__(path=path, source=source, reference=reference, version=version) + def __init__(self, path, source, reference, version, repository: Repository, skip_validation: bool = False): + super().__init__( + path=path, source=source, reference=reference, version=version, skip_validation=skip_validation + ) self.repository: Repository = repository @classmethod diff --git a/renku/core/template/usecase.py b/renku/core/template/usecase.py index 22eca78690..54b807d0bd 100644 --- a/renku/core/template/usecase.py +++ b/renku/core/template/usecase.py @@ -17,7 +17,10 @@ # limitations under the License. """Template use cases.""" -from typing import Dict, List, NamedTuple, Optional, Tuple +import os +import tempfile +from pathlib import Path +from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union import click @@ -29,6 +32,7 @@ from renku.core.management.migrate import is_renku_project from renku.core.template.template import ( FileAction, + RepositoryTemplates, TemplateAction, copy_template_to_client, fetch_templates_source, @@ -38,6 +42,7 @@ from renku.core.util import communication from renku.domain_model.tabulate import tabulate from renku.domain_model.template import RenderedTemplate, Template, TemplateMetadata, TemplatesSource +from renku.infrastructure.repository import Repository def list_templates(source, reference) -> List[TemplateViewModel]: @@ -242,3 +247,53 @@ def prompt_to_select_template(): return templates_source.templates[0] return prompt_to_select_template() + + +def validate_templates( + source: Optional[str] = None, reference: Optional[str] = None +) -> Dict[str, Union[str, Dict[str, List[str]]]]: + """Validate a template repository. + + Args: + source(str, optional): Remote repository URL to clone and check (Default value = None). + reference(str, optional): Git commit/branch/tag to check (Default value = None). + Returns: + Dict[str, Union[str, Dict[str, List[str]]]]: Dictionary containing errors and warnings for manifest and + templates, along with a ``valid`` field telling if all checks passed. + """ + + if source is not None: + path = Path(tempfile.mkdtemp()) + repo = Repository.clone_from(path=path, url=source) + repo.checkout(reference=reference) + else: + path = Path(os.getcwd()) + repo = Repository(path=path) + + if reference is not None: + path = Path(tempfile.mkdtemp()) + repo.create_worktree(path, reference=reference) + repo = Repository(path=path) + + version = repo.head.commit.hexsha + + result: Dict[str, Any] = {"manifest": None, "templates": {}, "warnings": [], "valid": True} + + try: + template_source = RepositoryTemplates( + path=path, source=path, reference="", version=version, repository=repo, skip_validation=True + ) + result["warnings"] = template_source.manifest.validate(manifest_only=True) + except errors.InvalidTemplateError as e: + result["manifest"] = e.args[0] if e.args else str(e) + result["valid"] = False + return result + + for template in template_source.manifest.templates: + template.templates_source = template_source + issues = template.validate(skip_files=False, raise_errors=False) + if issues: + result["templates"][template.id] = issues + result["valid"] = False + + return result diff --git a/renku/domain_model/template.py b/renku/domain_model/template.py index 1ad5ed3f96..ec136f5d39 100644 --- a/renku/domain_model/template.py +++ b/renku/domain_model/template.py @@ -23,7 +23,7 @@ import tempfile from abc import abstractmethod from pathlib import Path -from typing import Any, Dict, Generator, List, Optional, Tuple, Union, cast +from typing import Any, Dict, Generator, List, Optional, Set, Tuple, Union, cast import jinja2 import yaml @@ -38,12 +38,12 @@ class TemplatesSource: """Base class for Renku template sources.""" - def __init__(self, path, source, reference, version): + def __init__(self, path, source, reference, version, skip_validation: bool = False): self.path: Path = Path(path) self.source: str = source self.reference: Optional[str] = reference self.version: str = version - self.manifest: TemplatesManifest = TemplatesManifest.from_path(path / TEMPLATE_MANIFEST) + self.manifest: TemplatesManifest = TemplatesManifest.from_path(path / TEMPLATE_MANIFEST, skip_validation) @classmethod @abstractmethod @@ -93,31 +93,32 @@ def get_template(self, id, reference: Optional[str]) -> Optional["Template"]: class TemplatesManifest: """Manifest file for Renku templates.""" - def __init__(self, content: List[Dict]): + def __init__(self, content: List[Dict], skip_validation: bool = False): self._content: List[Dict] = content self._templates: Optional[List[Template]] = None - self.validate() + if not skip_validation: + self.validate() @classmethod - def from_path(cls, path: Union[Path, str]) -> "TemplatesManifest": + def from_path(cls, path: Union[Path, str], skip_validation: bool = False) -> "TemplatesManifest": """Extract template metadata from the manifest file.""" try: - return cls.from_string(Path(path).read_text()) + return cls.from_string(Path(path).read_text(), skip_validation) except FileNotFoundError as e: raise errors.InvalidTemplateError(f"There is no manifest file '{path}'") from e except UnicodeDecodeError as e: raise errors.InvalidTemplateError(f"Cannot read manifest file '{path}'") from e @classmethod - def from_string(cls, content: str) -> "TemplatesManifest": + def from_string(cls, content: str, skip_validation: bool = False) -> "TemplatesManifest": """Extract template metadata from the manifest file.""" try: manifest = yaml.safe_load(content) except yaml.YAMLError as e: raise errors.InvalidTemplateError("Cannot parse manifest file") from e else: - manifest = TemplatesManifest(manifest) + manifest = TemplatesManifest(manifest, skip_validation) return manifest @property @@ -129,7 +130,7 @@ def templates(self) -> List["Template"]: id=cast(str, t.get("id") or t.get("folder")), name=cast(str, t.get("name")), description=cast(str, t.get("description")), - parameters=cast(Dict[str, Dict[str, Any]], t.get("parameters") or t.get("variables")), + parameters=cast(Dict[str, Dict[str, Any]], t.get("variables") or t.get("parameters")), icon=cast(str, t.get("icon")), immutable_files=t.get("immutable_template_files", []), allow_update=t.get("allow_template_update", True), @@ -148,33 +149,46 @@ def get_raw_content(self) -> List[Dict]: """Return raw manifest file content.""" return copy.deepcopy(self._content) - def validate(self): + def validate(self, manifest_only: bool = False) -> List[str]: """Validate manifest content.""" + warnings = [] + if not self._content: raise errors.InvalidTemplateError("Cannot find any valid template in manifest file") elif not isinstance(self._content, list): raise errors.InvalidTemplateError(f"Invalid manifest content type: '{type(self._content).__name__}'") # NOTE: First check if required fields exists for creating Template instances - for template in self._content: - if not isinstance(template, dict): - raise errors.InvalidTemplateError(f"Invalid template type: '{type(template).__name__}'") + for template_entry in self._content: + if not isinstance(template_entry, dict): + raise errors.InvalidTemplateError(f"Invalid template type: '{type(template_entry).__name__}'") - id = template.get("id") or template.get("folder") + id = template_entry.get("id") or template_entry.get("folder") if not id: - raise errors.InvalidTemplateError(f"Template doesn't have an id: '{template}'") + raise errors.InvalidTemplateError(f"Template doesn't have an id: '{template_entry}'") + if not template_entry.get("id"): + warnings.append(f"Template '{id}' should use 'id' attribute instead of 'folder'.") - parameters = template.get("parameters") or template.get("variables") + parameters = template_entry.get("variables") if parameters: if not isinstance(parameters, dict): - raise errors.InvalidTemplateError(f"Invalid template variable type: '{type(parameters).__name__}'") + raise errors.InvalidTemplateError( + f"Invalid template variable type on template '{id}': '{type(parameters).__name__}', " + "should be 'dict'." + ) for key, parameter in parameters.items(): if isinstance(parameter, str): # NOTE: Backwards compatibility - template["variables"][key] = {"description": parameter} + template_entry["variables"][key] = {"description": parameter} + warnings.append( + f"Template '{id}' variable '{key}' uses old string format in manifest and should be" + " replaced with the nested dictionary format." + ) + if not manifest_only: + for template in self.templates: + template.validate(skip_files=True) - for template in self.templates: - template.validate(skip_files=True) + return warnings class Template: @@ -182,6 +196,7 @@ class Template: REQUIRED_ATTRIBUTES = ("name",) REQUIRED_FILES = (os.path.join(RENKU_HOME, "renku.ini"), "Dockerfile") + PROHIBITED_PATHS = (f"{RENKU_HOME}/*",) def __init__( self, @@ -235,33 +250,70 @@ def get_all_references(self) -> List[str]: return [] return self.templates_source.get_all_references(self.id) - def validate(self, skip_files): + def validate(self, skip_files: bool, raise_errors: bool = True) -> List[str]: """Validate a template.""" + + issues = [] + for attribute in self.REQUIRED_ATTRIBUTES: if not getattr(self, attribute, None): - raise errors.InvalidTemplateError(f"Template '{self.id}' does not have a '{attribute}' attribute") + issue = f"Template '{self.id}' does not have a '{attribute}' attribute" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) for parameter in self.parameters: - parameter.validate() + issues.extend(parameter.validate(raise_errors=False)) if skip_files: - return + return issues if self.path is None or not self.path.exists(): - raise errors.InvalidTemplateError(f"Template directory for '{self.id}' does not exists") - - # TODO: What are required files - required_files = self.REQUIRED_FILES - for file in required_files: + issue = f"Template directory for '{self.id}' does not exists" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) + return issues # NOTE: no point checking individual files if directory doesn't exist. + + missing_required_files: Set[str] = set() + for file in self.REQUIRED_FILES: if not (self.path / file).is_file(): - raise errors.InvalidTemplateError(f"File '{file}' is required for template '{self.id}'") + missing_required_files.add(file) + + if missing_required_files: + required_files_str = "\n\t\t\t".join(missing_required_files) + issue = f"These paths are required but missing:\n\t\t\t{required_files_str}" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) + + existing_prohibited_paths: Set[str] = set() + + for pattern in self.PROHIBITED_PATHS: + matches = set( + m for m in self.path.glob(pattern) if str(m.relative_to(self.path)) not in self.REQUIRED_FILES + ) + if matches: + existing_prohibited_paths.update(str(m.relative_to(self.path)) for m in matches) + + if existing_prohibited_paths: + prohibited_paths_str = "\n\t\t\t".join(p for p in existing_prohibited_paths) + issue = f"These paths are not allowed in a template:\n\t\t\t{prohibited_paths_str}" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) # NOTE: Validate symlinks resolve to a path inside the template for relative_path in self.get_files(): try: get_safe_relative_path(path=relative_path, base=self.path) except ValueError: - raise errors.InvalidTemplateError(f"File '{relative_path}' is not within the template.") + issue = f"File '{relative_path}' is not within the template." + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) + + return issues def get_files(self) -> Generator[str, None, None]: """Return all files in a rendered renku template.""" @@ -362,31 +414,42 @@ def has_default(self) -> bool: # a valid value anyways return self.default is not None - def validate(self): + def validate(self, raise_errors: bool = True) -> List[str]: """Validate manifest content.""" + issues = [] if not self.name: - raise errors.InvalidTemplateError("Template parameter does not have a name.") + issue = "Template parameter does not have a name." + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) if self.type and self.type not in self.VALID_TYPES: - raise errors.InvalidTemplateError( - f"Template contains variable '{self.name}' of type '{self.type}' which is not supported" - ) + issue = f"Template contains variable '{self.name}' of type '{self.type}' which is not supported" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) if self.possible_values and not isinstance(self.possible_values, list): - raise errors.InvalidTemplateError( - f"Invalid type for possible values of template variable '{self.name}': '{self.possible_values}'" - ) + if raise_errors: + issue = f"Invalid type for possible values of template variable '{self.name}': '{self.possible_values}'" + raise errors.InvalidTemplateError(issue) + issues.append(issue) if self.type and self.type == "enum" and not self.possible_values: - raise errors.InvalidTemplateError( - f"Template variable '{self.name}' of type enum does not provide a corresponding enum list" - ) + issue = f"Template variable '{self.name}' of type enum does not provide a corresponding enum list" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) if self.has_default: try: - self.default = self.convert(self.default) + self.default = self.convert(self.default) # type: ignore except ValueError as e: - raise errors.InvalidTemplateError(f"Invalid default value for '{self.name}': {e}") + issue = f"Invalid default value for '{self.name}': {e}" + if raise_errors: + raise errors.InvalidTemplateError(issue) + issues.append(issue) + return issues def convert(self, value: Union[int, float, str, bool]) -> Union[int, float, str, bool]: """Convert a given value to the proper type and raise if value is not valid.""" diff --git a/renku/infrastructure/git_merger.py b/renku/infrastructure/git_merger.py index 04a2b09e7b..caa8262fdb 100644 --- a/renku/infrastructure/git_merger.py +++ b/renku/infrastructure/git_merger.py @@ -103,7 +103,7 @@ def _setup_worktrees(self, client): for remote_branch in remote_branches: # NOTE: Create a new shallow worktree for each remote branch, could be several in case of an octo merge worktree_path = Path(mkdtemp()) - client.repository.create_worktree(worktree_path, remote_branch, checkout=False) + client.repository.create_worktree(worktree_path, reference=remote_branch, checkout=False) try: remote_repository = Repository(worktree_path) remote_repository.checkout(sparse=[database_path]) diff --git a/renku/infrastructure/repository.py b/renku/infrastructure/repository.py index d271b6b7e0..3bee54327f 100644 --- a/renku/infrastructure/repository.py +++ b/renku/infrastructure/repository.py @@ -323,16 +323,37 @@ def status(self) -> str: return self.run_git_command("status") def create_worktree( - self, path: Path, reference: Union["Branch", "Commit", "Reference", str], checkout: bool = True + self, + path: Path, + reference: Optional[Union["Branch", "Commit", "Reference", str]], + branch: Optional[str] = None, + checkout: bool = True, + detach: bool = False, ): """Create a git worktree. Args: path(Path): Target folder. reference(Union[Branch, Commit, Reference, str]): the reference to base the tree on. - checkout(bool): Whether to perform a checkout of the reference (Default value = False). + checkout(bool, optional): Whether to perform a checkout of the reference (Default value = False). + detach(bool, optional): Whether to detach HEAD in worktree (Default value = False). """ - self.run_git_command("worktree", "add", path, reference, checkout=checkout) + args = ["add"] + + # NOTE: pass args as string to ensure correct order + if checkout: + args.append("--checkout") + if detach: + args.append("--detach") + + if branch: + args.extend(["-b", branch]) + + args.append(str(path)) + + if reference: + args.append(str(reference)) + self.run_git_command("worktree", *args) def remove_worktree(self, path: Path): """Create a git worktree. diff --git a/renku/ui/cli/__init__.py b/renku/ui/cli/__init__.py index 4a85f3020e..8bdace3143 100644 --- a/renku/ui/cli/__init__.py +++ b/renku/ui/cli/__init__.py @@ -122,7 +122,7 @@ def get_entry_points(name: str): WARNING_UNPROTECTED_COMMANDS = ["clone", "credentials", "env", "help", "init", "login", "logout", "service", "template"] -WARNING_UNPROTECTED_SUBCOMMANDS = {"template": ["ls", "show"]} +WARNING_UNPROTECTED_SUBCOMMANDS = {"template": ["ls", "show", "validate"]} def _uuid_representer(dumper, data): diff --git a/renku/ui/cli/dataset.py b/renku/ui/cli/dataset.py index 5d5fe12e54..0d1b8d548a 100644 --- a/renku/ui/cli/dataset.py +++ b/renku/ui/cli/dataset.py @@ -106,16 +106,6 @@ You can specify output formats by passing ``--format`` with a value of ``tabular``, ``json-ld`` or ``json``. -To inspect the state of the dataset on a given commit we can use ``--revision`` -flag for it: - -.. code-block:: console - - $ renku dataset ls --revision=1103a42bd3006c94ef2af5d6a5e03a335f071215 - ID NAME TITLE VERSION - a1fd8ce2 201901_us_flights_1 2019-01 US Flights 1 - c2d80abe ds1 ds1 - Showing dataset details: .. code-block:: console @@ -513,12 +503,12 @@ from pathlib import Path import click +from lazy_object_proxy import Proxy import renku.ui.cli.utils.color as color from renku.command.format.dataset_files import DATASET_FILES_COLUMNS, DATASET_FILES_FORMATS from renku.command.format.dataset_tags import DATASET_TAGS_FORMATS from renku.command.format.datasets import DATASETS_COLUMNS, DATASETS_FORMATS -from renku.ui.cli.utils.callback import ClickCallback def _complete_datasets(ctx, param, incomplete): @@ -585,6 +575,7 @@ def create(name, title, description, creators, metadata, keyword): """Create an empty dataset in the current repo.""" from renku.command.dataset import create_dataset_command from renku.core.util.metadata import construct_creators + from renku.ui.cli.utils.callback import ClickCallback communicator = ClickCallback() creators = creators or () @@ -641,6 +632,7 @@ def edit(name, title, description, creators, metadata, keyword): """Edit dataset metadata.""" from renku.command.dataset import edit_dataset_command from renku.core.util.metadata import construct_creators + from renku.ui.cli.utils.callback import ClickCallback creators = creators or () keywords = keyword or () @@ -737,6 +729,7 @@ def show(tag, name): def add(name, urls, external, force, overwrite, create, sources, destination, ref): """Add data to a dataset.""" from renku.command.dataset import add_to_dataset_command + from renku.ui.cli.utils.callback import ClickCallback communicator = ClickCallback() add_to_dataset_command().with_communicator(communicator).build().execute( @@ -802,6 +795,7 @@ def unlink(name, include, exclude, yes): """Remove matching files from a dataset.""" from renku.command.dataset import file_unlink_command from renku.core import errors + from renku.ui.cli.utils.callback import ClickCallback if not include and not exclude: raise errors.ParameterError( @@ -872,10 +866,12 @@ def export_provider_argument(*param_decls, **attrs): def wrapper(f): from click import argument - from renku.core.dataset.providers import ProviderFactory + def _get_providers(): + from renku.core.dataset.providers import ProviderFactory + + return [k.lower() for k, p in ProviderFactory.providers().items() if p.supports_export] - providers = [k.lower() for k, p in ProviderFactory.providers().items() if p.supports_export] - f = argument("provider", type=click.Choice(providers))(f) + f = argument("provider", type=click.Choice(Proxy(_get_providers)))(f) return f return wrapper @@ -922,6 +918,7 @@ def export_(name, provider, publish, tag, **kwargs): """Export data to 3rd party provider.""" from renku.command.dataset import export_dataset_command from renku.core import errors + from renku.ui.cli.utils.callback import ClickCallback try: communicator = ClickCallback() @@ -945,6 +942,7 @@ def import_(uri, name, extract, yes): Supported providers: [Dataverse, Renku, Zenodo] """ from renku.command.dataset import import_dataset_command + from renku.ui.cli.utils.callback import ClickCallback communicator = ClickCallback() import_dataset_command().with_communicator(communicator).build().execute( @@ -973,6 +971,7 @@ def update(names, creators, include, exclude, ref, delete, external, no_external """Updates files in dataset from a remote Git repo.""" from renku.command.dataset import update_datasets_command from renku.core import errors + from renku.ui.cli.utils.callback import ClickCallback communicator = ClickCallback() diff --git a/renku/ui/cli/exception_handler.py b/renku/ui/cli/exception_handler.py index 8ee6c73ed8..42d75026a6 100644 --- a/renku/ui/cli/exception_handler.py +++ b/renku/ui/cli/exception_handler.py @@ -65,7 +65,6 @@ import renku.ui.cli.utils.color as color from renku.command.echo import ERROR -from renku.core.errors import MigrationRequired, ParameterError, ProjectNotSupported, RenkuException, UsageError from renku.ui.service.config import SENTRY_ENABLED, SENTRY_SAMPLERATE _BUG = click.style("Ahhhhhhhh! You have found a bug. 🐞\n\n", fg=color.RED, bold=True) @@ -88,6 +87,8 @@ class RenkuExceptionsHandler(click.Group): def main(self, *args, **kwargs): """Catch and print all Renku exceptions.""" + from renku.core.errors import MigrationRequired, ParameterError, ProjectNotSupported, RenkuException, UsageError + try: return super().main(*args, **kwargs) except RenkuException as e: diff --git a/renku/ui/cli/service.py b/renku/ui/cli/service.py index d60fd1b72d..6dd7f7a373 100644 --- a/renku/ui/cli/service.py +++ b/renku/ui/cli/service.py @@ -30,8 +30,6 @@ import renku.ui.cli.utils.color as color from renku.command.echo import ERROR -from renku.core.util.contexts import chdir -from renku.domain_model.tabulate import tabulate RENKU_DAEMON_LOG_FILE = "renku.log" RENKU_DAEMON_ERR_FILE = "renku.err" @@ -253,6 +251,8 @@ def worker_start(queue): @click.pass_context def ps(ctx): """Check status of running services.""" + from renku.domain_model.tabulate import tabulate + processes = list_renku_processes() headers = [{k.upper(): v for k, v in rec.items()} for rec in processes] @@ -273,6 +273,8 @@ def all_start(ctx, daemon, runtime_dir): """Start all service components.""" from circus import get_arbiter + from renku.core.util.contexts import chdir + services = [ { "name": "RenkuCoreService", diff --git a/renku/ui/cli/template.py b/renku/ui/cli/template.py index de59f17234..6a8212621c 100644 --- a/renku/ui/cli/template.py +++ b/renku/ui/cli/template.py @@ -111,13 +111,31 @@ won't work with a different Renku version. To update Renku version you need to use ``renku migrate`` command. + +Validating a template repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are developing your own templates in a template repository, there are +some rules that templates have to follow. To assist in creating your own +templates, you can check that everything is ok with: + +.. code-block:: console + + $ renku template validate + +Running this inside a template repository (not in a Renku project) will +check that the manifest and individual templates are correct and follow +Renku template conventions, printing warnings or errors if something +needs to be changed. """ import functools +import json from typing import TYPE_CHECKING, Any, Dict, List import click +import renku.ui.cli.utils.color as color from renku.ui.cli.init import parse_parameters if TYPE_CHECKING: @@ -238,6 +256,50 @@ def update_template(force, interactive, dry_run): _print_template_change(result.output) +@template.command("validate") +@click.pass_context +@click.option("json_format", "--json", is_flag=True, help="Return result as JSON.") +@click.option( + "-r", + "--reference", + type=click.STRING, + help="Git revision/branch/tag to validate the template at.", +) +@click.option( + "-s", + "--source", + type=click.STRING, + help="Remote template repository to clone and check.", +) +def validate_template(ctx, json_format, reference, source): + """Validate a template repository and check for common issues.""" + from renku.command.template import validate_templates_command + + result = validate_templates_command().build().execute(source=source, reference=reference).output + + if json_format: + click.echo(json.dumps(result)) + else: + if result["warnings"]: + click.secho("Manifest Warnings:", fg="yellow") + for warning in result["warnings"]: + click.secho(f"\t{warning}", fg="yellow") + if result["manifest"]: + click.secho(f"Manifest Errors:\n\t{result['manifest']}", fg="red") + if result["templates"]: + click.secho("Template Errors:", fg="red") + + for template_id, messages in result["templates"].items(): + click.secho(f"\t{template_id}:", fg="red") + + for message in messages: + click.secho(f"\t\t{message}", fg="red") + if result["valid"]: + click.secho("OK", fg=color.GREEN) + if not result["valid"]: + ctx.exit(1) + + def _print_template(template: "TemplateViewModel"): """Print detailed template info.""" from renku.core.util.util import to_string diff --git a/renku/ui/cli/workflow.py b/renku/ui/cli/workflow.py index 70f4b85080..5e354962ca 100644 --- a/renku/ui/cli/workflow.py +++ b/renku/ui/cli/workflow.py @@ -648,6 +648,7 @@ """ +import json import os import shutil import sys @@ -659,7 +660,7 @@ import renku.ui.cli.utils.color as color from renku.command.echo import ERROR -from renku.command.format.workflow import WORKFLOW_COLUMNS, WORKFLOW_FORMATS, json +from renku.command.format.workflow import WORKFLOW_COLUMNS, WORKFLOW_FORMATS from renku.command.view_model.activity_graph import ACTIVITY_GRAPH_COLUMNS from renku.core import errors from renku.ui.cli.utils.callback import ClickCallback diff --git a/renku/version.py b/renku/version.py index 5190e7c179..85785bc77f 100644 --- a/renku/version.py +++ b/renku/version.py @@ -22,7 +22,7 @@ try: from importlib.metadata import distribution except ImportError: - from importlib_metadata import distribution + from importlib_metadata import distribution # type: ignore __version__ = "0.0.0" __template_version__ = "0.3.1" diff --git a/tests/cli/test_save.py b/tests/cli/test_save.py index 022dfa6e24..a4f642a12b 100644 --- a/tests/cli/test_save.py +++ b/tests/cli/test_save.py @@ -45,7 +45,7 @@ def test_save_without_remote(runner, project, client, tmpdir_factory): client.repository.remotes.remove("origin") -def test_save_with_remote(runner, project, client_with_remote, tmpdir_factory): +def test_save_with_remote(runner, project, client_with_remote): """Test saving local changes.""" with (client_with_remote.path / "tracked").open("w") as fp: fp.write("tracked file") @@ -57,7 +57,7 @@ def test_save_with_remote(runner, project, client_with_remote, tmpdir_factory): assert "save changes" in client_with_remote.repository.head.commit.message -def test_save_with_merge_conflict(runner, project, client_with_remote, tmpdir_factory): +def test_save_with_merge_conflict(runner, project, client_with_remote): """Test saving local changes.""" client = client_with_remote with (client.path / "tracked").open("w") as fp: @@ -85,7 +85,7 @@ def test_save_with_merge_conflict(runner, project, client_with_remote, tmpdir_fa assert "save changes" in client.repository.head.commit.message -def test_save_with_staged(runner, project, client_with_remote, tmpdir_factory): +def test_save_with_staged(runner, project, client_with_remote): """Test saving local changes.""" client = client_with_remote diff --git a/tests/cli/test_template.py b/tests/cli/test_template.py index 3e5dfb399c..7e163e4eb2 100644 --- a/tests/cli/test_template.py +++ b/tests/cli/test_template.py @@ -19,12 +19,15 @@ import re import sys +from pathlib import Path import pytest from packaging.version import Version from renku.core.util.contexts import chdir +from renku.core.util.yaml import write_yaml from renku.domain_model.template import TemplateMetadata, TemplateParameter +from renku.infrastructure.repository import Actor, Repository from renku.ui.cli import cli from tests.utils import format_result_exception, write_and_commit_file @@ -61,11 +64,11 @@ def test_template_list_from_source(isolated_runner): assert "python-minimal" in result.output assert "julia-minimal" in result.output - result = isolated_runner.invoke(cli, command + ["-s", TEMPLATES_URL, "--reference", "0.1.10"]) + result = isolated_runner.invoke(cli, command + ["-s", TEMPLATES_URL, "--reference", "0.3.2"]) assert 0 == result.exit_code, format_result_exception(result) assert "python-minimal" in result.output - assert "julia-minimal" not in result.output + assert "julia-minimal" in result.output finally: sys.argv = argv @@ -209,15 +212,15 @@ def test_template_update(runner, client, client_database_injection_manager): """Test updating a template.""" result = runner.invoke( cli, - ["template", "set", "-f", "python-minimal", "-s", TEMPLATES_URL, "-r", "0.1.10"] + ["template", "set", "-f", "python-minimal", "-s", TEMPLATES_URL, "-r", "0.3.2"] + ["-p", "description=fixed-version"], ) assert 0 == result.exit_code, format_result_exception(result) with client_database_injection_manager(client): assert "python-minimal" == client.project.template_id - assert "0.1.10" == client.project.template_ref - assert "6c59d8863841baeca8f30062fd16c650cf67da3b" == client.project.template_version + assert "0.3.2" == client.project.template_ref + assert "b9ab266fba136bdecfa91dc8d7b6d36b9d427012" == client.project.template_version result = runner.invoke(cli, ["template", "update"]) @@ -225,7 +228,7 @@ def test_template_update(runner, client, client_database_injection_manager): assert "Template is up-to-date" not in result.output with client_database_injection_manager(client): assert "python-minimal" == client.project.template_id - assert Version(client.project.template_ref) > Version("0.1.10") + assert Version(client.project.template_ref) > Version("0.3.2") assert "6c59d8863841baeca8f30062fd16c650cf67da3b" != client.project.template_version result = runner.invoke(cli, ["template", "update"]) @@ -260,7 +263,7 @@ def test_template_update_dry_run(runner, client): """Test update dry-run doesn't make any changes.""" result = runner.invoke( cli, - ["template", "set", "-f", "python-minimal", "-s", TEMPLATES_URL, "-r", "0.1.10"] + ["template", "set", "-f", "python-minimal", "-s", TEMPLATES_URL, "-r", "0.3.2"] + ["-p", "description=fixed-version"], ) @@ -337,3 +340,101 @@ def test_template_set_with_parameters( template_metadata = TemplateMetadata.from_client(client=client_with_template) assert "new-parameter" in template_metadata.metadata assert "param-value" == template_metadata.metadata["new-parameter"] + + +def test_template_validate(runner, tmpdir_factory): + """Test template validate command.""" + + path = Path(tmpdir_factory.mktemp("valid")) + valid_repo = Repository().initialize(path) + + readme_path = path / "README.md" + readme_path.write_text("The readme") + valid_repo.add(readme_path) + valid_repo.commit("initial commit", author=Actor("me", "me@example.com")) + + with chdir(path): + result = runner.invoke(cli, ["template", "validate"]) + assert 1 == result.exit_code, format_result_exception(result) + assert "There is no manifest file" in result.output + + manifest = path / "manifest.yaml" + write_yaml( + manifest, + [ + { + "id": "test", + "name": "test", + "description": "description", + "variables": {"some_string": {"description": "somestr desc", "type": "string"}}, + } + ], + ) + + valid_repo.add(manifest) + valid_repo.commit("add manifest", author=Actor("me", "me@example.com")) + + with chdir(path): + result = runner.invoke(cli, ["template", "validate"]) + assert 1 == result.exit_code, format_result_exception(result) + assert "Template directory for 'test' does not exists" in result.output + + template_dir = path / "test" + template_dir.mkdir() + + renku_dir = template_dir / ".renku" + renku_dir.mkdir() + renku_ini = template_dir / ".renku" / "renku.ini" + renku_ini.write_text("a") + + valid_repo.add(renku_ini) + valid_repo.commit("add renku.ini", author=Actor("me", "me@example.com")) + + with chdir(path): + result = runner.invoke(cli, ["template", "validate"]) + assert 1 == result.exit_code, format_result_exception(result) + assert "These paths are required but missing" in result.output + assert "Dockerfile" in result.output + + dockerfile = template_dir / "Dockerfile" + dockerfile.write_text("a") + + valid_repo.add(renku_ini, dockerfile) + valid_commit = valid_repo.commit("add dockerfile", author=Actor("me", "me@example.com")) + + with chdir(path): + result = runner.invoke(cli, ["template", "validate"]) + assert 0 == result.exit_code, format_result_exception(result) + assert "OK\n" == result.output + + metadata_folder = renku_dir / "metadata" + metadata_folder.mkdir() + + project_file = metadata_folder / "project" + project_file.write_text("test") + + valid_repo.add(renku_ini, project_file) + valid_repo.commit("add prohibited file", author=Actor("me", "me@example.com")) + + with chdir(path): + result = runner.invoke(cli, ["template", "validate"]) + assert 1 == result.exit_code, format_result_exception(result) + assert "These paths are not allowed in a template" in result.output + assert ".renku/metadata" in result.output + + with chdir(path): + result = runner.invoke(cli, ["template", "validate", "--reference", valid_commit.hexsha]) + assert 0 == result.exit_code, format_result_exception(result) + assert "OK\n" == result.output + + result = runner.invoke(cli, ["template", "validate", "--json", "--reference", valid_commit.hexsha]) + assert 0 == result.exit_code, format_result_exception(result) + assert '"valid": true' in result.output + + +def test_template_validate_remote(runner, tmpdir_factory): + """Test template validate command on remote repository.""" + result = runner.invoke( + cli, ["template", "validate", "--source", "https://github.com/SwissDataScienceCenter/renku-project-template"] + ) + assert 0 == result.exit_code, format_result_exception(result) diff --git a/tests/core/models/test_template.py b/tests/core/models/test_template.py index 19652d4428..fd40419d1f 100644 --- a/tests/core/models/test_template.py +++ b/tests/core/models/test_template.py @@ -34,6 +34,7 @@ @pytest.fixture() def dummy_source(tmp_path): + """Provide a dummy (renku) source for a template.""" ref = importlib_resources.files("renku") / "templates" with importlib_resources.as_file(ref) as embedded_templates: shutil.copytree(str(embedded_templates), str(tmp_path)) @@ -96,7 +97,7 @@ def test_templates_manifest(): - id: R name: R Project description: An R-based Renku project - parameters: + variables: rate: type: number description: sample rate @@ -150,8 +151,8 @@ def test_templates_manifest_invalid_yaml(tmp_path): ("id: python", "Invalid manifest content type: 'dict'"), ("-\n - id: python", "Invalid template type: 'list'"), ("- no-id: python", "Template doesn't have an id:"), - ("- id: python\n parameters: p1", "Invalid template variable type: 'str'"), - ("- id: python\n parameters:\n p1: 42", "Invalid parameter type 'int' for 'p1'"), + ("- id: python\n variables: p1", "Invalid template variable type on template 'python': 'str'"), + ("- id: python\n variables:\n p1: 42", "Invalid parameter type 'int' for 'p1'"), ], ) def test_templates_manifest_invalid_content(tmp_path, content, message): @@ -160,6 +161,19 @@ def test_templates_manifest_invalid_content(tmp_path, content, message): TemplatesManifest.from_string(content) +def test_templates_manifest_warnings(tmp_path): + """Test creating a template manifest form invalid content.""" + content = "- folder: python\n name: python\n variables:\n p1: My parameter" + manifest = TemplatesManifest.from_string(content, skip_validation=True) + warnings = manifest.validate() + + assert "Template 'python' should use 'id' attribute instead of 'folder'." in warnings + assert ( + "Template 'python' variable 'p1' uses old string format in manifest and should be replaced" + " with the nested dictionary format." + ) in warnings + + @pytest.mark.parametrize("default, has_default", [(None, False), (42, True), ("", True), (False, True)]) def test_template_parameter_default_value(default, has_default): """Test parameter has not default only if default is None."""