From 7f1ea7e827bcce9ff17948d30d582dea8c972d9c Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Thu, 19 Mar 2026 09:52:53 -0700 Subject: [PATCH 1/5] fix for unknown actor (#256) --- microservices/gatewayApi/clients/portal.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/microservices/gatewayApi/clients/portal.py b/microservices/gatewayApi/clients/portal.py index e9ee7e19..a3ef9414 100644 --- a/microservices/gatewayApi/clients/portal.py +++ b/microservices/gatewayApi/clients/portal.py @@ -40,10 +40,13 @@ def record_gateway_event(event_id, action, result, namespace, message="", blob=" entity = 'gateway configuration' actor = "Unknown Actor" - if 'principal' in g and "clientId" in g.principal: - actor = g.principal["clientId"] - if 'principal' in g and "name" in g.principal: - actor = g.principal["name"] + if 'principal' in g: + if "name" in g.principal: + actor = g.principal["name"] + elif "client_id" in g.principal: + actor = g.principal["client_id"] + elif "azp" in g.principal: + actor = g.principal["azp"] payload = { 'id': event_id, From 5618ef78e582af84f8b32b29ef0d8db94db6143d Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Wed, 25 Mar 2026 14:15:42 -0700 Subject: [PATCH 2/5] APS-3966 Assign SDX Edge Server to Gateway (#241) Co-authored-by: James Elson --- .github/workflows/dev.yml | 10 +- microservices/gatewayApi/Dockerfile | 11 +- microservices/gatewayApi/config/test.json | 3 +- microservices/gatewayApi/poetry.lock | 1438 +++++++++-------- microservices/gatewayApi/pyproject.toml | 13 +- microservices/gatewayApi/tests/conftest.py | 9 + .../routes/v2/test_gateway_err_validations.py | 37 + .../gatewayApi/tests/routes/v2/test_sdx.py | 39 + microservices/gatewayApi/utils/deck.py | 16 +- microservices/gatewayApi/v2/routes/gateway.py | 55 +- .../gatewayApi/v2/routes/gw_status.py | 10 +- .../gatewayApi/v2/routes/namespaces.py | 13 +- 12 files changed, 933 insertions(+), 721 deletions(-) create mode 100644 microservices/gatewayApi/tests/routes/v2/test_sdx.py diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 561c2006..bd50fe2b 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -23,7 +23,7 @@ jobs: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 2 - uses: actions/setup-python@v5 with: python-version: "3.11" @@ -100,7 +100,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 2 - name: Check if build needed id: check run: | @@ -145,7 +145,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 2 - name: Check if build needed id: check run: | @@ -190,7 +190,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 2 - name: Check if build needed id: check run: | @@ -235,7 +235,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 2 - name: Check if build needed id: check run: | diff --git a/microservices/gatewayApi/Dockerfile b/microservices/gatewayApi/Dockerfile index 70a3df6a..bf48f3f9 100644 --- a/microservices/gatewayApi/Dockerfile +++ b/microservices/gatewayApi/Dockerfile @@ -5,7 +5,7 @@ # && go mod download \ # && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o deck \ # -ldflags "-s -w -X github.com/kong/deck/cmd.VERSION=$TAG -X github.com/kong/deck/cmd.COMMIT=$COMMIT" -FROM python:3.11-alpine3.20 +FROM python:3.13-alpine3.22 RUN mkdir /.kube @@ -26,17 +26,16 @@ RUN curl -sL https://github.com/kong/deck/releases/download/v1.5.0/deck_1.5.0_li cp /tmp/deck /usr/local/bin/deck_kong2_150 # gwa api (kong 3) -RUN curl -sL https://github.com/Kong/deck/releases/download/v1.45.0/deck_1.45.0_linux_amd64.tar.gz -o deck.tar.gz && \ +RUN curl -sL https://github.com/Kong/deck/releases/download/v1.53.1/deck_1.53.1_linux_amd64.tar.gz -o deck.tar.gz && \ tar -xf deck.tar.gz -C /tmp && \ cp /tmp/deck /usr/local/bin/deck && \ - cp /tmp/deck /usr/local/bin/deck_kong3_1450 + cp /tmp/deck /usr/local/bin/deck_kong3_1531 RUN python -m pip install --upgrade pip -# FIX: No module named 'urllib3.packages.six' -RUN pip uninstall urllib3 && pip install urllib3 + RUN cd /tmp && \ curl -sSL https://install.python-poetry.org > get-poetry.py && \ - POETRY_HOME=/opt/poetry python get-poetry.py --version 1.8.2 && \ + POETRY_HOME=/opt/poetry python get-poetry.py --version 1.8.5 && \ cd /usr/local/bin && \ ln -s /opt/poetry/bin/poetry && \ poetry config virtualenvs.create false diff --git a/microservices/gatewayApi/config/test.json b/microservices/gatewayApi/config/test.json index 53e5c4f9..bb31eff5 100644 --- a/microservices/gatewayApi/config/test.json +++ b/microservices/gatewayApi/config/test.json @@ -24,7 +24,8 @@ "kube-api": "http://kube-api", "kube-ns": "abcd-1234", "validate-upstreams": true - } + }, + "sdx-edge": {} }, "kubeApiCreds": { "kubeApiPass": "password", diff --git a/microservices/gatewayApi/poetry.lock b/microservices/gatewayApi/poetry.lock index ec2444cb..a43aaa1e 100644 --- a/microservices/gatewayApi/poetry.lock +++ b/microservices/gatewayApi/poetry.lock @@ -1,35 +1,32 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "anyio" -version = "4.11.0" +version = "4.12.1" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ - {file = "anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc"}, - {file = "anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4"}, + {file = "anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c"}, + {file = "anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703"}, ] [package.dependencies] idna = ">=2.8" -sniffio = ">=1.1" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -trio = ["trio (>=0.31.0)"] +trio = ["trio (>=0.31.0)", "trio (>=0.32.0)"] [[package]] name = "astroid" -version = "3.3.5" +version = "4.1.1" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.9.0" -groups = ["dev"] +python-versions = ">=3.10.0" files = [ - {file = "astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8"}, - {file = "astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d"}, + {file = "astroid-4.1.1-py3-none-any.whl", hash = "sha256:6b28522096f7e7a36ffcf3be60e77de15e2411ab3a713184beac33fb8f20c0c9"}, + {file = "astroid-4.1.1.tar.gz", hash = "sha256:445d831fe785df8c670bbb46b900b8424b82f85b4af187103f71a63a63ebed43"}, ] [[package]] @@ -38,7 +35,6 @@ version = "0.2.2" description = "Python decorator for async properties." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "async_property-0.2.2-py2.py3-none-any.whl", hash = "sha256:8924d792b5843994537f8ed411165700b27b2bd966cefc4daeefc1253442a9d7"}, {file = "async_property-0.2.2.tar.gz", hash = "sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380"}, @@ -50,7 +46,6 @@ version = "0.15.3" description = "The ultimate Python library in building OAuth and OpenID Connect servers." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "Authlib-0.15.3-py2.py3-none-any.whl", hash = "sha256:0f6af3a38d37dd77361808dd3f2e258b647668dac6d2cefcefc4c4ebc3c7d2b2"}, {file = "Authlib-0.15.3.tar.gz", hash = "sha256:7dde11ba45db51e97169c261362fab3193073100b7387e60c159db1eec470bbc"}, @@ -68,7 +63,6 @@ version = "1.7.0" description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "autopep8-1.7.0-py2.py3-none-any.whl", hash = "sha256:6f09e90a2be784317e84dc1add17ebfc7abe3924239957a37e5040e27d812087"}, {file = "autopep8-1.7.0.tar.gz", hash = "sha256:ca9b1a83e53a7fad65d731dc7a2a2d50aa48f43850407c59f6a1a306c4201142"}, @@ -78,223 +72,309 @@ files = [ pycodestyle = ">=2.9.1" toml = "*" +[[package]] +name = "blinker" +version = "1.9.0" +description = "Fast, simple object-to-object and broadcast signaling" +optional = false +python-versions = ">=3.9" +files = [ + {file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"}, + {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, +] + +[[package]] +name = "boto3" +version = "1.42.69" +description = "The AWS SDK for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "boto3-1.42.69-py3-none-any.whl", hash = "sha256:6823a4b59aa578c7d98124280a9b6d83cea04bdb02525cbaa79370e5b6f7f631"}, + {file = "boto3-1.42.69.tar.gz", hash = "sha256:e59846f4ff467b23bae4751948298db554dbdda0d72b09028d2cacbeff27e1ad"}, +] + +[package.dependencies] +botocore = ">=1.42.69,<1.43.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.16.0,<0.17.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.42.69" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">=3.9" +files = [ + {file = "botocore-1.42.69-py3-none-any.whl", hash = "sha256:ef0e3d860a5d7bffc0ccb4911781c4c27d538557ed9a616ba1926c762d72e5f6"}, + {file = "botocore-1.42.69.tar.gz", hash = "sha256:0934f2d90403c5c8c2cba83e754a39d77edcad5885d04a79363edff3e814f55e"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} + +[package.extras] +crt = ["awscrt (==0.31.2)"] + [[package]] name = "certifi" -version = "2024.8.30" +version = "2026.2.25" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" -groups = ["main"] +python-versions = ">=3.7" files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, + {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, + {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, ] [[package]] name = "cffi" -version = "1.17.1" +version = "2.0.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, + {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, + {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, + {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, + {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, + {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, + {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, + {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, + {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, + {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, + {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, + {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, + {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, + {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, + {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, + {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, + {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, + {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, + {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, + {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, + {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, + {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, + {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] [package.dependencies] -pycparser = "*" +pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} [[package]] name = "charset-normalizer" -version = "3.4.0" +version = "3.4.6" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.7.0" -groups = ["main"] +python-versions = ">=3.7" files = [ - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, - {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, - {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-win32.whl", hash = "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-win_amd64.whl", hash = "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6"}, + {file = "charset_normalizer-3.4.6-cp310-cp310-win_arm64.whl", hash = "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bc72863f4d9aba2e8fd9085e63548a324ba706d2ea2c83b260da08a59b9482de"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:0c173ce3a681f309f31b87125fecec7a5d1347261ea11ebbb856fa6006b23c8c"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c907cdc8109f6c619e6254212e794d6548373cc40e1ec75e6e3823d9135d29cc"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:404a1e552cf5b675a87f0651f8b79f5f1e6fd100ee88dc612f89aa16abd4486f"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e3c701e954abf6fc03a49f7c579cc80c2c6cc52525340ca3186c41d3f33482ef"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7a6967aaf043bceabab5412ed6bd6bd26603dae84d5cb75bf8d9a74a4959d398"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5feb91325bbceade6afab43eb3b508c63ee53579fe896c77137ded51c6b6958e"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f820f24b09e3e779fe84c3c456cb4108a7aa639b0d1f02c28046e11bfcd088ed"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b35b200d6a71b9839a46b9b7fff66b6638bb52fc9658aa58796b0326595d3021"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-win32.whl", hash = "sha256:9ca4c0b502ab399ef89248a2c84c54954f77a070f28e546a85e91da627d1301e"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4"}, + {file = "charset_normalizer-3.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:97d0235baafca5f2b09cf332cc275f021e694e8362c6bb9c96fc9a0eb74fc316"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ef7fedc7a6ecbe99969cd09632516738a97eeb8bd7258bf8a0f23114c057dab"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4ea868bc28109052790eb2b52a9ab33f3aa7adc02f96673526ff47419490e21"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:836ab36280f21fc1a03c99cd05c6b7af70d2697e374c7af0b61ed271401a72a2"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f1ce721c8a7dfec21fcbdfe04e8f68174183cf4e8188e0645e92aa23985c57ff"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e28d62a8fc7a1fa411c43bd65e346f3bce9716dc51b897fbe930c5987b402d5"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:530d548084c4a9f7a16ed4a294d459b4f229db50df689bfe92027452452943a0"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30f445ae60aad5e1f8bdbb3108e39f6fbc09f4ea16c815c66578878325f8f15a"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ac2393c73378fea4e52aa56285a3d64be50f1a12395afef9cce47772f60334c2"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:90ca27cd8da8118b18a52d5f547859cc1f8354a00cd1e8e5120df3e30d6279e5"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e5a94886bedca0f9b78fecd6afb6629142fd2605aa70a125d49f4edc6037ee6"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:695f5c2823691a25f17bc5d5ffe79fa90972cc34b002ac6c843bb8a1720e950d"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:231d4da14bcd9301310faf492051bee27df11f2bc7549bc0bb41fef11b82daa2"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a056d1ad2633548ca18ffa2f85c202cfb48b68615129143915b8dc72a806a923"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-win32.whl", hash = "sha256:c2274ca724536f173122f36c98ce188fd24ce3dad886ec2b7af859518ce008a4"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:c8ae56368f8cc97c7e40a7ee18e1cedaf8e780cd8bc5ed5ac8b81f238614facb"}, + {file = "charset_normalizer-3.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:899d28f422116b08be5118ef350c292b36fc15ec2daeb9ea987c89281c7bb5c4"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:423fb7e748a08f854a08a222b983f4df1912b1daedce51a72bd24fe8f26a1843"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d73beaac5e90173ac3deb9928a74763a6d230f494e4bfb422c217a0ad8e629bf"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d60377dce4511655582e300dc1e5a5f24ba0cb229005a1d5c8d0cb72bb758ab8"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:a26611d9987b230566f24a0a125f17fe0de6a6aff9f25c9f564aaa2721a5fb88"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:34315ff4fc374b285ad7f4a0bf7dcbfe769e1b104230d40f49f700d4ab6bbd84"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ddd609f9e1af8c7bd6e2aca279c931aefecd148a14402d4e368f3171769fd"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:80d0a5615143c0b3225e5e3ef22c8d5d51f3f72ce0ea6fb84c943546c7b25b6c"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:92734d4d8d187a354a556626c221cd1a892a4e0802ccb2af432a1d85ec012194"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:613f19aa6e082cf96e17e3ffd89383343d0d589abda756b7764cf78361fd41dc"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2b1a63e8224e401cafe7739f77efd3f9e7f5f2026bda4aead8e59afab537784f"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cceb5473417d28edd20c6c984ab6fee6c6267d38d906823ebfe20b03d607dc2"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-win32.whl", hash = "sha256:d7de2637729c67d67cf87614b566626057e95c303bc0a55ffe391f5205e7003d"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389"}, + {file = "charset_normalizer-3.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a4474d924a47185a06411e0064b803c68be044be2d60e50e8bddcc2649957c1f"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:9cc6e6d9e571d2f863fa77700701dae73ed5f78881efc8b3f9a4398772ff53e8"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef5960d965e67165d75b7c7ffc60a83ec5abfc5c11b764ec13ea54fbef8b4421"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b3694e3f87f8ac7ce279d4355645b3c878d24d1424581b46282f24b92f5a4ae2"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5d11595abf8dd942a77883a39d81433739b287b6aa71620f15164f8096221b30"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7bda6eebafd42133efdca535b04ccb338ab29467b3f7bf79569883676fc628db"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:bbc8c8650c6e51041ad1be191742b8b421d05bbd3410f43fa2a00c8db87678e8"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:22c6f0c2fbc31e76c3b8a86fba1a56eda6166e238c29cdd3d14befdb4a4e4815"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7edbed096e4a4798710ed6bc75dcaa2a21b68b6c356553ac4823c3658d53743a"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:7f9019c9cb613f084481bd6a100b12e1547cf2efe362d873c2e31e4035a6fa43"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:58c948d0d086229efc484fe2f30c2d382c86720f55cd9bc33591774348ad44e0"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:419a9d91bd238052642a51938af8ac05da5b3343becde08d5cdeab9046df9ee1"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5273b9f0b5835ff0350c0828faea623c68bfa65b792720c453e22b25cc72930f"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0e901eb1049fdb80f5bd11ed5ea1e498ec423102f7a9b9e4645d5b8204ff2815"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-win32.whl", hash = "sha256:b4ff1d35e8c5bd078be89349b6f3a845128e685e751b6ea1169cf2160b344c4d"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:74119174722c4349af9708993118581686f343adc1c8c9c007d59be90d077f3f"}, + {file = "charset_normalizer-3.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:e5bcc1a1ae744e0bb59641171ae53743760130600da8db48cbb6e4918e186e4e"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ad8faf8df23f0378c6d527d8b0b15ea4a2e23c89376877c598c4870d1b2c7866"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5ea69428fa1b49573eef0cc44a1d43bebd45ad0c611eb7d7eac760c7ae771bc"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:06a7e86163334edfc5d20fe104db92fcd666e5a5df0977cb5680a506fe26cc8e"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e1f6e2f00a6b8edb562826e4632e26d063ac10307e80f7461f7de3ad8ef3f077"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b52c68d64c1878818687a473a10547b3292e82b6f6fe483808fb1468e2f52f"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:7504e9b7dc05f99a9bbb4525c67a2c155073b44d720470a148b34166a69c054e"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:172985e4ff804a7ad08eebec0a1640ece87ba5041d565fff23c8f99c1f389484"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4be9f4830ba8741527693848403e2c457c16e499100963ec711b1c6f2049b7c7"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:79090741d842f564b1b2827c0b82d846405b744d31e84f18d7a7b41c20e473ff"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:87725cfb1a4f1f8c2fc9890ae2f42094120f4b44db9360be5d99a4c6b0e03a9e"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fcce033e4021347d80ed9c66dcf1e7b1546319834b74445f561d2e2221de5659"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ca0276464d148c72defa8bb4390cce01b4a0e425f3b50d1435aa6d7a18107602"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:197c1a244a274bb016dd8b79204850144ef77fe81c5b797dc389327adb552407"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-win32.whl", hash = "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4"}, + {file = "charset_normalizer-3.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:659a1e1b500fac8f2779dd9e1570464e012f43e580371470b45277a27baa7532"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f61aa92e4aad0be58eb6eb4e0c21acf32cf8065f4b2cae5665da756c4ceef982"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f50498891691e0864dc3da965f340fada0771f6142a378083dc4608f4ea513e2"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf625105bb9eef28a56a943fec8c8a98aeb80e7d7db99bd3c388137e6eb2d237"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2bd9d128ef93637a5d7a6af25363cf5dec3fa21cf80e68055aad627f280e8afa"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:d08ec48f0a1c48d75d0356cea971921848fb620fdeba805b28f937e90691209f"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ed80ff870ca6de33f4d953fda4d55654b9a2b340ff39ab32fa3adbcd718f264"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f98059e4fcd3e3e4e2d632b7cf81c2faae96c43c60b569e9c621468082f1d104"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:ab30e5e3e706e3063bc6de96b118688cb10396b70bb9864a430f67df98c61ecc"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:d5f5d1e9def3405f60e3ca8232d56f35c98fb7bf581efcc60051ebf53cb8b611"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:461598cd852bfa5a61b09cae2b1c02e2efcd166ee5516e243d540ac24bfa68a7"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:71be7e0e01753a89cf024abf7ecb6bca2c81738ead80d43004d9b5e3f1244e64"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:df01808ee470038c3f8dc4f48620df7225c49c2d6639e38f96e6d6ac6e6f7b0e"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-win32.whl", hash = "sha256:69dd852c2f0ad631b8b60cfbe25a28c0058a894de5abb566619c205ce0550eae"}, + {file = "charset_normalizer-3.4.6-cp38-cp38-win_amd64.whl", hash = "sha256:517ad0e93394ac532745129ceabdf2696b609ec9f87863d337140317ebce1c14"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-win32.whl", hash = "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-win_amd64.whl", hash = "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8"}, + {file = "charset_normalizer-3.4.6-cp39-cp39-win_arm64.whl", hash = "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8"}, + {file = "charset_normalizer-3.4.6-py3-none-any.whl", hash = "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69"}, + {file = "charset_normalizer-3.4.6.tar.gz", hash = "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6"}, ] [[package]] name = "click" -version = "8.1.7" +version = "8.3.1" description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.7" -groups = ["main"] +python-versions = ">=3.10" files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [package.dependencies] @@ -306,87 +386,128 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} [[package]] name = "coverage" -version = "7.6.3" +version = "7.13.5" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.9" -groups = ["dev"] +python-versions = ">=3.10" files = [ - {file = "coverage-7.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6da42bbcec130b188169107ecb6ee7bd7b4c849d24c9370a0c884cf728d8e976"}, - {file = "coverage-7.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c222958f59b0ae091f4535851cbb24eb57fc0baea07ba675af718fb5302dddb2"}, - {file = "coverage-7.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab84a8b698ad5a6c365b08061920138e7a7dd9a04b6feb09ba1bfae68346ce6d"}, - {file = "coverage-7.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70a6756ce66cd6fe8486c775b30889f0dc4cb20c157aa8c35b45fd7868255c5c"}, - {file = "coverage-7.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c2e6fa98032fec8282f6b27e3f3986c6e05702828380618776ad794e938f53a"}, - {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:921fbe13492caf6a69528f09d5d7c7d518c8d0e7b9f6701b7719715f29a71e6e"}, - {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6d99198203f0b9cb0b5d1c0393859555bc26b548223a769baf7e321a627ed4fc"}, - {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:87cd2e29067ea397a47e352efb13f976eb1b03e18c999270bb50589323294c6e"}, - {file = "coverage-7.6.3-cp310-cp310-win32.whl", hash = "sha256:a3328c3e64ea4ab12b85999eb0779e6139295bbf5485f69d42cf794309e3d007"}, - {file = "coverage-7.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:bca4c8abc50d38f9773c1ec80d43f3768df2e8576807d1656016b9d3eeaa96fd"}, - {file = "coverage-7.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c51ef82302386d686feea1c44dbeef744585da16fcf97deea2a8d6c1556f519b"}, - {file = "coverage-7.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0ca37993206402c6c35dc717f90d4c8f53568a8b80f0bf1a1b2b334f4d488fba"}, - {file = "coverage-7.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c77326300b839c44c3e5a8fe26c15b7e87b2f32dfd2fc9fee1d13604347c9b38"}, - {file = "coverage-7.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e484e479860e00da1f005cd19d1c5d4a813324e5951319ac3f3eefb497cc549"}, - {file = "coverage-7.6.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c6c0f4d53ef603397fc894a895b960ecd7d44c727df42a8d500031716d4e8d2"}, - {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:37be7b5ea3ff5b7c4a9db16074dc94523b5f10dd1f3b362a827af66a55198175"}, - {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:43b32a06c47539fe275106b376658638b418c7cfdfff0e0259fbf877e845f14b"}, - {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ee77c7bef0724165e795b6b7bf9c4c22a9b8468a6bdb9c6b4281293c6b22a90f"}, - {file = "coverage-7.6.3-cp311-cp311-win32.whl", hash = "sha256:43517e1f6b19f610a93d8227e47790722c8bf7422e46b365e0469fc3d3563d97"}, - {file = "coverage-7.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:04f2189716e85ec9192df307f7c255f90e78b6e9863a03223c3b998d24a3c6c6"}, - {file = "coverage-7.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27bd5f18d8f2879e45724b0ce74f61811639a846ff0e5c0395b7818fae87aec6"}, - {file = "coverage-7.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d546cfa78844b8b9c1c0533de1851569a13f87449897bbc95d698d1d3cb2a30f"}, - {file = "coverage-7.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9975442f2e7a5cfcf87299c26b5a45266ab0696348420049b9b94b2ad3d40234"}, - {file = "coverage-7.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:583049c63106c0555e3ae3931edab5669668bbef84c15861421b94e121878d3f"}, - {file = "coverage-7.6.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2341a78ae3a5ed454d524206a3fcb3cec408c2a0c7c2752cd78b606a2ff15af4"}, - {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a4fb91d5f72b7e06a14ff4ae5be625a81cd7e5f869d7a54578fc271d08d58ae3"}, - {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e279f3db904e3b55f520f11f983cc8dc8a4ce9b65f11692d4718ed021ec58b83"}, - {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aa23ce39661a3e90eea5f99ec59b763b7d655c2cada10729ed920a38bfc2b167"}, - {file = "coverage-7.6.3-cp312-cp312-win32.whl", hash = "sha256:52ac29cc72ee7e25ace7807249638f94c9b6a862c56b1df015d2b2e388e51dbd"}, - {file = "coverage-7.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:40e8b1983080439d4802d80b951f4a93d991ef3261f69e81095a66f86cf3c3c6"}, - {file = "coverage-7.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9134032f5aa445ae591c2ba6991d10136a1f533b1d2fa8f8c21126468c5025c6"}, - {file = "coverage-7.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:99670790f21a96665a35849990b1df447993880bb6463a0a1d757897f30da929"}, - {file = "coverage-7.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc7d6b380ca76f5e817ac9eef0c3686e7834c8346bef30b041a4ad286449990"}, - {file = "coverage-7.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7b26757b22faf88fcf232f5f0e62f6e0fd9e22a8a5d0d5016888cdfe1f6c1c4"}, - {file = "coverage-7.6.3-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c59d6a4a4633fad297f943c03d0d2569867bd5372eb5684befdff8df8522e39"}, - {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f263b18692f8ed52c8de7f40a0751e79015983dbd77b16906e5b310a39d3ca21"}, - {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79644f68a6ff23b251cae1c82b01a0b51bc40c8468ca9585c6c4b1aeee570e0b"}, - {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:71967c35828c9ff94e8c7d405469a1fb68257f686bca7c1ed85ed34e7c2529c4"}, - {file = "coverage-7.6.3-cp313-cp313-win32.whl", hash = "sha256:e266af4da2c1a4cbc6135a570c64577fd3e6eb204607eaff99d8e9b710003c6f"}, - {file = "coverage-7.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:ea52bd218d4ba260399a8ae4bb6b577d82adfc4518b93566ce1fddd4a49d1dce"}, - {file = "coverage-7.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8d4c6ea0f498c7c79111033a290d060c517853a7bcb2f46516f591dab628ddd3"}, - {file = "coverage-7.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:331b200ad03dbaa44151d74daeb7da2cf382db424ab923574f6ecca7d3b30de3"}, - {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54356a76b67cf8a3085818026bb556545ebb8353951923b88292556dfa9f812d"}, - {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebec65f5068e7df2d49466aab9128510c4867e532e07cb6960075b27658dca38"}, - {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33a785ea8354c480515e781554d3be582a86297e41ccbea627a5c632647f2cd"}, - {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f7ddb920106bbbbcaf2a274d56f46956bf56ecbde210d88061824a95bdd94e92"}, - {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:70d24936ca6c15a3bbc91ee9c7fc661132c6f4c9d42a23b31b6686c05073bde5"}, - {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c30e42ea11badb147f0d2e387115b15e2bd8205a5ad70d6ad79cf37f6ac08c91"}, - {file = "coverage-7.6.3-cp313-cp313t-win32.whl", hash = "sha256:365defc257c687ce3e7d275f39738dcd230777424117a6c76043459db131dd43"}, - {file = "coverage-7.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:23bb63ae3f4c645d2d82fa22697364b0046fbafb6261b258a58587441c5f7bd0"}, - {file = "coverage-7.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:da29ceabe3025a1e5a5aeeb331c5b1af686daab4ff0fb4f83df18b1180ea83e2"}, - {file = "coverage-7.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df8c05a0f574d480947cba11b947dc41b1265d721c3777881da2fb8d3a1ddfba"}, - {file = "coverage-7.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec1e3b40b82236d100d259854840555469fad4db64f669ab817279eb95cd535c"}, - {file = "coverage-7.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4adeb878a374126f1e5cf03b87f66279f479e01af0e9a654cf6d1509af46c40"}, - {file = "coverage-7.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43d6a66e33b1455b98fc7312b124296dad97a2e191c80320587234a77b1b736e"}, - {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1990b1f4e2c402beb317840030bb9f1b6a363f86e14e21b4212e618acdfce7f6"}, - {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:12f9515d875859faedb4144fd38694a761cd2a61ef9603bf887b13956d0bbfbb"}, - {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99ded130555c021d99729fabd4ddb91a6f4cc0707df4b1daf912c7850c373b13"}, - {file = "coverage-7.6.3-cp39-cp39-win32.whl", hash = "sha256:c3a79f56dee9136084cf84a6c7c4341427ef36e05ae6415bf7d787c96ff5eaa3"}, - {file = "coverage-7.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:aac7501ae73d4a02f4b7ac8fcb9dc55342ca98ffb9ed9f2dfb8a25d53eda0e4d"}, - {file = "coverage-7.6.3-pp39.pp310-none-any.whl", hash = "sha256:b9853509b4bf57ba7b1f99b9d866c422c9c5248799ab20e652bbb8a184a38181"}, - {file = "coverage-7.6.3.tar.gz", hash = "sha256:bb7d5fe92bd0dc235f63ebe9f8c6e0884f7360f88f3411bfed1350c872ef2054"}, + {file = "coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5"}, + {file = "coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0"}, + {file = "coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58"}, + {file = "coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8"}, + {file = "coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf"}, + {file = "coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9"}, + {file = "coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c"}, + {file = "coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf"}, + {file = "coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810"}, + {file = "coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17"}, + {file = "coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85"}, + {file = "coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b"}, + {file = "coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2"}, + {file = "coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a"}, + {file = "coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819"}, + {file = "coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0"}, + {file = "coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc"}, + {file = "coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633"}, + {file = "coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a"}, + {file = "coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215"}, + {file = "coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43"}, + {file = "coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45"}, + {file = "coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61"}, + {file = "coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179"}, ] [package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] +toml = ["tomli"] [[package]] name = "cryptography" @@ -394,7 +515,6 @@ version = "38.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70"}, {file = "cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb"}, @@ -441,7 +561,6 @@ version = "2.1.0" description = "A library to handle automated deprecations" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, @@ -452,21 +571,21 @@ packaging = "*" [[package]] name = "flask" -version = "2.1.3" +version = "2.3.3" description = "A simple framework for building complex web applications." optional = false -python-versions = ">=3.7" -groups = ["main"] +python-versions = ">=3.8" files = [ - {file = "Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"}, - {file = "Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb"}, + {file = "flask-2.3.3-py3-none-any.whl", hash = "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"}, + {file = "flask-2.3.3.tar.gz", hash = "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc"}, ] [package.dependencies] -click = ">=8.0" -itsdangerous = ">=2.0" -Jinja2 = ">=3.0" -Werkzeug = ">=2.0" +blinker = ">=1.6.2" +click = ">=8.1.3" +itsdangerous = ">=2.1.2" +Jinja2 = ">=3.1.2" +Werkzeug = ">=2.3.7" [package.extras] async = ["asgiref (>=3.2)"] @@ -478,7 +597,6 @@ version = "1.4.0" description = "Compress responses in your Flask app with gzip." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "Flask-Compress-1.4.0.tar.gz", hash = "sha256:468693f4ddd11ac6a41bca4eb5f94b071b763256d54136f77957cfee635badb3"}, ] @@ -492,7 +610,6 @@ version = "3.0.9" description = "A Flask extension adding a decorator for CORS support" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "Flask-Cors-3.0.9.tar.gz", hash = "sha256:6bcfc100288c5d1bcb1dbb854babd59beee622ffd321e444b05f24d6d58466b8"}, {file = "Flask_Cors-3.0.9-py2.py3-none-any.whl", hash = "sha256:cee4480aaee421ed029eaa788f4049e3e26d15b5affb6a880dade6bafad38324"}, @@ -508,7 +625,6 @@ version = "0.0.3" description = "Simple JWT integration with Flask" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "Flask-JWT-Simple-0.0.3.tar.gz", hash = "sha256:7ebc7a07005056f71e41ac323ff4ebac5e02356c9619e385ecd419084274b268"}, ] @@ -526,7 +642,6 @@ version = "3.36.0" description = "Swagger UI blueprint for Flask" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "flask-swagger-ui-3.36.0.tar.gz", hash = "sha256:f329752a65b2940ada8eeb57bce613f7c0a12856a9c31063bb9e33798554c9ed"}, ] @@ -536,188 +651,156 @@ flask = "*" [[package]] name = "gevent" -version = "22.10.2" +version = "25.9.1" description = "Coroutine-based network library" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "gevent-22.10.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:97cd42382421779f5d82ec5007199e8a84aa288114975429e4fd0a98f2290f10"}, - {file = "gevent-22.10.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:1e1286a76f15b5e15f1e898731d50529e249529095a032453f2c101af3fde71c"}, - {file = "gevent-22.10.2-cp27-cp27m-win32.whl", hash = "sha256:59b47e81b399d49a5622f0f503c59f1ce57b7705306ea0196818951dfc2f36c8"}, - {file = "gevent-22.10.2-cp27-cp27m-win_amd64.whl", hash = "sha256:1d543c9407a1e4bca11a8932916988cfb16de00366de5bf7bc9e7a3f61e60b18"}, - {file = "gevent-22.10.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4e2f008c82dc54ec94f4de12ca6feea60e419babb48ec145456907ae61625aa4"}, - {file = "gevent-22.10.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:990d7069f14dc40674e0d5cb43c68fd3bad8337048613b9bb94a0c4180ffc176"}, - {file = "gevent-22.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f23d0997149a816a2a9045af29c66f67f405a221745b34cefeac5769ed451db8"}, - {file = "gevent-22.10.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b43d500d7d3c0e03070dee813335bb5315215aa1cf6a04c61093dfdd718640b3"}, - {file = "gevent-22.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b68f4c9e20e47ad49fe797f37f91d5bbeace8765ce2707f979a8d4ec197e4d"}, - {file = "gevent-22.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1f001cac0ba8da76abfeb392a3057f81fab3d67cc916c7df8ea977a44a2cc989"}, - {file = "gevent-22.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:3b7eae8a0653ba95a224faaddf629a913ace408edb67384d3117acf42d7dcf89"}, - {file = "gevent-22.10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8f2477e7b0a903a01485c55bacf2089110e5f767014967ba4b287ff390ae2638"}, - {file = "gevent-22.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddaa3e310a8f1a45b5c42cf50b54c31003a3028e7d4e085059090ea0e7a5fddd"}, - {file = "gevent-22.10.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98bc510e80f45486ef5b806a1c305e0e89f0430688c14984b0dbdec03331f48b"}, - {file = "gevent-22.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:877abdb3a669576b1d51ce6a49b7260b2a96f6b2424eb93287e779a3219d20ba"}, - {file = "gevent-22.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d21ad79cca234cdbfa249e727500b0ddcbc7adfff6614a96e6eaa49faca3e4f2"}, - {file = "gevent-22.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e955238f59b2947631c9782a713280dd75884e40e455313b5b6bbc20b92ff73"}, - {file = "gevent-22.10.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5aa99e4882a9e909b4756ee799c6fa0f79eb0542779fad4cc60efa23ec1b2aa8"}, - {file = "gevent-22.10.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d82081656a5b9a94d37c718c8646c757e1617e389cdc533ea5e6a6f0b8b78545"}, - {file = "gevent-22.10.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f4bfd74c178351a4a05c5c7df6f8a0a279ff6f392b57608ce0e83c768207f9"}, - {file = "gevent-22.10.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ff3796692dff50fec2f381b9152438b221335f557c4f9b811f7ded51b7a25a1"}, - {file = "gevent-22.10.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f01c9adbcb605364694b11dcd0542ec468a29ac7aba2fb5665dc6caf17ba4d7e"}, - {file = "gevent-22.10.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9d85574eb729f981fea9a78998725a06292d90a3ed50ddca74530c3148c0be41"}, - {file = "gevent-22.10.2-cp36-cp36m-win32.whl", hash = "sha256:8c192d2073e558e241f0b592c1e2b34127a4481a5be240cad4796533b88b1a98"}, - {file = "gevent-22.10.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a2237451c721a0f874ef89dbb4af4fdc172b76a964befaa69deb15b8fff10f49"}, - {file = "gevent-22.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:53ee7f170ed42c7561fe8aff5d381dc9a4124694e70580d0c02fba6aafc0ea37"}, - {file = "gevent-22.10.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:96c56c280e3c43cfd075efd10b250350ed5ffd3c1514ec99a080b1b92d7c8374"}, - {file = "gevent-22.10.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6c144e08dfad4106effc043a026e5d0c0eff6ad031904c70bf5090c63f3a6a7"}, - {file = "gevent-22.10.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:018f93de7d5318d2fb440f846839a4464738468c3476d5c9cf7da45bb71c18bd"}, - {file = "gevent-22.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ed2346eb9dc4344f9cb0d7963ce5b74fe16fdd031a2809bb6c2b6eba7ebcd5"}, - {file = "gevent-22.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84c517e33ed604fa06b7d756dc0171169cc12f7fdd68eb7b17708a62eebf4516"}, - {file = "gevent-22.10.2-cp37-cp37m-win32.whl", hash = "sha256:4114f0f439f0b547bb6f1d474fee99ddb46736944ad2207cef3771828f6aa358"}, - {file = "gevent-22.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:0d581f22a5be6281b11ad6309b38b18f0638cf896931223cbaa5adb904826ef6"}, - {file = "gevent-22.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2929377c8ebfb6f4d868d161cd8de2ea6b9f6c7a5fcd4f78bcd537319c16190b"}, - {file = "gevent-22.10.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:efc003b6c1481165af61f0aeac248e0a9ac8d880bb3acbe469b448674b2d5281"}, - {file = "gevent-22.10.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db562a8519838bddad0c439a2b12246bab539dd50e299ea7ff3644274a33b6a5"}, - {file = "gevent-22.10.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1472012493ca1fac103f700d309cb6ef7964dcdb9c788d1768266e77712f5e49"}, - {file = "gevent-22.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c04ee32c11e9fcee47c1b431834878dc987a7a2cc4fe126ddcae3bad723ce89"}, - {file = "gevent-22.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8729129edef2637a8084258cb9ec4e4d5ca45d97ac77aa7a6ff19ccb530ab731"}, - {file = "gevent-22.10.2-cp38-cp38-win32.whl", hash = "sha256:ae90226074a6089371a95f20288431cd4b3f6b0b096856afd862e4ac9510cddd"}, - {file = "gevent-22.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:494c7f29e94df9a1c3157d67bb7edfa32a46eed786e04d9ee68d39f375e30001"}, - {file = "gevent-22.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:58898dbabb5b11e4d0192aae165ad286dc6742c543e1be9d30dc82753547c508"}, - {file = "gevent-22.10.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:4197d423e198265eef39a0dea286ef389da9148e070310f34455ecee8172c391"}, - {file = "gevent-22.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da4183f0b9d9a1e25e1758099220d32c51cc2c6340ee0dea3fd236b2b37598e4"}, - {file = "gevent-22.10.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5488eba6a568b4d23c072113da4fc0feb1b5f5ede7381656dc913e0d82204e2"}, - {file = "gevent-22.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:319d8b1699b7b8134de66d656cd739b308ab9c45ace14d60ae44de7775b456c9"}, - {file = "gevent-22.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f3329bedbba4d3146ae58c667e0f9ac1e6f1e1e6340c7593976cdc60aa7d1a47"}, - {file = "gevent-22.10.2-cp39-cp39-win32.whl", hash = "sha256:172caa66273315f283e90a315921902cb6549762bdcb0587fd60cb712a9d6263"}, - {file = "gevent-22.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:323b207b281ba0405fea042067fa1a61662e5ac0d574ede4ebbda03efd20c350"}, - {file = "gevent-22.10.2-pp27-pypy_73-win_amd64.whl", hash = "sha256:ed7f16613eebf892a6a744d7a4a8f345bc6f066a0ff3b413e2479f9c0a180193"}, - {file = "gevent-22.10.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a47a4e77e2bc668856aad92a0b8de7ee10768258d93cd03968e6c7ba2e832f76"}, - {file = "gevent-22.10.2.tar.gz", hash = "sha256:1ca01da176ee37b3527a2702f7d40dbc9ffb8cfc7be5a03bfa4f9eec45e55c46"}, + {file = "gevent-25.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:856b990be5590e44c3a3dc6c8d48a40eaccbb42e99d2b791d11d1e7711a4297e"}, + {file = "gevent-25.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fe1599d0b30e6093eb3213551751b24feeb43db79f07e89d98dd2f3330c9063e"}, + {file = "gevent-25.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:f0d8b64057b4bf1529b9ef9bd2259495747fba93d1f836c77bfeaacfec373fd0"}, + {file = "gevent-25.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b56cbc820e3136ba52cd690bdf77e47a4c239964d5f80dc657c1068e0fe9521c"}, + {file = "gevent-25.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c5fa9ce5122c085983e33e0dc058f81f5264cebe746de5c401654ab96dddfca8"}, + {file = "gevent-25.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:03c74fec58eda4b4edc043311fca8ba4f8744ad1632eb0a41d5ec25413581975"}, + {file = "gevent-25.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a8ae9f895e8651d10b0a8328a61c9c53da11ea51b666388aa99b0ce90f9fdc27"}, + {file = "gevent-25.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5aff9e8342dc954adb9c9c524db56c2f3557999463445ba3d9cbe3dada7b7"}, + {file = "gevent-25.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1cdf6db28f050ee103441caa8b0448ace545364f775059d5e2de089da975c457"}, + {file = "gevent-25.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:812debe235a8295be3b2a63b136c2474241fa5c58af55e6a0f8cfc29d4936235"}, + {file = "gevent-25.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b28b61ff9216a3d73fe8f35669eefcafa957f143ac534faf77e8a19eb9e6883a"}, + {file = "gevent-25.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5e4b6278b37373306fc6b1e5f0f1cf56339a1377f67c35972775143d8d7776ff"}, + {file = "gevent-25.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d99f0cb2ce43c2e8305bf75bee61a8bde06619d21b9d0316ea190fc7a0620a56"}, + {file = "gevent-25.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:72152517ecf548e2f838c61b4be76637d99279dbaa7e01b3924df040aa996586"}, + {file = "gevent-25.9.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:46b188248c84ffdec18a686fcac5dbb32365d76912e14fda350db5dc0bfd4f86"}, + {file = "gevent-25.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f2b54ea3ca6f0c763281cd3f96010ac7e98c2e267feb1221b5a26e2ca0b9a692"}, + {file = "gevent-25.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7a834804ac00ed8a92a69d3826342c677be651b1c3cd66cc35df8bc711057aa2"}, + {file = "gevent-25.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:323a27192ec4da6b22a9e51c3d9d896ff20bc53fdc9e45e56eaab76d1c39dd74"}, + {file = "gevent-25.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6ea78b39a2c51d47ff0f130f4c755a9a4bbb2dd9721149420ad4712743911a51"}, + {file = "gevent-25.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dc45cd3e1cc07514a419960af932a62eb8515552ed004e56755e4bf20bad30c5"}, + {file = "gevent-25.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34e01e50c71eaf67e92c186ee0196a039d6e4f4b35670396baed4a2d8f1b347f"}, + {file = "gevent-25.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acd6bcd5feabf22c7c5174bd3b9535ee9f088d2bbce789f740ad8d6554b18f3"}, + {file = "gevent-25.9.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:4f84591d13845ee31c13f44bdf6bd6c3dbf385b5af98b2f25ec328213775f2ed"}, + {file = "gevent-25.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9cdbb24c276a2d0110ad5c978e49daf620b153719ac8a548ce1250a7eb1b9245"}, + {file = "gevent-25.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:88b6c07169468af631dcf0fdd3658f9246d6822cc51461d43f7c44f28b0abb82"}, + {file = "gevent-25.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b7bb0e29a7b3e6ca9bed2394aa820244069982c36dc30b70eb1004dd67851a48"}, + {file = "gevent-25.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2951bb070c0ee37b632ac9134e4fdaad70d2e660c931bb792983a0837fe5b7d7"}, + {file = "gevent-25.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4e17c2d57e9a42e25f2a73d297b22b60b2470a74be5a515b36c984e1a246d47"}, + {file = "gevent-25.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d94936f8f8b23d9de2251798fcb603b84f083fdf0d7f427183c1828fb64f117"}, + {file = "gevent-25.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:eb51c5f9537b07da673258b4832f6635014fee31690c3f0944d34741b69f92fa"}, + {file = "gevent-25.9.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:1a3fe4ea1c312dbf6b375b416925036fe79a40054e6bf6248ee46526ea628be1"}, + {file = "gevent-25.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0adb937f13e5fb90cca2edf66d8d7e99d62a299687400ce2edee3f3504009356"}, + {file = "gevent-25.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:427f869a2050a4202d93cf7fd6ab5cffb06d3e9113c10c967b6e2a0d45237cb8"}, + {file = "gevent-25.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c049880175e8c93124188f9d926af0a62826a3b81aa6d3074928345f8238279e"}, + {file = "gevent-25.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b5a67a0974ad9f24721034d1e008856111e0535f1541499f72a733a73d658d1c"}, + {file = "gevent-25.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1d0f5d8d73f97e24ea8d24d8be0f51e0cf7c54b8021c1fddb580bf239474690f"}, + {file = "gevent-25.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ddd3ff26e5c4240d3fbf5516c2d9d5f2a998ef87cfb73e1429cfaeaaec860fa6"}, + {file = "gevent-25.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:bb63c0d6cb9950cc94036a4995b9cc4667b8915366613449236970f4394f94d7"}, + {file = "gevent-25.9.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f18f80aef6b1f6907219affe15b36677904f7cfeed1f6a6bc198616e507ae2d7"}, + {file = "gevent-25.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b274a53e818124a281540ebb4e7a2c524778f745b7a99b01bdecf0ca3ac0ddb0"}, + {file = "gevent-25.9.1-cp39-cp39-win32.whl", hash = "sha256:c6c91f7e33c7f01237755884316110ee7ea076f5bdb9aa0982b6dc63243c0a38"}, + {file = "gevent-25.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:012a44b0121f3d7c800740ff80351c897e85e76a7e4764690f35c5ad9ec17de5"}, + {file = "gevent-25.9.1.tar.gz", hash = "sha256:adf9cd552de44a4e6754c51ff2e78d9193b7fa6eab123db9578a210e657235dd"}, ] [package.dependencies] -cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} -greenlet = {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\""} -setuptools = "*" +cffi = {version = ">=1.17.1", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} +greenlet = {version = ">=3.2.2", markers = "platform_python_implementation == \"CPython\""} "zope.event" = "*" "zope.interface" = "*" [package.extras] -dnspython = ["dnspython (>=1.16.0,<2.0) ; python_version < \"3.10\"", "idna ; python_version < \"3.10\""] -docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput", "zope.schema"] -monitor = ["psutil (>=5.7.0) ; sys_platform != \"win32\" or platform_python_implementation == \"CPython\""] -recommended = ["backports.socketpair ; python_version == \"2.7\" and sys_platform == \"win32\"", "cffi (>=1.12.2) ; platform_python_implementation == \"CPython\"", "dnspython (>=1.16.0,<2.0) ; python_version < \"3.10\"", "idna ; python_version < \"3.10\"", "psutil (>=5.7.0) ; sys_platform != \"win32\" or platform_python_implementation == \"CPython\"", "selectors2 ; python_version == \"2.7\""] -test = ["backports.socketpair ; python_version == \"2.7\" and sys_platform == \"win32\"", "cffi (>=1.12.2) ; platform_python_implementation == \"CPython\"", "contextvars (==2.4) ; python_version > \"3.0\" and python_version < \"3.7\"", "coverage (>=5.0) ; sys_platform != \"win32\"", "coveralls (>=1.7.0) ; sys_platform != \"win32\"", "dnspython (>=1.16.0,<2.0) ; python_version < \"3.10\"", "futures ; python_version == \"2.7\"", "idna ; python_version < \"3.10\"", "mock ; python_version == \"2.7\"", "objgraph", "psutil (>=5.7.0) ; sys_platform != \"win32\" or platform_python_implementation == \"CPython\"", "requests", "selectors2 ; python_version == \"2.7\""] +dnspython = ["dnspython (>=1.16.0,<2.0)", "idna"] +docs = ["furo", "repoze.sphinx.autointerface", "sphinx", "sphinxcontrib-programoutput", "zope.schema"] +monitor = ["psutil (>=5.7.0)"] +recommended = ["cffi (>=1.17.1)", "dnspython (>=1.16.0,<2.0)", "idna", "psutil (>=5.7.0)"] +test = ["cffi (>=1.17.1)", "coverage (>=5.0)", "dnspython (>=1.16.0,<2.0)", "idna", "objgraph", "psutil (>=5.7.0)", "requests"] [[package]] name = "greenlet" -version = "3.1.1" +version = "3.3.2" description = "Lightweight in-process concurrent programming" optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "platform_python_implementation == \"CPython\"" +python-versions = ">=3.10" files = [ - {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6"}, - {file = "greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80"}, - {file = "greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395"}, - {file = "greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39"}, - {file = "greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942"}, - {file = "greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01"}, - {file = "greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c"}, - {file = "greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af"}, - {file = "greenlet-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798"}, - {file = "greenlet-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef"}, - {file = "greenlet-3.1.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7"}, - {file = "greenlet-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef"}, - {file = "greenlet-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d"}, - {file = "greenlet-3.1.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e"}, - {file = "greenlet-3.1.1-cp39-cp39-win32.whl", hash = "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c"}, - {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, - {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, + {file = "greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca"}, + {file = "greenlet-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f"}, + {file = "greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be"}, + {file = "greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5"}, + {file = "greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd"}, + {file = "greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395"}, + {file = "greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f"}, + {file = "greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643"}, + {file = "greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b"}, + {file = "greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124"}, + {file = "greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327"}, + {file = "greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5"}, + {file = "greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492"}, + {file = "greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71"}, + {file = "greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e"}, + {file = "greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a"}, + {file = "greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2"}, ] [package.extras] docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] +test = ["objgraph", "psutil", "setuptools"] [[package]] name = "gunicorn" -version = "20.1.0" +version = "25.1.0" description = "WSGI HTTP Server for UNIX" optional = false -python-versions = ">=3.5" -groups = ["main"] +python-versions = ">=3.10" files = [ - {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, - {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, + {file = "gunicorn-25.1.0-py3-none-any.whl", hash = "sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b"}, + {file = "gunicorn-25.1.0.tar.gz", hash = "sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616"}, ] [package.dependencies] -setuptools = ">=3.0" +packaging = "*" [package.extras] -eventlet = ["eventlet (>=0.24.1)"] -gevent = ["gevent (>=1.4.0)"] +eventlet = ["eventlet (>=0.40.3)"] +gevent = ["gevent (>=24.10.1)"] +http2 = ["h2 (>=4.1.0)"] setproctitle = ["setproctitle"] -tornado = ["tornado (>=0.2)"] +testing = ["coverage", "eventlet (>=0.40.3)", "gevent (>=24.10.1)", "h2 (>=4.1.0)", "httpx[http2]", "pytest", "pytest-asyncio", "pytest-cov", "uvloop (>=0.19.0)"] +tornado = ["tornado (>=6.5.0)"] [[package]] name = "h11" @@ -725,7 +808,6 @@ version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -737,7 +819,6 @@ version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -759,7 +840,6 @@ version = "0.27.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, @@ -773,7 +853,7 @@ idna = "*" sniffio = "*" [package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +brotli = ["brotli", "brotlicffi"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -781,14 +861,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.10" +version = "3.11" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.6" -groups = ["main"] +python-versions = ">=3.8" files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] [package.extras] @@ -796,30 +875,28 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" -groups = ["dev"] +python-versions = ">=3.10" files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] [[package]] name = "isort" -version = "5.13.2" +version = "8.0.1" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.8.0" -groups = ["dev"] +python-versions = ">=3.10.0" files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, + {file = "isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75"}, + {file = "isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d"}, ] [package.extras] -colors = ["colorama (>=0.4.6)"] +colors = ["colorama"] [[package]] name = "itsdangerous" @@ -827,7 +904,6 @@ version = "2.2.0" description = "Safely pass data to untrusted environments and back." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, @@ -835,14 +911,13 @@ files = [ [[package]] name = "jinja2" -version = "3.0.3" +version = "3.1.6" description = "A very fast and expressive template engine." optional = false -python-versions = ">=3.6" -groups = ["main"] +python-versions = ">=3.7" files = [ - {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, - {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, ] [package.dependencies] @@ -851,13 +926,23 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jmespath" +version = "1.1.0" +description = "JSON Matching Expressions" +optional = false +python-versions = ">=3.9" +files = [ + {file = "jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64"}, + {file = "jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d"}, +] + [[package]] name = "jwcrypto" version = "1.5.6" description = "Implementation of JOSE Web standards" optional = false python-versions = ">= 3.8" -groups = ["main"] files = [ {file = "jwcrypto-1.5.6-py3-none-any.whl", hash = "sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789"}, {file = "jwcrypto-1.5.6.tar.gz", hash = "sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039"}, @@ -869,73 +954,100 @@ typing-extensions = ">=4.5.0" [[package]] name = "markupsafe" -version = "3.0.1" +version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ - {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-win32.whl", hash = "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-win32.whl", hash = "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b"}, - {file = "markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, + {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, + {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, + {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, + {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, + {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, + {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, + {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] @@ -944,7 +1056,6 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -956,7 +1067,6 @@ version = "2.5.0" description = "A dot-accessible dictionary (a la JavaScript objects)" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "munch-2.5.0-py2.py3-none-any.whl", hash = "sha256:6f44af89a2ce4ed04ff8de41f70b226b984db10a91dcc7b9ac2efc1c77022fdd"}, {file = "munch-2.5.0.tar.gz", hash = "sha256:2d735f6f24d4dba3417fa448cae40c6e896ec1fdab6cdb5e6510999758a4dbd2"}, @@ -966,36 +1076,34 @@ files = [ six = "*" [package.extras] -testing = ["astroid (>=1.5.3,<1.6.0) ; python_version == \"2.7\"", "astroid (>=2.0) ; python_version >= \"3.4\"", "coverage", "pylint (>=1.7.2,<1.8.0) ; python_version == \"2.7\"", "pylint (>=2.3.1,<2.4.0) ; python_version >= \"3.4\"", "pytest"] +testing = ["astroid (>=1.5.3,<1.6.0)", "astroid (>=2.0)", "coverage", "pylint (>=1.7.2,<1.8.0)", "pylint (>=2.3.1,<2.4.0)", "pytest"] yaml = ["PyYAML (>=5.1.0)"] [[package]] name = "packaging" -version = "24.1" +version = "26.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, + {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] [[package]] name = "pluggy" -version = "1.5.0" +version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.8" -groups = ["dev"] +python-versions = ">=3.9" files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] +testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "ply" @@ -1003,7 +1111,6 @@ version = "3.10" description = "Python Lex & Yacc" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "ply-3.10.tar.gz", hash = "sha256:96e94af7dd7031d8d6dd6e2a8e0de593b511c211a86e28a9c9621c275ac8bacb"}, ] @@ -1014,7 +1121,6 @@ version = "2.10.0" description = "Python style guide checker" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, @@ -1022,33 +1128,45 @@ files = [ [[package]] name = "pycparser" -version = "2.22" +version = "3.0" description = "C parser in Python" optional = false +python-versions = ">=3.10" +files = [ + {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, + {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, +] + +[[package]] +name = "pygments" +version = "2.19.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false python-versions = ">=3.8" -groups = ["main"] files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pyjwt" -version = "2.9.0" +version = "2.12.1" description = "JSON Web Token implementation in Python" optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c"}, + {file = "pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b"}, ] [package.extras] crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=8.4.2,<9.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] +tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] [[package]] name = "pylint" @@ -1056,7 +1174,6 @@ version = "1.7.2" description = "python code static checker" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "pylint-1.7.2-py2.py3-none-any.whl", hash = "sha256:c7a3ee11db42d00334671b778f042793c837b73f5883132158284b7dbd6f8184"}, {file = "pylint-1.7.2.tar.gz", hash = "sha256:ea6afb93a9ed810cf52ff3838eb3a15e2bf6a81b80de0eaede1ce442caa5ca69"}, @@ -1071,24 +1188,24 @@ six = "*" [[package]] name = "pytest" -version = "8.3.3" +version = "8.4.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.8" -groups = ["dev"] +python-versions = ">=3.9" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, + {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, ] [package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1" +packaging = ">=20" pluggy = ">=1.5,<2" +pygments = ">=2.7.2" [package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" @@ -1096,7 +1213,6 @@ version = "5.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, @@ -1111,14 +1227,13 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.15.1" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false -python-versions = ">=3.8" -groups = ["dev"] +python-versions = ">=3.9" files = [ - {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, - {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, + {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, + {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, ] [package.dependencies] @@ -1127,13 +1242,26 @@ pytest = ">=6.2.5" [package.extras] dev = ["pre-commit", "pytest-asyncio", "tox"] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "python-dotenv" version = "0.19.2" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.5" -groups = ["dev"] files = [ {file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"}, {file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"}, @@ -1148,7 +1276,6 @@ version = "4.7.2" description = "python-keycloak is a Python package providing access to the Keycloak API." optional = false python-versions = "<4.0,>=3.9" -groups = ["main"] files = [ {file = "python_keycloak-4.7.2-py3-none-any.whl", hash = "sha256:c2751a1ddda7362b6922b0093b553343dcae0f6e39e47be489116ae66d8a9bbb"}, {file = "python_keycloak-4.7.2.tar.gz", hash = "sha256:9a7fbef6df7b6ad1978ab65d340cc5048e547df1e11771ace661a198932cc4e4"}, @@ -1168,7 +1295,6 @@ version = "6.0.1" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, @@ -1225,19 +1351,18 @@ files = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.5" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" @@ -1251,7 +1376,6 @@ version = "1.0.0" description = "A utility belt for advanced users of python-requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] files = [ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, @@ -1261,36 +1385,31 @@ files = [ requests = ">=2.0.1,<3.0.0" [[package]] -name = "setuptools" -version = "75.1.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" +name = "s3transfer" +version = "0.16.0" +description = "An Amazon S3 Transfer Manager" optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, - {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, + {file = "s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe"}, + {file = "s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920"}, ] +[package.dependencies] +botocore = ">=1.37.4,<2.0a.0" + [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.5.2) ; sys_platform != \"cygwin\""] -core = ["importlib-metadata (>=6) ; python_version < \"3.10\"", "importlib-resources (>=5.10.2) ; python_version < \"3.9\"", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.11.*)", "pytest-mypy"] +crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main", "dev"] +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -1299,7 +1418,6 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1311,7 +1429,6 @@ version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -1323,7 +1440,6 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -1331,115 +1447,99 @@ files = [ [[package]] name = "urllib3" -version = "2.2.3" +version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, + {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, + {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0)"] [[package]] name = "werkzeug" -version = "2.2.2" +version = "3.1.6" description = "The comprehensive WSGI web application library." optional = false -python-versions = ">=3.7" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, - {file = "Werkzeug-2.2.2.tar.gz", hash = "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f"}, + {file = "werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131"}, + {file = "werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25"}, ] [package.dependencies] -MarkupSafe = ">=2.1.1" +markupsafe = ">=2.1.1" [package.extras] -watchdog = ["watchdog"] +watchdog = ["watchdog (>=2.3)"] [[package]] name = "zope-event" -version = "5.0" +version = "6.1" description = "Very basic event publishing system" optional = false -python-versions = ">=3.7" -groups = ["main"] +python-versions = ">=3.10" files = [ - {file = "zope.event-5.0-py3-none-any.whl", hash = "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26"}, - {file = "zope.event-5.0.tar.gz", hash = "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd"}, + {file = "zope_event-6.1-py3-none-any.whl", hash = "sha256:0ca78b6391b694272b23ec1335c0294cc471065ed10f7f606858fc54566c25a0"}, + {file = "zope_event-6.1.tar.gz", hash = "sha256:6052a3e0cb8565d3d4ef1a3a7809336ac519bc4fe38398cb8d466db09adef4f0"}, ] -[package.dependencies] -setuptools = "*" - [package.extras] docs = ["Sphinx"] -test = ["zope.testrunner"] +test = ["zope.testrunner (>=6.4)"] [[package]] name = "zope-interface" -version = "7.1.0" +version = "8.2" description = "Interfaces for Python" optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.10" files = [ - {file = "zope.interface-7.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2bd9e9f366a5df08ebbdc159f8224904c1c5ce63893984abb76954e6fbe4381a"}, - {file = "zope.interface-7.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:661d5df403cd3c5b8699ac480fa7f58047a3253b029db690efa0c3cf209993ef"}, - {file = "zope.interface-7.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91b6c30689cfd87c8f264acb2fc16ad6b3c72caba2aec1bf189314cf1a84ca33"}, - {file = "zope.interface-7.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b6a4924f5bad9fe21d99f66a07da60d75696a136162427951ec3cb223a5570d"}, - {file = "zope.interface-7.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80a3c00b35f6170be5454b45abe2719ea65919a2f09e8a6e7b1362312a872cd3"}, - {file = "zope.interface-7.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b936d61dbe29572fd2cfe13e30b925e5383bed1aba867692670f5a2a2eb7b4e9"}, - {file = "zope.interface-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ac20581fc6cd7c754f6dff0ae06fedb060fa0e9ea6309d8be8b2701d9ea51c4"}, - {file = "zope.interface-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:848b6fa92d7c8143646e64124ed46818a0049a24ecc517958c520081fd147685"}, - {file = "zope.interface-7.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec1ef1fdb6f014d5886b97e52b16d0f852364f447d2ab0f0c6027765777b6667"}, - {file = "zope.interface-7.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bcff5c09d0215f42ba64b49205a278e44413d9bf9fa688fd9e42bfe472b5f4f"}, - {file = "zope.interface-7.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07add15de0cc7e69917f7d286b64d54125c950aeb43efed7a5ea7172f000fbc1"}, - {file = "zope.interface-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:9940d5bc441f887c5f375ec62bcf7e7e495a2d5b1da97de1184a88fb567f06af"}, - {file = "zope.interface-7.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f245d039f72e6f802902375755846f5de1ee1e14c3e8736c078565599bcab621"}, - {file = "zope.interface-7.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6159e767d224d8f18deff634a1d3722e68d27488c357f62ebeb5f3e2f5288b1f"}, - {file = "zope.interface-7.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e956b1fd7f3448dd5e00f273072e73e50dfafcb35e4227e6d5af208075593c9"}, - {file = "zope.interface-7.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff115ef91c0eeac69cd92daeba36a9d8e14daee445b504eeea2b1c0b55821984"}, - {file = "zope.interface-7.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec001798ab62c3fc5447162bf48496ae9fba02edc295a9e10a0b0c639a6452e"}, - {file = "zope.interface-7.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:124149e2d42067b9c6597f4dafdc7a0983d0163868f897b7bb5dc850b14f9a87"}, - {file = "zope.interface-7.1.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:9733a9a0f94ef53d7aa64661811b20875b5bc6039034c6e42fb9732170130573"}, - {file = "zope.interface-7.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5fcf379b875c610b5a41bc8a891841533f98de0520287d7f85e25386cd10d3e9"}, - {file = "zope.interface-7.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0a45b5af9f72c805ee668d1479480ca85169312211bed6ed18c343e39307d5f"}, - {file = "zope.interface-7.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af4a12b459a273b0b34679a5c3dc5e34c1847c3dd14a628aa0668e19e638ea2"}, - {file = "zope.interface-7.1.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a735f82d2e3ed47ca01a20dfc4c779b966b16352650a8036ab3955aad151ed8a"}, - {file = "zope.interface-7.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:5501e772aff595e3c54266bc1bfc5858e8f38974ce413a8f1044aae0f32a83a3"}, - {file = "zope.interface-7.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec59fe53db7d32abb96c6d4efeed84aab4a7c38c62d7a901a9b20c09dd936e7a"}, - {file = "zope.interface-7.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e53c291debef523b09e1fe3dffe5f35dde164f1c603d77f770b88a1da34b7ed6"}, - {file = "zope.interface-7.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:711eebc77f2092c6a8b304bad0b81a6ce3cf5490b25574e7309fbc07d881e3af"}, - {file = "zope.interface-7.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a00ead2e24c76436e1b457a5132d87f83858330f6c923640b7ef82d668525d1"}, - {file = "zope.interface-7.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e28ea0bc4b084fc93a483877653a033062435317082cdc6388dec3438309faf"}, - {file = "zope.interface-7.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:27cfb5205d68b12682b6e55ab8424662d96e8ead19550aad0796b08dd2c9a45e"}, - {file = "zope.interface-7.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e3e48f3dea21c147e1b10c132016cb79af1159facca9736d231694ef5a740a8"}, - {file = "zope.interface-7.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a99240b1d02dc469f6afbe7da1bf617645e60290c272968f4e53feec18d7dce8"}, - {file = "zope.interface-7.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc8a318162123eddbdf22fcc7b751288ce52e4ad096d3766ff1799244352449d"}, - {file = "zope.interface-7.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7b25db127db3e6b597c5f74af60309c4ad65acd826f89609662f0dc33a54728"}, - {file = "zope.interface-7.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a29ac607e970b5576547f0e3589ec156e04de17af42839eedcf478450687317"}, - {file = "zope.interface-7.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:a14c9decf0eb61e0892631271d500c1e306c7b6901c998c7035e194d9150fdd1"}, - {file = "zope_interface-7.1.0.tar.gz", hash = "sha256:3f005869a1a05e368965adb2075f97f8ee9a26c61898a9e52a9764d93774f237"}, + {file = "zope_interface-8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:788c293f3165964ec6527b2d861072c68eef53425213f36d3893ebee89a89623"}, + {file = "zope_interface-8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9a4e785097e741a1c953b3970ce28f2823bd63c00adc5d276f2981dd66c96c15"}, + {file = "zope_interface-8.2-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:16c69da19a06566664ddd4785f37cad5693a51d48df1515d264c20d005d322e2"}, + {file = "zope_interface-8.2-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c31acfa3d7cde48bec45701b0e1f4698daffc378f559bfb296837d8c834732f6"}, + {file = "zope_interface-8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0723507127f8269b8f3f22663168f717e9c9742107d1b6c9f419df561b71aa6d"}, + {file = "zope_interface-8.2-cp310-cp310-win_amd64.whl", hash = "sha256:3bf73a910bb27344def2d301a03329c559a79b308e1e584686b74171d736be4e"}, + {file = "zope_interface-8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c65ade7ea85516e428651048489f5e689e695c79188761de8c622594d1e13322"}, + {file = "zope_interface-8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1ef4b43659e1348f35f38e7d1a6bbc1682efde239761f335ffc7e31e798b65b"}, + {file = "zope_interface-8.2-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dfc4f44e8de2ff4eba20af4f0a3ca42d3c43ab24a08e49ccd8558b7a4185b466"}, + {file = "zope_interface-8.2-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8f094bfb49179ec5dc9981cb769af1275702bd64720ef94874d9e34da1390d4c"}, + {file = "zope_interface-8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d2bb8e7364e18f083bf6744ccf30433b2a5f236c39c95df8514e3c13007098ce"}, + {file = "zope_interface-8.2-cp311-cp311-win_amd64.whl", hash = "sha256:6f4b4dfcfdfaa9177a600bb31cebf711fdb8c8e9ed84f14c61c420c6aa398489"}, + {file = "zope_interface-8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:624b6787fc7c3e45fa401984f6add2c736b70a7506518c3b537ffaacc4b29d4c"}, + {file = "zope_interface-8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc9ded9e97a0ed17731d479596ed1071e53b18e6fdb2fc33af1e43f5fd2d3aaa"}, + {file = "zope_interface-8.2-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:532367553e4420c80c0fc0cabcc2c74080d495573706f66723edee6eae53361d"}, + {file = "zope_interface-8.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2bf9cf275468bafa3c72688aad8cfcbe3d28ee792baf0b228a1b2d93bd1d541a"}, + {file = "zope_interface-8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0009d2d3c02ea783045d7804da4fd016245e5c5de31a86cebba66dd6914d59a2"}, + {file = "zope_interface-8.2-cp312-cp312-win_amd64.whl", hash = "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640"}, + {file = "zope_interface-8.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:6068322004a0158c80dfd4708dfb103a899635408c67c3b10e9acec4dbacefec"}, + {file = "zope_interface-8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2499de92e8275d0dd68f84425b3e19e9268cd1fa8507997900fa4175f157733c"}, + {file = "zope_interface-8.2-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f777e68c76208503609c83ca021a6864902b646530a1a39abb9ed310d1100664"}, + {file = "zope_interface-8.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b05a919fdb0ed6ea942e5a7800e09a8b6cdae6f98fee1bef1c9d1a3fc43aaa0"}, + {file = "zope_interface-8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccc62b5712dd7bd64cfba3ee63089fb11e840f5914b990033beeae3b2180b6cb"}, + {file = "zope_interface-8.2-cp313-cp313-win_amd64.whl", hash = "sha256:34f877d1d3bb7565c494ed93828fa6417641ca26faf6e8f044e0d0d500807028"}, + {file = "zope_interface-8.2-cp314-cp314-macosx_10_9_x86_64.whl", hash = "sha256:46c7e4e8cbc698398a67e56ca985d19cb92365b4aafbeb6a712e8c101090f4cb"}, + {file = "zope_interface-8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a87fc7517f825a97ff4a4ca4c8a950593c59e0f8e7bfe1b6f898a38d5ba9f9cf"}, + {file = "zope_interface-8.2-cp314-cp314-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:ccf52f7d44d669203c2096c1a0c2c15d52e36b2e7a9413df50f48392c7d4d080"}, + {file = "zope_interface-8.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aae807efc7bd26302eb2fea05cd6de7d59269ed6ae23a6de1ee47add6de99b8c"}, + {file = "zope_interface-8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c"}, + {file = "zope_interface-8.2-cp314-cp314-win_amd64.whl", hash = "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48"}, + {file = "zope_interface-8.2.tar.gz", hash = "sha256:afb20c371a601d261b4f6edb53c3c418c249db1a9717b0baafc9a9bb39ba1224"}, ] -[package.dependencies] -setuptools = "*" - [package.extras] docs = ["Sphinx", "furo", "repoze.sphinx.autointerface"] test = ["coverage[toml]", "zope.event", "zope.testing"] testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "^3.11" -content-hash = "d665d77703826b8666f362a16958bd4bff175982a6ed4863b8c7419f909789e3" +content-hash = "eb8cd6b5f26a6c0b94e8e4d6f6311baadb63381fb05aad6f2d0befc37628a8c2" diff --git a/microservices/gatewayApi/pyproject.toml b/microservices/gatewayApi/pyproject.toml index af34ecf5..5f742509 100644 --- a/microservices/gatewayApi/pyproject.toml +++ b/microservices/gatewayApi/pyproject.toml @@ -7,25 +7,26 @@ authors = [] [tool.poetry.dependencies] python = "^3.11" -werkzeug = "2.2.2" +werkzeug = ">=2" ply = "3.10" cryptography = "38.0.4" authlib = "0.15.3" flask-swagger-ui = "3.36.0" -Jinja2 = "3.0.3" +Jinja2 = ">=3" PyYAML = "6.0.1" munch = "2.5.0" -flask = "2.1.3" +boto3 = ">=1.9" +flask = "2.3.3" flask-compress = "1.4.0" flask-cors = "3.0.9" -gevent = "22.10.2" +gevent = "^25.5.1" # greenlet = "2.0.2" -gunicorn = "20.1.0" +gunicorn = "^25.1.0" python-keycloak = "4.7.2" httpx = "0.27.2" -urllib3 = "2.2.3" requests = "^2.32" flask-jwt-simple = "0.0.3" +urllib3 = "^2.5.0" [tool.poetry.group.dev.dependencies] autopep8 = "^1.5.7" diff --git a/microservices/gatewayApi/tests/conftest.py b/microservices/gatewayApi/tests/conftest.py index 99ad02dc..27c0f8aa 100644 --- a/microservices/gatewayApi/tests/conftest.py +++ b/microservices/gatewayApi/tests/conftest.py @@ -69,6 +69,8 @@ def get_group_by_path(path): return {"id": "g003"} elif path == "/ns/customcert": return {"id": "g004"} + elif path == "/ns/sdx01": + return {"id": "grpsdx01"} else: return {"id": "g001"} def get_group(id): @@ -100,6 +102,13 @@ def get_group(id): "perm-domains": [ ".api.gov.bc.ca", ".custom.gov.bc.ca" ] } } + elif id == "grpsdx01": + return { + "attributes": { + "perm-data-plane": ["sdx-edge"], + "perm-domains": [ "sdx01.servers.sdx" ] + } + } mocker.patch("v2.services.namespaces.admin_api", return_value=mock_kc_admin) diff --git a/microservices/gatewayApi/tests/routes/v2/test_gateway_err_validations.py b/microservices/gatewayApi/tests/routes/v2/test_gateway_err_validations.py index eca517b4..6b13d991 100644 --- a/microservices/gatewayApi/tests/routes/v2/test_gateway_err_validations.py +++ b/microservices/gatewayApi/tests/routes/v2/test_gateway_err_validations.py @@ -145,3 +145,40 @@ def test_valid_strict_dp_upstream(client): } response = client.put('/v2/namespaces/mytest3/gateway', json=data) assert response.status_code == 200 + + +def test_key_sets_and_keys_require_tags(client): + configFile = ''' + key_sets: + - name: my-key-set + tags: ["ns.mytest", "another"] + keys: + - name: my-key + tags: ["ns.mytest", "another"] + ''' + + data = { + "configFile": configFile, + "dryRun": True + } + response = client.put('/v2/namespaces/mytest/gateway', json=data) + assert response.status_code == 200 + + +def test_key_sets_and_keys_invalid_tags(client): + configFile = ''' + key_sets: + - name: my-key-set + tags: ["ns.other", "another"] + keys: + - name: my-key + tags: ["ns.mytest", "another"] + ''' + + data = { + "configFile": configFile, + "dryRun": True + } + response = client.put('/v2/namespaces/mytest/gateway', json=data) + assert response.status_code == 400 + assert "invalid ns tag ns.other" in json.dumps(response.json) diff --git a/microservices/gatewayApi/tests/routes/v2/test_sdx.py b/microservices/gatewayApi/tests/routes/v2/test_sdx.py new file mode 100644 index 00000000..b6e88a6b --- /dev/null +++ b/microservices/gatewayApi/tests/routes/v2/test_sdx.py @@ -0,0 +1,39 @@ +import yaml +import pytest +import json +from v1.routes.gateway import validate_upstream +from tests.testutils import trimleft +from unittest import mock + + +def test_success_sdx_call_empty(client): + data={ + "configFile": '---', + "dryRun": False + } + response = client.put('/v2/namespaces/sdx01/gateway', json=data) + assert response.status_code == 200 + assert json.dumps(response.json) == '{"message": "Sync successful.", "results": "Deck reported no changes"}' + +def test_success_sdx_call(client): + configFile = ''' + services: + - name: my-service + host: myupstream.local + tags: ["ns.sdx01.qualifier"] + routes: + - name: route-1 + hosts: [ sdx01.servers.sdx] + tags: ["ns.sdx01.qualifier"] + plugins: + - name: acl-auth + tags: ["ns.sdx01.qualifier"] + ''' + + data={ + "configFile": configFile, + "dryRun": False + } + response = client.put('/v2/namespaces/sdx01/gateway', json=data) + assert response.status_code == 200 + assert json.dumps(response.json) == '{"message": "Sync successful.", "results": "Deck reported no changes"}' diff --git a/microservices/gatewayApi/utils/deck.py b/microservices/gatewayApi/utils/deck.py index 62ba7bbe..e76583f0 100644 --- a/microservices/gatewayApi/utils/deck.py +++ b/microservices/gatewayApi/utils/deck.py @@ -1,12 +1,20 @@ -def deck_cmd_sync_diff(deck_cli, cmd, select_tag, state): +def deck_cmd_sync_diff(deck_cli, cmd, select_tag, state, kong_addr = None): if deck_cli == "deck" or deck_cli.startswith("deck_kong3_"): - return [ deck_cli, "gateway", cmd, "--config", "/tmp/deck.yaml", "--skip-consumers", "--select-tag", select_tag, state] + args = [ deck_cli, "gateway", cmd, "--config", "/tmp/deck.yaml", "--skip-consumers", "--select-tag", select_tag] + if kong_addr: + args.extend(["--kong-addr", kong_addr]) + args.append(state) + return args else: return [ deck_cli, cmd, "--config", "/tmp/deck.yaml", "--skip-consumers", "--select-tag", select_tag, "--state", state] -def deck_cmd_validate(deck_cli, state): +def deck_cmd_validate(deck_cli, state, kong_addr = None): if deck_cli == "deck" or deck_cli.startswith("deck_kong3_"): - return [ deck_cli, "gateway", "validate", "--config", "/tmp/deck.yaml", state ] + args = [ deck_cli, "gateway", "validate", "--config", "/tmp/deck.yaml" ] + if kong_addr: + args.extend(["--kong-addr", kong_addr]) + args.append(state) + return args else: return [ deck_cli, "validate", "--config", "/tmp/deck.yaml", "--state", state ] diff --git a/microservices/gatewayApi/v2/routes/gateway.py b/microservices/gatewayApi/v2/routes/gateway.py index 05073b6a..9051d01b 100644 --- a/microservices/gatewayApi/v2/routes/gateway.py +++ b/microservices/gatewayApi/v2/routes/gateway.py @@ -47,6 +47,10 @@ def delete_config(namespace: str, qualifier="") -> object: ns_svc = NamespaceService() ns_attributes = ns_svc.get_namespace_attributes(namespace) + dp = get_data_plane(ns_attributes) + kube_api_url = app.config['data_planes'][dp].get("kube-api") + kong_addr_override = app.config['data_planes'][dp].get("kong-addr") + log = app.logger outFolder = namespace @@ -68,7 +72,7 @@ def delete_config(namespace: str, qualifier="") -> object: deck_cli = app.config['deckCLI'] log.info("[%s] (%s) %s action using %s" % (namespace, deck_cli, cmd, selectTag)) - args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder) + args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder, kong_addr_override) log.debug("[%s] Running %s" % (namespace, args)) deck_run = Popen(args, stdout=PIPE, stderr=STDOUT) @@ -78,6 +82,9 @@ def delete_config(namespace: str, qualifier="") -> object: log.warn("%s - %s" % (namespace, out.decode('utf-8'))) abort_early(event_id, 'delete', namespace, jsonify(error="Sync Failed.", results=mask(out.decode('utf-8')))) + elif kube_api_url is None: + log.debug("[%s] No kube API URL configured, skipping route deletion" % (namespace)) + elif cmd == "sync" and not local_environment: try: session = requests.Session() @@ -87,10 +94,8 @@ def delete_config(namespace: str, qualifier="") -> object: "select_tag": selectTag, "ns_attributes": ns_attributes.getAttrs() } - dp = get_data_plane(ns_attributes) - rqst_url = app.config['data_planes'][dp]["kube-api"] log.debug("[%s] - Initiating request to kube API" % (dp)) - res = session.put(rqst_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( + res = session.put(kube_api_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( app.config['kubeApiCreds']['kubeApiUser'], app.config['kubeApiCreds']['kubeApiPass'])) log.debug("[%s] - The kube API responded with %s" % (dp, res.status_code)) if res.status_code != 201: @@ -156,18 +161,22 @@ def write_config(namespace: str) -> object: ns_attributes = ns_svc.get_namespace_attributes(namespace) dp = get_data_plane(ns_attributes) + kube_api_url = app.config['data_planes'][dp].get("kube-api") + kong_addr_override = app.config['data_planes'][dp].get("kong-addr") # Build a list of existing hosts that are outside this namespace # They become reserved and any conflict will return an error reserved_hosts = [] - all_routes = get_routes() - tag_match = "ns.%s" % namespace - for route in all_routes: - if tag_match not in route['tags'] and 'hosts' in route: - for host in route['hosts']: - reserved_hosts.append(host) - reserved_hosts = list(set(reserved_hosts)) + do_enforce_reserved_hosts = app.config['data_planes'][dp].get("enforce-reserved-hosts", True) + if do_enforce_reserved_hosts: + all_routes = get_routes() + tag_match = "ns.%s" % namespace + for route in all_routes: + if tag_match not in route['tags'] and 'hosts' in route: + for host in route['hosts']: + reserved_hosts.append(host) + reserved_hosts = list(set(reserved_hosts)) dfile = None select_tag_qualifier = None @@ -328,7 +337,7 @@ def write_config(namespace: str) -> object: log.info("[%s] (%s) %s action using %s" % (namespace, deck_cli, cmd, selectTag)) - args = deck_cmd_validate(deck_cli, tempFolder) + args = deck_cmd_validate(deck_cli, tempFolder, kong_addr_override) log.debug("[%s] Running %s" % (namespace, args)) deck_validate = Popen(args, stdout=PIPE, stderr=STDOUT) @@ -339,7 +348,7 @@ def write_config(namespace: str) -> object: abort_early(event_id, 'validate', namespace, jsonify( error="Validation Failed.", results=mask(out.decode('utf-8')))) - args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder) + args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder, kong_addr_override) log.debug("[%s] Running %s" % (namespace, args)) deck_run = Popen(args, stdout=PIPE, stderr=STDOUT) @@ -349,6 +358,8 @@ def write_config(namespace: str) -> object: log.warn("[%s] - %s" % (namespace, out.decode('utf-8'))) abort_early(event_id, 'publish', namespace, jsonify(error="Sync Failed.", results=mask(out.decode('utf-8')))) # skip creation of routes in local development environment + elif kube_api_url is None: + log.debug("[%s] No kube API URL configured, skipping route creation" % (namespace)) elif cmd == "sync" and not local_environment: try: if update_routes_flag: @@ -385,8 +396,8 @@ def write_config(namespace: str) -> object: "overrides": route_payload["overrides"] } log.debug("[%s] - Initiating request to kube API %s" % (dp, route_payload_log)) - rqst_url = app.config['data_planes'][dp]["kube-api"] - res = session.put(rqst_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( + + res = session.put(kube_api_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( app.config['kubeApiCreds']['kubeApiUser'], app.config['kubeApiCreds']['kubeApiPass'])) log.debug("[%s] - The kube API responded with %s" % (dp, res.status_code)) if res.status_code != 201: @@ -397,9 +408,9 @@ def write_config(namespace: str) -> object: if has_namespace_local_host_permission(ns_attributes): session = requests.Session() session.headers.update({"Content-Type": "application/json"}) - rqst_url = app.config['data_planes'][dp]["kube-api"] + log.debug("[%s] - Initiating request to kube API for Certs" % (dp)) - res = session.get(rqst_url + "/namespaces/%s/local_tls" % namespace, auth=( + res = session.get(kube_api_url + "/namespaces/%s/local_tls" % namespace, auth=( app.config['kubeApiCreds']['kubeApiUser'], app.config['kubeApiCreds']['kubeApiPass'])) log.debug("[%s] - The kube API responded with %s" % (dp, res.status_code)) if res.status_code != 200: @@ -453,7 +464,7 @@ def cleanup(dir_path): log.error("Error: %s : %s" % (dir_path, e.strerror)) def validate_base_entities(yaml, ns_attributes): - traversables = ['_format_version', '_plugin_configs', 'services', 'upstreams', 'certificates'] + traversables = ['_format_version', '_plugin_configs', 'services', 'upstreams', 'certificates', 'key_sets', 'keys'] allow_protected_ns = ns_attributes.get('perm-protected-ns', ['deny'])[0] == 'allow' if allow_protected_ns: @@ -483,7 +494,7 @@ def validate_tags(yaml, required_tag): def traverse(source, errors, yaml, required_tag, qualifiers): # If at root level, allow different resources than if its traversed down a level if source == "": - traversables = ['services', 'upstreams', 'consumers', 'certificates', 'ca_certificates'] + traversables = ['services', 'upstreams', 'consumers', 'certificates', 'key_sets', 'keys', 'ca_certificates'] else: traversables = ['routes', 'plugins'] @@ -635,7 +646,7 @@ def tags_transformation(namespace, yaml): def traverse_tags_transform(yaml, namespace, required_tag): object_count = 0 log = app.logger - traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'ca_certificates'] + traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'key_sets', 'keys', 'ca_certificates'] for k in yaml: if k in traversables: for item in yaml[k]: @@ -670,7 +681,7 @@ def traverse_has_ns_qualifier(yaml, required_tag): def traverse_has_ns_tag_only(yaml, required_tag): log = app.logger - traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'ca_certificates'] + traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'key_sets', 'keys', 'ca_certificates'] for k in yaml: if k in traversables: for item in yaml[k]: @@ -691,7 +702,7 @@ def has_ns_qualifier(tags, required_tag): def traverse_get_ns_qualifier(yaml, required_tag): log = app.logger - traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'ca_certificates'] + traversables = ['services', 'routes', 'plugins', 'upstreams', 'consumers', 'certificates', 'key_sets', 'keys', 'ca_certificates'] for k in yaml: if k in traversables: for item in yaml[k]: diff --git a/microservices/gatewayApi/v2/routes/gw_status.py b/microservices/gatewayApi/v2/routes/gw_status.py index 194746eb..e5cdb898 100644 --- a/microservices/gatewayApi/v2/routes/gw_status.py +++ b/microservices/gatewayApi/v2/routes/gw_status.py @@ -26,9 +26,15 @@ def get_statuses(namespace: str) -> object: ns_svc = NamespaceService() ns_attributes = ns_svc.get_namespace_attributes(namespace) + dp = get_data_plane(ns_attributes) + kube_api_url = app.config['data_planes'][dp]["kube-api"] res = [] + if kube_api_url is None: + log.error("[%s] No kube API URL configured, skipping status retrieval" % (dp)) + return make_response(jsonify({"message": "The data plane does not support this operation"}), 400) + try: session = requests.Session() session.headers.update({"Content-Type": "application/json"}) @@ -38,11 +44,9 @@ def get_statuses(namespace: str) -> object: "conf": app.config['hostTransformation'], } - dp = get_data_plane(ns_attributes) - rqst_url = app.config['data_planes'][dp]['kube-api'] log.debug("[%s] - Initiating request to kube API" % (dp)) - res = session.get(rqst_url + "/namespaces/%s/service-status" % namespace, + res = session.get(kube_api_url + "/namespaces/%s/service-status" % namespace, json=service_payload, auth=(app.config['kubeApiCreds']['kubeApiUser'], app.config['kubeApiCreds']['kubeApiPass'])) diff --git a/microservices/gatewayApi/v2/routes/namespaces.py b/microservices/gatewayApi/v2/routes/namespaces.py index 31684690..36fd6b81 100644 --- a/microservices/gatewayApi/v2/routes/namespaces.py +++ b/microservices/gatewayApi/v2/routes/namespaces.py @@ -91,6 +91,9 @@ def delete_namespace(namespace: str) -> object: ns_svc = NamespaceService() ns_attributes = ns_svc.get_namespace_attributes(namespace) + dp = get_data_plane(ns_attributes) + kube_api_url = app.config['data_planes'][dp].get("kube-api") + kong_addr_override = app.config['data_planes'][dp].get("kong-addr") outFolder = namespace @@ -109,7 +112,7 @@ def delete_namespace(namespace: str) -> object: log.info("[%s] (%s) %s action using %s" % (namespace, deck_cli, cmd, selectTag)) - args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder) + args = deck_cmd_sync_diff(deck_cli, cmd, selectTag, tempFolder, kong_addr_override) log.debug("[%s] Running %s" % (namespace, args)) deck_run = Popen(args, stdout=PIPE, stderr=STDOUT) @@ -118,7 +121,8 @@ def delete_namespace(namespace: str) -> object: cleanup(tempFolder) log.warn("%s - %s" % (namespace, out.decode('utf-8'))) abort_early(event_id, 'delete', namespace, jsonify(error="Sync Failed.", results=mask(out.decode('utf-8')))) - + elif kube_api_url is None: + log.debug("[%s] No kube API URL configured, skipping route deletion" % (namespace)) elif cmd == "sync" and not local_environment: try: session = requests.Session() @@ -128,10 +132,9 @@ def delete_namespace(namespace: str) -> object: "select_tag": selectTag, "ns_attributes": ns_attributes.getAttrs() } - dp = get_data_plane(ns_attributes) - rqst_url = app.config['data_planes'][dp]['kube-api'] + log.debug("[%s] - Initiating request to kube API" % (dp)) - res = session.put(rqst_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( + res = session.put(kube_api_url + "/namespaces/%s/routes" % namespace, json=route_payload, auth=( app.config['kubeApiCreds']['kubeApiUser'], app.config['kubeApiCreds']['kubeApiPass'])) log.debug("[%s] - The kube API responded with %s" % (dp, res.status_code)) if res.status_code != 201: From 60205cbe722c85d4432253c24a263dec9a423f8b Mon Sep 17 00:00:00 2001 From: Russell Vinegar <38586679+rustyjux@users.noreply.github.com> Date: Thu, 26 Mar 2026 10:22:58 -0700 Subject: [PATCH 3/5] APS-4266 - Step CA One-time-use token API for SDX (#258) * add sdxStepTokenApi --- .github/workflows/dev.yml | 54 ++ .github/workflows/master.yml | 20 + microservices/sdxStepTokenApi/.gitignore | 35 + microservices/sdxStepTokenApi/Dockerfile | 45 ++ microservices/sdxStepTokenApi/README.md | 61 ++ microservices/sdxStepTokenApi/app.py | 48 ++ microservices/sdxStepTokenApi/clients/step.py | 131 ++++ .../sdxStepTokenApi/config/settings.py | 15 + microservices/sdxStepTokenApi/entrypoint.sh | 3 + microservices/sdxStepTokenApi/main.py | 46 ++ microservices/sdxStepTokenApi/poetry.lock | 694 ++++++++++++++++++ microservices/sdxStepTokenApi/pyproject.toml | 30 + .../sdxStepTokenApi/routers/routes.py | 34 + .../sdxStepTokenApi/sdx-ca-token-api-spec.md | 136 ++++ .../sdxStepTokenApi/tests/conftest.py | 10 + .../sdxStepTokenApi/tests/test_routes.py | 94 +++ .../sdxStepTokenApi/tests/test_step.py | 145 ++++ 17 files changed, 1601 insertions(+) create mode 100644 microservices/sdxStepTokenApi/.gitignore create mode 100644 microservices/sdxStepTokenApi/Dockerfile create mode 100644 microservices/sdxStepTokenApi/README.md create mode 100644 microservices/sdxStepTokenApi/app.py create mode 100644 microservices/sdxStepTokenApi/clients/step.py create mode 100644 microservices/sdxStepTokenApi/config/settings.py create mode 100644 microservices/sdxStepTokenApi/entrypoint.sh create mode 100644 microservices/sdxStepTokenApi/main.py create mode 100644 microservices/sdxStepTokenApi/poetry.lock create mode 100644 microservices/sdxStepTokenApi/pyproject.toml create mode 100644 microservices/sdxStepTokenApi/routers/routes.py create mode 100644 microservices/sdxStepTokenApi/sdx-ca-token-api-spec.md create mode 100644 microservices/sdxStepTokenApi/tests/conftest.py create mode 100644 microservices/sdxStepTokenApi/tests/test_routes.py create mode 100644 microservices/sdxStepTokenApi/tests/test_step.py diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index bd50fe2b..473caae3 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -87,6 +87,15 @@ jobs: poetry run coverage run --branch -m pytest -s -v poetry run coverage xml + - name: Test coverage for SDX CA Token API + run: | + export PATH=/root/.local/bin:$PATH + cd microservices/sdxStepTokenApi + poetry env use python3.14 + poetry install --no-root + poetry run coverage run --branch -m pytest -s -v + poetry run coverage xml + - name: SonarCloud Scan uses: sonarsource/sonarqube-scan-action@master env: @@ -317,3 +326,48 @@ jobs: labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} + + gwa-sdx-ca-token-api: + needs: sonar-scan + name: Docker Image for gwa-sdx-ca-token-api + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Check if build needed + id: check + run: | + if git diff --name-only HEAD^ HEAD | grep -q "^microservices/sdxStepTokenApi/\|^.github/workflows/dev.yml"; then + echo "build_needed=true" >> $GITHUB_OUTPUT + else + echo "build_needed=false" >> $GITHUB_OUTPUT + fi + - name: Skip message + if: steps.check.outputs.build_needed == 'false' + run: echo "No changes in sdxStepTokenApi, skipping build" + - name: Sanitize tag name + if: steps.check.outputs.build_needed == 'true' + id: tag + run: echo "tag=$(echo '${{ github.ref_name }}' | tr '/' '-')" >> $GITHUB_OUTPUT + - name: Set up Docker Buildx + if: steps.check.outputs.build_needed == 'true' + uses: docker/setup-buildx-action@v3 + - name: Log in to GitHub Container Registry + if: steps.check.outputs.build_needed == 'true' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + logout: false + - uses: docker/build-push-action@v5 + if: steps.check.outputs.build_needed == 'true' + with: + context: microservices/sdxStepTokenApi + file: microservices/sdxStepTokenApi/Dockerfile + push: true + tags: ghcr.io/bcgov/gwa-api/gwa-sdx-ca-token-api:${{ steps.tag.outputs.tag }} + labels: | + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 51a3f7fc..cd490f43 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -81,6 +81,15 @@ jobs: poetry run coverage run --branch -m pytest -s -v poetry run coverage xml + - name: Test coverage for SDX CA Token API + run: | + export PATH=/root/.local/bin:$PATH + cd microservices/sdxStepTokenApi + poetry env use python3.14 + poetry install --no-root + poetry run coverage run --branch -m pytest -s -v + poetry run coverage xml + - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@master env: @@ -157,6 +166,17 @@ jobs: file: microservices/csitOasValidationApi/Dockerfile push: true tags: ghcr.io/bcgov/gwa-api/gwa-csit-oas-validation-api:${{ steps.release.outputs.tag_name }} + labels: | + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} + + - name: Create gwa-sdx-ca-token-api docker image related to the release + uses: docker/build-push-action@v5 + with: + context: microservices/sdxStepTokenApi + file: microservices/sdxStepTokenApi/Dockerfile + push: true + tags: ghcr.io/bcgov/gwa-api/gwa-sdx-ca-token-api:${{ steps.release.outputs.tag_name }} labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} \ No newline at end of file diff --git a/microservices/sdxStepTokenApi/.gitignore b/microservices/sdxStepTokenApi/.gitignore new file mode 100644 index 00000000..13d4fb0e --- /dev/null +++ b/microservices/sdxStepTokenApi/.gitignore @@ -0,0 +1,35 @@ +# General Ignore +.idea +.DS_Store + +# Python Ignore +__pycache__/ +*.py[cod] +*$py.class +*.so + +# Distribution / packaging +.Python +build/ +dist/ +*.egg-info/ +*.egg + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Environments +.env +.venv +env/ +venv/ + +# mypy +.mypy_cache/ diff --git a/microservices/sdxStepTokenApi/Dockerfile b/microservices/sdxStepTokenApi/Dockerfile new file mode 100644 index 00000000..abbc48a3 --- /dev/null +++ b/microservices/sdxStepTokenApi/Dockerfile @@ -0,0 +1,45 @@ +FROM python:3.14.3-alpine3.23 AS builder + +WORKDIR /build + +RUN apk add --no-cache build-base libffi-dev curl + +RUN curl -sL https://github.com/smallstep/cli/releases/download/v0.30.0/step_linux_0.30.0_amd64.tar.gz -o /tmp/step.tar.gz && \ + tar -xf /tmp/step.tar.gz --strip-components=1 -C /tmp && \ + mv /tmp/bin/step /usr/local/bin/step && \ + rm /tmp/step.tar.gz + +RUN pip install --no-cache-dir poetry==2.3.2 + +COPY pyproject.toml poetry.lock ./ + +RUN poetry config virtualenvs.create true && \ + poetry config virtualenvs.in-project true && \ + poetry install --no-root --without dev + +# --- runtime --- + +FROM python:3.14.3-alpine3.23 AS runtime + +WORKDIR /app + +RUN apk add --no-cache openssl ca-certificates + +COPY --from=builder /usr/local/bin/step /usr/local/bin/step +COPY --from=builder /build/.venv /opt/venv + +# Create step config directory and make it writable for any user +RUN mkdir -p /step && chmod 777 /step + +ENV PATH="/opt/venv/bin:$PATH" \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + STEPPATH=/step + +COPY . /app + +RUN chmod +x /app/entrypoint.sh + +EXPOSE 8080 + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/microservices/sdxStepTokenApi/README.md b/microservices/sdxStepTokenApi/README.md new file mode 100644 index 00000000..6b09ab85 --- /dev/null +++ b/microservices/sdxStepTokenApi/README.md @@ -0,0 +1,61 @@ +# SDX CA Token API + +A FastAPI microservice that wraps the `step ca token` CLI to generate one-time-use tokens for the Step CA certificate authority. + +See [sdx-ca-token-api-spec.md](sdx-ca-token-api-spec.md) for the full specification. + +## Endpoints + +| Method | Path | Description | +|--------|-----------|--------------------------------------| +| POST | `/token` | Generate a one-time CA token | +| GET | `/health` | Health / readiness check | + +## Environment Variables + +| Variable | Required | Default | Description | +|--------------------------------|----------|------------------------------------|-----------------------------------| +| `STEP_CA_URL` | Yes | | In-cluster CA URL | +| `STEP_CA_FINGERPRINT` | Yes | | Root CA fingerprint for bootstrap | +| `LOG_LEVEL` | No | `DEBUG` | Python log level | +| `STEP_PROVISIONER_PASSWORD_FILE` | No | `/etc/step-provisioner/password` | Path to provisioner password file | +| `STEP_PROVISIONER_KID` | No | | Provisioner key ID | +| `STEP_PROVISIONER_ISSUER` | No | | Provisioner issuer name | + +## Local Development + +```bash +# Install dependencies +cd microservices/sdxStepTokenApi +poetry install + +# Run the app (requires step CLI and CA access) +export STEP_CA_URL='https://your-ca-host:443' +export STEP_CA_FINGERPRINT='your-sha256-fingerprint-hex' +export STEP_PROVISIONER_PASSWORD_FILE="$HOME/sdx-provisioner-password" +# optional: +# export STEP_PROVISIONER_KID='...' +# export STEP_PROVISIONER_ISSUER='...' +poetry run uvicorn main:app --host 0.0.0.0 --port 8080 + +# Run tests +poetry run pytest -s + +# Run tests with coverage +poetry run coverage run --branch -m pytest -s +poetry run coverage xml +``` + +## Docker + +```bash +docker build -t sdx-ca-token-api . + +docker run --rm -ti \ + -p 8080:8080 \ + -e STEP_CA_URL='https://your-ca-host:443' \ + -e STEP_CA_FINGERPRINT='your-sha256-fingerprint-hex' \ + -e STEP_PROVISIONER_PASSWORD_FILE=/etc/step-provisioner/password \ + -v /absolute/path/on/your/machine/provisioner-password:/etc/step-provisioner/password:ro \ + sdx-ca-token-api +``` diff --git a/microservices/sdxStepTokenApi/app.py b/microservices/sdxStepTokenApi/app.py new file mode 100644 index 00000000..78df3865 --- /dev/null +++ b/microservices/sdxStepTokenApi/app.py @@ -0,0 +1,48 @@ +from contextlib import asynccontextmanager +import logging + +from fastapi import FastAPI, Request, status +from fastapi.exceptions import RequestValidationError +from fastapi.encoders import jsonable_encoder +from fastapi.responses import JSONResponse + +from config import settings +from clients.step import bootstrap +from routers.routes import router + +logger = logging.getLogger(__name__) + + +@asynccontextmanager +async def lifespan(app: FastAPI): + bootstrap( + ca_url=settings.step_ca_url, + fingerprint=settings.step_ca_fingerprint, + ) + yield + + +def create_app(): + app = FastAPI( + title="SDX CA Token API", + description="API to generate one-time tokens for Step CA", + version="1.0.0", + lifespan=lifespan, + ) + + app.include_router(router) + + @app.exception_handler(RequestValidationError) + async def validation_exception_handler( + request: Request, exc: RequestValidationError + ): + return JSONResponse( + status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, + content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), + ) + + @app.get("/health") + async def get_health(): + return {"status": "ok"} + + return app diff --git a/microservices/sdxStepTokenApi/clients/step.py b/microservices/sdxStepTokenApi/clients/step.py new file mode 100644 index 00000000..d41a22b5 --- /dev/null +++ b/microservices/sdxStepTokenApi/clients/step.py @@ -0,0 +1,131 @@ +from subprocess import Popen, PIPE, TimeoutExpired +from typing import Callable +import logging +import re + +logger = logging.getLogger(__name__) + +DEFAULT_TIMEOUT_SECONDS = 30 + + +def run_step_command( + args: list[str], timeout: int = DEFAULT_TIMEOUT_SECONDS +) -> tuple[int, str, str]: + """Runs a step CLI command and returns (return_code, stdout, stderr). + + Raises: + RuntimeError: If the command times out or fails to execute. + """ + process = Popen(args, stdout=PIPE, stderr=PIPE) + try: + stdout, stderr = process.communicate(timeout=timeout) + except TimeoutExpired: + process.kill() + stdout, stderr = process.communicate() + raise RuntimeError( + f"step command timed out after {timeout}s: {' '.join(args)}" + ) + return ( + process.returncode, + stdout.decode('utf-8') if stdout else "", + stderr.decode('utf-8') if stderr else "", + ) + + +def bootstrap( + ca_url: str, + fingerprint: str, + runner: Callable = run_step_command, +) -> None: + """Bootstrap the Step CA root certificate. + + Must succeed before the app can serve requests. + Raises RuntimeError on failure. + """ + args = [ + "step", "ca", "bootstrap", + "--ca-url", ca_url, + "--fingerprint", fingerprint, + "--force", + ] + logger.info("Bootstrapping Step CA from %s", ca_url) + + return_code, stdout, stderr = runner(args) + if return_code != 0: + msg = f"step ca bootstrap failed (rc={return_code}): {stderr or stdout}" + logger.error(msg) + raise RuntimeError(msg) + + logger.info("Step CA bootstrap succeeded") + + +def _validate_subject_and_san(subject: str, san: list[str] | None) -> None: + """Validate subject and SAN values before invoking the step CLI. + + This limits the characters and length of user-controlled values that are + passed as command-line arguments, reducing the risk of abuse. + """ + if not subject: + raise RuntimeError("subject must not be empty") + + if len(subject) > 255: + raise RuntimeError("subject is too long") + + # Allow common characters used in DNS names, emails, and IPs. + pattern = re.compile(r"^[A-Za-z0-9_.*:@\-]+$") + if not pattern.match(subject): + raise RuntimeError("subject contains invalid characters") + + if san: + if len(san) > 100: + raise RuntimeError("too many SAN entries") + for entry in san: + if not entry: + raise RuntimeError("SAN entries must not be empty") + if len(entry) > 255: + raise RuntimeError("SAN entry is too long") + if not pattern.match(entry): + raise RuntimeError("SAN entry contains invalid characters") + + +def generate_token( + subject: str, + san: list[str] | None = None, + provisioner_password_file: str = "/etc/step-provisioner/password", + provisioner_kid: str = "", + provisioner_issuer: str = "", + runner: Callable = run_step_command, +) -> str: + """Generate a one-time token via ``step ca token``. + + Returns the token string on success. + Raises RuntimeError on failure. + """ + _validate_subject_and_san(subject, san) + + args = [ + "step", "ca", "token", subject, + "--provisioner-password-file", provisioner_password_file, + ] + + if san: + for s in san: + args.extend(["--san", s]) + + if provisioner_kid: + args.extend(["--kid", provisioner_kid]) + + if provisioner_issuer: + args.extend(["--issuer", provisioner_issuer]) + + logger.debug("step ca token: subject=%s san=%s", subject, san) + + return_code, stdout, stderr = runner(args) + if return_code != 0: + msg = f"Failed to generate token: {stderr or stdout}" + logger.debug("step ca token failed: %s", msg) + raise RuntimeError(msg) + + token = stdout.strip() + logger.debug("step ca token succeeded for subject=%s", subject) + return token diff --git a/microservices/sdxStepTokenApi/config/settings.py b/microservices/sdxStepTokenApi/config/settings.py new file mode 100644 index 00000000..5ef47dca --- /dev/null +++ b/microservices/sdxStepTokenApi/config/settings.py @@ -0,0 +1,15 @@ +from starlette.config import Config +import os + +config = Config(env_file=".env" if os.path.exists(".env") else None) + +log_level = config('LOG_LEVEL', default='DEBUG') +step_ca_url = config('STEP_CA_URL', default='') +step_ca_fingerprint = config('STEP_CA_FINGERPRINT', default='') + +provisioner_password_file = config( + 'STEP_PROVISIONER_PASSWORD_FILE', + default='/etc/step-provisioner/password' +) +provisioner_kid = config('STEP_PROVISIONER_KID', default='') +provisioner_issuer = config('STEP_PROVISIONER_ISSUER', default='') diff --git a/microservices/sdxStepTokenApi/entrypoint.sh b/microservices/sdxStepTokenApi/entrypoint.sh new file mode 100644 index 00000000..791d2e7e --- /dev/null +++ b/microservices/sdxStepTokenApi/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exec /opt/venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 8080 diff --git a/microservices/sdxStepTokenApi/main.py b/microservices/sdxStepTokenApi/main.py new file mode 100644 index 00000000..023c5f18 --- /dev/null +++ b/microservices/sdxStepTokenApi/main.py @@ -0,0 +1,46 @@ +from config import settings +import logging.config + +logging.config.dictConfig({ + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'json': { + '()': 'pythonjsonlogger.json.JsonFormatter', + 'format': '%(levelname)s %(name)s %(funcName)s %(message)s', + 'timestamp': True, # Adds ISO-8601 timestamp field + 'reserved_attrs': [ # Exclude uvicorn's color_message field + 'color_message', 'args', 'created', 'exc_info', 'exc_text', + 'filename', 'levelno', 'lineno', 'module', 'msecs', 'msg', + 'pathname', 'process', 'processName', 'relativeCreated', + 'stack_info', 'thread', 'threadName', 'taskName' + ], + }, + }, + 'handlers': { + 'console': { + 'level': settings.log_level, + 'class': 'logging.StreamHandler', + 'stream': 'ext://sys.stdout', + 'formatter': 'json', + }, + }, + 'loggers': { + 'uvicorn': { + 'propagate': True, + }, + 'fastapi': { + 'propagate': True, + }, + }, + 'root': { + 'level': settings.log_level, + 'handlers': ['console'], + }, +}) + +from app import create_app + +logger = logging.getLogger(__name__) + +app = create_app() diff --git a/microservices/sdxStepTokenApi/poetry.lock b/microservices/sdxStepTokenApi/poetry.lock new file mode 100644 index 00000000..ff7613a6 --- /dev/null +++ b/microservices/sdxStepTokenApi/poetry.lock @@ -0,0 +1,694 @@ +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. + +[[package]] +name = "annotated-doc" +version = "0.0.4" +description = "Document parameters, class attributes, return types, and variables inline, with Annotated." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, + {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anyio" +version = "4.13.0" +description = "High-level concurrency and networking framework on top of asyncio or Trio" +optional = false +python-versions = ">=3.10" +groups = ["main", "dev"] +files = [ + {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, + {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, +] + +[package.dependencies] +idna = ">=2.8" + +[package.extras] +trio = ["trio (>=0.32.0)"] + +[[package]] +name = "autopep8" +version = "1.7.0" +description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "autopep8-1.7.0-py2.py3-none-any.whl", hash = "sha256:6f09e90a2be784317e84dc1add17ebfc7abe3924239957a37e5040e27d812087"}, + {file = "autopep8-1.7.0.tar.gz", hash = "sha256:ca9b1a83e53a7fad65d731dc7a2a2d50aa48f43850407c59f6a1a306c4201142"}, +] + +[package.dependencies] +pycodestyle = ">=2.9.1" +toml = "*" + +[[package]] +name = "certifi" +version = "2026.2.25" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, + {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, +] + +[[package]] +name = "click" +version = "8.3.1" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, + {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} + +[[package]] +name = "coverage" +version = "7.13.5" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5"}, + {file = "coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930"}, + {file = "coverage-7.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0"}, + {file = "coverage-7.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0"}, + {file = "coverage-7.13.5-cp310-cp310-win32.whl", hash = "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58"}, + {file = "coverage-7.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d"}, + {file = "coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743"}, + {file = "coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd"}, + {file = "coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8"}, + {file = "coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf"}, + {file = "coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9"}, + {file = "coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01"}, + {file = "coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256"}, + {file = "coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf"}, + {file = "coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c"}, + {file = "coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf"}, + {file = "coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810"}, + {file = "coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1"}, + {file = "coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a"}, + {file = "coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6"}, + {file = "coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17"}, + {file = "coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85"}, + {file = "coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b"}, + {file = "coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d"}, + {file = "coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd"}, + {file = "coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479"}, + {file = "coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2"}, + {file = "coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a"}, + {file = "coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819"}, + {file = "coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f"}, + {file = "coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6"}, + {file = "coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0"}, + {file = "coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0"}, + {file = "coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc"}, + {file = "coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633"}, + {file = "coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b"}, + {file = "coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90"}, + {file = "coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea"}, + {file = "coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a"}, + {file = "coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215"}, + {file = "coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43"}, + {file = "coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45"}, + {file = "coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61"}, + {file = "coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179"}, +] + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "fastapi" +version = "0.135.2" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "fastapi-0.135.2-py3-none-any.whl", hash = "sha256:0af0447d541867e8db2a6a25c23a8c4bd80e2394ac5529bd87501bbb9e240ca5"}, + {file = "fastapi-0.135.2.tar.gz", hash = "sha256:88a832095359755527b7f63bb4c6bc9edb8329a026189eed83d6c1afcf419d56"}, +] + +[package.dependencies] +annotated-doc = ">=0.0.2" +pydantic = ">=2.9.0" +starlette = ">=0.46.0" +typing-extensions = ">=4.8.0" +typing-inspection = ">=0.4.2" + +[package.extras] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] +standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.8" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be"}, + {file = "httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "idna" +version = "3.11" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.3.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, +] + +[[package]] +name = "packaging" +version = "26.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, + {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pycodestyle" +version = "2.14.0" +description = "Python style guide checker" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"}, + {file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"}, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, + {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.41.5" +typing-extensions = ">=4.14.1" +typing-inspection = ">=0.4.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"}, + {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"}, + {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"}, + {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"}, + {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, + {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, + {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, + {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, + {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, + {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, + {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"}, + {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"}, + {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"}, + {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"}, + {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"}, + {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"}, + {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"}, + {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"}, + {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"}, + {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"}, + {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"}, + {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"}, + {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"}, + {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"}, + {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"}, + {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, + {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, + {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, +] + +[package.dependencies] +typing-extensions = ">=4.14.1" + +[[package]] +name = "pygments" +version = "2.19.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "8.4.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, + {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "5.0.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, + {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-json-logger" +version = "3.3.0" +description = "JSON Log Formatter for the Python Logging Package" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7"}, + {file = "python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84"}, +] + +[package.extras] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] + +[[package]] +name = "starlette" +version = "1.0.0" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "starlette-1.0.0-py3-none-any.whl", hash = "sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b"}, + {file = "starlette-1.0.0.tar.gz", hash = "sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149"}, +] + +[package.dependencies] +anyio = ">=3.6.2,<5" + +[package.extras] +full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["dev"] +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, + {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + +[[package]] +name = "uvicorn" +version = "0.34.3" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885"}, + {file = "uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[metadata] +lock-version = "2.1" +python-versions = "^3.14" +content-hash = "90260f411a3e073063997e91b75e37697c3081e893df13bf885139dacb453860" diff --git a/microservices/sdxStepTokenApi/pyproject.toml b/microservices/sdxStepTokenApi/pyproject.toml new file mode 100644 index 00000000..25cfce39 --- /dev/null +++ b/microservices/sdxStepTokenApi/pyproject.toml @@ -0,0 +1,30 @@ +[tool.poetry] +name = "sdx-ca-token-api" +version = "1.0.0" +description = "API to generate one-time tokens for Step CA" +package-mode = false +authors = ["Your Name "] + +[tool.poetry.dependencies] +python = "^3.14" +fastapi = "^0.135.0" +uvicorn = "^0.34.0" +pydantic = "^2.10.0" +python-json-logger = "^3.2.1" + +[tool.poetry.group.dev.dependencies] +autopep8 = "^1.7.0" +pytest = "^8.2.0" +pytest-cov = "^5.0.0" +pytest-mock = "^3.14.0" +httpx = "^0.28.0" + +[tool.coverage.run] +relative_files = true +omit = [ + "tests" +] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/microservices/sdxStepTokenApi/routers/routes.py b/microservices/sdxStepTokenApi/routers/routes.py new file mode 100644 index 00000000..bc25f6de --- /dev/null +++ b/microservices/sdxStepTokenApi/routers/routes.py @@ -0,0 +1,34 @@ +from fastapi import APIRouter, HTTPException +from pydantic import BaseModel +from clients.step import generate_token +from config import settings + +router = APIRouter( + prefix="", + tags=["token"], +) + + +class TokenRequest(BaseModel): + subject: str + san: list[str] | None = None + + +class TokenResponse(BaseModel): + token: str + + +@router.post("/token", response_model=TokenResponse) +async def create_token(request: TokenRequest) -> TokenResponse: + """Generate a one-time token for the Step CA.""" + try: + token = generate_token( + subject=request.subject, + san=request.san, + provisioner_password_file=settings.provisioner_password_file, + provisioner_kid=settings.provisioner_kid, + provisioner_issuer=settings.provisioner_issuer, + ) + return TokenResponse(token=token) + except RuntimeError as e: + raise HTTPException(status_code=500, detail=str(e)) diff --git a/microservices/sdxStepTokenApi/sdx-ca-token-api-spec.md b/microservices/sdxStepTokenApi/sdx-ca-token-api-spec.md new file mode 100644 index 00000000..e9df8995 --- /dev/null +++ b/microservices/sdxStepTokenApi/sdx-ca-token-api-spec.md @@ -0,0 +1,136 @@ +# SDX Step CA Token API — Microservice Spec + +## Purpose + +A FastAPI microservice that wraps the `step ca token` CLI to generate one-time-use tokens for the Step CA certificate authority. Callers use these tokens to obtain X.509 certificates from the CA. + +This service runs in the same OpenShift namespace as the Step CA server and is accessed only by other services in the namespace (no external route). + +--- + +## API Specification + +### `POST /token` + +Generate a one-time token for the Step CA. + +#### Request Body + +```json +{ + "subject": "my-service.clients.sdx", + "san": ["alt-name-1.clients.sdx", "10.0.0.5"] +} +``` + +| Field | Type | Required | Description | +| --------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `subject` | `string` | Yes | The Common Name / DNS Name / IP for the certificate. Must match one of the CA template rules above. When there are no additional Subject Alternative Names configured (via the --san flag), the subject will be added as the only element of the 'sans' claim on the token. | +| `san` | `list[string]` | No | Additional Subject Alternative Names (DNS, IP, email, URI). | + +#### Response `200 OK` + +```json +{ + "token": "" +} +``` + +#### Response `500 Internal Server Error` + +```json +{ + "detail": "Failed to generate token: " +} +``` + +### `GET /health` + +Basic health/readiness check. + +#### Response `200 OK` + +```json +{ + "status": "ok" +} +``` + +--- + +## Implementation Details + +### CLI Command Construction + +The service shells out to the `step` CLI. Example invocation: + +```bash +step ca token my-service.clients.sdx \ + --provisioner-password-file /etc/step-provisioner/password \ + --san alt-name-1.clients.sdx \ + --san 10.0.0.5 +``` + +- `--provisioner-password-file` is mounted as a Kubernetes secret. +- `--san` is repeated for each entry in the optional `san` list. +- All other flags use CA defaults (provisioner selection via `--kid`/`--issuer` may be needed depending on the provisioner config in tfvars — check at implementation time). +- `--ca-url` and `--root` are omitted; they come from environment / bootstrap (see below). + +### Startup: Bootstrap Root Certificate + +On startup (before serving requests), the application must bootstrap the root CA cert: + +```bash +step ca bootstrap \ + --ca-url $STEP_CA_URL \ + --fingerprint $STEP_CA_FINGERPRINT +``` + +This writes the root cert to `~/.step/certs/root_ca.crt` (the default `STEPPATH`). After bootstrap, subsequent `step ca token` commands can omit `--root` entirely since it becomes the default. + +Run this as part of application startup (e.g., a FastAPI lifespan event). If bootstrap fails, the service should not become ready. + +### Environment Variables + +| Variable | Description | Example | +| --------------------- | --------------------------------- | ----------------------------------------------------- | +| `STEP_CA_URL` | In-cluster CA URL | `https://sdx-ca-step-certificates.b8840c-dev.svc:443` | +| `STEP_CA_FINGERPRINT` | Root CA fingerprint for bootstrap | `abc123...` (SHA-256 hex) | +| `LOG_LEVEL` | Python log level | `DEBUG` | + +### Mounted Secrets + +| Mount Path | Source Secret | Description | +| -------------------------------- | ----------------- | ---------------------------------------------------------------------- | +| `/etc/step-provisioner/password` | (TBD secret name) | Provisioner password file, referenced by `--provisioner-password-file` | + +### Logging + +Log the following on each token request: + +- `subject` +- `san` (if provided) +- Success/failure status +- Timestamp + +Use structured JSON logging to match other services in the platform. + +--- + +## Access / Auth + +- **Internal only**: No OpenShift Route. The service is accessed via its in-cluster Kubernetes Service DNS name (e.g., `sdx-ca-token-api-generic-api..svc`). +- **No authentication layer** required — network isolation within the namespace provides access control. + +--- + +## Summary Checklist + +- FastAPI app with `POST /token` and `GET /health` +- Pydantic model: `subject` (required str), `san` (optional list of str) +- `step ca bootstrap` at startup (lifespan event), fail if unsuccessful +- Shell out to `step ca token` with constructed args +- Structured JSON logging of subject/SAN on each request +- Dockerfile with Python + step CLI +- Unit tests (mock subprocess calls) +- No external route — internal cluster access only diff --git a/microservices/sdxStepTokenApi/tests/conftest.py b/microservices/sdxStepTokenApi/tests/conftest.py new file mode 100644 index 00000000..cea343ca --- /dev/null +++ b/microservices/sdxStepTokenApi/tests/conftest.py @@ -0,0 +1,10 @@ +import os +import sys + +os.environ["STEP_PROVISIONER_PASSWORD_FILE"] = "/etc/step-provisioner/password" +os.environ["STEP_PROVISIONER_KID"] = "" +os.environ["STEP_PROVISIONER_ISSUER"] = "" +os.environ["STEP_CA_URL"] = "https://test-ca.invalid" +os.environ["STEP_CA_FINGERPRINT"] = "00" * 32 + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) diff --git a/microservices/sdxStepTokenApi/tests/test_routes.py b/microservices/sdxStepTokenApi/tests/test_routes.py new file mode 100644 index 00000000..5960f9d1 --- /dev/null +++ b/microservices/sdxStepTokenApi/tests/test_routes.py @@ -0,0 +1,94 @@ +from unittest.mock import patch +from fastapi.testclient import TestClient + +# Patch bootstrap before importing app so the lifespan doesn't try to call +# the real step CLI during tests. +with patch('clients.step.bootstrap'): + from app import create_app + + app = create_app() + client = TestClient(app) + + +@patch('routers.routes.generate_token') +def test_create_token_success(mock_generate): + mock_generate.return_value = "eyJhbGciOiJFUzI1NiJ9.payload.sig" + + response = client.post("/token", json={ + "subject": "my-service.clients.sdx", + "san": ["alt.clients.sdx", "10.0.0.5"], + }) + + assert response.status_code == 200 + data = response.json() + assert data["token"] == "eyJhbGciOiJFUzI1NiJ9.payload.sig" + mock_generate.assert_called_once_with( + subject="my-service.clients.sdx", + san=["alt.clients.sdx", "10.0.0.5"], + provisioner_password_file="/etc/step-provisioner/password", + provisioner_kid="", + provisioner_issuer="", + ) + + +@patch('routers.routes.generate_token') +def test_create_token_no_san(mock_generate): + mock_generate.return_value = "token-no-san" + + response = client.post("/token", json={ + "subject": "my-service.clients.sdx", + }) + + assert response.status_code == 200 + data = response.json() + assert data["token"] == "token-no-san" + mock_generate.assert_called_once_with( + subject="my-service.clients.sdx", + san=None, + provisioner_password_file="/etc/step-provisioner/password", + provisioner_kid="", + provisioner_issuer="", + ) + + +@patch('routers.routes.generate_token') +def test_create_token_failure(mock_generate): + mock_generate.side_effect = RuntimeError( + "Failed to generate token: error from step CLI" + ) + + response = client.post("/token", json={ + "subject": "my-service.clients.sdx", + }) + + assert response.status_code == 500 + data = response.json() + assert "Failed to generate token" in data["detail"] + + +def test_create_token_missing_subject(): + response = client.post("/token", json={}) + + assert response.status_code == 422 + + +def test_create_token_missing_subject_with_san(): + response = client.post("/token", json={ + "san": ["alt.clients.sdx"], + }) + + assert response.status_code == 422 + + +def test_create_token_invalid_body(): + response = client.post("/token", content="not json", + headers={"Content-Type": "application/json"}) + + assert response.status_code == 422 + + +def test_health(): + response = client.get("/health") + + assert response.status_code == 200 + assert response.json() == {"status": "ok"} diff --git a/microservices/sdxStepTokenApi/tests/test_step.py b/microservices/sdxStepTokenApi/tests/test_step.py new file mode 100644 index 00000000..1581af02 --- /dev/null +++ b/microservices/sdxStepTokenApi/tests/test_step.py @@ -0,0 +1,145 @@ +from clients.step import bootstrap, generate_token +import pytest + + +def mock_runner_success(args): + """Simulates a successful step CLI invocation.""" + if "bootstrap" in args: + return 0, "The root certificate has been saved.\n", "" + return 0, "eyJhbGciOiJFUzI1NiJ9.test-token-payload.signature\n", "" + + +def mock_runner_failure(args): + """Simulates a failed step CLI invocation.""" + if "bootstrap" in args: + return 1, "", "error connecting to CA: dial tcp: connection refused\n" + return 1, "", "error generating token: unauthorized\n" + + +class TestBootstrap: + def test_bootstrap_success(self): + bootstrap( + ca_url="https://ca.example.com:443", + fingerprint="abc123", + runner=mock_runner_success, + ) + + def test_bootstrap_failure_raises(self): + with pytest.raises(RuntimeError, match="step ca bootstrap failed"): + bootstrap( + ca_url="https://ca.example.com:443", + fingerprint="abc123", + runner=mock_runner_failure, + ) + + def test_bootstrap_args(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "ok\n", "" + + bootstrap( + ca_url="https://ca.example.com:443", + fingerprint="abc123", + runner=capturing_runner, + ) + assert "step" in captured_args + assert "bootstrap" in captured_args + assert "--ca-url" in captured_args + assert "https://ca.example.com:443" in captured_args + assert "--fingerprint" in captured_args + assert "abc123" in captured_args + assert "--force" in captured_args + + +class TestGenerateToken: + def test_generate_token_success(self): + token = generate_token( + subject="my-service.clients.sdx", + runner=mock_runner_success, + ) + assert token == "eyJhbGciOiJFUzI1NiJ9.test-token-payload.signature" + + def test_generate_token_failure_raises(self): + with pytest.raises(RuntimeError, match="Failed to generate token"): + generate_token( + subject="my-service.clients.sdx", + runner=mock_runner_failure, + ) + + def test_generate_token_with_san(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "test-token\n", "" + + generate_token( + subject="my-service.clients.sdx", + san=["alt.clients.sdx", "10.0.0.5"], + runner=capturing_runner, + ) + san_indices = [i for i, a in enumerate(captured_args) if a == "--san"] + assert len(san_indices) == 2 + assert captured_args[san_indices[0] + 1] == "alt.clients.sdx" + assert captured_args[san_indices[1] + 1] == "10.0.0.5" + + def test_generate_token_without_san(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "test-token\n", "" + + generate_token( + subject="my-service.clients.sdx", + runner=capturing_runner, + ) + assert "--san" not in captured_args + + def test_generate_token_with_provisioner_flags(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "test-token\n", "" + + generate_token( + subject="my-service.clients.sdx", + provisioner_kid="my-key-id", + provisioner_issuer="my-issuer", + runner=capturing_runner, + ) + assert "--kid" in captured_args + assert "my-key-id" in captured_args + assert "--issuer" in captured_args + assert "my-issuer" in captured_args + + def test_generate_token_without_provisioner_flags(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "test-token\n", "" + + generate_token( + subject="my-service.clients.sdx", + runner=capturing_runner, + ) + assert "--kid" not in captured_args + assert "--issuer" not in captured_args + + def test_generate_token_subject_in_args(self): + captured_args = [] + + def capturing_runner(args): + captured_args.extend(args) + return 0, "test-token\n", "" + + generate_token( + subject="my-service.clients.sdx", + runner=capturing_runner, + ) + assert "my-service.clients.sdx" in captured_args + assert "--provisioner-password-file" in captured_args From 63d2213ac44dadb8b493e3c9e7eef61093f42c2e Mon Sep 17 00:00:00 2001 From: Russell Vinegar Date: Thu, 26 Mar 2026 10:30:22 -0700 Subject: [PATCH 4/5] remove old /docs dir --- .github/workflows/gh-pages.yml | 18 --- docs/AVAILABLE-PLUGINS.md | 3 - docs/COMMON-CONFIG.md | 3 - docs/OCP4-MIGRATION.md | 153 ------------------ docs/SSL.md | 3 - docs/guides/assets/oauth2.png | Bin 186080 -> 0 bytes docs/guides/intro-signed-jwt.md | 3 - docs/guides/tutorial-idp-client-cred-flow.md | 3 - docs/guides/user-journey.md | 3 - docs/samples/service-plugins/service-acl.yaml | 12 -- .../service-plugins/service-gwa-endpoint.yaml | 10 -- .../service-gwa-ip-anonymity.yaml | 11 -- .../service-ip-restriction.yaml | 10 -- .../service-plugins/service-jwt-keycloak.yaml | 29 ---- .../service-plugins/service-key-auth.yaml | 9 -- .../samples/service-plugins/service-oidc.yaml | 26 --- .../service-plugins/service-rate-limit.yaml | 25 --- .../service-request-transformer.yml | 32 ---- .../service-plugins/service-spec-expose.yaml | 10 -- docs/static/openapi/.env | 4 - docs/static/openapi/kong-with-edits.yaml | 21 --- docs/static/openapi/simple.yaml | 26 --- 22 files changed, 414 deletions(-) delete mode 100644 .github/workflows/gh-pages.yml delete mode 100644 docs/AVAILABLE-PLUGINS.md delete mode 100644 docs/COMMON-CONFIG.md delete mode 100644 docs/OCP4-MIGRATION.md delete mode 100644 docs/SSL.md delete mode 100644 docs/guides/assets/oauth2.png delete mode 100644 docs/guides/intro-signed-jwt.md delete mode 100644 docs/guides/tutorial-idp-client-cred-flow.md delete mode 100644 docs/guides/user-journey.md delete mode 100644 docs/samples/service-plugins/service-acl.yaml delete mode 100644 docs/samples/service-plugins/service-gwa-endpoint.yaml delete mode 100644 docs/samples/service-plugins/service-gwa-ip-anonymity.yaml delete mode 100644 docs/samples/service-plugins/service-ip-restriction.yaml delete mode 100644 docs/samples/service-plugins/service-jwt-keycloak.yaml delete mode 100644 docs/samples/service-plugins/service-key-auth.yaml delete mode 100644 docs/samples/service-plugins/service-oidc.yaml delete mode 100644 docs/samples/service-plugins/service-rate-limit.yaml delete mode 100644 docs/samples/service-plugins/service-request-transformer.yml delete mode 100644 docs/samples/service-plugins/service-spec-expose.yaml delete mode 100644 docs/static/openapi/.env delete mode 100644 docs/static/openapi/kong-with-edits.yaml delete mode 100644 docs/static/openapi/simple.yaml diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml deleted file mode 100644 index f62b5590..00000000 --- a/.github/workflows/gh-pages.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Build and Deploy -on: - push: - branches: [ dev ] -jobs: - build-and-deploy: - runs-on: ubuntu-latest - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v2.3.1 # If you're using actions/checkout@v2 you must set persist-credentials to false in most cases for the deployment to work correctly. - with: - persist-credentials: false - - - name: Deploy - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/static diff --git a/docs/AVAILABLE-PLUGINS.md b/docs/AVAILABLE-PLUGINS.md deleted file mode 100644 index cfda916e..00000000 --- a/docs/AVAILABLE-PLUGINS.md +++ /dev/null @@ -1,3 +0,0 @@ -Current list of plugins available on the API Gateway. - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform/gateway/available-plugins diff --git a/docs/COMMON-CONFIG.md b/docs/COMMON-CONFIG.md deleted file mode 100644 index df9987b3..00000000 --- a/docs/COMMON-CONFIG.md +++ /dev/null @@ -1,3 +0,0 @@ -# Common Gateway Controls - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform/gateway/common-config diff --git a/docs/OCP4-MIGRATION.md b/docs/OCP4-MIGRATION.md deleted file mode 100644 index 04c4558c..00000000 --- a/docs/OCP4-MIGRATION.md +++ /dev/null @@ -1,153 +0,0 @@ - -# Upstream Services Migrating from OCP3 to OCP4 - -## What do I need to do to setup my Service on the new APS Gateway? - -### Configure the APS Gateway - -As part of migrating your service to OCP4, you will need to prepare the Gateway configuration for your Service. An example of what it would look like: - -``` -services: -- host: ..svc - name: - port: 80 - protocol: http -``` - -The routes will have a minor change by no longer using the `https` protocol as SSL termination will be performed at the `OCP4 Edge` and the traffic to the `APS Gateway` will be unencrypted: - -``` -services: -- host: ..svc - name: - port: 80 - protocol: http - routes: - - name: -route-get - hosts: - - kirk.data.gov.bc.ca - protocols: - - http - methods: - - GET - paths: - - "/" -``` - -The appropriate `tags` need to be added and optionally any `plugins` added. - -Apply your changes to the `APS Gateway` by running the `gwa pg` command (see the [API Provider Flow](/USER-JOURNEY.md) for detailed instructions). - -### Add the Kubernetes Security Policy (KSP) - -The `APS Gateway` needs to be able to route to your service from within the OCP4 cluster. To do this, add the following KSP to your OCP4 namespace (update the `podSelector` label matching based on your Pod labels): - -``` -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: allow-traffic-from-gateway-to-your-api -spec: - podSelector: - matchLabels: - name: my-upstream-api - ingress: - - from: - - namespaceSelector: - matchLabels: - environment: test - name: 264e6f - - from: - - namespaceSelector: - matchLabels: - environment: prod - name: 264e6f -``` - -### Remove all Routes/Ingress - -In `OCP3` you most likely had routes for `*.api`, `*.data` or `*.apps`. For `OCP4` your `Pod Service` does not need to have an external route because the `APS Gateway` is acting as the entry point for your service. - -You should ensure that you do not have any routes that have the host as `*.api.gov.bc.ca`, `*.data.gov.bc.ca`, or `*.apps.gov.bc.ca`. Having routes with these hosts will conflict with the routes that the `APS Gateway` will create automatically based on your configuration. It is ok to create routes under the `.apps.silver.devops.gov.bc.ca` domain for dev and testing. - -### Regression test your Service - -Regression testing is being performed in the `APS Gateway` test environment. When you apply your changes in the test environment, your routing URLs are transformed into a custom vanity domain. - -For example, a route for `kirk.data.gov.bc.ca` results in a public route: - -`https://kirk-data-gov-bc-ca.test.apsgw.xyz` - -This is what you will use to peform your regression testing. To find out the exact public route for your services, go to the `Services` tab on the `APS Services Portal`. - - -### Switch production traffic to your OCP4 Service - -**APS Gateway Production Setup** - -When the Production instance of the `APS Gateway` is ready, communication will go out to API Owners as additional tasks will be required to enable the service on our Production environment: - -| Task | Responsibility | -| -------------------------------------------------------- | -------------- | -| Create namespace and service account on the `APS Gateway` production instance | API Owner | -| Apply your dev/test/prod Gateway configuration (either in your CI/CD pipeline or manually) | API Owner | -| Update `Kong14` Service upstream host from `https://142.34.143.180` to `https://142.34.194.118` | APS Team -| Decommission your OCP3 projects | API Owner | - -### Final big-bang switchover - -At the completion of regression testing, a big-bang switchover to the new APS Gateway will be performed by updating the DNS to point to the `OCP4 Edge`. - -| Task | Responsibility | -| -------------------------------------------------------- | -------------- | -| Ownership of the Gateway configuration transitioned to Service teams | API Owners -| Regression testing of services complete | API Owners -| APS Gateway Production Setup completed | API Owners -| **Switchover** Update DNS for *.api.gov.bc.ca, *.data.gov.bc.ca to point to 142.34.194.118 | APS Team | - - -At the time of switchover, we expect that there will be a mix of upstream services running on OCP3, running on OCP4, running on DataBC Servers and running on external cloud. But the expectation is that all the teams will have ownership of the Gateway configuration for their respective Services, and empowered to do ongoing changes. - - -# Appendix - -## Terminology - -* `WAM` : Web Application Management -* `Kong14` : The current Kong 0.14 implementation run on Data BC infrastructure (142.34.140.8, 142.34.5.17) -* `APS Gateway` : The new Kong 2.1.x implementation run on Openshift Container Platform V4 (OCP4) -* `OCP3 Edge` : The OCP3 Edge server (142.34.208.209, more known as *.pathfinder.gov.bc.ca, or 142.34.143.180, more known as *.pathfinder.bcgov) -* `OCP4 Edge` : The OCP4 Edge server (142.34.194.118), more known as *.apps.silver.devops.gov.bc.ca) -* `Pod Service` : The actual Kubernetes Service that is run within your Pod (`oc get services`) -* `OCP3 Route` : A Route on the OCP3 Edge that is the relationship between your Pod Service and the OCP3 Edge - -## How it works currently - -Current (Oct 2020) flow for `*.api.gov.bc.ca` and `*.data.gov.bc.ca` domains where the upstream is on OCP3, is: - -`Internet` -> `Kong14` -> `OCP3 Edge` -> `Pod Service` - -On `Kong14`, a Service example looks something like this and is administered via email to David or Craig, and they use Konga: - -``` -services: -- host: 142.34.143.180 - name: apidata-ocp-https-kirk-jobs - port: 443 - protocol: https -``` - -With the route: - -``` - routes: - - hosts: - - kirk.data.gov.bc.ca - protocols: - - http - - https -``` - -The `kirk` team is then responsible for creating an `OCP3 Route` and the `Pod Service`. - diff --git a/docs/SSL.md b/docs/SSL.md deleted file mode 100644 index f6bee911..00000000 --- a/docs/SSL.md +++ /dev/null @@ -1,3 +0,0 @@ -# SSL Termination - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform/gateway/ssl diff --git a/docs/guides/assets/oauth2.png b/docs/guides/assets/oauth2.png deleted file mode 100644 index 3e6450d3c4089d1d5a50ad1a5be4b0561a72d79f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186080 zcmdqJ^-~^QvjvI<270#J?AzC~t`nt;y3EMtL-OC`@oM!GA77f+1<`u>bw1{;&|z zE5gRP4k`crTWZ_s?|<+3d!r93aHm$VWjv$Oe=kR2{eb+RM*{bwlEG5jBE&>Ynb7`^ zA#bbpep>$@1O8b~7z&)inzTltS@vJE{<*|A9`O9v8-xl5llqCv$s1`LWHu)P28hiny`{+|sY_4P(?KwYHPDfsVgl3uwY{IBg1BN0WF z-@+op&mU3#-%S&H+ce1k-k$%zZQ4EyY+ZQHu_n zcluE&+fS`dBfPzN5#a9pwNUq7D7;T|J+CN`yas2^qiSo*J&%_b>QEaY(UnA>p*kxK zVtfSBDaf!gtEexj(zDJVzc_avGe3HKB-^TK8O1vCb07d*l^a3Z~CCL?~0p^fjr0Y{6DyET9hPQ z`lAm|I0k+j-UDTV62{JKSNVyzYEXpMw*{uYi=*9X0DgFYkn`79CyQZsK40qZ-y;c^ z7-PPCX*Z2TEX#FgkZ*Y}NlaOifJjtI0}=ZOVT&7CG6%c93oYo(=}rR)#uTD};of&I zsKnsT7dSYBSjs1A@BC>P$#e{EaaZ$hQvHcM$Hq8J7O8M=S;`^xzqxibp0G zyb|v+1-h!U$ba;f zx1r76{~I1WvB1$ANWG|qoQ=rktC4?{yw5VJFfV%-ngpQ`0`4oGQ0f4UDl*0P;X^|f zA`$t*{vjl?DjB?qHXW7toIc=>{8aURJ$JX)Xd7;k@NTpue4XFjRiHi4cD z-nrB(1@qFSKd2wgJ|*D$lzbAD_9B^6n8smWm7Yo>v!8qK5m0AC6xj|lE+}hgEkjmv z8b`Jv{1#4-{|zS@q28zs(+H@#TIR56{^Xw$tJGAopTn*=NC07@@=S!boLH44q)n=&hxi?=(o^bdB{t*_B0{RiKV0 z2pT%+e^TX>9b_Kh^1ovENUAS!P^$Zi%Y;_=(Xe#%AnH5rrJS339PGBif zP8>YfPD|QVZNW*+SEOn(m7|UmLp8C;-vG&UCl8THW_Bi!fq#;p~K_h~b$C*KIvuXXR4ZGwK?g8yPT+FsOXI?B8Sm4&r{g zhxzQPFId_M9>QOC@#`-Kqp>bwuvp>}6?V*Fe=l0~EALw4$gg-IIPc4dntWP629k43 zz!)ldV^T3i?kW1%WAjN;JK>@(L+b0M6RK!=4`1)%2y9bp8PV#j9uh_=nUnvDhX|9b z^$b*8CDqFusN-NU=3&ui73PU450h`+rHC*0LZT6&B6IA`e^{f2SQdTrID-Fp99YP* zx6&?o^MG|=RZOE)T|r!uczzfbei>|?ap=7bg-qWWR&{aUD6?1iSNst4_df^kI_;}8 z<5fx!tL++TIRhGPqeXwQ`_DI(N?Qd_XLt>ybH7L#lLjaq409D>&Lu$_-VzK8N~|%CgCJTb%yxMT>x)1%ufZj-gb#Eh5nQS5ky=xSxUg zQrzU;SS&x0nH<4uw1XxK)eXq8Ai6vCR<&$EWi6d# zhWBy7GOL8RO|LM<5eGATztRGb-yoD(r9=KdTkHS_bx|ns<8|RX8b%_7XwwWMdS2+Y z^J^TF?F=rq;YO!VaBy(vRK860W6`FwLB9a=8HWT!1Y!y!tASLB14!BF!=Is?cQWZ9 z%%+9(k=Bo36a1Hm<1eeHRVR<%C*5|0!2R?*7n;8b#&c`NG=?Jkk0#)-NQ|Iq>2FSW z*{8fy!_LWerkIi-2pBLM?K~*VI-x4cVW+%~y-s5EM12pCg#285l^+YY^;+(;f=V$VBL~Q zeQ7qWKJVAtqhu;O2#+|hx5HV-J7yHkUx|b+4)Iv5LgGmu@ewrx(?s>w*j5VVA3;X@pz8GgxHK z4KMoBw)M}J< zceJ1rK5gL)@<>h?$7`g!i{r&X99OV$&fid?y_B24m+0Ti@`^02Y$oUv3sApW-Qzs? zBc)zziiG8U#w$+jPDYlq&3v=4{cYK*VRL-QOJu#wIQ@CxsLFbkyXnQo>k+@A(V49M z=@5VP(G@&2H1w=cKsOj$*B$rqgc+V9!7=BdT(5&@-Q)7T+{1BkH?!P_7Gmh()qSKRg6uO>77r>vL2(#m$tingPQmJh%Ck7Cf4!v%EQ zU{ou0BVL{#w<~Do^;Z@kKj>#+Fk7#1hU2lpe_wT>>JJ}$ujq8+j}Xw9;d)rSA43q; zRC^-yl1Pd8IM$xbcLdjZv!!(B)MbcCuMy6MkHGAFrqBCwx1D^u&T;-!YHxd;kYu#E z1<`uejc|9CKk#j;Nlm}9?Y5uiwAByxGpqbhsNirR1A7!>6O+xO%8vfb+#p<)7(#-w zgpl0f_vPt6spacrv?kOwC@Hv0_+_Q1@&Md(q;BPI`ZsJ@K&husJ|;Jyt{+i*`$wqc zBjR&68J>2WlSOjd67ajb;2{$}YGKZU9UL4qK1}S9Gx8I~ow|cz>o~-~@wlde(wq0z z9<%4qo_Fp#UY~8~AOEP7F<5k?4P*pvM+p!$K|Tf_Sj%O-?DIM2`Kw8-+$?`5{?jo4 z%X_)+l^es6?K32K1Vo>zI;NccclXogs267C!EJ%?E_a z_w(5X=hHrO>Pt%f6i)S&+x2BpqJQU_(}u<-~1xvY{hTDkfhgBrco=(;I`odQ?)a#b~ah2cD7-}dVUUbx|Q~M*YHF_ zPyeQt$!IW|H2I@BdVwy_ujF^r(+uPrB{an)&b#pkyW>cbc)*tM;&@3>Ga8BD0Zq^g0! z7MrpKp`^ln0`aP}hkO`B$M^)v*!sl%(T&XZ{&$km?r2I;Sy^uuRfZqW>pkq&7RLF$ z-|c3OOhso~gLW9*i)WhlYnB9Y|Co|>|HCJ(Z^JZ&l3%XVY}%Q7j~~CwFK_fM)H3xC zC(!+V3L7U3k|1hCF_Ud2u-_X`FlwDJdHs%j((+7cSr#@RhOHYszwQj#W?%E|nr(hF zR)+Dt*h%_yWX}vfljD+opW$YAfba@C!wVwcG`cJ_?PJYUiGMoxP9gm5$}|R2tpU^9NE1|fmZ|r zbdmOVZEND)N7n{AFC3DQUqq!%ncx;{AQC)nh&wK6zq0=(XQo-)$*;B$`DGX%k4awq zni(AIH0n^CSAJ-&fYHf68hKHn#i$nuS+kXrJw-JVQ|F z^RYF6fsd?tDke(bpj;=TxM1*d<}HbBd}*E1f%JBVxSeSW1uSj}wB@T}#j?WhJS_+$ zI~RVD=uzU!dv78?2tG-dvg{>l*TgGZWY@NseW|b#>Q44@vq~k2XN;|S144d}15!UM zI>BP(SO?qjt85=RB+Ce~FceLA z%ms%l?u&e#RuR`neR06qKAc8YeEREb!C)a;H`%q(AJ6D79sXo??w)U1>=qeXg7nlN zK(%ULO1PrF5-jVo&EZ~$?!|Tfa`ICpvt|JyZH>r&R&wLpqt-EqtgWO;;5FCm7&ey| zz<~{m*HVeM4)|^Xu86+v6YnVwZM;mIIk8q)uLQYltx^WP<(7&J?{v3p>w+|tyQSI$ zuHT`|(S@P%4NY22AZoZgis4dE~4dJAjU(pRn8s%-#GcNy@Wlpd@`L&ACELRZ5 zC-x1bEGqau$wZ#4nhKRghE0#Yu|KM{gq6z8dHQxQ334)3@Vm{@x@72RZ{C~Gm6Ua+ z<}n>=PVdEMEuNJGg{H~~<=Uw!f>j+sXld9Y2l7hwr^~^x6d#)p*A+J7&1kU<+AG4O z!YdSK>Rc-MQXw54<*Av^J~Y9G$%HPtuoVyE@%!F zd#2=5<5o$j?RxHK!{ep8{pmuKHFqmyInI0KR?cnDboR|yFyGNIBWB-eW8Lo3Q56eo z_yv1TGq1<uC zUP!HY+^$aLyT zKE3^Yb>zhG+pO>HN^Gh%Y|XLKV0MWoYr~263S*`an#m~t(j3*H}Toi zCg#tvT-~VLktGa**QS@Ukq6%vyNip|&k@PcAISEo8RYh7 zuvvPo3wjxP*=3Xd2{3|1iD8**#FQ7| zNqFC_5sAcP#F2km({sI2y&~`=iR9nKS-G8fjERXMO(a4an{|H3=QzJN%i0u}E|6L- z*^c7I=`%^V+d4W8_*q@s6;Gq|VY4jm{AEBdcyF1)pBeW;6+POl!#@9-ouF=XKqXMwRddJb5eH zXMW~4A7xYdCzorqLotoI5Wcr)AAq@>-wY;??1Uk9_wIPUrrj|HZ6@H}ZdE4<^aWtQ zLZ9;9QuC+YLR)uuy*oTQLc_%k$<#>UJRgLtUMH2%pAt)wEQB5>%~sw8-Z3Uzfz7fM zqOKi+TE}`2Z^9^_Mx>JhntJ^LZFqi6$haGO(BfPqnKdSo;s3rJQB6m-yTF51bMTJf64y}&&I|!MQCub zGt{_`Qb@|4U+7#%*nEo9`fx~hcQtaVQ00KT>+wQ?%zGy2es-e8c|T)|^LQ=eQfyG!7eaRm)ts-z*&w z(9khIpBKJJQkAM%sgy>`1u7bJ=Z?-BS(J4X_Zn5??9jzCy1*((H7yypE3NlWwxpmp zOfIwPRR5FFNh1J`im%|uK(v&2c@7(l6f#T#2Nrp-IfF_uj(vJw#EX^na#Y|~=P<0? z^))J^=l)Nze(Xm5h^?GQ>p0&}h;7$18uZW3m>XZSZntc(GZ>mIvOH^XpkU!N`@IEYfo!#Z4Y+X0K_VHBm2lbyhr+@2)YxFwQk-SpgZXGEcd>R`Y z6JCK=dkzkFMwyh=Yw9Z4qaAanV+X6g$~&@|lbe#tj}VPWD3((x!!(qvoH788BE2;B zGlqh#M>O9S9*J92^qP^5`@maf+OC>S`PWyM1igD1JZ9J=j~o?c=un-cst8egW#`Rp z#r(7baiyHgeEX_)uu4?U8+R)X8Ug5hezR<2^vB>ax2Xs$Y5fA#l>f5kz|3_mrSUSb zV`D0fxa*bw5gi&DI+^3ti}S40?|d^oMRM#<$R$$~^18<@;SC-ugx-Xn|LvL^3Q&Lv z$npJdaNb+J-J!Wz{jS#vM4x0LwFPdsuk`;ee3I?`~EM3{9jx<3+2{H#D2U70NPc;zkQBTr<|3nQ`F>z@A3XYb#+)eisS~o5QjauI*fJ+j$?f}A-WSc?_zkNalFTS$_Ov+C zprdd3_@^ft57sZ(!4tcyq$&I~g=2BMX3an|{`3<~!?%0O?qfcpxLo8ku8?w9LV*re zgtru>74^(EGoNH}p6wa$IOJ~KxdvasG^9vrJ!;Q<_%QKnL=N$(u(BPaE3sK{4zkz} zhBqqRE&D%IIwmiX-%rv#(&rx%5V!fXVtzVKGF3Wg3qn4GsQVqe>=g<2N1CcXYLZ=hQ<8Gx?=5n-PrLvRxmm;>_hyj;~-Emh?+~VR4HP zp9&kTH{x^+*~~aVkWWZ%(I4!1+#!N;*WDcx}Y`&{?lxuaVthvIQm7m^m|rhg4X)aPUWa zKKq$GI^Th^AeAZt)ixvQq}~X>TLTo;wIBm!EYQN?VmvtI9~oh_n(md_>UR`rdpQoj zASDUDakJbuNdW$-p9YvYoh0%f`WbbL{ps@{frlTdM)iSD1+3v?b#F8ct-h*?(ZWwd zogYH2I<~(IF>-zqed7(fAyDp(eSk2KYk){g5{D3S>@^9;dIAlb|blh&$5 z*6$Y5Wvw)#&343wowC6KTcFsuwBUQjnKm_zm*<|561Af&xoj6VAmN+LjybEfYcR6s zC2n}S9rNq;R#RoE*v9zFs%(hXm*b=g)qh}jv;+_;C~n=2ky4G9_%*IWKlit?1QM>2 zO4D%P{c@1su;r1glH4zYpc4IBYUD3thh;JTv%gJwfnLhUIj)2NF11|QjX@`L3IzWur-b>dz^Idh4Y9kKoAwKP%{_R78LWaSylCnol1 z8}wK=qKGTz`FCZa!k!J+;7j;GW;%{28owz1$kZQqeDLf!VZUo1YDRZi{jQ|0a{FhOC-U6(kORzp<7 zy*&N=g7%t#M$Ns!d@iG9Ac+zZ*O8#?5BF(G=~LiD@r@ihnib^MqX7qTxM6M%A{eYHo^kT_Lt^5lNX|i(QiC-&!G1(*+>?AVC z{A_WM-#M^}v?l|kY(!y&@IP9Bb3SmOVWS=vUB>KV1QG{nDDM=FD$K@~Ou~vRSo%O# zqE^=9kx&j%+Z!^~EW+8a>>NIkf9|fWqb!W1Y$C|nDCfwF5T)n-MbJ=Be1ckfd?l~; z)ovB%#qn`8W-FI|5_kr^a(7BS(q^>IN&AFf2*`m3rc>+5Rf?GPtx@sF)Q66SLr{ ze0?b&A)O{tLy!_+9Ug2hnl%xTrvsj@`?;9=^=#4^yBiu7QDocg8vb^FL=W+Vz`)O< z*mO?Ss)FR>t<>ZJtOQKz0%|>@?jn#U$R4q;M&FloS$6up(8Vr}Z~iPS9BCN&!qkZ8 zoO}rPjN$5IM}n$8jfb4Mlwix{NY2Cy##?5PL34PEyv+>1plKkE-vFlY%8l0oCi$d( z5|@F~Ll&BmR|ijIctdev+|;g^$0Snu@s5$|)rY z2M0C)b{UcR@AP~7`=wp`2Z+7GH2_d-0v&eNo%{XA>!1gOff`(OVk!Ygi)uw}^)M=L zpn~~@Rt@HtBIfe4-c;i{4Za~_sZ8ac++r9%(Kor3U~(&5DdyT7FQ?Cx?V_fs>lu>ZapxEWOga-+yRC1Az>Y(}={4u;`+O^L}`>+}p*vtlNPjbI(z^ z8mHdD)eRob5GQ_T(6#2Aw|>Cz7lcTm@^8>`(DS$M#&ga;RXyK+C#YH53!F6V z5xGBgJvu*^H|-L{(xFSyx|v5-5=1e-Ml@OSjt5?NCPcGS+EUI8Pcmi&Sdiexg(~5J z*ESmZ4Go1&2zv~ns9!F%OP;vF*W9$`nz%7}*kgiYzd;B`SZ-kZp;r_4eKCEU#Psi# zG=e{`<1cnJwMFFkB?us;EonE5{t5)CSbaRi7AXW-)h~nhWP@Z7bz*-i5av#at1$9o zAjK3*%F2p*csx60QPI-EBOxJC#*b)ooqLV21~wsXDl+7fiI<|MK7~p*F7B*WYsLp4 z(fg8U7DOKmB9FF$~7523smKB5V{hzm;-F-c;Od znp^|q(X1(w6RzhqHdWr;`?45vi4CB)(6>-+)NoI4)A7t+(f;uD>1j}Bs43@{lg_FYEA9}zR2y$6Cy_QL(n zalxscNvih@fjE6PJ>~>9r5rAdDok)e>|9uc#o{idOsu3bK-J8x_FMB9K+kvaJrh~0C)8#u3s z6Rl&9Ux|K^}-AVsFpd-P2S3U!uoFRjMMjbjMdN)vG^GY6~(2xr{j$OwHU#Q#9=~jkd`U8^C7N z5s(&!h4c(3Nn}qfG@vGVER1&+?>Vu)k@&SpC;IuuXe&$6OR~nYXl`5Lo-rFd0%9{q0>_N*n znXo0g-_qQ0S@X6(UC1Efv&-6T0R72mMjH2TnwE?3s^}j|J8h3!QJ&X1osmV_rqC_u zCXI>?5{4b8C6iHxg%K-;cE`_~XS%+8r5y;}dzXF6Y(vh@LO6(Heo_e#?*VTTC<@=V z&a+ShMKgf!b&FIEtf{@L>h-1MugHe)&MO6$NYKo7yx%C7dbY<$K~Z@Te=BmG$D@Y0}n(x>sD zAT4}J?JiegOtOk|A73IM@`j?^N&p@kw=WVD-8;U!ZEIb@!$^3YFQ7kG`j~y{`6?va zpUH5nu=L&|gMQ{MxgYW@K+jk9mLph~@W%oY2of(>oLE=lsC4EAuzE#hNsOLsL_QYV z^&x-*X&xobeK3V7?S7Ga=4>p`#ogXN3; zg)`H^u)I+)jz~#*+9AG{Zgmet2>u{LgMQz1+vMw+8YVy1N0S#q-RATo1E?)Nz}W3<8`g`Axf?qbj-UDIb%+N1k)S;fG-J;J|iW za@7+f6fc5T zirrX@L>~Qa^d*6v?H6C*=cK8*XG$7e* zx&581y*b}1c)?RSZG}~$iv^w_3_P97svT#RF_uHsk=sD&KBM-4N2I`T+Q*+hx0QK^ zW^?MB(vQw)hN#+2Ua4G6*&X~#9oNQR9TA>Z1iVRe#L6f1F__aEnj#%kB`ogg2$%8!E5V zh^J*yz=Xe;7gQDrFpbfEQSOjDOEwZ;Mv3KmsE^TJ6!PuoWyeBZXl38+U{i)X7-h46 zT5pXw^Oxw7ct3u_^V?&gIh0f@P#5+kKsPLEg zfSh90_IB2#K2IBxu#lp{zh91uC^&Cj_8PArlpYbOZNM5aH6yvb4S=Q7+EWil{3@{G zSity(Oc`qvboPXR_?FQ&L!|)a>FYfa_B25L)+pEsZyr*151ra&E>wJBv*ahGcT6v^DjmKysh1&x{fMCXU!hWwEe7 z7!R{W-@(O*zIKRRbL`jgDg9jlhZIqv?c>GPg5qy2uKm@0hg zkxZ4P6J8+ED;qB;?c@aQ0gncP@eS7s~G8*qULnWr1GUN%=ENJh^(NQ zH9c-&OSU;mxtBBwYZt0lSmW?79IcKy6+yt>Rx}inzKQ~>4^M<^@V79ramj9Q5RL=- z9WHi*Ht|k4dv=s`c?Rh7VC{O(@`#2?V_wdMCP8siFTl$Miff#k+fO=|A0rIguiV>! zbU|{69R)}MRNQF%Si)y}{j}52KF?wY9q(*95tA;N5l4LeQiVm9BxjNz#S@}LCv+S- zuRmN#pR&7o#q!X4l+Vrlyb&pLKBY#?kVN5<@R+#;0@dFJEfgVuE_|(J9E3szTSx&j z@wV8{=#7bQ;!~0~MR$MnMeB2U@VTVB7>_a;%@!b~vBXRJCP=D`!?{VnEXO7$6e#Z( zB{EwcjC;k6!yi3++F&rX!&i>F;1&{mhbmZgGwOuzEpb;~k{nl`k+1Jo&Zv zz5R(uy12!>TZH<&0I=|5gSnuBhprCmoE>t3*A_>sz3f6@LqzOimOZO)NO zacj=;mfbiDAOr@jGZ?ke78oJgci+)x;6}x_B1G4{`dMMn2ePEF_Vco(l~QgFmiOoQ zWuX75dS3+6NaXwl?{6HMf%K>9(_v5Uhtn2_@Q!`>^xKwc+ny{hvl0=b>2H@a182SA z2gx3K~pmoq_B(eA?Vlk@i@vQCU&HB@v! z-F6oHki*4GFk*W9p*JGaX=?hTU5oP}+$zc&Ft(ZSdkF!6@iW!|#CspTaPNs_?|jy+ zXzs0vL4qrM|I%<(T!?sP-kGr|m``%diKQF8N_7rgKA8V><;}bH|r&Dig z@MdYyoezIE2``zB-Jy7Tjh^fh?50(J`%#ZmTPWab&(wxiYc|o(wU=&WH^0#46M$-2 zDYmt1jmmVWRiY8&V4`lAIaJ@a)t0XWsfj*>r|DnD9M~4pHmR)_Xi}>b^PT&X=g6o0 za`u$hzEcggb^uUX7)y0iF`4>tr+bbmrK?NJl@5bQ*A)Hm}|S?0cEO&Xh~YeF)E_n ziNP*x`Ty*~h-qJ+5mce+2^m!(Z>n~}so(cD9(!mwuSndWn7ZjXknNPGZNZ3!)qs{A zT=_bbo94WTq+VBzQ)?y=qFc>YuoP!3i#IcmuOd6R`N5^)`e@$hNu$s}{*^!ZX0ojx zJ955?)7LK)P_*)Z95gMvOY4sl9KIH@STtnd{b?&As&PzYO)Z@>TCDYm{x03_+W4Hq zQTnKz*IWMh$8nIi_>J43)hQyYnud*Td_Nj2)L&!~Q$H_|e&o>!=#@p|&mFh*BU6=~ zYW#eax`wt#S&ek@RoE@;WV%It#nF?J3DuQ;zq8bC!`yy#V0b{m4LpdN`0y-Y&O}Dp zBo{_+-qe@gh$b$D(Jf)WrkU=w_({FC7^>E6Ojyn#pKHSEw98&2ypxwRmTUPYH1iu` z@s$3&YVQRt|#-IgOT3du_ zr0L%PzVHF_Sb;YcCAZIV`(?CavMWt%^|8|t8>0$^T1qpFpoY>r0LCyl&8)(z#FiVM zlTY+mv!p?PE$CGLsc(L>^^$5UFs&eYh3nyG)3Sn;bKJAc;`9t$rDhn)8WjU}!-^e( zsoX1ysen7o&AQFHAkI9gj-oAI9AX|fLrGCPGgDNy%J;$A@;zgIZCh~n>wM~Dw`kRb zlirpYozE&;b2{JogR`_kv`}p#89$-jCBWXfe*zGFL?+CO7OhNv24+uCO0Fz87>o+@ zZpp9Eo>)?%!af)VE_LTlq3bYsRps>RlPZzcr8$F()hPWlYq#y&y-b^6Oay}NZEuG? z?E`&z0%{N{nJUq~$Z!QBy)Lz0*y3jazl75H%>o`G*s^J2Lz8K@AW3PlKa_Egrn4O5 z7FsSQ5pdcQ+wLy~ns-~Q@@Lw_I~nU=Lg{kiJSnDJUDSZ72raeMMO05l;6S#zG&_jt zyTRV2#t87Ca|Q8*MnL+rSN;vae+Ih>1b;~;H5Q59~6^0y~ zcli+F=#qMzfuhgQ$jXO-X%qWh;$&1M>WNJp_6x~J;xCd@{n7cyHJ!S-^dEx1E!p3P zfJUF2kkQ5Kj}5#0(!NPA{OqOAj`K?cXH&ySQ%5YKm<%s75Z6UHp{gBwwX#C0wvIX7vP*)wV=HhqfDfKjs{S z6AM!LabIBD%J#EP=Y3JSf=aDOGfO-KoSbfIMih4KewWpw0Rl=Mp(;Jeaa|(k;d)hP zYSCd#V^iwT$Z;bjx&mp^klkRzwFG8s4gSTr4McZ3Le2cwJ0)#X z0e=fqk1h43IiA~V;pg`s$=)jYAhkbq(t2z>v~v)%+SB?<(fX&WmUwfIRsxoKis<~` z3t?`I%NZaQVW2E!XgNC7n!urLj&u9qI(9M+P3HltO!0}}qe^=jFrB34i(sD=q1@lZ z>ON-l63Vek0gI}2`PU})r7H9v^o79VUaWLesnsL(Qqz7iV-7uW0Y}zPw{RNbazLGV zSSUX#A^#_KwiPVttK@}H_k=7 zwHm?J0$H3f+`2~&hj;PrzQS*oFTv`GBD%*gpSc`un$($DF}o{|gQ&*M=tb30JGEI$ z^o08tVA~bDlZZ-m(5la>B)-@a@*>rp^_q2IWI%j&M(pm+*(hf8r=o>3C>BA*LWB9N zj@dmt--VHY__^O279q+f=yEOzJipZYE>lpEDQKhGYF2ZbaA4c1D%uws^#lS^;NZyO zX$@$BRbkYdz-qWA9Lhs^z5_7AgX{l+jAYRQW7W@R6NgWh$AbQzE(FWrRjRj?)uiT^ z-FuhaJzwR_{Y=^eB`CX=)oBt^h*A%hxY~5%cqsQ=cUbl8`G}I0f@I{vIG~ZzpR<7_OiMHmGl#;edk5cp*0JZ&FTSt^PF!pw?wRa$HF%XUfmhwj@WWxrpJ1S&>@bQgT~@odPfAl{Ho5~ZD<|ON0%N<>qmmGe$=Ta7fQ$cz>(eW_pN+$AS@St0a#Pz#UE& zBDY;v*yj5u85P=SuxwCQx1WlRlPlETM&X2lykE$W{?hL{Sm4hd(hw^z7)XtJ^+p474z;deasl<{nCC=qqS^84B+Ub)ul;~ z4}dYvZiRGeP{K&Sq8ML!3XW9%caBf6;VtC=fjs&xkdwAJHh<%QaCCIs$O2S<(Bl8J zvKYugXD6*@{py%5F;dlMM(D#kM6Sck_78m*&9~Goo3%j~<)6&wO z0b=g0PDqsaN`fFlCmjB#GZFWjMKgh>8{*eHm^JsyPl!akI8QHSwd37@ERz{fT>t5K zed&S=u8;;S{SSNh;~4l*pY&poMM!99;8@MZdua;OeVL8=VHJ!xFQY|}ySDnmelMu$ zc?1B|v+5w>BebcBiNQ!BLrnp{$AkWAvm*|lt3#MY$NeroA}$LQKD%Y7FEoO@l9J!< zuBpljw zeyl4lhHG=Z?rwFt^t3yElh_nyd1~&G6t_H{v{buZe+4$}jBrXq@$Z=AmykD7lAIe6 zyfm5Z<4665RVR#u2!jwBrGgD6uX}_@?nCOQQ?FMH6$U1z&zKw~4ipp=cYu(}_Tiv# z#H_rsZNnGAKkrlW2k!~y_|E|?F??X>FX#o07GM14NE5*9_ruO%+D$m)d~P{M7B4WiVJ!zAf=b1 zo!6KhAHICPS^oUu<9yZyWAyTLpL6kg)6miPUQOG_cDsKw-G00an5!T&$5Xzrx3l~9 za=#~Y*st`NF94Y807nsc`bI7I!{Sf(TafKeD~)=4M5y3*QSVS(gycYE!cbpdh;-Y2 zTty$bfJ`hApi9QD%4RWHsVAWD8<-|w@Q=!inEz!LeE*Xw%e_Xq zS1X`{XRBm_fZ&bwi}aXO`By^q6B2^nPFhYb@$fo49C2rFZ~N!8Tu+Wz7%X2*0n`Is-EAC4&U+0J5_Y zfN{PVsh+0$SJvZ;>Lc*9iNbj?NZwTm!~z~^85!Goo$s6ZNxHEg_OA}6V=^)rM8jRI zlXRRk(t53c5gkJ*2Ve#RuFL3}8!j7JOkWKkg00kY){#!e@^oJi*x1>zyq=HrC|1t; z@oglpsbK_0#>Nuhm0n8cU&5RunkhcAvkxtRXh zw>6hNtJ9l@CbCID8Do1S@9cOH#?-EkXqQ6G>-pp?bwSAX6;s#aT4iQ#PPz^&1fNcH zvH9>~glPbHQQB8pr|+6yO0~MN_1sDQqvwI%PJcH|Aqpxh$LEy7{;>m&-th&){t^O-Ik{9=SXdmE$|y$mk|_`6*@4EaSfADH z>UZo9ONT!vRU4pQ=a*A6XH4IEcKqxuI^9g z15*q>_he;ThV8I$crt%dWJf=|8@aA*yU~RE{2}k~1>`@FV2QXmR3a_WuZ;x?1P-wFCZ)Ij2J!ldD2Qh%d*>3Mzy%y-SH zfXx1+c4}k1kp9Y1+&!_A*U$**?G+V3=K-wukA@pe*9-bbE5{QCu!9+5vJ>mGfKAJ@ zJU?#L{>CpLo-AC1>Y#B?l~4SS7T~1yQjW&IruSIy^&yG+?&phsR~)h!iTYd1q>N`e zVm|*B;-o*VGO7aB;RA%Fy;vyppWBloQ<_Y3yuDOB)Q+toSO^uQ zA{CsCaH$5O*$a=jghZH7CC@~CTw-p60+bUx01SDclQLIu-#ia7{+j4*;m-2r;-$H^ z^#FM{SD>X`Z?vl422?d<<*W5G^?14Tl9^ml@X(+n(isY-?4xF%`%2#!6=R)U3U! zeTtetWpKX-#=P=(>jCnYRi@FxL;C+(G%fvKkHi7 zM#*X*`eN;^*3RC&XW>7w4C|b>u}!Rpv0=row+Zd8d)GP!W_ITCo6ep8a+dFDcadm7 zk_R!`$bcn?inrVS6wYtpet3cp7N)x!%zuQhhiq%({7fChOO#1`@=7~@!RmSKqM$Jy zj=N2y#0hMYz zUj*$A7jW`}qyJSXIATMUG?2WeWL6Y9I+CHq_Ga-RXK$I`xILzb^!pPmTHMc484n@f zi%O=$@VjXbrgLH8AP;Rfjl2IzHXJ0LsOup>Kox27@$#s#Zd$AJ947}wTYUIT=|6=b z9{P1Kd-Px%xBN@NQMaXlf5@h*#9uvI3&5t0ZH9XOXM*d_=gHNF9(MrIN(8zNW4Zg zIkADsFpD*)uwh^BFP07&1P@6_DEkO1E5W1_A#KeC?F8nZFTrgfqYs+fE!pI?3{Nm{%_P-4xT@HQ z+ZU8cn3t)&+9~fsJuz!`WC%&VW*7OHl#bo=Qo0wywWpG4#4)iW12Z6 zb4@=9J=weV0!?~1ZhV(QEHFMhkvp;DH5oO4;k)ga&h#9%cjR%e9Ezjz^Qz~t=4Lf@ zE8O1$WcgKbKo<_7$9vrq7%g1&$q@@IGLCSHDWCwR{G%6usre5BrS)L5Y2N#oB>7$& zD_i-yD_PolFvj7iIR=vJSU(IQ1$|=$S)lA!=iEtX;r5xSKbS4j{;0ql#KCQBxATj} z%|iq;bW66EDyXMN?GBjfVvy3a7g^4$9zZ4G9!i&)>T|Q@11ULSzUWIPqz%Suvn$tw zYCt}`a_A#_HGUSM!QfMY&EJMOL>D5IepCMVN*=wkj;e-Sk>-Y;0QRli$x?^R;0Q~! z(H%)%$?^o_J(C%GB2!N&wp|Q|wWACfL9$c_0yyCK0iBeN0Ti)~pFEughL&$KT`p3X z8xQCyte1PF1pXhs&MGRdplj0!fuO-%65I*y5ZnX78h3XHjk{}b3+@3Lx5nKixVyUq zf(Dzz_szfNVrI?FS$)}c&aT?K-u={D>aZ@j{;&Fm>q=-?)K_kky#1fTcQq!dN?pZ1 zeTC^I4BRmF62fjAv1TC7H#o;XkZ6#8lA*>PGx&cD)W#^7Wdd==_jP~rA6!U=4c+-c z`CER%3JOC>hsc`;fkT)QB^AJw{)Ee;){IG-i#dg78La|h&}WcMRhoFiq57^5?oATk z+6XFru503^kz7e^rn=HiJJ%D1puKnPS3d`fBealWNH zTA*Li#Ci$@or+aL!C^fgu$TBUuRxAdC36zmmgfdt%h%)F>V!=vP_?SDf4r?(AVN-Nw z2G4{qEIPyB-DY~RC7xngnXNA}Xpy)!70D{PbS75SWQHghOZ2L^@^z@e5%d~cw808) z(5AK6k~xzQ2>z+SW0RHYur#3{lT1E(S(LDsnO~jO)DVlwamJVUqEU>u*VR!v?7q*$ zk;w5td(aj;AeMLzmq=nFM6g_0rdw*OUu5Mj1LON!$B}K!VbjTemKkiHhdyj)JjR3*F+7hdEpJ;x};!cBv4ZU?p+lC4TU4bPwQpf<`6alu|Hat3aJc4eJ zuE}6pkSN8QJ(IXUv8@GH>_LO5YUyk;dfo1ulBT5^))jI@X3;<^sNnZ8XTgA4tR2%E ziL#^snO zbY+W^d!fZ074y8Uy zdi)O-_jOd68fI>HOVtURXZ&DxTqYLv=zl6QXmT{42XZKFJq z0!1214G@iCmd)X0sODIliLhCOe$Z}4Bp)I}W@QUWWuXgYQVcWn_s_=$oI9H8xWB6> zA&D%TsIqF;O{!H8oQq6JUr&a3xijO6#%8by*!-QxkDxk?hiL3S%RBEq>lh<@;%bA2 zGrmZbm|#c`DJR4n#EuQmG8=Ehn;RY2<29i4x%5XC-db=2t4}>qBH!dV*&lGP?X|JY zK?+6)gzpo1x8F}%G_Dl)IB&f^t|C=HPe~`AU`1feOp2&eQU_cZ#Enr#UJlsBrHmvo zr3!y%Zj77O-53}zL?aRQq>s|&H}_hnmP%aqv~my`)jeC+Jywyaj}09u#p8w00{Ut_ zjLauHMou0Z+C(+VGb9DMKQ$US$0#8rnkd3ky__13(p&qV(a{6ydsljJ@mWy5f}#U= zW-uAaqDr+wl%JZ+Dq!BF3k}59raQ?z>uAbN4J*=SgB(vo2#DPU=X(V=uWz1x$d78& ztJP@BFJFe+vwn0-+>*PBnhvxI@L3nV3SBA&bLlpbjS^BY_2Y#(B?MuF>LG&fgSXQ? zEu0X8GPQmI5(|k$P6CDo7e7e}fFA$bkO^Ull&2^ zg?lc1S_h1Cl2Uzfyk>p)&X4&P!A+AfQI)r{N#h|{PdgJhTUY@#e~O@FT=TynzR%8f z7OA7-E1V(Z2|BU_vz_ItM_Rix^*A*+py<9glu^<2k^v3D5?JL(D7{zn)-yt-*wE{* z@h=TCUE%k>s3JJi+s(=Mp0=Q*OHHa5W*E}0`g|uUdNqM4d7+hv-2GXXOYOo2>u;|g znI?^Io(p3kZYwAOr;Oe?-! zy;aJ!Rz5}r=fUpN@}G;BCi&#$Y9+D%J6dl0AVU}O28 zvNm<=K*NEY#?~De3w$7sr1+^|Lz;1>Q-yn01w2Gp){3z9=ci`va4;mr6 z&O2Ybhm=S_ajM1kj}|ewPe_$M0h8CDrrL=nQ6ivtvn3v=Efp8b#J7!j1kA?l9-}l> z%MyT?;#o^^ zA^Q8K?|6)r2bUq4Eni1VqP9E_(Z~o4L!~};F;hEEm>zP;^wO6+&Ma{jbQJCG?lhR+MuOl8bjeGlN zRA7hDkQ9bDTsP!9y60$Ca^jL{6#fVbv?3AZuY*xoh;hoKO(u?xeb_(KQU~ z(?MWo4WOib*x)uB*0)1crvfXhNIdG3Xd%4|cJH{l^dGl%a>eCh53bD+0nFez_pnkM zC$Y*jFn^f055*Qo-a#Q=GhRcxOQu_nZJ+|Zylp9r;V+_X1MFT?TqCCEaw!O+yg2KB z+NYySU;`@Uf2m5E*VTMBrhVK(+KGOGJ!tYAXcgwO4t@1%>LHsWdd%2@?r%7Fxp?Mb zQ(U!mVpDK*WCXCFv1~pQ3S1b9rN5#7K7A{Taexo2Ccuq;!5f;tKWOb2LMTRF_RrY9 z$-P}B+BJQL&1Oi1O(H>4W`dceHzFv?3Ip6N&C(0)mPpgMw-ieh#auL5Gk5IM@~mHM z{cM@OOP*l#FbO$LE;fP&1`K#HL-4`B59)CZ=e~mC+?`cBfp(NH$Xt0O4}SS(M0aC@ zIn9CI3P4T2rgjYMLxD-ou{T~{0fa_l^{|H5Lf!|xk&jhzlfr04l_lt!YK1lPC8cfn zZO0m7T8#!l4Uj-heijo$m~H2eg^*ZT028Q!Ft9>EX_4)E|1DH5`wYXvKlx>}o!KrjBu>{${IX$pcjc$XWX1e|$sJEdFHdQUV&2Rk$V&qr zl-4OANmk+Mtjc#Hb+}KvZ-I+NxkeUP8DH{g)KUe`zDposLJRWtuT)LV-!`0v{0^tk zB=4$iGE(-}T2L0TF0}|a-eIqX%&4VZ>TS(RP5~ekoyUfk>YT-`$fFx`2aa^2(z-M) zZ%`O#ohp*M*9g#`m8*(6UcH4ZM$~-zmFF<@&I>z6no~yHzsBl8&Gy|1L*y!>_h8 z0U^EfbLXSWm;}h2v!p+TLTkUh*62e^voZ@!^l6_~f*!pa6zAtE)))ToIB*kW#nFAz zlb46Ix~#}e`;eIBiU*>b- z*fVdw8vG6~EE6vC$rX7g_+megD#S^XO{_57P;##d@gkgaHeFy|mu@JvoCLmYsfm zb_JmFM_6i4O~gyffzAp21Ql)l18sFa;YQcQGb`ThCJhR@F7NH}-y|PswqOE*+=BUJ z=VT8Qmln0xN@9fmvy~^|VU5IBU;c6aC6520e;8Zx(cj!SESf&99L2OT!CNNvnDoP> zCw^hLRZLyOFrp5_u(JO}P_0Q>Ij)j2jx30-)$}sV_^@p|? zcZP}K;c~0*b8~P=fY$)87RMmfP|kzUEE`1mEQ5ngNvX?g+^^xogP!(vvG`#_(G^M>=0HwQ&sRF1(tm=^j zMI-6ZZTR~d^zuM#6lg=P8+mtr4(Lpq zzmd{VCI3gv@}ZcX;|BlC4z3)$Y7-U*!5YFA%R_NzvymzsJ_YrIpUSg|+4{TT;>k)j zoPtIBJ_aR0dPdD%q}hB*!7@A2UcEo&jVp}x@MDzXYN2Fxrv}d?`?c@8jNp`a>gJE^ z&&VMfB01B6RL0PEqTlxJd5_YI^%*@Jb`ux>RJ1(2+pllalFUK4Bi?seQAtGi&qI zTSX@pluQbkp0LiwjLKtqM#)om=@S-&!k@{3ewYmFpGp`0$W_z|`hk#P-twW5sN?T6 zH2&gAeolMQNAWGVAu3NCy9RlCkNP--e9%KZm#tAsz`vl3#Ale zS(TnECRgF96n>}TFDkcD!Tbm*Hf!*|g4jS3BMnfRwZk8*MKwL!IXC6{ED7dLF`6S_!_c_pm zL@w+ZxN{BSKd0l-NcLwX^LkU}q7-RmFu~;AV5rR3E}`N+&X<=%ofDgfBZ3!r&P7oK zJ8X^r-uR|F^+yW>C8Sgi1pG`7>=B;m@2-ph$ce1VWlS$`;_B%XAaf)F6wMMp%7uu} zY8uCH%Y^*&q)tjJqb*cVD=ih#UPUeI3+C^&u;mXzX^J3VJOtlv)ESCZKRGadDd_U9 zHYPsNVLmpQghh;>wg)+0W6Nv36(*dRhF~@;Vx+$Cc0W zQlNXUGT(FT9eJB)(0Q0%t2NNcfLdS7w>0>_wwRfgi2UispB>irlI;p>!{n&hukWf(^d}IR&tnKPS{)@`=?^4hG|?Xk5!`$?)FW1AL~T z485t#-OwRAJAA0N|4x(Ys5IkYy(9zXUKUV)FJF$V9{Pi&pY`$+I`GW)k{;{HRYZ=? z)Q^~39UMOdUol+~U8$9OzdK$RL=^k>_&$sA6tuL~Va{j$1!#%{*R7d{zK*s>@i3e} ztaHcwxKm){hA?3~;;_5-RQj&Xf5i~daK8zWHy@fu0M>Y!22hdEfu{HD)h||o3IJ=2+>;Qb)Wj-laDyA z^}>04-G46u`pT87q~)S0xLvCqiAGi=;kN*kS?-IEZE7Uwuy|ka{$ARk=I%^@_<5Za z{@$yVcS7b`BR;$ck^~O;{P>gcw0v9{I5s`>+EX&=ymnaze6*HtSf|)sUJp0%N6#-c zNUt1Co*y((U&(Y&<~dI*=eu3wn?N{aPJT{Hux)=CU)StR`fA^T(-@uuDhzUJDr01{ zEJ!W87Tz`vJC$-HwXpzkS}OHHWN)quQa_93e#v)S9DA<@$`3H>iKG;vOu)Q!MuL63 z{f;9qJsF_VmdeU#@J+NZ28j@ns3$@6v*zJptmZL}lrl*9P0#>7Xfi~1aX-;prb)6v zok*;jlPYBJS-cC}T>)K69v8l});7n;=IS0vLVgLBU)KwKTf{74l9x|APdE)hW{_=P6`M5^T`P_3owC9<;9_UY_u$Y}tSqx84M`=$6nnbC9ek4^_^S7mH z;mUio8kjCRd)NrEC=x%Lc62=I3*X!DyREGAtkNmQ+QF5*v1KFEwq7PPshOmE?=Wi7 zmuFI1(pslRstQ{Il^L7|ks1KH+iBb54W+xkn#Pf`@>IcH!P3M=ZEuwDDE}CVF2FleEV=3nObXR z?C_#@cXGP_y;BCuq33#jqkpJ@l#LD3Gm5~!a_`G*&4u78?}GKLEwhnWvX?@s-dl~Q zrw6y)DA(^B3)9v6dY(iXZi1jegn^I2uu-yjVo;-pF2%CxS>a}>oFsK3CfUp1yiB8E zDFk^^-N&C-V#iSBsmEij&9YUM-sHbaYNyPl%vZQYhPE#KJB=D#d9b5I709P}h8$*O zzDm;yZ#3zzm2Zc0>GGd=@12>kbsfTFDkhKhsO zfqUMqo2}Uk9@`G-8P2L-T!kSZCe+ z)v-M+^zzBW+Wzn zG_=?QRfNLO=sA0OL)USfN4oLnUuwy2g=I$H&A@rODhGrt^p5v5q0HQh=pxq%V6Z}I zS@`$L$g3JTSY+%1i@cbo>ql*+<^wX5y(a=0Pn~%(-+8C0=vT|d0pl{)1sNa|Pbm#V z-2N@wcSOA!=};QG)B*4JDpxEtFUQZY@aB_{)XLs^O4#I6Puz2;BewdPhCcMO{K^`S zhU4VFj}KXh`!aeOS&P^q#4=-UqnPhM7Af~;a5h|&sRD9zPxWAqmAK=cTKI`tLKqA2 zhz_@!zvF@q_u;LjwkmIvm9j`$=r1$oR~Bj*a3S;jOLyY?$1o2@A&moZy6D@$3A}wz zXR8v=#voQuqkQ|04YA|ad0YxN_H>rp`>3d>#-};ojqubMxrM786$OAgT=B2!rzdv4 zV#Q~-qC66;cH7T%bpV*I?fwy(ZWZ+i_Rm>ADm(5`o0^(_I&M4j93x1P6_EFD!P7fa zW~$P0q|lN44cb|Mww0%CU|eO>-mAGqZlC5#(m2GSkHCU zIpr}l;YDQkKDn{_o2{3Z!1Lq2(2I%Q*nlUqM%5d@eKUESon5zGec5k&KTLZPYe@Rr zWzN5sMSe6EI!M_EUqN1T{MZauvb|3F0P^Oeh?WRF2MR#)z>=}`Q)vmHD;Zy*>ZZf}_ zykGjKZ@77#!_Faaxms9*gYP3>;dj=zZQP@|My3S;*i4k(5^{{fO01gM*kL_^R3GN7 z3Ax?&uY>plP#LJ`VoUQ&PTNabF^6T9f!=xKX`?OmTKkVKk z$XNtes@aHk_&hlb$g3NVMx~HBW(PXlZH5{jP8I%iTW`bnUM4wMDiOqtpZ+ubO=vSh zj=8I@r9#{(v}afEYNfBg-)MgVO|}w6M0Mw(gb(}v{{AN~n0gI>H}zM!si`H$GC8er?V1m%{Tl$j&29epND%43+q!mtwlz6m z5FxCAiFGcp7$FCWYQb5C--pw&>95U+q2c^ek-ZEvez#S9bFk2k#YfCJogGL8N?m4L zM4|pGwP+|52Txb$G^ZN)wVA%G?q8~v0d0Y-6aIE9(OgT^7Ki_$#3+ zgQT8E1yzRJK>>G^9_L>0D20L+ww~`<8B?18Ayq>P-HQK#++1S~Yl$8UFV+7T@Wjo;P@buhr zSGIq1uO~K5VBG=>evV3!!j@nQKtog79|*nNk5`^8|B@%V@X>KuG<5?&KB}0rf5(;U zyJEn@irI!`@(Yk3``pSPYv*0|lzz_QmKicUa6 zu>o~^{u?&xboK0X;&cPipJ==Ff$`F3{Fm)lTy&aivEDAoWxsX;-@wXkwDY?`W1}z= zlQv?+p;FDah9!{9C?Es+d#iTA(jV@_3`AuSEsl24AXrZGF}KNii77zKR=IEFGfJ@V zriX7~<(qR^hD4@&@C_+`jkcI55w>k+%+~BUS%tiB9iP$GXJ7kK#IriTx7@C0a?<0& zuU|<>af1tRy?zCf?*@dP{Ubj&BfMgm^70?HwzeD&3sbg$8G#-HH(>8i)aDG^0)V?B zoyQx2X#EgS=|r`$6fYDYxg%3d0Q$G1`TS_MG%hyQZ?h*99(JYKBxLijbi1l{fgz_~ z>A?euyxYI_Bkcf@elTg{Z$V;=>QoCMxAvr%Uo0Dmr#bN98=IrP`4k*N!qi&ov*c`J!4?LTMGk}V-2qt8BwTa?j@$~*J2-SCUFgFkt*e4@FsM7Gy} zeRl5Cb+bNOzPrr77Y2R#m&t|Vy23?h+#g*FkwxQ0klPoED$pB{qdEe>+{nhXOj@Q< z30*J#E8Z(<|E^cxYvlc}Nl^8yA9_9xo}Q@h(Rk4k&f2gj?1{{S{SX_<5U3n1pR+C6 z%B!^e3ztMYb&6DTAWtWcf~RG|vH7c+Su)kuOtFK>8i&t%0Cd z1Pc|9-a0}!-D2*gG?%hqPn&xO& zJs7~j9k8^`b*m`eTQByIuy@ZO$cZg&9434sIa0cFf;*vl6X>pYg(L$qMPsnc7OPwH zfpU%#GgZ)Q^fh%MwbcB^3H3Nepgrm`a!U$EYyD=WzVb5h6);toRSkbe2e2^ZOM-=z*3_T{+S5pKVO-G93E7)@n|SJ!hS^KiBcBsxnAdIiiyudYr$ zuAe(FW<0d2dR(?qery1(Z{@r08%^-4Z(L1(8+doS99Su zdGsFn(k)}t9A}}>C%q2K*c76h%FqU4ICZf4rF+;?Q~igze(&eLBu{j0{hr$gQ*{k@ zt4LJ5ij3%~vVHWVnRmAD+Z#vLiNFE;Oa`65GaoRgYS}h$?@nnNS$`1Vn2w-44oNZU zG@=6*>j!IXEp7`MZBms)@VQZ&Q(*|DwiugHzA_<7v#TG+j5E*#ojsoI<>S&-0PxYahI0w-L$W*l3gjqdhDJVQ?bEpgl!@V!Tf=wrl$s7hcX7v+OEF zPD2Cly5d2Rl`1GzLG_b0Xq=qrxdNflyIS=NmV@;?YI;Xz%;S_Sioh`vof*FGGQ!ID z9*5&aSjrD@Dj$Q7?Y(ne7)om>GCHs|dNuYZ82Vjwb(nMI8RY1sL|djlp9FQvYKP=m z3aQ0TJ=b9g#?oOUj8$bxj1vhK!bCl28rn(bc929)F`bjMISXNI0_VfEfSfY2(vXw& zpGtrkyo|5#uXF?Ia;oLeskZQRYVX?vyDQn z2JaiL?XM+Ny=dx=+52JM{_dCpYzH?KzF}bf;jJ5LhFn|Uz6p^nn{Z5h>*)n)`QVB$094wg`HO-lr z)?P`4n3r#fQvfX{zoT;tb6`%dlj1nLm9fX_V*QLIZF78%yrjCJ9u!2NSC<<(p1c)i z!*D*9>rB0=8DcA;@;jGq;Lm5Wgb7(Utf6Ql#o5WfCWA%*i!OM6#HUs7eF$#TO z-s%0L(02z{L^1+%QzG5)m(hPpj}FB5D-f2OB#0jY*Uv87Cx%sw%$au&8JF$rdNvLU zF-a=cWhH~9ZoMb5pGsvjaS|b%zj9UEY6pF)AS4qBMM^Jv1> zK?uE)o_yHiw#7m;$2=*MW^b@|+MTZ_Is zkfeDl%iRn8f@BN7Fm!CQDlTml$q>v66UiYHQ{8G*Mrev3E5si2TN7jG7!i%}vtl{7 zf+U&P%yWMEM3x^hgCdFGS8v;Fn-AQg(Q0y%)OUS;?jP&N4i3T4V$1_bowjA4R<3LS zFK<7{JiR6L*dd15; ze}#7;(bf{G@N)jgn&+*QyugZQUe>N`L!q~!4kL1XE6f1_-8kcONV3{uqpt6|NlU2; zwF6Xc@)wYp=}FmGv$Oa_aXBZvHYD0=w0zk;U`T`g>bqLHe|Y5dPMfQ1bN$BJF5q!J z92&+|5_~!?8+{kCV6rwwrZR;3CA7)@NDwRbagnb-LXm`ViquV}0iio}Ap4zkCGozz zMZ&Q1m|<|zyP_wp`hfY8*2fJa%!kC-Z0Q753W zWRQg?lW;{&YV12gA^wJ_P}ruN>o*zLB5a5qM^gMIzn1d@9m`-nX%EeVNO`S% zvQ)TVQBv+G4h6au>zg+9E9ixQD7x4W;v+hfK}GPYn^3ogBOY?U6URKcEQ8`AMdG~? zEQ2VcXHZS22>1xQaps}u)}#xzD?x0(kk>DWYp)wng_n_Od2MW{?MF(aS^JoAzp|MO z=jsjj-XyEX2hQ)9YP!36WCau-^&VzGUutG#KuCW!05kelxt!?;qFWZvBDdZ<21(25g zQ~9(@e=9tu7`?}ZMgyO3-;Q@m+(FIn~T;fTtQx% zIhN@9HLs`(MdhSgJh+Of3^;2cqDKZwMSA|#fH})fra$SXz=P|<9KTt|!uz4s&%&ko z)Y@`0I-D(RN>}3uf;0H}>R;hJ+&{nd&mn_pizXKK2+?R1=0)ue3sOeJnvuwF_~Bux zH}bB(%bJsT5xW(E)6o`7p5qi(*kY;zM%k$f)8N`NKkuzt^I4tn*Pa%nFR&!GQ)4Wj zON9^}85Jiu!_~A!jGwrYXbel~Z$Pud3QG|{p*(n(T3N#}0Kuo~wTufydSN>mVkrs3 zdNJ{&Be@65i}f3M%0{bly*Cpa+q>GF#BIcR{&AF-bl?>-i_!ff*&N74O!ngeKK<`k zU^@DMhyAoc+jbhB7Mb%p10clnjQriUi68Ug>Lw70+~g_x!vJSSC&18MkLdIFj~5Kw z-v+l#AoB)_mX~vzsV7+-fG%fkq?O_{4#npOD@;s*&kdTHNB`t*^In;WD$sLrBa-voorT-tdFcAtUXMu+C}hkm+LNCxzZt&&Kyb8 z=xFE?jtpga?>?YKoJfU(7Dpa1GdNm@TiKw4TclxCo&NWROP8`|GX4fqlQ1#&qS05E znonRVRT*LOKPCHeZ{%927W{tcN%-_fXt}6wpjR$QBHv+;i5sMR6!t*Me`1ldCuvK% zI{dD?M0nyB2M!hG=hiY)tr8hY+}jWf}Xcg zn%=jprrU&*`EoB-tpq`55odU*G?7e*=4-fvjly=o8&R}K_=A!ua3RdJo%DGk)?|Ce=(SO?Qr!}* zR{Dwt@ONp4?RZ-FCOjoI$Q`UE1BP9AOxa;WPN+}I98K#>-EatMt~t(}={xIx5%{mw z}3TA!lq&z8U^YXAqMI$#X18%5O?k?sqQR7^4Nr~q*CRPCeH5&I z!bKMKUX!Y@4Bbu2hec$tNDb6z#eie@C<@xeok_Ik$eqG{M7HTHhqKqKQdk8P5Z5{2 zVM|!%s`KPUu64={Q$q5xYcEkK`$8X7%2Ggrf*>|#hZyu85sodlJ;9Vd?g`LhV)ptl z8u1lOc*Ymc6Wk491%CT(JGW+OSD=YVFHF9!3N_*TC)WXawSQvlQiRtg|f@SS4c3YSA z@8(o%fUnOUPFB1TGyH0*s+tuvZ>1jeYfbD+!W7x)F~!%ZXT|{9aWRpxmSTFn;H4?& zUp%>RFEB(7)?Mj%Wh&f2^`A-A2vSugCGSQhfP2Q+ixx5RFEcleYkDb{=5?yWp*D2` z;J$9ezYy$@0`+cYsn>LaJ0Ph-^nho5>$lVhV2*s`RqTw52^t-i;ueMGkDPqJ(iZW zvRI{AR-|)?ub+%xEBkAD)ZpLDRORl4v-*A&1RXtX6KA%`7B1CvuOIsVO|<%Ls#YD; zjs7-tLwv(Yud;@S?rLKZrf10{OR+FZ^f`5W>n{Psq&<5tgEQ%Fg8E|VI0+oDc!qRL zc&bX4)t!B^RtPPMg{H`=46Iyx0GB>2#$j6PO?i`#U#?J{1$JkD5|J1qpHbh<+qTSx zJ67j8m?39jzz@Z` z6c1$V9>&X8R}eQUnKj$*!(c(6AA5ilMStWFMcWLSkC2k15+n8&(G)CkDAp_aWm{AS zld#WQ%9QRRXHbD}I6}8H!g+7PO`KGNdAVx1-|1Y}3SQFmpBPXqtX+O*_!Xi{(x$X~ zZ-Z&Sk9MgU#A^GwQvY+-z~&Y9usf_KJj-9=r9|rjn)ocP5P!{GIrKWg_~4GOQun`H zH_AVYh9<08uZWOqbWDgeetu^s(pbXeE%Ta80&Sc@nwplPh5p>O6RWJphthSQ1U_BR z!7uV!K6l)iR?`bGJh7ePs=$B~w~K4EOjzL+_}(lS)r^h3*CL>=A#i~!9QKj6m**!g zPIEvphV093#+FGt#91lv`$jn&oZt$NlhiM{wbf45mq?f2{Bwe)YuOR>P+A+EXKvxMNmdKcEaiaoBZ^1x&U=jZm=3#y9=v@f_>CD znH$HHl?qQC$B=lAT9%kRPsGF2gSo3!EYj$;OGD7-=kiO-`s-@U+xlryjYQ{fNgs06 z<$J&1UfjYZQUBGPV=ur_*FJ7fTs4qR&=We0F!+S0J^5gI`^j09c^?95Vk>f#yGkK+ zAa4m#r)`j68^X|jj@A_$B@m0-!f ztkXr0fDbGwb1=+iRR+O@B)GsG)_zGjFvaO4%`S(i_{L`hJ?&ghR&ZruxV4@^Dk=%Nj5w1|y_RLG#>1AC1?5VXf%S4( zO3HLGhw)fM_!Pt-8sDA6;ogAtcqn45fGemWUq2^KPSL@NP~(y4ZmF=TsXriB6IKVF6%eX^>q!2OAt=c=7bz7S586 z5T%CpTotRHse0@9P;CGGMi{Pipk)M_2DB%R$lCd@4LSU-atH)zb2A!UZsU{j*+Mtd zgkoGICwM7;L@1e*e%rvBGjV`)hvP#!CL8`gr{VAD#Ki=X=t^-K7`zRZv5e1S;_@y2OY#ft{#z{jy1V-JBAQC)-#ju}yZXD2{39yAci7El)* zpZV(M8Ehqf?qnd&2XP&(V0bxCj9qntaP#WCa4vn)!tPvXaor>%`nVfFd z>KR_MXF2PCvdT6|+lTrbV(A7j(1Od&$MMJ~mJrw3##P@E(MA)e(iUwXZdX&Fdk%7g zK?B$F94t;b{9-~tp0zSwh)4Wa@VP{~epBI`uDdp~`~kh{XTi9Yf_bItY53Ao9K)}P z!DxgpWCp-NN9z-enSHrJn);;^-wpIegp?rm5DP?MSjMsJee^viR7lreB88Ggz7*RK z>VwsbI$iI9VR`s?QKm%LJSxTU3IR-Ekpleqt`;xeQo{TUw)S5mi&WC`z%~A*$gIIe zl*C={;7t7}VdZoz;IfemgGZ#$-ZYfP;9jnVGKtrHna_V~+>7Y75Iz$@tnjmadoghx zZMjl;12f+jM-X!quO^Bo($`6bhT%(LOLn)9GzJ*NfUimn;;2onup~d0G?|#h_L1DR zAMf=rEM=7n-mfT$$>0SiF*pXff+5#agywO~W;`I#rns#O2K`$?sIRl2atoT+Qrs=vwmJ{xoJl7WCA7(uY3en7 zj{GNm{&2nWIF7w`!fr;@4J=;bLvGHHAH(@oaM8;2Ygq?G8 z*T)pIGdiCGat_Ssj0xHrg0=o!MZIx!CR64G8DaRh;S+g=-vG!`wNZ`U$hJ$%qmt)9 z&=^%$EN~U4D}FZq+KHDo>kYjWc542Q({?l2Oy+$Y#w|#*if_m64z4R|KDSaEU$o+ zmdZzKZ^#p=zK$^N+6mU<*_fcaU}~C7ip=jOa@U^%rNrrdsVE{ldB63DCc;;oPCTT- zB#zJ#f~}cHPSLPhndXBIrQ;unG8*`hM6gf)Dl+(ad1D$w<&`Hg!XI4ug#szQwSj z3PTHP{N3Vkg5>H9 zwQ1AL7R}BsS6}4&hJ|Q*JtPEPG7uw00;5A}S?Qj$0AvFqv;SxZ!~9E*q-|q*@Mvv{ ze7)MeI-F9dKfj4Z4cO?imD4+`r6Fx_95&G9_TnTb24e}pPB=a#{X$|A$oiVeLj>!d zp;x}=xT?X^l~oK$q7FuHa(T`uPm+w{b)k;c;fCkH{D&aUh)#;`7}j7_>ny~ixN)(! zq_(SKR6uAkJ#WtsgZK9zK9XAH$5Zjj0u?s#NTLI8r#(nXVg&TB(HbFxE@BL9n4ON`4>rKdi*PF{| zJ!UmQk`TQV)t(+Z7~-WZSuM>)zh5lk=LtbO9N1~5RHN2##cveY$z*x^b?ViZ z$Ql+`q{;^IP_em5fSc^Du2?e;MxFn@RfhMaRjXUm*qDGN1nsCX=$gtG3O^GH8CcP3 zh&FKw|9UrpAkC=k09+~(=o(_2$?_|A0e`6^q28yQ-WH-?)a-cmD1!&PoaN<0&(F5N z>n@-WOC9Sdq#-iGLccH0OqR>vhId2{H9XB2J8;~K36lj&|AO63;dR3UYIL_-XkW!^ zdEOAcp#~VERk85H)BTBIaYaEwcIz5LYzzHgbiH$QU0>7%+N7~4lE!w@ z*tTukw$a$Oaid1>z4S1{Hy!vmXTO+ErAQVMp#kAkU3l;S?z{lzz<7p4koV-3Gpa8ZIeqln*x=%DJE) z*CwMXE*sU_n{`VsF2jzke^?DtHlA;-{wCp|H7n`9~|YI6;b(oq0owdBsW<_Ktpaqp>aE zn|Y}f1!?D>as?wi*d*pD4a@J3(YF`q~x-+s`QD4!13uT32PxDzeI+`l@am+fy?jDBXML9tI^`Jh6+?JI6Hf`{$K&- zTd*cF+Ol)X=ih#5@tF&N#v4|m*y=1qWr+{t=TM0P;|hM0A{5j52RX$^YU1aIE%XR6 z<@*;|${JPw3GwszK&3qVGdS@z zjI{eL=Ic&8A!<>w+a*Dq>BaI(bIaX(34NB>4dH zOIi$V)VkZPeGQ3)OfjL>ewa3C4r@$=v0vf;hY)i(BOt*iKSI0l3{p;X!1NKG0P;%e1 z#H#@4O1x8BK>2*T_~$P9j}%AIUd&lj?<~D^J#}l{@N#h7@M7bxg-CClhowz$DqWwx zItbuOSR&&ut-VEQc6+Z9H!W9I>e)a2`{$;ZUQH*IGUYc2?mSh}yQJ!byy0Z>*EtK{ zu-noZ!Dw=M7bti&4oO=OU5NoVIgiq?SUkkHS#5|I$L%o!pyr;2EMty8{}Iig{+DRB zwJ<%6@`#_thX>z0_fh+9Wii(9S_ZD(YGEf3!7YK$`7~1J&nJ95{ruYBj*qI^Mh6Sq zvpH~ezj$U+x$zme!g9$2_M>*`3BvV{&s=N}v$cJ-2Clp|oDN0>etq1BtNee4@b5a- z5@z#6J1Np3A%4h_I5JjMXIdABkFgjp@hiJ+gv- z!D@E2#t-C}joZ2d*Sx`>rXBH<^{O0VsH44}g+ixwe5g!a{tFD<_(QiN7IQS}BLfR3 z;{X0}@Fv5Dux^tF%Hcg++Wp|r>K}y?hiP&pZO-%Kliq1hNX;|gP^{o>3_4Y+d*2>) z*}@@z41fdFzVn&B>irUOmcF;e1cUiRH>HkLfLFP-XKVC$1)X+~iZkjjDYT!q`{sxj zmG=BVy=VNp`@G8f32+j&c|LD4-02T#2B=LQTb!0F>;Rhx4xRF6H=t$s_RnveFdS0L z%tw2_c|g=P+D3Qgff=9FeXTyw6sQ>qjW*iC|4AYYt6Jz|N-U6r9;mqF9t$SUBk1S6oc} zp%dDC+4&59i(-#$2$rO=_0Y}0HsF^KMNY!eLsn;k1?IR$bu?E}eST*Rjf@nvvZ}mpgdFTYU}S9Uu7q&mxf9IjtC2Os=~Pn>sx94| z0^=a!!nSq_mY(niw1!-y)GC2Va2`8*YTRz=Q&-j!_smeuw{u;0oMa%WYlF zh}UjUJZ=?BZ8o*7WeNDPRy&Wenb*k2uf{%&54iV&TYYYVvi{t@0d>{&qN{94LE1;Q zKece}wrMhX`*^tWPebjrrpmhd?bPxh6*&G(lT@TxD$s3;zHPpHy%{ci-+XKkOdS0>*5kr~qT^ ztiDGRB0p&T8+En3_kU3VVHOg}R9b?EUVV3m)i(ZPQ>gAcbS4+L{vQFrKg}%hSBF=J zXu_-qrj{{Sleea;G_LUyZ()!uGLLdTtHISU_`LL2UwAoOI)X#OF^|6Z z1O$n|jZ+Mg!yl=6qXpii+Qq9T_@oZm?-ZC8!suI{I+~;;=e#% zr3Dod)-_+M0C}RKirl`u0a3X61kSCS_LElHn(xw{h$na_D5zK$e(Qly@E)ebry7D2 zbPr9*^Z!!vr0u8>_>9SOd-JsKD>!Ct(;#82+Smpo3Bv#m{n?Gu8(bt$(EAk&P*{Io z{CI(0=hm4U;gDa0oiVhX5wdfrSf+Xe-VvpY^=beV72SL0TD_V@oS!# zZTT-KCtJ4QC_bZ}&0V!zZdNPEd*G&|AjI@^i4 z5HmxUhPiLs4Czr&;G6e7(W3{F)BODbGRprTCawD-8giZJQ4HF*?q*3Ar>IYFzJ`F;MGK+xR&FJ+3MgA2sWE*oTfW0Hl~XS`{Sine{Qy_%VGaC?40 z*UMTTV$^)Bro<-CQLPy$)&A)H9?h`xleCoy;8H|8c>1)9e5 zq;^Ic1yO%xCkjh-rC!BSj!BtL=WSzxh0q^Y#)CgxgwC0qihj)ur(u@Hr;;Dzv@5xr zEYSk&2Wwg_3^@WcP3_|Lp6^7^K}%!2s>EOrs$ytdCalBJE)U{zVpQ&m<}%!WDol6D1`Seq=%>?ItIzRv8tY)_xHbKLOgk0Pt3kqe(flv`40 z%4@0nN0wv^_zlai%7p>l5;yii@sXXUil#S9DVSdPBh-#LvlfIFQ`v7O^YE z6dcf2o__Q|uW!jKdGZEX_IE^&8Ul=&S(jM1Fs%=S>D3dbeuU9nBC1E=W(GeKMm^V zc|&uiI9$!i!(lT^*Ezn_X+n$s1JQ`Z|GN4Qw`9mc**P~EZ~dQjR}$| z$w0CGybw8az9q0i(R3@2_GDakTidTVWb#S`y4KjplUC5oU*>TbKh#X>!ulKYC+&&| zym!9fh(w16p0~xxjjlx|P<#GQS{N4@BP&q_x`zHt5E(*qL-D5ZgX{vsCH{lv==e0l z$8jq$gZcJKy_pVQh|-G!UKLs zP${MoMs{2uU6IZJ=+WU9rP{Xs!Ngzp;cXCTKk;1H%9W8f-vMQcd}y+kaF}jN=y?xG zJhUc~Ma1k^{;BMgc`+#RBT`K2G$khh zk>cNL;na1{O%lsXbDKwt8Ds+Fj`C>m*zfqVfoh5lDFh?CxAA~Hv54uvG=ND`F1;)+ zJOqp-2O`H##jK5izEO@pcgpl8Lr0o7>~>)`scvsIp5z2curg+zip7l`rk{Ga&) z8q-7eFlr!vwDy<9s-#?h#$)Z*C$EXU*1v_TQg(kJBigAfOLMkrPtbn8Zcae0X^dOj zjU^XrZg4U5X&5J3RRe7WTxY&1LS(?=|9DQOtL;!8oYx02qd#ys(&(U+a9tI}(2HY% zeA;+@iGz9;FR87c6g;1(w~YEtfVSjn8=oAZ$~J8Ucb=?nQDhAL@Jt3IxBerByu*mC z!fEoH;ou|DoS%pToB=h;e5#Val`ls~!4FO-h6=_1`XNnbZL4D;{)Q}bn@{FD93L4Q z)t;y3A9uHisW!1Ct0K6)R&&`Jf1j1JGtNcfc$v=2;J_bza1I(z z?&(wl0WT>eGK4BFOKzQ!YqeT?%6p+jvbP{=n%-)N$xdVacA?xmt?0p1}!1dM@-uHidh z{Hffslfz{@)bBX2aeuy0t(pG)Tvb#w0Y||qJ1Kc}s210zaWMMALwE|mAXQMR;*FM? zdOK(8^EpT2_JKNitaL`)N5#tryz0Q*L(cG!n9=z9u-GJ|i!`0>4$$>#ICKzo^$m1=H>TCMKA6e2cmqkb!E- zSzC{3rEBWsht+Nj&fLMXfQIq=`R3d1ItBeop+j5D-{cOQP~#jAvaZ1cxl*tPt>7~h z`NE(h{N{5pHjLEbGC4v)tik~G_l{O5mmXa2BF$}6Dco6+1S}?@@GbZAhN4i7OtQgJ zY^#+&1RDG^!kYY>T_HIxe$dW)6`<3Ssfqg+53i+?!9A{#kn zUVdt8XS%Y;WxCEGAl-whb-1&TX9*6+-;EoXkG+mpJ~FRGX6)ME3c4(KhCKRFn|p(c05z2tl2uX*7-gxh4_QLd6E#pQZ|e!ZTUjnjh=T25J=I zXKW(mpZvsXPamEGh}Ql2YR+}g6FCX)XpS4IX#m% zp&z3nxm_i{4?3F35Jk<-il?ACNy)wPAyV*(cwyr45KG3}RFsPrd}Depa+0YFWrG`a z*8A7X(tO_^(z(`>cw52A=2-UeaJFThBHO+YoQS@E03TFZK% zVV>pS647|_*V!+=Na`g%X`R9^O6XuaPOxuAY=1kjs3CE8QA-xLV?LvfnD5ZJ9z{)b z3D=<-jjY~@^;6D38x5B>RhnNW$To#EQE;e*IkB^#UiQLwLVjFD#A>-JPU3zX%&<6G1nwo}>PL58Q=|^pK_}`8PGf#kxZg&bqr&`h zGq@rhTZZ@GEkg)WpdEwtd}6LNbp@k2xooeAe5T*k;1%W6;TNr$GBFxd&(4!BiXqD9 zejnFL2fkuPRGJv_w)3QKhHo0M6y{BkPNsU0jAf=YMZMp@l%6Zudk-1{jk6c2fp!gLzKWTChc&qkwS~2) z2Fwu zR%mD+IWgMmS}oRbA~wyc_CAJnZ-7`7#nH1 zGjs{PVQx{fEH@WC!7*V;zD4_A4le~SjIY0>$x`f-IX%DLZ$*w{7v1@4!zPHv$C)2U zE5pmm-yuTrPx5P(_vPzRe06v+U-t!$JIMG82Pq8>a%-CJFaT=mDc8z+o#WW^;JONH zoqgO#4}mGyxR%zwZQ3oM!^W^2ijLI$4GspQ9|!N3QBmC@6_pjmuC>??rFL1lM7_Z^ zR=2W8*XLg<(Qf&Q;2j2VE)ckxQr5HOK_>cZ&9*L2`$@KY5@Nw(k(k-zUp4ED5#8?3 zLUOP(BWx81Im`&E0790sVQ$wXl^|_pNcV+P`^$|~F=NGGaZH}Ps%p^iusFfe!?*V9 zu0>QGJReuhMX5eul*YXbn-9K=d`)Z$w^LO9} zz;Q{%8R3a2_Wk z8?FwG&1BW#(|>^gYZA+JgP=+mL|LC{4H<_LQ&GVJELb8)4%2;jn8vU73rypjEZ1b3 z*EH()Re5X?WYJP5d7cPf9$#5u)feXGw`$E9g^X7haGalAJpPRo;qbdKi$>u`=qJ77 zcW6A^Tas24n1uUwmES9Ax2)Y{=na%9_Q~M&yW>xCW@Dz8V>kw)!;&L-+}PiP7ZBlctiwpXq_E;5B%z&@nwNQGpbduO zl5O2@g+tp645)79J$xMmtUKjZR088<@xz0P_{=fo$NqxaFTzbp3S=9jW zXRzZR!u=TRcim%hX*jbUXS+gEw4G+%*>kf$X8SLCmc^r=!ex5|o5k=1As!Gr_^+oi zYBLHxP|N%CJs*nUQ24-fj?jMUZc*{RMDy_ttn|$mj1k(B8tM!s8(R1pYi$H@q`S>*pkm z_@1m!9h*tZ;D*Cax$nA*4;cQ9% z(^)gv&~{xw)`$r)#D>A#^4IpVAlFwLh!pcI)bg83AoX z&FG%I1pa-X?G}M$R8FRVh_u+4#w0{(RRG^H99ukS2~S8 zgX?c~Sm=Xe^pZ+D=D_?w1TO{3#Zf}uI!pzKv$oo22u5F{W0a?M3>=;yecQBm!#OQU zujgi&a;Re9g|aC;q;=nOmbKi-_!#QrT-L{!%)|cQ=1|v}O5bXd^w6b9%MeBvR=`9Z zVCKkdn?>4krjo4Z}Gh1D4Gjd6qf9=*7ocjm2OoXOdDvIE%YV@`Mu4wyHV;YO$ z4MIC;Mk+Wov{&6EBY?#@s)t7vX}}PjxX)0r2p+J^u>BIK&5rQiVu5o($Oa}W@QN|G z#sNiUMeGv?ogUspg*2G`-S6t3W|iS&J5Te=%b4xHvZ}#9!&%#YR56%vqjRkQ|6$>J zDNCxY`<~o~>jOUPof&(kzI=%|W&q#)nZ}98wPy4AqV=7TzWyL;B#6G?aqsl3)gnQ>dlf2I6X@i`uo!RTik)dU7 zfCnoRRack1()%hss)h24nxdCh>cCt+E@B9V##a6s4QWqqIU*&Fc&Hw_5VqM9@M=nC zF@(}_^+H18dtpA)iVFiY2!O<=L7SE+^=i6`)Ag~S&vyF>+o0PUtl4~AyZI;;{(81H z>#7QUsuwUZ3Z=?)0S_W@g8B1!0d2v!63%&Tna{mF-G?+#{xoIy6uZyuJnSlHqnX%% z;OYJ_kR1oDulMc)IHa*B(yRM|tW0a6D!?hiZ~m0)Ii7Tdh%xf|;C-q60|yIq!wn!3 zD!!gKG)EuMs?livkTub;U?t*GE?~G#S{bNw0yeDyN>;`HyYX!;Z})y}2b!YZ)uM_m z1~2Kt+QhGu2NwFEiE8 z#P$ASJ5Q!lQjz#Q5!=HbN-8;2#JzX#9YpqrlLILxnIT@8&$1waa;A&cV@56e2@dYt zTsCbhE1C-2u91TuVAT#5&Jdjf(ZzSeaJgYc~Jv5#7R<}8C|8I zPwj120_9q*3Zdvnwr!wPDUn~!OStbnTvDB=Ra!DKNP@ceDgF}b%95XMF)f!oMdsbb zWyv&sBv^jn8OfCj;|io~o8DWTxu@uElaK zq|hX;Z<}=+z9;fYShxx}!Eshh~v!=^V zmxqD}oAZXnQBfVX9Xu_86IvSTX%!t%e2tq5AB7q#^(jTThP+}35O zz(iMB8sp-!*gHO;*@o)`jPg(w$H$09-M6gWsD6jryX;I;zy#pw2 zw2Q-9`Ik$*agH`QH5MCi&(XAxF%$LpZU2Qj=30^9rL9i(Vb0SqDvvEMt%$c@3Y8Ra z)BxPq9GOOv6m8r=C1NaBAh2Y+AtnC1Jw?_abf_%vsIMF@mw`xK;T{z$ITQ`+R>Mmh(;&+D1&^*D}=^u`0Swx%krV z3VDBNV_t6@+eu^3dC7O^_Qoyc>y4T%-#*w3 zGiq?!oQMpPBjxar@Ptq$CrLdK#`9dE6=UTDnDLS;Mz0NxT1Xm}xhZqHA}hL$a1+6< zMVGbv6>Edv{KEj?GhN-NZuI42w?k23e}F0eI4Myy%ac1jZi)#hH2%~04M#xEKfe8jA43%@XHt`Cy3m^xGg*0HTIREvI6z zZLz1i8NKm#sUp9fomG~LVR|SS)D+V9Q_7;Gq6*s^yq_V=-8P1O`*F~3eARHrVJA?) zJvug4V?1QmPuVZ&GII>J+u{n@a+JCJxg?~7RAj~}t8w^uhR;;zE5cmZ?vh$FYC;31 zU5CmFYx@Way-%W(WQ0_LU>O1*AO6~{TVRa(bhoQnm13YCY{#UevdZOK^S)+#*BQ`X z2=;2p#$^u#oHPHL?hByVe)U3QG`(pNI6?gvj`KQmRQRp@N#OPs+yOL!9i}gj00NV8 z1zl$;G&KABZ^OUfJ>dh0{`~jU6wxp+iHDLTes$n+L&tyfOrp?8RtiHgD?r}>4&7x- z2f0|glSic6r7%qMZ*+q^Jb18MoDT2F!Uuj)L>{;9bcVu50zugU4{Ro#@ISBrM$(65 z@uK)dH%Pn+1%6`-W^IVV_d5mu!GDPUHqs04%TQ*te8^5h+w&k`aDhh>)!Pri$RoDC z`@DgQ0^1RL$~d7Fl@;Bqn}CYHWz{QX;Go|JDvxNMrVRDbDG#nMVjtxV>N#8GFw3M!*{yXw_yf5USI47iaz!D?)O9XGAe3l`~FAzB7W$o!}z`67nrOH=?$7> zO*#3k+oR*#l8VMUk0Pe3@S!>t6a5nq4fkHK5X)J)esE+c79!{UcO!ge%*g`iXlBu1 zvgTSYn!fCE(tQnXFG4)YLX1$(WU3bp>4VpVQhwbqELL>Q?d>R0d>i;9>$H}Xk3~=Q z|6cSo-I}X%eui%8B>&81v{`)7pFcW1HR z0HuipP~)*4cU&fgq`$+@nqRCify=JT;6k7UmX~4oo3-#}gsg`s1=1M#=X&N6RFc@A5QRM%e)Yx~{OC zt1m!O{-bBXIKrpqqc?cz?;3?Smd#k0!+mT?td^Hu7Ce4KvqA93S9hbXH?7nFkgDLY z`X4!{tEsu&02-`6d=8N9p9 z4^%EMj~3dhcEZ*@gVX_vZN4Wizsj9kv)rRFe8n zBfp=VYqZX=60a`?G(#awHM+k7%4{(Jn%5*Jq@VC@^_~Sg;S@5Zsy0^I8-l}w`%P{I zhX$~9!vR4pBB~76SeNl7ulP*%A5^yw804-MDswYZLmmQwvFdx>{5(Ih-JTqz+cO`I zmrIkZGeB^)-vv5iQ@<{0{rw?t1V;3_$GOIR^u1q1{gfT3I9Gij(rI0-NcNsbAMC56 zGsiIX5&&P3^>B*9pwe=EQG*XOEARJmtHx<0uV<+;cR#)totTCt1-!S-=}oBR+%gta z^GrmUbY&GclA<5(@vV0QrNpvjvjn*>ns=ic7~$XDFTHNo?oJoUSUD8h4OUpCxZ=>r z{3QbDh)gQ+JCr#bIgZj7)VE@CWZd>)BG@j{Xl95kOa{Iu=Q>AiPb^PO4PI^cT_5d6 z8Ei#^MfBFF6a{Pe$bjeUgRObzCktb!V1zb>W7ca?i3F#)VZdgNTawkALY8qBH__@< zNGktWi>y5dERT(Q>#J0q$kOa^(b?r<8RUu z@%C4@m1t7K6^C4h$~ZTbfUD%l13}C%Zk}n~EdyL=hwQ2p{$)CnwkI5`5M_ z-YGa*uA}<%w2vL$>&^r zch-YYmFDAjmp0zx3F@qz(kMrj%K?nE`U^>bpMdz{L6uQqop&-2aGLe)S@5e&f*I40 z=FRdZaq0MU-Oo9|xR4sFN5>}Oz7A3K8*V!j@7|eg_J2kv?gq@PBcY4ra#mJomRL7<*V$KwI= zC;l^YX7V+}hvPB9;yX8i$5GErA86Sm3-S)2ZQn@nGr#^xci7Pj@BG8Q;q~r0uE~rH zFR11%R>U9ry$GQfeKyORtK@rotcL4~L&jt^l~6fI=ca4&HsxK6S|#m<2tprA7-TlD z*<0|?>0SWVH2p^a!sE`$brZrv{~+-Dhak)Mwgv`g{g0t)2cgC*Vd`)FITS~pC?xuF zSR*ZhFEZ-eYFs)$CL)-n*vMERXi)DmY}%Bp4LN)UK9Yp*p1_{!^x3 ze~2h>SC*GZ?81xu0^gaK@@KMl)21taN90k+Q`Hn8+_)KDV>q-^*>-_;xxOqExKkJP zHBLp@a-|+M`t)n@*MG#T#Jd-GK@?JnThl_wm^OUXmtZblf1kN8qThCm$|@=b26qr$ zUbcs>x0)rut)?d2kg^zGK&ra=rn3D0j%AC6EBU6$U%dqHzZ!p4=i~b!H!2+DF96TQ zu0i!RuPC;nE8U>~th}2P*5og^rLZ>N!CVQnH2^0dHaD#4TB=U2{eKn}c@NWuN;P6mO%HB6PfNWcv_v+ZK?jQ*eK+X!5x$ou_ZGlvOH-?HhrcwU&nJDUf zweiEJHds2O2lpMvck1h#R_YjAc&q6wrIM2B7ZOe|XhOSa_LQ$rdvVv>LBs|lQ@SKH zWVmcp3Jh2Id35?n6` z{?n=?ZDsmebe>G6`?*$(&wb zjW_V`Tk!{VxA@!zUad;A`@8^%?u-ljL+i(%5k{?0D3gN*Via4YSA_n$4^G1Hrkb}; zPSx7gp%XhS+pS|&Ni^%OhZ)W8XE^1f>H)8-Pxzx> zulv!PUv9>1r*ok7x2`|4INm7nyuXQ20&GSo=g4;W4;${lOfHNE>1O0KE~`P+uU-Ky zb%#4|ArHF&O(s(E;9#>n!f}lB3U=U*)&CMPs}XP&|M>~=adUTAr=p8B8=628LTvCz zQSKh}D54me?>Bf?)urqZHGb-Q`H8)i&6N_sWs>E|NlN6cgw=*ujKhFkQj5LL+6v!( zlnou)SF$~brH+WGL;vi68<;78p&HeUM`qRaot(cO6Qio-qR{+$cu(wln~HcVAIxuG z@bb?U<0Q{BL3~oe*c3g1%iV-3Y62=vhomBZiMX_M!c-!IX5f;i!L;0^$R%foC$E)x zV|mZA(Bxq4W#WiyQMz5|UQJCY0De^UV!Idqcl$yA%ZQ2@$=B_oc0=@z=etD)%4&f2w~mJPv1@T$+tyec-|Zs5byV zm$i8k+zPCTtJ4dvr9hLVe3OCHz9+iiAYVO`)rliGy1E4E2lRH|al)?2nWUVeE`!89 zFAkCsu>xXS?d+#EXyG6+uF}#q`PR=*n69x@Nf?&OMhZz0)5B}^t+{Ub6on*pmW2f9 zK5O9@xyyw@lNHwKLZX)>eetF>$Hlb8Xgtv~foL(LBtHxK3pE&;?CRv(^B}H|ZI6;S zwc*W5rLa@oH1`HaDk7_jq^0g`X`T=3*npg9 z!qmU}bGl7ew{%^XZAkvB?$0;K>3|=!$P8Ml&RD6r89^nWoC+vlqU4->_k$v#p^<=d zjg6adp7Fqc_@MHf6Y`}My?}k3#t+`E5bQ#^47T15Ll$uQTzSH~Ny2C=gf1 zoI+750>NDc%Osb3u(RrF^!)Zp5|oqR zhHbSi`Y^Gu7GTsIr6E|&npv8nggRo!j}@Oy-_p=uxQXFjc^IMnk&i*Q%rXX% z^-5gAP_3P6NYUSA%kLdYa}IerL_?2Hs$2iislLz*j>fR{sd;ayC@J}W$Z!6#{g4QT zO{1iwlxzlde?}G-67mz@N7;KkJgw@|VMlsuL0{{9+=0IyM;%SoX|vh>p=CEhp;rGJ zRfhMNod4yj58MS{);rr+f3!tx0CJBTj0{^?Hfis(7Ug5wA?DB zXDANqccAnVO)wE;=2sWv7iYJipLx={s$;G~a1?@P*)6Tm|C zIpn1?%QyvE`L4OcV7Xyj@fr)7A|LDzo>-_RcYR!#9E&q>Qx^(vv6{6b*^oQXpzF`u z#x7%cNZ9G8*_C)rCJ8+5=2dZkq79{NW;nL42kL60CAuuGP(fAaKU(9-bedSM+k=Td z0E^%Adb#a**a$m2vw&^m>`0tn2HfAdcY?`mfICPvI}C(=w8ZS1ACxNN+1SrJC67#h zM68Fzu3!$nq}_k$l%s>p2;xjiZUh4k46@il@emkph3UOD@$K1-_;DAo>;x2NSaR*k zr6RE8cZiO$&x7uA{)@1xAW4o6DxnmF5>YX=4h844C7+!Y19sv0F%N);H3ei|gS~@O zhqe=rhTEU?L#Ia!LA?c}h(uM;+pzki%c%I6R4qmztkQ=u_1BT-8ZWxLh4fRU-{x0t z6c(ju#4;?}uZ4B{s+L09WUr06rKC0JJu2tpwS-fG!2&7OcP z^$zUw%k3281|a=Q&&+8!h=4%EuO?jXTArUT?0~5I=gBDDdBat$#jap)lx1(!$wsH3*({Weh`sVZ8ne3;u%uqHHA)k6e^WBF>EvVkVeJkItuShL!u=f~5S+24n-=>jQ}V~cNc zdH&D>p3(x&0Lk$t-M?7a!3GB5xzvnM!+E@pY|pe3k189yZL;vTKpBgG4dJZ3be_Ls zF;S+E_w z-)i_Cdzm5e&cDH~8#X<(Ry`anPD8M@q*99rV6CxaLqvtVF!n&7BF^ep+uzi2JVq;| zCwpC4;Y@<>;9rg3y_aWoyPIuyuV$o}LJqrAgc1`HC|Xs7riepX6fb&lhmgMCr&^Rm zmX%laAHsjdw&di@>~im2AO1PfZ)%brNFysfC@68>kN?{hX%_Ezjz#vj^xKKZ?d@5s^smNnnO;GUS(HvElkD??=$=LkXkLw(t2Mf^ytyvT z>n%;GXIEGJDucP?RK7P^iuW!+Bf*oLZ)XgoO6d~$txr9d5?;l;+g`*JzdZfP7rx{7 z<~v9LN#ICM%Vi`W`4wa_G9_=rXE433cD3<-HCJCmj{7{$HWmMtZ-OB3d5Zr5A@ahV zU8PEg;q_;SypDx-8zvQjr!Top*Ztoz9IsoKcJ5P(aUj=*Bf??CV=HD2i3Uj>E|B}Q!|^EP z@0f|A+ltwVc|o^#Ldt-$$j*1tZq(^|ORNIn;@!ckFGgJ4Fruk(i79iUnIf0#Lb5*x z7*y9ok+D3yd;FlDyDeAHXKg^&V%x!)VxxC+83x1(NN#I7uGg5LlX8@cx9t|u4s4bA48-ZF9@pn>}NrSuu>(rCYQK3A3Qo!2t}2i7v0$Qld} zo)Tydu-dCI98S_{QJEnf+qCR~<5}dY&A4|nlGzd*Ip52C81DjCMZyUKxp@6vcGT5l z%kkFO%5dI@(W>{nuc?2fKJKAaKx#DLJFlP3H|)(Mh)2?wNwviofD#@fy~WC(2;eWpj7}AoiJ}lVueyx88DObYXi$79 zBx-^-5e&XBIk(;5Ih444l5dLY<>1nZpdxNWtH^S{-~k;i3;ig#hP`H$Z5-cmIXfP* z={=^())Nwp|8BUM>)j5;(92pm37z79WF$e_T9u0}pYv%DqoKjQ= z;S>%^YYZG@k+67`R8^&92yVrnLC0h?Fz2h!vjmSGZ-T4>JwRL*F#U+jGpz?3UZX%< z=K8TpRkkshQ8W?nSlt`j+ZMlO;~TW+sGO87Rr<9mOkbArPLYV5gtuq$*!xO^Td@ic z9=7(jHU=l*O9rX~GgEl9xHUSYCl5>zL@wP_3tSfCKMWoop5L>Dh*o%>=#;YQ;YFEV zaGMNIGImaC`-w9gxLq%g@NXQC^k7ZLvOkC3p3j*EV1o#qaB}nV{@TB1;<(IwBG|aJ zsh61)HnpPRbv*IkmElGT6V#Y1eg=2kfTM#i(DT_=ERs%c6Ai%-7;NVb^liXQ_El3P zF>FBRxW@S98a3})w!e&*S;!76;A!FNxPNUJ6Qj4>AD(CpW|mu1eK5w<)nBe&cLiwm zkA3A=0~?)$0y));Dnj=};8_6fG^E?#O``xG71>totF;F6MT3{e>qo$#gXUe$buUH? zsJ9=aStl+iQKj2}&&)s{-Ry-)o}Cc_s0 z1k0*S3>+yE#Vn{yg!FS_&KAUwt5%f4q`S{Z>` zrSiuYlM(y2qfPAXNQoxHtG`t6%`9_D=sFBv#A#6629HEMthd{^9k)!mA71RQZ^D?K z@A;=DmCe)URCqaTf}^c3%!I`r1MJm9MyreVKm`w1$D14zuW^nlds6QTzU7Le{;78J zjw*D_y~MXKzrSwWCQv9stj!Q^Om^H4up_UKVPzZRR=SWk>{D+rL06DbxbmC$bCM zzoc;Sm$C6b!9(Xt9vj2pcpWY`@DwRG0G1i+XmdOb1gvp>Wk)&O74d}?WG*4gqqY-x^$piFuO z_IK(cU}k~ENIpO*#U1abjf!)VpCsv?al@@2NW^U-lkUWvZ6XPe4P!_DTW>htRUctd zj?e5~s?K(}+wU4AG^ID%PXliCBDM9t#D{!U3i!KJVSxMlV})X1eixCe;et5pc!>-p z#J>lpHNbve8e%oThPFLRsNurE9N1{{_V)gU1`b>Du<`D?*mAm&(T6CEm_&Xi5G7=1 zH@WOyrFie$*|5;Wxn?6obENd8D9foe9G^=D-iFv=$>(Nj^_}L~qN}P^(quf1gkyRB zgc0%!c;<8nKGz!<&pQY{{u+nPI6RV=GsX;6UzKrpYIs_rY|ZC0G_59d^on^^2WY(7s#=2|ed_CbJJI{|W!D&hveA8F zTPypOKw5$>2$iG#mRX9s3*`rm!-jqCv}#$zA){ZWKSf=}VKzq%`K#IwBoV&0)#H~y zarhV~!z(dn4#r-xx0TlP&68ovN7IvG|3NAZ5)a`@6uKS=!+}K#90wN$g z@Muk=w@xKD6o=6sU%?2BSu{ghl1m*vUzqlnALB^wtrP$Aj)8FVf;Yj13Lh0C2~J2I zBOc9RI1$CerkxjQnZt7j)aViF;Rrf<=5*!#vI(*4^#JyMcOP;*U=Sq*WyzwJ5*+3A zB;JbQ5OX$;m5QQI(KfiwD`VApp?fnzmG%3Zi&4J9n9BZXdh9hnvn3pF1_b0mK8t7M z>TD@Pvxa4%ebOpvlgg_qtF**RH5>xe%Kt&wS9Zk}HC=Y2!2<->puyce32wpNY22L< zJP_R7gL|N{#v6AJuEAY{+jQ2N_ruIQ&ze8beeS*I)Y(#X<Rvy{S4Tm%Nh3X;I@l=(rJ-rNaHG zg34Sjw0|~!4CSqD_Nwj;d0VWxrDX+4$_cyGA*#FEtU~8_RRwB=3_im#k+U~^kbE%ZZzGx36JMoPEoX@Cy#5K75?<#h2&7#o*gT0=0FsJ21O zZ^CETOTn|lrkCOrCxq;5Z}0ocxj<|-KS;hXL!{Xq)VH)pc>P$E z()u}QD}Xpir0*4e=`TcKr;1-iPkz>Q;$}bxiixyB=*gh{L`u#He32Ul*yy|34+p}6m8lE_N+ba;uGC}cRY=nAX8zIvyA;6wps|LjTLixfh-|@QPV*pt9+QPut zun>Z|bsr-GqVGhS(nJ)99L!9&?_w=3DOWFBWq+)gOLzg;P>3Ab)j%5&#qzClC%;)~ zsLq96Tg2n8x*@<7!LI^w^&+u~Wz?Hv#!wlX8eadGZ|+85vYG*Z2YGh|-@T|uTq%}s zHDiPW+eja!ybt-WS9f4cs!> z8prUC$%x3g(&NDyWs#~S&1c?a@kN%yud3^b_z>+q8+5(1pf%JvC%t~tsm}~d{g#5x z5YBkvyk0DcWq|C1r@_zNVK)i-=?|b}(4kxdj>fJBE!_mCDG{zOaC)UuJ%I=iRyAu+ z3`ubB%($ea=A&mbu`K-Z^4Nvp@}Q)3Ka3K6IdmO-iGPkS^8@y+<$ommQowLqG$O>8 z_sYQg>d|t0;bbCl+Twrw&Sa(25M4OqCgl>!uC9KBH+FkrBo+IPipjzkQ!M|M zEJVBA%WwzMb~kHxKvnsd zo6+8Y3aaGGqi!P&`WV4H?v<*U$P(*Z+eSULOWoaywl_oXeiMYu=7)aJDgQerS_7KH zX|W-jm;L>ghr>X>CWXP)v|Hjyj}7$RTDOrA?bab7zBgoqP_XgfLv}WCfiBB?V%eIn zQOMzMH&<%HdEhGpdX9`l)y5YNh!5U+4pmFVhU6Z~)c{PJty<%?|6MNs*CQS+s_i5@ zQY4D-imK|G?=cbrODCO3;G_WB{glAah*W%Qktx`mAjM-e@%NbHphM%u(yqlu4OQOn zEjeg%1Rp9uwWg$wy3W;+oF4{XBI{ADOMy#(PcljDtPkm}=GAb`WM{&{mL=yfShtaFv-fp(K@`* zxba|TZce@Ww+;6=?96p!Uxl}w&ms^_--<6n9(RWgr%J=bp9nXG5AAVk#2hc$bWQ7z zNsvC+!Ph9TWmKoM*c3>?L?l)6r{fEmh(r6O=0&P@*`I)Q*T186442H~r58 zntvWd+A&&hL(GVPoi&*TK0wgd+Tff=|E2k_7xuH)MIxQ>H13$HQU)zbBGw&HwSqQBMJH+n5`QmGWMqoejg7N+eB}v5 zD;+oeX9k|$q+TMg737o2O_T__9Bj_SA|}7N7z<+KhNX4xvSEt=Iw|xdiHvPN?Gx-l zUaAo%^*VF8*N-Zht(STjUznC{i@dpeZP+IOjd$zX%U6u>_{?$tHb#(#9d=qm z?dvxQn1cNvF{dq67GM(ttCA}l{ApAf&2mbprk-NG+}ugM9~>$8c`rnaDb4lz=!4U1 z?rnAaj7N(cYL<5M!SSif}#W|Vc)e}QksiGL2Q8qzPHwakMBN=2i) zcHx%`1DB_~t0H+ntmGnZ6tGxM5Pj_=~NS9_au?1>xK9BDF48m8Q z0{~LBb7lvnHv#7~~Q+tB7O|?Fu0Qahsq;84yZAv_z&* zTW65NG~z}a+?Dw-91@0pKH9t?mu@0Dp(+)P3q+@Ow~>}32wgwJB2JTeE=m>thaLS* z>$dQWx6VVV9EizeYM9cZ?sD8 zf7ji#!jbZm7R#h|z;b22(RQbrVaEt3IA^5e(<<3o?Sx13#@DMXr)O> zzB^7R(O5EVQ?UIG1;@7DfSQ9o;5|Ck5GK1Vw|$RszBPd zO6~tWbFT7!iLY(`!B6WJ^s-W#k-A?k0kI)PXumNIhy9-F&!w&7!>e`9dhw_$67AFi zvT9w-bvG>v{mPg)Gb4bH1%I&+%^fruD#?v&K$`OI^rl>H)5gV@dOP%o8M+FF{7Nxq zKv{^LV$T@PyA|K?I{3Wq>1OeFS{4><=dFrKhZv(MK5>*LinJfO=UC$2Na%Y?{o!uN z21+!NKy8y(b;HoqDa$=_e$7%Yq!Ko{dUi_6d))7`oO`mcdtaLW6lK_H_;!VF#rSVC zmg$$xT4ljDBa1et^lA3DhU3}`_Jd{j0$sefVYhJKb^ds=Vkr=H-Bcg{NQStWL7C?w z%i*dGiD;|Cuv`;?FWQ$s;&hg1J1g8GER%IN#Eb_cru2e>`^) z`dXkS&O8UkhDVp-YYP5F{?&DJ?vv;moV!jyOWVAWe|y`@!_k_|8k}N3EE@8p%Qrlr z*TaJ0^l+cc(b3*esfa_$9Lv%^BETywC|wkV-7N4G0_SW%EDjGTg*xa*HL)U%2K_Z@ zFmAJwXrEXw^ldwDG4LHhFFJ1n(gTPW%N&B>AFLs=Wjr={k?a0U8LTI+La2S~iF;2v zl9DS3hyfp>NUpf!%#TebJbtU&m;9iYFjD#e@0OCJ$)Yl88IIh0&^7wLV6%UztGuh4 zgARv`d)$7?@hd3`PD;H5RquC(`Qb2wYOVP)$2B}gyj-uQu(y1cE8n* zIBfyMTA8-6Sy%D>7bo;UiXkiK!!j75$WIFNdf?)ZUmH(k-!r+};*2Vv`$=TNA==yZ zknvky*tv7yOvdgKLv3CX#AxVL5b5nA`>8UXW$!7gJ3K3Y8a`s9f z;m2AA=(20Ed&O%<*N@sD=KOw+yAwxdp|1$(@2I7C<)HAh)NfHV71VseAY}2w$%gj@ z=O*7q^qUd~hmw=O!*`{Zqk@} zw=?jo@JL9Hr!7hbp~}r$&3~d*(zV!=)45h<_*I_t>g)VVziq;xq43k8kJ0^e8)7%U z7tAiw9A;X03G>h7PyHU;; zhgLf0pyMr$jobVbf3xu}Tne5tZAPjI*zvBu&s4WUy-QmvC8%Qf5OrwGx&SazP6-VI zo+`MdN&r}a-sSdzo&k6oh?NGfGG!pmrFQi;zh^#$EoXV|DOh*^#h(y&xjg}7jy z%%j2CYF=DlIut)5WdJK=`nGQGHN{Kf(GFKu&H7a#Q1&LjnVCo9SguS#Ee2SNvEE6n z){t$9H`1mni|ZP>H#~~iDf{X`BIoD#rE%mi7e_5671yo++ZJg?3PaPj z?C;TjHL09;}7OB|ytAqj6AqZi)^L49Lx51Fbx_hi6r0lUd?yhyIdI70< z>Pc492Tl0#xQ^4L8^L=w-BQy>&kLTL?BDlwtDd#tn(jwf8QmXLg%IVr8=%8oE0&C{ zBKz`bnWuEVxAN&p<{O0hx-u6?MJK?jO^xHWQG;xpL`*h-HqAwetgHr@Rppn{=38=s z`@%%qYYFCbrvBD^*ZIA(0KQ0n*RH(GdgEo2+sX&{WkAb9q1jQ)^}+Dj7Rz}P%Q?&n zdI$zaSe0Qsz;)47vA`zr7G_w*sfGFEv8)M^nA)l0cH^}-Mm~i(emq-99t0|?w_8-j zXV#80?tSUCPHD9je6T95eYo;MD_n*P;MHy#AopQjHF$i1Av!QD06&ftUm;gBqgAp( zG3btsULR7`H8fZ-QbMc5gxX(h_DvVb6M&X0dAN^KVnnCCjqW;No=8h@SR#Mp+U|EV zIsKmQLPZ^zsb<-Gzo0mqJA|aARbUuJ7)Lzh%K-aG_!*ud2582Qnd#q{~Ye zm|61FI?LnLuO$&O->2Ey`z_c)A`wqJU;WYr-OE=z*L|ZwGJd3Ma7^|87Q!9B{(cqT z>J%EyJT1@K{24|?6eJRGG5<(&3nP)>X@hO6o29l^UzA)Q2{}x^+cdxbGZp9ilznk; z){aOVjCk6-M}80MeeayMo;jfRT$r8Xm!`sAaz$$TlhQ%GxGS=QiC*>bJ=_91r07cU z;oo~{MJ&xYf4*HGff|10B4#xN(&WSHStcl$fFaC|th#Zp6sw&FIUcnKrI4My{=LGlfr*I^GA z4f_XM?$mCqUgnyXz$mxTR6@Q(zlU9x4VJiiC~P@wFd|#Vhwc9}ZB;;yvsTzufU)MC zY!$RtVvB0E1JE7Jy{bDN4*NN2#4sHL@pNJP2QOprEY1O~5Pq=GM``4UjSRN*Dh>l@ zv6Oz(K&D@9s#Nh|`p$iL|KV%NAjiqxX2BMxfPZUtf&YftX%UoK_VxzG$7qv<VYm8I!zHxpkNx4q!e18gq6CkVr6EKD{mH-dTb4CT+OYM{?yB--hkxCeJD(qh zZwhTH6EmA>g6>Zh6xq&KyTG;u@Bi;t6*qY1_0`5jACHU0h{S?t|DlO0-qe-@h2O9r z?9_yr zbFClhUNWE3jciUTgjic0orL`(&M0shm>E)oJgQ#uhcxYuT3833Hc=0z|NOdXJ$BL( zPS{A>oJKu}TbHw;qGADO6>N$X3o5%{4s{+X|IDVwjz6xvTi8TqaqWl#Va~vF(tH|b zEH6?#!oOJ07MLSm&Lz3hp_Z0`S+nnKt0^gBdM>J2S!(cL57naZ<5tczx{vlrjc1h? zEHsnPSHy74f;HPZtrTeLatMTR@P>w;BAYzPez25<$@*11VC0oc(a^V=JSw|4CUZ6KoVg0cj2}$p~<(Dc76)f^{Iwdd-jfK^zHG)w6*{6 zo5rJc&hLF}O!72MAT&gDo%D26R4!a(WO!qeM~h`SA~6$FqmX#JD3nNKG3T{B#Aof! zW1E7BA?x?av$GL2-sB60xMOj4dgfcM8(CRB22U7;OL2Axv+>4H>Ej>AE{-iXDtry) z8Fcl3nt>!d18I$8UbYBzEZ>GBQS!+Pp}ll_ZSGbzxGE+!_ew~9qc~Yd#H`)8vtmx+ zFF754tu0V{4pzLWKvU=EUFj6Es1t2%zgbY6ZrE!959Pheuc&w^u7raf=Yxdr3!G$~ zR#UISmZZP8qAic6bd^XxZJFqN(|cSQGRU4O+83cqSf`UtNz!2Pv?~KNtVWKct8OYY z{L%I*Saljlan&`Kb$6$MtbgLtnfim`Giw&GB&`?$B^%lCv?04`?m5#E7@1tg{;~2k7l%Zkl17VBM@pY^x z6lo;Hr_(0Sa#$~Zq+y~4Fdf&`qq5T^B;o~NG^T1v<9&fu1;ByHJYD>78_B}t?0wyR z0&s5$6K%*;0WR;p_dae~-Zc23b6+|F!T`C>X&Ld@$c8}5h8<2JCh87~5)5tmMqry8 zdcx1VD#Z%BvOucHrt%B`GrMvy22Vi06*S+P!g*2yUVN0BonW*{Fs1>R7QRK@rLS)h zyABKskQ(oDH?>>%E{YCu!3@=UyaSL*zmuT@Qa!pT#dt2#_TNu`KPt35djT(QJiGfL zea8g|U`|6ks$9WE;1;^BT~7a2rTz!b8~}vamgI>f;OcGwn2U5_ixb5F*nL=wT+XyL zeMCNX4qei@ji!))9Yuaz?69F9iqm8{{zOwlW@eg6HgWdtwSI6sE@g4ZcceL&i>pvk zejLY+?H6Xu4@tCBjwx47^~m~h*&E4;8vCehUwefjye{{Hv{YKIJ(d*rmZrqZ!!&ix z$n8A~IopQ`^wZY99S-Z{#P=t7N(_$h_ID{EPzWMAHqQG)EZQBF^iF=d>`U#pLD9^dop@4iQ~Gsgmv_yP`KY^d2cuNjq_I9t5awdv zy*>jOKsZrIykP&k#I@|impVjwQ?Qk_dP~#9?`Lb~!WsO}g^Eg{ZnhLPfp(d-?BX)E z9)rKv7e)P@)$voMi+oxYtmDZ7$nXad<*BBBx`%EzAwg^7`o3Q@*}TW8VohZwbGg>{ zXGZesE3_OKMX-X>(aM{t#t}rJ=$Rx6d=+kttxLby0{YqFBec;j*nFeN+nwsVB5p+deOIzE)2 zMYCSqA`KwUGklt3l^J(k+bq?;f|?V#K8YW!jKeqe_T7k8uKfd%e}4J90vsacn0BTg zMZaty?FRwj6&AXy*p?8Pr)AkS4Ew0$?Nsdp`bJ33p+Tk`yf6$+*hq_Cc9=HG8WGVd zQ|okzhdF}`t?M`K&fkQq+$>VjfzZ%p|78*t$6=0%N(_mT{OTP^x)B!Aspc072Ap;) zzsYEofn$fG%n;toF9Ot;x>=Ld5Y`uIP<0YW+l&oCSsL94l<>6;wgr2;qTmYCMp?oS zzon(}1kiZsjilrHav|-aP{Mp+;NO~j#>nG1O%GwuCz@UbQZEqE{m#bS`tyJ|Dr2mM zNDX^+KLKpES-42!?MhMYm7K*}!p?Ub;1Sl=!8K&^q77oo?go!N^*#5)BwChD1KKVb zoD~v6D-v=wId&Yijr|~OacU^F9quWasJi~-t&g*MAlp@aY?@?%DBF{; zPk(PKFbXFg%Hi$-RnQJG}8~%(+ zJ^T)?&5Av0Ma_gA5M1PXn3U|ayp*L{=hCp4b1tG}gjDlYa03#Bm9i;QWjoOk(811R zQAwOPqCbQpB%nanxUtr^dT2;bC=uXKfxN*StAS=j4;nXV&fYR<@bc5Y!JcQl?Xb1X zp6L#2arbeT3#u0AQ)z#l_sIF7o;ML-b=NZ5K-$mIxOc41{oHTEIB zt!b`w#+ZlG4#6HmX-@UmBlPqZI<;P@gLobwZzynO0xAt|-5A+Tq44Zxr|fBB`ab}+ zuHF>i22D7vQeP7bVuTe8Jm=m;sUxE&0bkVT!ygecTUbTSux67FAXE3+0TS+Kbu}Z) z56bSjY1sx+3;I777B~ekNPnz`mg)cO7ru4V=6QVM4D3cIPt?q%YX68U`k24n~fRL*Vo+T=Ve(P-k+|);LBYP(YW-ge- z=6*EuR^ohZFb=z^gPQt>1LM(+-TFD((budgSXNFrbe3TFuZ(ei1A}Y!yA<-<#nNJl z9Q5ebcx(u1e{7dP8`^i;;wzFkNEoSaIGAqS$4%c@!M|z2L6UePtuu5TLQ8%Dw=RR`#pPUz2L57Z6T4(iT8DqZyFWVNhtDCdy0x$u!rLE`tKNO>g}W(BQ}5+TA7vu&Mq?@DI%7U`)}^O8gIT zy|5WTRCE)jV}~v!Wr|taJg&6O??VlqP{QRgvg1s%@8Ib6h$4sED&`&+FLp&<+_rG`P^By(4nzB0bp zz$P>(3H=S0Y48dJ++t8R($5rPmS#+1yktzJ&u)yyCQDE)#H@j?-rY`ODyG(#44gC` z1$^oseQS%~`-OIEPli9u=wqB$F&)1)e7&_oK@XHjZ>yz_d2THFCucD_)C@f>a0Z*6 zl$oB~zy2SScCs3M6tclD^PrvLs|ZpHFn_y|o9;AGY|3^ZfATKkCzVnHgk8V-=6#ol zAvlS@k7h()lc?9B*rlgcJi$+umN0F3669^4WitN_j$5#?X+gGH<`( zcYC~!RcQ7=js;8GLXjq%zRl{`%rF!nT-B8nvL)f&@9n2QIoN*tqkm!+sS4!=_l75D z)_1PzY;e-xacCpDmG^0+h1~Klw2EBnvbAvjU&7edo(b>t=xkBDa(%4jVoM6KM%N@_ z?N?w3v-HumAh(MoF(2RTiChAZvv~z=J3BXD*zO9t80{l?rD{fO*HfCYH&dp`ORav+ zs3Kz4r-T?HrUasJ;nc7oT#|^p)tMR~4W)e~$V(H#O#R7W94RNaQ{ZSZm?6?4+i5uT z%a07VRs=IRCCuM7fi6W*Mqi;^@IWW0a~qk1w&u!{GPBTT>t zjqQwek6oA)J1WV(C72UnYyK680xjyJ$sgzN_4~X-b1cXp&JTFPLNqUP# zB>D|<-1+)4ykxWCV|eMeDO(TWoF}uaB(;m?NDkk|A5hwr`o%OiHYVC%T=Rv!WVbOy z1mSODnkl+=Hy-hDf)XNvTJuLWP%?4cPEYSxnuuRm8_I~_F!Fj6rcJ{i`tV<)j>@Y-j5EMA6bb_Sb@O;~@KE2veVIB;(Bj}rJQ8H0n!#VhB2*bDK1Qo)tW<~B?(J+=$mPg3 zkIcvlz1|v6bVigo9P*-t0+?x`sg#~j_cWCin0|D-enu&A^=3g2SEoDhEQ2yoXaX2E z*O{4T96+>88(^MQh9=)n^Gh~?B}nnR#&!<3Q_gVvh_HV)MJk;0=3W%72QG&y=nHIi zO~pvNwXCpAMO=D0fGH;nCuOeo#XyQDIUC27DxNy$**1!9ek~e>+sSY_nOOMNT!w^N zFZG=aqg0B5)`GlvL7%`J-jZ&$OOkwa#CWc*V9 z{zC+zO?=R*mKNQ&oA%`=Be?{Fcd4DJ6-wllqv+^qvdVvTOJbjR%`!%HAnLngPZAyr zCdfKq^YAGDJ7=Q$M+xG$6Zz1QGy*<_Op;Detp#f&KpuhXvoV-SC?Tm%222^iiw{8b zRHa5lL|hU(SxjAzhrc1s7n?}ulK%R4|GoX?o}Vq8lj<99G!G~MKAlrG}aSUKO+ne}b+;u6Nw9)_{KnUAWQI-VS-wWf=F zBfn=37RoTs9l>@$qR7p{C)TznBqAOg^^Xz3&VL#|cfe8FvI<7>xtR6Y{lT(?P4Rvo zRb2bw@J62$qmW_~{N66O>w6$LO%zdEvYeEJ;4{YQr272u14^B#NfRxr?f6h-S?6kE|PY?~5psqmgwN zOJhp1J)>JGoR;Haz~-A96*nT}erYjY{GN(1^MlS%KQt7JJqKk|_9U1EJ5lB-19w6$ zlov&rJsU~)q}g#@ce~vAZ1^SkVX#`Sx>?S!1Xjbuse4pPwfvXjzr0vsLQiHWc1Qe; zUL}--%pY}6x$%3VAFG(^{4(i`zFmaClw$kMvYdKGW`c5y+mj}{n z=FivjsazAnYD!|yZe`WsgK^m&$OCbSCUcWF~Wfb++iy$X_G>X+Pt2E2G!Ht?2v9YP^eX zuJ@Z)%I?dGO{)wA6M_ax0$X+h`>!`Cs~*dWfy>E!D@9$)DYc$QRZYXNc?>L%WL^;A z=R1Fm>yEZIeN2&Kr*vMk;uZIG1fqHke{jvY!4FxIB`L6O$>6O&`&%h4~E z0W#+R^4DHm<-yfgZ(VZ85q|S_{uKDAx^*~&!0-cG$6bCeCm3{&DKyfcWl;Voa`C8u3A|xUzY- z=OSqoMK&(!!t;H+7Jz)KJ9$LdWPLZq$^fnXCS@>Qm5C)s<=Dbl^x4l-DtdjL{kROlQ zHV=dMH)6EOGE+s`$N913uD}DKy_+HMUZd@Z;qr~mU8=jt_*d3T zym7OZdbOQCBsS9A)2Lhn!q4kmZaiYznu9f~(#8BcR-AeiT_$TS4}!un9s5Uhrv2L+ zW^3S)9oW>0+kT0O-E9PepHF`bKZpb|0`Kqdr_0@Kb=dtovcBzFHN)(ic24GV<~Q75 z=IA=JM>DzfZV~g2YX&5UNkT>@Ob^4-iTNC|6ub_3h&;|uzv`=~#3yNhhCDk*Qvx$9 zX<;Jc=5G%NC15A#hA6>3JMaC#T26~mLd0xTx)?E8)|b8P1_T`}(QO&;haqY6&B$Ma zem-YE&AuRw#xLCM7sQ%p+Be4YwA?0DH7zR9i9QxCnNR!V4x;qL#$&Bz)4(*}aZJ^a zkFd5KGNPev)vDg*<<)kpV}~liNpYtA`;x40`TD*+C!AJCK=4+Kkd4v05?ew=e->M; zB1F04<-rya0+U2nqc7OW4~>kZGMp(Tn8k`{0ykeCPg#)3U6O>a7Z94CZ&6pE zUY_$v-S%q`oT$Qb3lRY^BY$gU;QIl_{cdwR<5d0Fo|Q+92r{lpfRtt}=ivPIy%x@E zL&CPiEa!1rmjz%e%_f+8u98MqK12*}CajfI6X#}Pj8m!Kebyrr?pw-KMkMkOyg86o z!bLvL7Y$l}Cs2o5{l#{7$rI6o&h&W*r5i%Ae^|tq@9_|)|2YNU!r~Lt^h3d83y!(Xq!l5l7a(Huy8JKdZO*BV&z-EF;83{`^85x@XlA_Eerb!`^Hr1TpxMC2HT&J>qV(X)UPc!s?Fx3 z$u6^asl&g^)IiJjP05P9>vH6ocQJpD(klQ*trUJK`4RYF*<3hKvETi@w7@^E8m!fr z^4fk8|9901m&p4Gc$o8TbEeAzWKHTRYuzfUh5GyE;;g(DjNsB+XjtOKd#`2l(|X+l3tW_G638&FGm(zZo;e_X(Dxsz(dc=z?` zVqmAH2UDK(wHu91W*`Rfa=UjPl)CDX8nlvj-0^riEb4c)jC21~a0^>kwZG=PX(I!l;ddWehmj3CX1+pu!VqhivHjzmX&MKz#V5tt*J-l4fO!X8PbvB3X9$qM9cR>IJ^aw5&W_b zi2y@7eG-y5sVa&*#p<&{$3)0q;%m%WY{~*kIl$F^S@zT)&BrihyX+dQK?=VT4>&me z2%#BPPPs%@7)C;edvGhfhMk$Dt$PnBl#Az%CoL1O_$F9&@>u@A+siM%l@=ElRW&qb z3(Z#6?!Ps*-F2Zi|EZT4Vct#2a_T~aL9HL;Db21HBO$4Vw5id}+B(@+(wM0w6eMhk zbc(7-;Vo4xy7gZIcs$oWT4&CyHm>{mc-w87C%Zx=XX`AL-xEQ{pJ&=^R{b7X_=aF} zRp?(kUO9-qo=<+)6(!gfixp-XAoI?HLAWM#u^0YyVQ=t1Y82<+u&tfY<q%3rU2Px!<-?KVAZ#boNt5~HD|nq7u1>&)?uuMHfhPGW z9EMAbyrjt?XPEaFnG^5oVLj5iY2W86^S|jmpi8}>ZN%}5lTlh!m^8)~3(|nn33voj^x*HSxNSLEh7P`)f|{C@0Y^26A^*efr8bN{L)x7BO= zs(Zt>g|hh$zL_i`z)nFEJQ{sahk&S6qnqBb8PH6dGi&~7Ki762yp6OCbY+DqxS!xN z#|+MHttF1}X@81YtUJs7ipBSP9F{02(LQ?AvoJJA^`?MQP+Orik?S ztU%&<-S4X5A77=Bq`p9y<3dp+MzSkl`IXEo46fMG?@ojFcv%lq$TUs(WxvPeHaK=< zXn-z6&pDgS_xI1s=__ScS0FIVb$2{f=vx271^AQX30hfg z8V02r(Df(_YrxWwu>M6nR>nl-;*OFblz9XH0#di*MX+@)rmAMk=YK=GKq&tA?VlML zZOuCknlx`uU@0Vn_x(NRVZQD53>MvxP~zGbsnfEOoP_tSub+?{nrojfXFO2}AFq$- zN$hF@gQl9+{FFt%zAAz+O+>|V9y(wM(o10Hdx3if%{OQY_L=#G6!Rs!5I0ziW$R1V z=hAmXj~gvPvJKnsaEKCtqH*h<9g1Qe1JRmXU~MdfZ?X&(-@;l#!~m}BJzR?HjCIGMP0EK^*O zX4z~8z7|a{QlnVdIOu6=hEYc-k-Iru z8r|}Y)>)skOu37BYdMM-`;z4>Cl)@92QUBbCM;!FeK#T3Pzc{nzvbY_r#Tf+e>9A^ zFveIO-0ier73#I4C@$$?t_j5?HqmTG0t2`BAX0dTSkc>J))nR`K$D|i z2E(lwzr?u6Gohl@{<7nz`}M1dL&UF7;q=>aKR;bt>Kk^Bv!;yAqjAr|cq>dpqr;j8 z)sfPZeX0CT1?j=o8J4$vg)agw9gDB|$E;v;}`1K_Cz(X!sqXTI+G` zuPm`$!RFh!ik&ig3Nji>!FQbkJFK~Yk zgHu|&xD8lna4q<8giY+VFum$F+DC@`@yu({V)l}rqMp{7IC2O(P1-VEl6djHWiXByYQlt zpC}_tYT(Z z;hl_9o+SbK5R2=t19hsa%+^e?c-5$R2~5cxhzYwlism7WLti$`#ulU#wM={%tGKi| z(oDy#6WGElM|p`Dv9@y5`qIf5@FLZ|t2A%`Tk0RaQ$LIdR8sxW+aRYz364-ye2o#{ z&^pD^su*wF0`ol!yPKsB6#h`-9Mf)3S>$N;?tTP2=PGf2TgM>zPn~F3Rkr=E%gy_C zM1b>&VtH`$rD`3iml=gaSuM@sE?m`8XVt-(@@#}rOw za|>cZudNXJ?Rwmpx2UPgY3vfK!pt(b6s^+ZMBXi=?!VcIy#F+SXG29mbz@Bl6Qa)_ zIPf1^Uav=F!2_ofng>Pmt3?C0?W1=&x!+!*(S;5Nzx&`&eqHO+8fm6hPN2{Esx)`f zoE>lHXLqsK*ssG4txC~aKx3C0P zg`LZC?c>2z)fH!+BP@_4|H$=MCW=bU@s^1ZI^|!roWyKpeA_P)t}hFc%83#@LQiKu zWnF|#h1eS*{H{4@;mq&_AN{!$FXNb=fiRm{Ae6*Dc*9&l7`JzjNPJrNr(}b{a+aEe<%hYbM~T>p>MHAj z>o;hkKUNn6#}g<8iZnbBBJ{(4Y))iHwFi-n$iM0 z0nz_$b18mv%uu+u$jS2UZA8%`P6_HuGs2k($(0P@r$h&Xo zS_)Z$K#d#*^AmnW$Wa&~bb+pQxC}w33aL~BWNg$gW5mpvj(1g5U$4I8X&@bu8gW>d zF61=V&6v(%n_^evz;=+8tG|8FNk^Pme%S}MD4Cls*I+_a>wK>L%$PEo%EGHJtzIf% z7{Me=KSJong}=wboJ@3uFFSF%io03XU%u+T?C#PtOJIxBlk-ScX@?wLtJ{Xl{KZ>? z^3c{hG{iNM4bzuDmFgp-ZcK`VTw5(4!!v2lvpaP*I%z+~IR%Ume6ixi9EfF6 zHlD`|?B{vIwAZ4VSX2p@GNt>`1#xQ2OTpN{w2j7qnemr_M3=U}v4d$NgcMl7Ue^EN zFbkiqjt^OpaIUNR7Bs7d=UdMSMAST2W!M8iTihQk1e9*m#ty+WrHxZ~~yy2Hm`*k;O@> z?2s?y@#&?+0J7Wclah51PBYDwr6fSqy1EwghYzQRJU`INdm^A|fX@t8W5DZklDFmuJakCVG3^Id+6~*}f3Upsy2HYaQ@4`geKckhhwKJo^U1xywKt zEUICFm1#c4z1bS{v(mJ(h$A&)(O4{P(NF(_fC&Fs9ml$dsDB~sl&IGTGT_lsOI`(M z)Tr0jJfasz_}=Gol>AK|Znv$q__jbeLIm(j3`9wrSEoSB;=(=(712X9PV)Ia?bh3| z^sG&=zv~^;)hiNPbugm8_Q!`!#e>O^lNI1_CflUs?XrfQ$@iZc6F`UL?6|VNJfqTmE$p1~uc4xsZ<0YlONlhC@^c6{$%y>;z2L z_(B6CuTar=on{5HLH;z(jd*STY-2BXpX7nU5V$gPbZl`Pd{tUJL5ssIRnQ+3`dw69 z>~Vf{*iO>x;@G`W-$1Cq$Gu-S^OTpWl)72)5wo6huy^#L z_aZML)fUPykD*0@c6`={jZtk$K8lh`P|ZHR*PlDfLywr-_vYD#JP2AA)E?iC5+acKHAV_%wG8rZUqs9Lm134dYo%r`8O&?}4mo zXgF|y?osRjiDr&8GA0g-yzmeh=SYA#6#b8y7R{_irKMN^@K~b)Kd>T+(wn=xGEUfa z)T2W&%(MHY`owY~oh_LK^_}sls1v;Rb#f|b)qNi0l%75q&&TN(L??cs2lZF$wbr#@ zU)=|k1isrgpm(Zo(TlaDhW(U@P-84^r_>M&OL0!>Pu`;Rx9rfcSUlTsgb*d2uP4p@ z0Tl`>0f>1nv)0)M3E!<^ee5sR)Vs) z`nW60H_j#lb@ITz<1KXEe>FLW^_GW$;+0#6?(o$KfbRqNzQhy}ZHodX)4HM7bbNTS zY2GWtDwO{*=klkf>c54}=i6C|?Rf!O&RvK-PTtr8`G{$7RqZdY%F-eiIXF*pXPI&g zym{0STZV>1_i`F>9rYbjZ7Uv`7EUMcmJ8Ni5Q`zPIWuvZ{0%O%3$q>SHcVtWY!Ek^ zjUUrwdI8viIB-_LAHc;rwaXo4hQ#(wMr5@Y{*FbOxF2OChe9b#GQ(sNh{Nu;1 zqPqL^K7H0+`&px!)xSj4LY~p`Ybc5Hq12#GtVCIWv_yxNtPU zGp^tv4vu|lS^9b%b~L>jw-_6c@BoT|hOOo7PTiYagVP41&V?djjGb=|jn%%-rBBoM zDLdwKa-I0|1_|GSUy07Wo#kxhX6)AE;)D(2{pXV5qQu0AKWU+L+E~wWgzL~yf zB{S{{bf00XSIyzV#P-ppIWGL@XLVN4z^4Yh(z8MNEniwFP|vS6!=h&h8`Ll9_HGSm!CSvg2J~)fAGQ`UX?q{G&dWQIP&yQQ2;n(jwc1`XR#g3fBDs$g%>ed%M*M>FwVCjB7fe#N!0 z1$^^v!hg)(J@sgw2`I4KcO6U&-q&+1+NxC)#<5Ts(XXa{4tjHzN0E8d=tC*2vW==x z>BGHlU3Yz_TxR7?T`i}Sj3iR8zi%4gm{UwU2iU?0=oxKb#p?NJ3@|IUjd@r{f}r?J zTE{g(O!&TL10X#RSJO5J9Ht%VXHC$u@fYI+MH;-ea3X@}l7he>jDCh7)kq}7_;{uH3Us1{-;-W*F26UHVY6*Lg+K+&2MZ=V{_jD9HirrU`f>GK>gWOqfI^)v!Z(lXPYihv!2>~ zwE=`7bim8Qj?txOO^rshIZU5jh^Xn;{~Ut zUzGLJ%FgRm(;wj%2v~i!swk*4kAC;7L0K_HZh~A<4lKXdY^~_dlzg}|ZT6ydl?fxj zeW**P_xvs!+2A2RZ_?nC!BSsPop+dCi9^7TX6glPDYbp=0wX;hM5Bn&J%KNYR{Zk| zo_w9lyb2%XN_R*bSrg*9X(b)ym#{3ud;afTn%FflOhF)67}(KK3ya~TOKa%DrQQ*4 zm$em>0iQ*cYTD0Kkfl;IfeOAK?4PO`y2hZxU@rL)n!F!=A?zkyNh9u#R5sc#$=|F8 zini>F#@jK`peBsDVeMZJVT(ySNdMONtX70u$h(+DE!5tE?d|X|g!SBKMTh-j!0X2l zY|!CYibrf3){9L9@6)^V^LU8Uq>{-@;qV779C&HceQUYJc=Gg9g{HA{xDYi>P5LoH zCHGCpX5&MZ--l15WBsw-FVMU`-MKTUvb5Ndq|aP92O875mHK3p%@Ff zz+CvZNh~zW(f+6pXX>9m{VM#1^YU-e>hovKl)KT!4LeY_p5OAS+Y<_5_p>Pr13p@s zc)d1fHzKQ(p0V>I6zqhQ`Nkv-$H6za0mB1$@=C{-Qw~-ANcDjsr2`zT!jx;Iu}@Bw zDfgci)K&}ndWY_=bm2Y|as^mj)Dtr5Va6^w7g5_Qv*BzqDe8Z$rh&7^VxhyPFmBdn zg6bVl3-YQ%%wV;bv2Zsg0gPgDd+63R>Fm|fEz|}h$)Pz6-=N20$eI~gcpkPNXt&Zx zyE8#mQcwpT1cvx-V&zb2VEurSS1fCkWUo55s%iScEV`;#-c7S_AYAZnAMjt#9c zWtq+gn=+$C3+ol^;WhH$FCmsJL(zqLPn5U143^{2muPp!R;NgZ4w-;cUqZ-i5ifJp zAQy6jPNT$@94%I_EA;HKW>%05O+fse>?!9*Tqj4uR57PtVsSlJsMAS5lQs?RGAzG*LDws4b-ujQ`!8o`GA%R26=G zx+hXN(6UOnM*7K4U;=U!m}yfFqaZ-3Wt07wFQhW^ z{XF2brOo|_4oEKy!9M}S$%@@K>Lq}9&{tq)UvL|52HKE7rjR8#-1&V2(p$cy*3G9U87b?+rh!#J*D)z^{$1(!ma6PnV>qe&)Zy&b`A}cA*ofiqP<1S_{Q5JQs0Yr8q^>GTxi>5>)uE!)o7euuYG77DCeZnvx6-K;&vlk&c zy4>MomjbJ>Wju-8Z)>XiW5j*;umk6-T7x-$!(n)jU1M=fP4ybTnquo=(t)?9lG z4$5y!KZ^H$p{MPX z6l^qpcWTynt_H5A0e-oP&oDZT{p&h)nEQ=ZF*F3G2cWLhB736Iy-bzWsmXs8M=hLb z9gL4jfp-e{5^KNU2{g`0sgKX?VOD&K$!&`$xc z&z^5a5WFDam%D8a>uE~wgYOXyiqk+hm4O5d`R;c1$KW+!oPB86(D#HEnC7hn^5ax* zOW@7DM1x2-?9VrPX4*U*yKD_uLgg`CD@x~pYUy`n1F^w9bzToP$I!>NK0$N^w}5>ihEG9#~x}h*Z;tS$aN&lOePH(Wh#rbO{r5d?NT5E7NbC46i6upq5B$OewpoqfbDyCuKchlI(6h^~5}^ddN3NWoo-hVR zF%3_h{ZDVC$o6Rm{FsrB0rjo$RpRg8lDqSXf|W@Ft1!(PrXK4y014wwLvGyL0hYse z&>;|(yRfyKX6RFfKL{8xj%cx?hJo2!rrBbpZ#c?);(Wybn9l`RBMfF*`uh5IT}FY= z8a&I^)c3&PxLaoS*;mHu1Ov}C4W1Qy&gb5J$7`sdtM00RsXhmlfbSRYA5Zzj#6z+! ztjbTOp&%+uPPywQP)sZ%h6f;!X}+<)_OJ=nhpZj^Jj+cpC^*IRm8nH4UQVR}nX(?D zvK%5CquWj3w7Wg$T{;vCb#F&)UADZXK>(YTzoxe<4 zOY09aha~6+jrLMNPIdtOIqdKh>XwXdFaxF&x6%9rFL%WJuBD8DuQo;spDX@LzUZG<^*)g zz7Hm=;Feu{W<+!+3Gxj94WI<#{Te2EHO@KnT>=5`fNKLjT|#(0Xr;!aFLeo{=4R0> z{x84D9AF&ehqGn#1zJY4Uv>fCYe!}CA0NP$d6n9-doeY)?r~lXV~g~qE}{2$nrRO% zjoN4rf7;$4RN+0nb@U*Y_41rAayh1?U9DhL-}!Z_b_HFD8`fBldmrXF%e!DmVU@C7o<4K~ycD@__T zGOKz5d(joii$Z&g>MIlR0d!S*mSZ*u=(37EczIz}UmAb4CMZw0pJbPw5wfPJX&I>a zez!B2hV;vFaI$68?v+3H$+n1Zwm&&re@(GBe9RJ8Bdc#msoC`i3aq{x= z?tb5V&h^?tdTX-$o{-O80b&W>Rp~XSW@ZwnyaNKXthR*yraJ%`WN1vIj{h$wZbS_q%v`YX@f!7;=>N~h857Sl{9({3%$^ig6$T*LU16)3z) zC&;K}lHhw?qZ&Rc|F(Uv4bAn4sk3I?w{#y3_k>1U3h7X(^C#WZ2Ai49rro7RTbvt_ zZtK+iB>9S1KE)kL%F$I+b=QIdESo4PlUSKagN8!gYJcl;j)#RD4pkR>kWD+_Vl4W# z*je$QLrEqU-X9dr+6f7Oc|h^)IPXQt^b^Zo9Zsa?CgIkgX2iRt2RT|a?SWRS1MhJD zE;glPLtdqkvoZN;Q^&;g%C}}0xtQ`c=Kt-$IU21nd=rz)zvHip&~jVUqn8Gtg4J!vb?1NQt?5Xaoy+&_|O`BfAr8NCe3q^mcR;#7o4 zYBibb?qUb;?;zWtZ^2FKbp#$us}FHV3k<=tWY9M;#oUU~&{aHNR;#8P@#;K{E@==! zmrg~k!IzoDuns+xb1IlR2;cQx_G@^GJ>jhyK3cm=vkc1BnG zQ!26>mHm2adCPjnEpOS@QIdEKpRVR?XOi5J70@FKpd}zenY4t7T;jtYKU1@3XqyW} zB+8!1Q_B%$j!Ral!`p76+X*gBwJQLrXuG1XkLvDFtR$UPJG#!xT!uyfYRKAtUE`T4 z0exd0=sH!=)U@+>p6Yu8j$3sO^UIwPhOeH{a@ys{1#uH&)gBr~LH?j`ruzKje7Z&N|!ZdSZyV<%8d~hSDs7PCK726`mje zV+!&1zKjoilE86mTBO3{y_wLXT*I%~H}m)uYl}-2A<@J!RcHa`q~mBes1nxChR7j> zY&hOzvwlly`|zR7;?cRf1~qnqU&EUZoAgfm_%|KHg7Tg0QinqPitchkQ}*6ouwEwG zX`5c{e}Ke?6+hkHnLBUq1OMB5AcP=sAevwdKpel1Jm*QB2M&uV7|JOuWLFl=ClBSz zqO6|8Mm<5)oiS^vAHJ@^r80i7>Wk*BoU>#N(5D*A&j=^TC{A_DM}D#pw~x`l%Pnl3cF8zG$80J%D(-@#Q$*g6fsY-u=Z8eNsKsAb_9| zvWbP|8F}xfz&c5&oUgi0&G{#m*eq1%aJT}1l1gNh#Vhs_h%}K?MV(0$EZb@jUq$dJ zVc$R3697!s#-~w~*eY_@fNJnI2c1<$8NX+H%Uo5OWcS|h2ZbpCMSbH=;|&0YSY_>; zlD2%?Mmq2JNLmhlL?_P$6)ggAD?Ern!2K>jqVbxblM;ZXl=0mNM!4RT+Jj-{-TG~; znCpL|({fl|;U-$A;0OfcFjw@oM4;+$%deRKtSjZ+t(;*TR7&|Hygc@)?N;f)xGYYc zX1d8muWr#JwN>BiBFP+t=qlxVGH~{Vhw*va)@x}?oMJC`*Xpqq10}MUVXofTS-rJ5 z(mBNW@nVQ#u0xIrl|?E2&n^^in@nOQkld!S(|T0>4G6?5|FZ$SlO-v_`WxX2FM#zj z`Hd8OW<%Hv_z@Uo{mwdWum5-fv?iP=zS!fGjfi?;?QS@5f6isFMHKA8ZE!rISxq?R zzaMpC=IPoR&yjkB$+L&M=B_yVgF|>3#o(gE8cnhxS7rH#7K<*#Sj5n>kjj4p78)*V zeR-F0Z`mkyA6|k+c9_~#g2|XJ7YZ2~Qm(=0a9= zycs2Y!{(n(`e|z`RyI!csZ`}(?a4Y!d=!su&|ToBOp>EwqhnZB zK@^1N6#_vGyh=sv>fC$t6c0U~3fv9Lm@I<_-?I)+qK&54m&YUjNZbivU-=J4h!nu? z`%DD@ZfoRGD06f6zK7QC*hel=Q6rBf3j(F|@5qQ0*bsG_{@$wEL1LE~x%X9}ZBuzO zdd36zP6kD6>weaWg#9vjUrE4lFgPLb!dMmZrtgdXB7S#*3&&e6D&;bLY^Crk3k^hy z4YDXXP95lAfrcm{2CankH6=GW0HmIaxqrS~zQ8))knZ*ZLc+O4B42Fw7`Qi@fb-mk zwkF^OvJ2v`m4%I{PZxPOC^#gh9SL&LfnNoA0X~y?DV)I&pVEpS+(6a)>rWxuWk|Lg zx%Tjt78=5;erzj$owH&o|2Qu$#`*P;2BFaJLhwgN>V}woOpBuP(uS$Ur*{E^Ra*T1 z;s8gx>$FN8gEF!9SCU0kX=P1ioSs2v4c^ zy*|13y{pB!G(~4ig9OHhi3v`y4G-iDJbWmP_XwS(rTre~pb5$v6N|*wJGr;C_l-@> zZT}=OpX8lqtcTq6AfU7*A$wmovbw*1ig08(5q8o`X^uT>tJOBvfND-N3ed?w3w4R- z+d_2b$HI^l{;b_7L+&jZJwBDmtpHRzf)-#*q~Xqw5CU~z%woKcxf13cG6A!*nX8M3 zwxOx1SzJe{)M(&$hP&hvQq7TX#LCQZg1n!q1?W#E{g{i~n~ID(VAcSOHl<-$1yZdr~& zlinWhREOSf==j+oaUwYxXJbEEqt-p!w%M4)gBJzn(Q>Cn?CQ&o)hM#h#?5=yy7i8G zUErSZGRa%OXd`y(8N@OmJ>|@3xN}eTL?d=fwlEQ&&S=bK0z$|^?rl-vSv7}sy*pRj z05R*@`d6wMI)vbr{J3|$84QoVetBPP-!P%CvfXU$lX4;#U{gQVtJPhjK~2EY>~CG# zAEj0yGjO_%zHeh*L`Uf+5Uh0x;)jXaG`*ZC+rgXqASc+#jgA5;%<`e
V;*m1Rk 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 z

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

}2 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%0DeHX4O4R<;q5V8>_`)=Xp?J#y0 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%0D)0~a&Ki8_!|Nk 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 z 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 diff --git a/docs/guides/intro-signed-jwt.md b/docs/guides/intro-signed-jwt.md deleted file mode 100644 index 97cade3a..00000000 --- a/docs/guides/intro-signed-jwt.md +++ /dev/null @@ -1,3 +0,0 @@ -# Signed JWT Authentication - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform diff --git a/docs/guides/tutorial-idp-client-cred-flow.md b/docs/guides/tutorial-idp-client-cred-flow.md deleted file mode 100644 index 12ad0705..00000000 --- a/docs/guides/tutorial-idp-client-cred-flow.md +++ /dev/null @@ -1,3 +0,0 @@ -# Protecting an API with OAuth2 Client Credential Flow - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform diff --git a/docs/guides/user-journey.md b/docs/guides/user-journey.md deleted file mode 100644 index 04c10c43..00000000 --- a/docs/guides/user-journey.md +++ /dev/null @@ -1,3 +0,0 @@ -# API Owner Flow - -> :exclamation: This document has moved to the BC Gov API Services Docs site at: https://bcgov.github.io/aps-infra-platform diff --git a/docs/samples/service-plugins/service-acl.yaml b/docs/samples/service-plugins/service-acl.yaml deleted file mode 100644 index 727e0d60..00000000 --- a/docs/samples/service-plugins/service-acl.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: acl - tags: [ _NS_ ] - config: - allow: - - pir-dev - deny: null - hide_groups_header: true - diff --git a/docs/samples/service-plugins/service-gwa-endpoint.yaml b/docs/samples/service-plugins/service-gwa-endpoint.yaml deleted file mode 100644 index 7e365379..00000000 --- a/docs/samples/service-plugins/service-gwa-endpoint.yaml +++ /dev/null @@ -1,10 +0,0 @@ - -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: bcgov-gwa-endpoint - tags: [ _NS_ ] - enabled: true - config: - api_owners: [ CONSUMER_OWNER_1, CONSUMER_OWNER_2 ] diff --git a/docs/samples/service-plugins/service-gwa-ip-anonymity.yaml b/docs/samples/service-plugins/service-gwa-ip-anonymity.yaml deleted file mode 100644 index d5bbd64f..00000000 --- a/docs/samples/service-plugins/service-gwa-ip-anonymity.yaml +++ /dev/null @@ -1,11 +0,0 @@ - -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: gwa-ip-anonymity - tags: [ _NS_ ] - enabled: true - config: - ipv4_mask: 0 - ipv6_mask: 0 diff --git a/docs/samples/service-plugins/service-ip-restriction.yaml b/docs/samples/service-plugins/service-ip-restriction.yaml deleted file mode 100644 index 14d8f839..00000000 --- a/docs/samples/service-plugins/service-ip-restriction.yaml +++ /dev/null @@ -1,10 +0,0 @@ - -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: ip-restriction - tags: [ _NS_ ] - enabled: true - config: - allow: [ "10.10.10.0/24" ] diff --git a/docs/samples/service-plugins/service-jwt-keycloak.yaml b/docs/samples/service-plugins/service-jwt-keycloak.yaml deleted file mode 100644 index c08c9d48..00000000 --- a/docs/samples/service-plugins/service-jwt-keycloak.yaml +++ /dev/null @@ -1,29 +0,0 @@ -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: jwt-keycloak - tags: [ _NS_ ] - enabled: true - config: - client_roles: null - allowed_iss: - - https://authz-264e6f-dev.apps.silver.devops.gov.bc.ca/auth/realms/aps - run_on_preflight: true - iss_key_grace_period: 10 - maximum_expiration: 0 - claims_to_verify: - - exp - consumer_match_claim_custom_id: false - cookie_names: [] - scope: null - uri_param_names: - - jwt - roles: null - consumer_match: false - well_known_template: https://authz-264e6f-dev.apps.silver.devops.gov.bc.ca/auth/realms/aps/.well-known/openid-configuration - consumer_match_ignore_not_found: false - anonymous: null - algorithm: RS256 - realm_roles: null - consumer_match_claim: azp diff --git a/docs/samples/service-plugins/service-key-auth.yaml b/docs/samples/service-plugins/service-key-auth.yaml deleted file mode 100644 index d723d65a..00000000 --- a/docs/samples/service-plugins/service-key-auth.yaml +++ /dev/null @@ -1,9 +0,0 @@ -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: key-auth - tags: [ _NS_ ] - config: - key_names: - - X-API-KEY diff --git a/docs/samples/service-plugins/service-oidc.yaml b/docs/samples/service-plugins/service-oidc.yaml deleted file mode 100644 index bb570885..00000000 --- a/docs/samples/service-plugins/service-oidc.yaml +++ /dev/null @@ -1,26 +0,0 @@ - -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: oidc - tags: [ _NS_ ] - enabled: true - config: - response_type: "code" - introspection_endpoint: "https://{HOST}/auth/realms/{REALM}/protocol/openid-connect/token/introspect" - filters: null - bearer_only: "no" - ssl_verify: "no" - session_secret: null - introspection_endpoint_auth_method: null - realm: "kong" - redirect_after_logout_uri: "/" - scope: "openid" - token_endpoint_auth_method: "client_secret_post" - logout_path: "/logout" - client_id: "" - client_secret: "" - discovery: "https://{HOST}/auth/realms/{REALM}/.well-known/openid-configuration" - recovery_page_path: null - redirect_uri_path: null \ No newline at end of file diff --git a/docs/samples/service-plugins/service-rate-limit.yaml b/docs/samples/service-plugins/service-rate-limit.yaml deleted file mode 100644 index 8af8af3c..00000000 --- a/docs/samples/service-plugins/service-rate-limit.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# policy: local | redis -# limit_by: consumer | ip | service | header | path -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: rate-limiting - tags: [ _NS_ ] - enabled: true - config: - fault_tolerant: true - hide_client_headers: false - limit_by: consumer - policy: local - minute: 10 - header_name: null - second: null - hour: null - day: null - month: null - year: null - enabled: true - protocols: - - http - - https diff --git a/docs/samples/service-plugins/service-request-transformer.yml b/docs/samples/service-plugins/service-request-transformer.yml deleted file mode 100644 index 3021cb2e..00000000 --- a/docs/samples/service-plugins/service-request-transformer.yml +++ /dev/null @@ -1,32 +0,0 @@ -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - config: - add: - body: {} - headers: {} - querystring: {} - append: - body: {} - headers: {} - querystring: {} - remove: - body: {} - headers: - - Cookie - querystring: {} - rename: - body: {} - headers: {} - querystring: {} - replace: - body: {} - headers: {} - querystring: {} - enabled: true - name: request-transformer - protocols: - - https - - http - tags: [ _NS_ ] diff --git a/docs/samples/service-plugins/service-spec-expose.yaml b/docs/samples/service-plugins/service-spec-expose.yaml deleted file mode 100644 index 993578ba..00000000 --- a/docs/samples/service-plugins/service-spec-expose.yaml +++ /dev/null @@ -1,10 +0,0 @@ - -services: -- name: MY_REST_API - tags: [ _NS_ ] - plugins: - - name: kong-spec-expose - tags: [ _NS_ ] - enabled: true - config: - spec_url: "https://raw.githubusercontent.com/bcgov/api-specs/master/gwells/gwells.yaml" diff --git a/docs/static/openapi/.env b/docs/static/openapi/.env deleted file mode 100644 index da0441ab..00000000 --- a/docs/static/openapi/.env +++ /dev/null @@ -1,4 +0,0 @@ -GWA_NAMESPACE=openapi-tests -CLIENT_ID=sa-openapi-tests-tihw03lvo5 -CLIENT_SECRET=40f4852f-a71f-47ed-ad65-fc6f60471234 -GWA_ENV=dev diff --git a/docs/static/openapi/kong-with-edits.yaml b/docs/static/openapi/kong-with-edits.yaml deleted file mode 100644 index 0e243879..00000000 --- a/docs/static/openapi/kong-with-edits.yaml +++ /dev/null @@ -1,21 +0,0 @@ -_format_version: "1.1" -services: - - name: Sample_API - url: https://httpbin.org - plugins: [] - routes: - - tags: - - OAS3_import - - ns.openapi-tests.loc - name: Sample_API-path-get - methods: - - GET - hosts: - - openapi-gen-sample.api.gov.bc.ca - paths: - - /headers - strip_path: false - tags: - - OAS3_import - - ns.openapi-tests.loc - diff --git a/docs/static/openapi/simple.yaml b/docs/static/openapi/simple.yaml deleted file mode 100644 index cec10c20..00000000 --- a/docs/static/openapi/simple.yaml +++ /dev/null @@ -1,26 +0,0 @@ -openapi: 3.0.0 -info: - title: Sample API - description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML. - version: 0.0.1 -servers: - - url: https://hlth-pnet{environment}.gov.bc.ca/v1 - variables: - environment: - default: ".api" # Production server - enum: - - ".api" # Production server - - -test.api # Test server - - -dev.api # Dev server -paths: - "/headers": - get: - summary: Returns the request headers that the upstream receives. - description: Optional extended description in CommonMark or HTML. - responses: - '200': # status code - description: A JSON object of request header name and values - content: - application/json: - schema: - type: object From 1bf200a1b13b933bfa4499cfd2f75b3a8d5e744e Mon Sep 17 00:00:00 2001 From: Elson9 Date: Thu, 26 Mar 2026 11:03:32 -0700 Subject: [PATCH 5/5] fix get_group_by_path 404 handling for Keycloak 26 compatibility (#257) * fix get_group_by_path 404 handling for Keycloak 26 compatibility * service account gwa-cli backwards compatibility * Add defaultClientScopes needed for kc26 * Add more logging to service account client scopes * Revert cli compatibility changes * Remove safe_get_group_by_path in get_namespace functions * add missing ns_group_summary --- microservices/gatewayApi/clients/keycloak.py | 16 +++++++++++++++- microservices/gatewayApi/v1/routes/namespaces.py | 12 ++++++------ .../gatewayApi/v1/routes/serviceaccounts.py | 1 - .../gatewayApi/v1/services/namespaces.py | 6 +++--- .../gatewayApi/v2/services/namespaces.py | 6 +++--- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/microservices/gatewayApi/clients/keycloak.py b/microservices/gatewayApi/clients/keycloak.py index 8d59ba0c..e49502ac 100644 --- a/microservices/gatewayApi/clients/keycloak.py +++ b/microservices/gatewayApi/clients/keycloak.py @@ -17,4 +17,18 @@ def admin_api(conf): keycloak_admin = KeycloakAdmin(connection=keycloak_connection) - return keycloak_admin \ No newline at end of file + return keycloak_admin + + +def safe_get_group_by_path(keycloak_admin, path, **kwargs): + """Returns None when a group path doesn't exist, regardless of + python-keycloak version or Keycloak server version.""" + try: + result = keycloak_admin.get_group_by_path(path, **kwargs) + if isinstance(result, dict) and "error" in result: + return None + return result + except KeycloakGetError as e: + if e.response_code == 404: + return None + raise \ No newline at end of file diff --git a/microservices/gatewayApi/v1/routes/namespaces.py b/microservices/gatewayApi/v1/routes/namespaces.py index e42794ae..97c6be38 100644 --- a/microservices/gatewayApi/v1/routes/namespaces.py +++ b/microservices/gatewayApi/v1/routes/namespaces.py @@ -19,7 +19,7 @@ from v1.auth.auth import admin_jwt, enforce_authorization, enforce_role_authorization, users_group_root, admins_group_root -from clients.keycloak import admin_api +from clients.keycloak import admin_api, safe_get_group_by_path from utils.validators import namespace_valid, namespace_validation_rule ns = Blueprint('namespaces', 'namespaces') @@ -99,7 +99,7 @@ def delete_namespace(namespace: str) -> object: try: for role_name in ['viewer', 'admin']: - group = keycloak_admin.get_group_by_path("%s/%s" % (get_base_group_path(role_name), namespace)) + group = safe_get_group_by_path(keycloak_admin, "%s/%s" % (get_base_group_path(role_name), namespace)) if group is not None: keycloak_admin.delete_group (group['id']) @@ -149,12 +149,12 @@ def membership_sync (namespace, role_name, desired_membership_list): base_group_path = get_base_group_path (role_name) - group = keycloak_admin.get_group_by_path("%s/%s" % (base_group_path, namespace), search_in_subgroups=True) + group = safe_get_group_by_path(keycloak_admin, "%s/%s" % (base_group_path, namespace), search_in_subgroups=True) if group is None: log.warn("[%s] Group %s/%s Missing!" % (namespace, base_group_path, namespace)) create_group (namespace, base_group_path, role_name) - group = keycloak_admin.get_group_by_path("%s/%s" % (base_group_path, namespace), search_in_subgroups=True) + group = safe_get_group_by_path(keycloak_admin, "%s/%s" % (base_group_path, namespace), search_in_subgroups=True) group = keycloak_admin.get_group (group['id']) @@ -195,10 +195,10 @@ def create_group(namespace, group_base_path, role_name): log = app.logger keycloak_admin = admin_api() - parent_group = keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(keycloak_admin, group_base_path) if parent_group is None: keycloak_admin.create_group ({"name": get_base_group_name(role_name)}) - parent_group = keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(keycloak_admin, group_base_path) keycloak_admin.create_group ({"name": namespace}, parent=parent_group['id']) log.debug("[%s] Group %s/%s created!", namespace, group_base_path, namespace) diff --git a/microservices/gatewayApi/v1/routes/serviceaccounts.py b/microservices/gatewayApi/v1/routes/serviceaccounts.py index b5e3b2c5..f778d68b 100644 --- a/microservices/gatewayApi/v1/routes/serviceaccounts.py +++ b/microservices/gatewayApi/v1/routes/serviceaccounts.py @@ -124,4 +124,3 @@ def delete_service_account(namespace: str, client_id: str) -> object: except KeycloakGetError as err: log.error(err) abort(make_response(jsonify(error="Failed to delete service account"), 400)) - diff --git a/microservices/gatewayApi/v1/services/namespaces.py b/microservices/gatewayApi/v1/services/namespaces.py index 29073134..33a4299a 100644 --- a/microservices/gatewayApi/v1/services/namespaces.py +++ b/microservices/gatewayApi/v1/services/namespaces.py @@ -1,7 +1,7 @@ from v1.auth.auth import users_group_root, admins_group_root from flask import current_app as app from v1.auth.auth import admin_jwt -from clients.keycloak import admin_api +from clients.keycloak import admin_api, safe_get_group_by_path class NamespaceService: @@ -39,10 +39,10 @@ def create_or_get_ns(self, namespace, initial_username): for role_name in ['viewer', 'admin']: group_base_path = get_base_group_path(role_name) - parent_group = self.keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(self.keycloak_admin, group_base_path) if parent_group is None: self.keycloak_admin.create_group({"name": get_base_group_name(role_name)}) - parent_group = self.keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(self.keycloak_admin, group_base_path) new_users_group_id = self.keycloak_admin.create_group(payload, parent=parent_group['id']) log.debug("[%s] Group %s/%s created!" % (namespace, group_base_path, namespace)) diff --git a/microservices/gatewayApi/v2/services/namespaces.py b/microservices/gatewayApi/v2/services/namespaces.py index b6198808..90199007 100644 --- a/microservices/gatewayApi/v2/services/namespaces.py +++ b/microservices/gatewayApi/v2/services/namespaces.py @@ -1,7 +1,7 @@ from v1.auth.auth import users_group_root, admins_group_root from flask import current_app as app from v1.auth.auth import admin_jwt -from clients.keycloak import admin_api +from clients.keycloak import admin_api, safe_get_group_by_path class NamespaceService: @@ -41,10 +41,10 @@ def create_or_get_ns(self, namespace, initial_username): for role_name in ['viewer']: group_base_path = get_base_group_path(role_name) - parent_group = self.keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(self.keycloak_admin, group_base_path) if parent_group is None: self.keycloak_admin.create_group({"name": get_base_group_name(role_name)}) - parent_group = self.keycloak_admin.get_group_by_path(group_base_path) + parent_group = safe_get_group_by_path(self.keycloak_admin, group_base_path) new_users_group_id = self.keycloak_admin.create_group(payload, parent=parent_group['id']) log.debug("[%s] Group %s/%s created!" % (namespace, group_base_path, namespace))