From 7f582f2973a051b35b42a74d4e5158237e6a01ba Mon Sep 17 00:00:00 2001 From: dlovell Date: Fri, 10 Oct 2025 06:16:39 -0400 Subject: [PATCH 1/2] chore(pyproject): add feast; loosen dependency versions for feast --- nix/xorq.nix | 5 + pyproject.toml | 5 +- requirements-dev.txt | 120 ++++++-- uv.lock | 665 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 642 insertions(+), 153 deletions(-) diff --git a/nix/xorq.nix b/nix/xorq.nix index 855df0217..bcc087fe1 100644 --- a/nix/xorq.nix +++ b/nix/xorq.nix @@ -177,6 +177,11 @@ let psycopg-c = (prev.psycopg-c.overrideAttrs (addResolved final [ "setuptools" ])).overrideAttrs(addNativeBuildInputs [ pkgs.postgresql.pg_config ]); + feast = prev.feast.overrideAttrs (compose [ + (addResolved final [ + "setuptools" + ]) + ]); }; pyprojectOverrides-editable = final: prev: { xorq = prev.xorq.overrideAttrs (old: { diff --git a/pyproject.toml b/pyproject.toml index 193deae76..deeb7a4e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dependencies = [ "pyarrow-hotfix>=0.4,<1 ; python_version >= '3.10' and python_version < '4.0'", "geoarrow-types>=0.2,<1 ; python_version >= '3.10' and python_version < '4.0'", "pythran>=0.17.0 ; sys_platform == 'darwin'", - "atpublic>=5.1", + "atpublic>=3.0", "parsy>=2", "python-dateutil>=2.8.2", "pytz>=2022.7", @@ -30,7 +30,7 @@ dependencies = [ "toolz>=0.11", "typing-extensions>=4.3.0", "pyyaml>=6.0.2", - "cloudpickle>=3.1.1", + "cloudpickle>=3.0", "envyaml>=1.10.211231", "xorq-datafusion==0.2.4", "opentelemetry-sdk>=1.32.1", @@ -41,6 +41,7 @@ dependencies = [ "strenum>=0.4.15 ; python_version <= '3.10'", "uv>=0.7.20", "rich>=13.9.4", + "feast>=0.55.0", ] requires-python = ">=3.10" authors = [ diff --git a/requirements-dev.txt b/requirements-dev.txt index a347e8d9c..e2720c9d8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -27,6 +27,7 @@ anyio==4.10.0 # openai # sse-starlette # starlette + # watchfiles appdirs==1.4.4 ; python_full_version < '4' # via pins appnope==0.1.4 ; sys_platform == 'darwin' @@ -68,6 +69,8 @@ beautifulsoup4==4.13.4 # via nbconvert beniget==0.4.2.post1 ; sys_platform == 'darwin' # via pythran +bigtree==0.31.0 + # via feast black==25.9.0 # via # blackdoc @@ -115,6 +118,7 @@ click==8.2.1 # via # black # dask + # feast # pyiceberg # quartodoc # uvicorn @@ -128,10 +132,12 @@ codespell==2.4.1 colorama==0.4.6 # via # click + # feast # griffe # ipython # pytest # tqdm + # uvicorn comm==0.2.3 # via ipykernel coverage==7.10.7 @@ -143,6 +149,7 @@ cryptography==45.0.5 # xorq dask==2025.1.0 # via + # feast # xorq # xorq-hash-cache databackend==0.0.3 ; python_full_version < '4' @@ -157,6 +164,8 @@ decorator==5.2.1 # ipython defusedxml==0.7.1 # via nbconvert +dill==0.3.9 + # via feast distlib==0.4.0 # via virtualenv distro==1.9.0 @@ -172,8 +181,12 @@ exceptiongroup==1.3.0 ; python_full_version < '3.11' # pytest executing==2.2.0 # via stack-data +fastapi==0.116.1 + # via feast fastjsonschema==2.21.1 # via nbformat +feast==0.55.0 + # via xorq filelock==3.18.0 # via # snowflake-connector-python @@ -234,12 +247,18 @@ griffe==1.9.0 # via quartodoc grpcio==1.74.0 # via opentelemetry-exporter-otlp-proto-grpc +gunicorn==23.0.0 + # via + # feast + # uvicorn-worker h11==0.16.0 # via # httpcore # uvicorn httpcore==1.0.9 # via httpx +httptools==0.6.4 + # via uvicorn httpx==0.28.1 # via # jupyterlab @@ -289,6 +308,7 @@ jedi==0.19.2 # via ipython jinja2==3.1.6 # via + # feast # jupyter-server # jupyterlab # jupyterlab-server @@ -310,6 +330,7 @@ jsonpointer==3.0.0 # via jsonschema jsonschema==4.25.0 # via + # feast # jupyter-events # jupyterlab-server # mcp @@ -376,15 +397,21 @@ mdurl==0.1.2 mistune==3.1.3 # via nbconvert mmh3==5.2.0 - # via pyiceberg + # via + # feast + # pyiceberg more-itertools==10.7.0 # via blackdoc multidict==6.6.3 ; python_full_version < '4' # via # aiohttp # yarl +mypy==1.17.1 + # via sqlalchemy mypy-extensions==1.1.0 - # via black + # via + # black + # mypy nbclient==0.10.2 # via nbconvert nbconvert==7.16.6 @@ -405,6 +432,8 @@ notebook-shim==0.2.4 # notebook numpy==2.2.6 ; python_full_version < '3.11' # via + # dask + # feast # pandas # pythran # scikit-learn @@ -412,6 +441,8 @@ numpy==2.2.6 ; python_full_version < '3.11' # xgboost numpy==2.3.2 ; python_full_version >= '3.11' # via + # dask + # feast # pandas # pythran # scikit-learn @@ -461,6 +492,7 @@ packaging==25.0 # via # black # dask + # gunicorn # ipykernel # jupyter-events # jupyter-server @@ -472,6 +504,8 @@ packaging==25.0 # vendoring pandas==2.3.1 # via + # dask + # feast # pins # xorq # xorq-feature-utils @@ -491,6 +525,7 @@ pathspec==0.12.1 # via # black # blackdoc + # mypy pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' # via ipython pins==0.9.0 ; python_full_version < '4' @@ -513,6 +548,7 @@ ply==3.11 ; sys_platform == 'darwin' pre-commit==4.3.0 prometheus-client==0.22.1 # via + # feast # jupyter-server # opentelemetry-exporter-prometheus # xorq @@ -526,12 +562,15 @@ proto-plus==1.26.1 ; python_full_version < '4' # via google-api-core protobuf==6.31.1 # via + # feast # google-api-core # googleapis-common-protos # opentelemetry-proto # proto-plus psutil==7.0.0 - # via ipykernel + # via + # feast + # ipykernel psycopg==3.2.10 # via xorq psycopg-c==3.2.10 @@ -544,9 +583,11 @@ ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_pla # terminado pure-eval==0.2.3 # via stack-data -pyarrow==21.0.0 +pyarrow==20.0.0 # via + # dask # datafusion + # feast # xorq # xorq-datafusion # xorq-feature-utils @@ -561,19 +602,22 @@ pyasn1-modules==0.4.2 ; python_full_version < '4' # via google-auth pycparser==2.22 # via cffi -pydantic==2.11.7 +pydantic==2.10.6 # via + # fastapi + # feast # mcp # openai # pydantic-settings # pyiceberg # quartodoc -pydantic-core==2.33.2 +pydantic-core==2.27.2 # via pydantic pydantic-settings==2.10.1 # via mcp pygments==2.19.2 # via + # feast # ipython # ipython-pygments-lexers # nbconvert @@ -581,8 +625,10 @@ pygments==2.19.2 # rich pyiceberg==0.9.1 # via xorq -pyjwt==2.10.1 ; python_full_version < '4' - # via snowflake-connector-python +pyjwt==2.10.1 + # via + # feast + # snowflake-connector-python pyopenssl==25.1.0 # via snowflake-connector-python pyparsing==3.2.3 @@ -609,7 +655,9 @@ python-dateutil==2.9.0.post0 # trino # xorq python-dotenv==1.1.1 - # via pydantic-settings + # via + # pydantic-settings + # uvicorn python-json-logger==3.3.0 # via jupyter-events python-multipart==0.0.20 @@ -637,10 +685,12 @@ pyyaml==6.0.2 # via # dask # envyaml + # feast # jupyter-events # pins # pre-commit # quartodoc + # uvicorn # xorq pyzmq==27.0.1 # via @@ -657,6 +707,7 @@ referencing==0.36.2 # jupyter-events requests==2.32.4 # via + # feast # gcsfs # google-api-core # google-cloud-storage @@ -736,7 +787,9 @@ soupsieve==2.7 sphobjinv==2.3.1.3 # via quartodoc sqlalchemy==2.0.42 - # via pyiceberg + # via + # feast + # pyiceberg sqlglot==25.20.2 # via # ibis-framework @@ -746,7 +799,9 @@ sse-starlette==3.0.2 stack-data==0.6.3 # via ipython starlette==0.47.2 - # via mcp + # via + # fastapi + # mcp strenum==0.4.15 ; python_full_version < '3.11' # via xorq strictyaml==1.7.3 @@ -754,9 +809,13 @@ strictyaml==1.7.3 structlog==25.4.0 ; python_full_version < '4' # via xorq tabulate==0.9.0 - # via quartodoc -tenacity==9.1.2 - # via pyiceberg + # via + # feast + # quartodoc +tenacity==8.5.0 + # via + # feast + # pyiceberg terminado==0.18.1 # via # jupyter-server @@ -766,7 +825,9 @@ threadpoolctl==3.6.0 tinycss2==1.4.0 # via bleach toml==0.10.2 - # via vendoring + # via + # feast + # vendoring tomli==2.2.1 # via # black @@ -774,6 +835,7 @@ tomli==2.2.1 # codespell # coverage # jupyterlab + # mypy # pytest tomlkit==0.13.3 ; python_full_version < '4' # via snowflake-connector-python @@ -795,7 +857,9 @@ tornado==6.5.1 # notebook # terminado tqdm==4.67.1 - # via openai + # via + # feast + # openai traitlets==5.14.3 # via # ipykernel @@ -810,6 +874,8 @@ traitlets==5.14.3 # nbconvert # nbformat trino==0.335.0 +typeguard==4.4.4 + # via feast types-python-dateutil==2.9.0.20250708 # via arrow typing-extensions==4.14.1 @@ -822,10 +888,12 @@ typing-extensions==4.14.1 # black # datafusion # exceptiongroup + # fastapi # ibis-framework # ipython # mistune # multidict + # mypy # openai # opentelemetry-api # opentelemetry-exporter-otlp-proto-grpc @@ -845,13 +913,12 @@ typing-extensions==4.14.1 # sqlalchemy # starlette # structlog + # typeguard # typing-inspection # uvicorn # xorq typing-inspection==0.4.1 - # via - # pydantic - # pydantic-settings + # via pydantic-settings tzdata==2025.2 # via # ibis-framework @@ -871,13 +938,22 @@ urllib3==2.5.0 # xorq-weather-lib uv==0.8.4 # via xorq -uvicorn==0.35.0 ; sys_platform != 'emscripten' - # via mcp +uvicorn==0.34.0 + # via + # feast + # mcp + # uvicorn-worker +uvicorn-worker==0.3.0 + # via feast +uvloop==0.21.0 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' + # via uvicorn vendoring==1.2.0 virtualenv==20.33.0 # via pre-commit watchdog==6.0.0 # via quartodoc +watchfiles==1.1.0 + # via uvicorn wcwidth==0.2.13 # via prompt-toolkit webcolors==24.11.1 @@ -888,6 +964,8 @@ webencodings==0.5.1 # tinycss2 websocket-client==1.8.0 # via jupyter-server +websockets==15.0.1 + # via uvicorn xgboost==3.0.3 # via xorq xorq-datafusion==0.2.4 diff --git a/uv.lock b/uv.lock index 0aadfd8bc..a95f20581 100644 --- a/uv.lock +++ b/uv.lock @@ -437,6 +437,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/e4/6e8731d4d10dd09942a6f5015b2148ae612bf13e49629f33f9fade3c8253/beniget-0.4.2.post1-py3-none-any.whl", hash = "sha256:e1b336e7b5f2ae201e6cc21f533486669f1b9eccba018dcff5969cd52f1c20ba", size = 17242, upload-time = "2024-06-28T10:20:03.197Z" }, ] +[[package]] +name = "bigtree" +version = "0.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/56/ca/6af16e30de081340c18ffeff075bbac5ebc2e90b4fae09cf7adb49afc49d/bigtree-0.31.0.tar.gz", hash = "sha256:8505e703946663db3d4356c8b2935424e5bafbb8c618a44d339f7bea8010f770", size = 1345129, upload-time = "2025-09-11T08:29:44.717Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/45/aad9fd88cf999f165e05b476b17b304cc7f2898aa980d30377da8509ab1d/bigtree-0.31.0-py3-none-any.whl", hash = "sha256:67f1cd8100d58eb96c736099cccf986d3eec14e447b630ce54d518e0c2cf05cb", size = 106696, upload-time = "2025-09-11T08:29:46.143Z" }, +] + [[package]] name = "black" version = "25.9.0" @@ -945,6 +954,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/a0/016d956a3fec193e3a5b466ca912944669c18dccc736b64a9e28ccdcc5f7/dask-2025.1.0-py3-none-any.whl", hash = "sha256:db86220c8d19bdf464cbe11a87a2c8f5d537acf586bb02eed6d61a302af5c2fd", size = 1371235, upload-time = "2025-01-17T16:54:09.918Z" }, ] +[package.optional-dependencies] +dataframe = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pandas" }, + { name = "pyarrow" }, +] + [[package]] name = "databackend" version = "0.0.3" @@ -1014,6 +1031,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, ] +[[package]] +name = "dill" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/43/86fe3f9e130c4137b0f1b50784dd70a5087b911fe07fa81e53e0c4c47fea/dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c", size = 187000, upload-time = "2024-09-29T00:03:20.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a", size = 119418, upload-time = "2024-09-29T00:03:19.344Z" }, +] + [[package]] name = "distlib" version = "0.4.0" @@ -1101,6 +1127,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, ] +[[package]] +name = "fastapi" +version = "0.116.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" }, +] + [[package]] name = "fastjsonschema" version = "2.21.1" @@ -1110,6 +1150,47 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/90/2b/0817a2b257fe88725c25589d89aec060581aabf668707a8d03b2e9e0cb2a/fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667", size = 23924, upload-time = "2024-12-02T10:55:07.599Z" }, ] +[[package]] +name = "feast" +version = "0.55.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bigtree" }, + { name = "click" }, + { name = "colorama" }, + { name = "dask", extra = ["dataframe"] }, + { name = "dill" }, + { name = "fastapi" }, + { name = "gunicorn", marker = "sys_platform != 'win32'" }, + { name = "jinja2" }, + { name = "jsonschema" }, + { name = "mmh3" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pandas" }, + { name = "prometheus-client" }, + { name = "protobuf" }, + { name = "psutil" }, + { name = "pyarrow" }, + { name = "pydantic" }, + { name = "pygments" }, + { name = "pyjwt" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "sqlalchemy", extra = ["mypy"] }, + { name = "tabulate" }, + { name = "tenacity" }, + { name = "toml" }, + { name = "tqdm" }, + { name = "typeguard" }, + { name = "uvicorn", extra = ["standard"] }, + { name = "uvicorn-worker" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/f0/96045f569dde1b358c52e9952b74cf9e9174c6040a759a5aaf7f8854c91e/feast-0.55.0.tar.gz", hash = "sha256:76e65319115db017a607c7507166b866300ba5bf48c5b245d544a1307c11d872", size = 6235170, upload-time = "2025-10-14T14:52:02.193Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b6/35ded77acda7d51a6ca1ccb16d1c16b888ac314b70c61f99d8e2dc63cb35/feast-0.55.0-py2.py3-none-any.whl", hash = "sha256:e1b804dbe5502aa5550b48fa1feb2aaecd682e6e729ac05ed61240cb37439af1", size = 7716278, upload-time = "2025-10-14T14:51:59.152Z" }, +] + [[package]] name = "filelock" version = "3.18.0" @@ -1527,6 +1608,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/34/80/de3eb55eb581815342d097214bed4c59e806b05f1b3110df03b2280d6dfd/grpcio-1.74.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd3c71aeee838299c5887230b8a1822795325ddfea635edd82954c1eaa831e24", size = 4489214, upload-time = "2025-07-24T18:53:59.771Z" }, ] +[[package]] +name = "gunicorn" +version = "23.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/72/9614c465dc206155d93eff0ca20d42e1e35afc533971379482de953521a4/gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec", size = 375031, upload-time = "2024-08-10T20:25:27.378Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/7d/6dac2a6e1eba33ee43f318edbed4ff29151a49b5d37f080aad1e6469bca4/gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", size = 85029, upload-time = "2024-08-10T20:25:24.996Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -1549,6 +1642,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, ] +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639, upload-time = "2024-10-16T19:45:08.902Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/6f/972f8eb0ea7d98a1c6be436e2142d51ad2a64ee18e02b0e7ff1f62171ab1/httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0", size = 198780, upload-time = "2024-10-16T19:44:06.882Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b0/17c672b4bc5c7ba7f201eada4e96c71d0a59fbc185e60e42580093a86f21/httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da", size = 103297, upload-time = "2024-10-16T19:44:08.129Z" }, + { url = "https://files.pythonhosted.org/packages/92/5e/b4a826fe91971a0b68e8c2bd4e7db3e7519882f5a8ccdb1194be2b3ab98f/httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1", size = 443130, upload-time = "2024-10-16T19:44:09.45Z" }, + { url = "https://files.pythonhosted.org/packages/b0/51/ce61e531e40289a681a463e1258fa1e05e0be54540e40d91d065a264cd8f/httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50", size = 442148, upload-time = "2024-10-16T19:44:11.539Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/270b7d767849b0c96f275c695d27ca76c30671f8eb8cc1bab6ced5c5e1d0/httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959", size = 415949, upload-time = "2024-10-16T19:44:13.388Z" }, + { url = "https://files.pythonhosted.org/packages/81/86/ced96e3179c48c6f656354e106934e65c8963d48b69be78f355797f0e1b3/httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4", size = 417591, upload-time = "2024-10-16T19:44:15.258Z" }, + { url = "https://files.pythonhosted.org/packages/75/73/187a3f620ed3175364ddb56847d7a608a6fc42d551e133197098c0143eca/httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c", size = 88344, upload-time = "2024-10-16T19:44:16.54Z" }, + { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029, upload-time = "2024-10-16T19:44:18.427Z" }, + { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492, upload-time = "2024-10-16T19:44:19.515Z" }, + { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891, upload-time = "2024-10-16T19:44:21.067Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788, upload-time = "2024-10-16T19:44:22.958Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214, upload-time = "2024-10-16T19:44:24.513Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120, upload-time = "2024-10-16T19:44:26.295Z" }, + { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565, upload-time = "2024-10-16T19:44:29.188Z" }, + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683, upload-time = "2024-10-16T19:44:30.175Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337, upload-time = "2024-10-16T19:44:31.786Z" }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796, upload-time = "2024-10-16T19:44:32.825Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837, upload-time = "2024-10-16T19:44:33.974Z" }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289, upload-time = "2024-10-16T19:44:35.111Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779, upload-time = "2024-10-16T19:44:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634, upload-time = "2024-10-16T19:44:37.357Z" }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214, upload-time = "2024-10-16T19:44:38.738Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431, upload-time = "2024-10-16T19:44:39.818Z" }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121, upload-time = "2024-10-16T19:44:41.189Z" }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805, upload-time = "2024-10-16T19:44:42.384Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858, upload-time = "2024-10-16T19:44:43.959Z" }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042, upload-time = "2024-10-16T19:44:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload-time = "2024-10-16T19:44:46.46Z" }, +] + [[package]] name = "httpx" version = "0.28.1" @@ -2484,6 +2613,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, ] +[[package]] +name = "mypy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/a9/3d7aa83955617cdf02f94e50aab5c830d205cfa4320cf124ff64acce3a8e/mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972", size = 11003299, upload-time = "2025-07-31T07:54:06.425Z" }, + { url = "https://files.pythonhosted.org/packages/83/e8/72e62ff837dd5caaac2b4a5c07ce769c8e808a00a65e5d8f94ea9c6f20ab/mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7", size = 10125451, upload-time = "2025-07-31T07:53:52.974Z" }, + { url = "https://files.pythonhosted.org/packages/7d/10/f3f3543f6448db11881776f26a0ed079865926b0c841818ee22de2c6bbab/mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df", size = 11916211, upload-time = "2025-07-31T07:53:18.879Z" }, + { url = "https://files.pythonhosted.org/packages/06/bf/63e83ed551282d67bb3f7fea2cd5561b08d2bb6eb287c096539feb5ddbc5/mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390", size = 12652687, upload-time = "2025-07-31T07:53:30.544Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/68f2eeef11facf597143e85b694a161868b3b006a5fbad50e09ea117ef24/mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94", size = 12896322, upload-time = "2025-07-31T07:53:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/a3/87/8e3e9c2c8bd0d7e071a89c71be28ad088aaecbadf0454f46a540bda7bca6/mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b", size = 9507962, upload-time = "2025-07-31T07:53:08.431Z" }, + { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, + { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, + { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, + { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, + { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, + { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, + { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, + { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, + { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, + { url = "https://files.pythonhosted.org/packages/5b/82/aec2fc9b9b149f372850291827537a508d6c4d3664b1750a324b91f71355/mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", size = 11075338, upload-time = "2025-07-31T07:53:38.873Z" }, + { url = "https://files.pythonhosted.org/packages/07/ac/ee93fbde9d2242657128af8c86f5d917cd2887584cf948a8e3663d0cd737/mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", size = 10113066, upload-time = "2025-07-31T07:54:14.707Z" }, + { url = "https://files.pythonhosted.org/packages/5a/68/946a1e0be93f17f7caa56c45844ec691ca153ee8b62f21eddda336a2d203/mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", size = 11875473, upload-time = "2025-07-31T07:53:14.504Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0f/478b4dce1cb4f43cf0f0d00fba3030b21ca04a01b74d1cd272a528cf446f/mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", size = 12744296, upload-time = "2025-07-31T07:53:03.896Z" }, + { url = "https://files.pythonhosted.org/packages/ca/70/afa5850176379d1b303f992a828de95fc14487429a7139a4e0bdd17a8279/mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", size = 12914657, upload-time = "2025-07-31T07:54:08.576Z" }, + { url = "https://files.pythonhosted.org/packages/53/f9/4a83e1c856a3d9c8f6edaa4749a4864ee98486e9b9dbfbc93842891029c2/mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", size = 9593320, upload-time = "2025-07-31T07:53:01.341Z" }, + { url = "https://files.pythonhosted.org/packages/38/56/79c2fac86da57c7d8c48622a05873eaab40b905096c33597462713f5af90/mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", size = 11040037, upload-time = "2025-07-31T07:54:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c3/adabe6ff53638e3cad19e3547268482408323b1e68bf082c9119000cd049/mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", size = 10131550, upload-time = "2025-07-31T07:53:41.307Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c5/2e234c22c3bdeb23a7817af57a58865a39753bde52c74e2c661ee0cfc640/mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", size = 11872963, upload-time = "2025-07-31T07:53:16.878Z" }, + { url = "https://files.pythonhosted.org/packages/ab/26/c13c130f35ca8caa5f2ceab68a247775648fdcd6c9a18f158825f2bc2410/mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", size = 12710189, upload-time = "2025-07-31T07:54:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/c7d79d09f6de8383fe800521d066d877e54d30b4fb94281c262be2df84ef/mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", size = 12900322, upload-time = "2025-07-31T07:53:10.551Z" }, + { url = "https://files.pythonhosted.org/packages/b8/98/3d5a48978b4f708c55ae832619addc66d677f6dc59f3ebad71bae8285ca6/mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", size = 9751879, upload-time = "2025-07-31T07:52:56.683Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, +] + [[package]] name = "mypy-extensions" version = "1.1.0" @@ -3378,45 +3552,55 @@ wheels = [ [[package]] name = "pyarrow" -version = "21.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ef/c2/ea068b8f00905c06329a3dfcd40d0fcc2b7d0f2e355bdb25b65e0a0e4cd4/pyarrow-21.0.0.tar.gz", hash = "sha256:5051f2dccf0e283ff56335760cbc8622cf52264d67e359d5569541ac11b6d5bc", size = 1133487, upload-time = "2025-07-18T00:57:31.761Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/17/d9/110de31880016e2afc52d8580b397dbe47615defbf09ca8cf55f56c62165/pyarrow-21.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e563271e2c5ff4d4a4cbeb2c83d5cf0d4938b891518e676025f7268c6fe5fe26", size = 31196837, upload-time = "2025-07-18T00:54:34.755Z" }, - { url = "https://files.pythonhosted.org/packages/df/5f/c1c1997613abf24fceb087e79432d24c19bc6f7259cab57c2c8e5e545fab/pyarrow-21.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:fee33b0ca46f4c85443d6c450357101e47d53e6c3f008d658c27a2d020d44c79", size = 32659470, upload-time = "2025-07-18T00:54:38.329Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ed/b1589a777816ee33ba123ba1e4f8f02243a844fed0deec97bde9fb21a5cf/pyarrow-21.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:7be45519b830f7c24b21d630a31d48bcebfd5d4d7f9d3bdb49da9cdf6d764edb", size = 41055619, upload-time = "2025-07-18T00:54:42.172Z" }, - { url = "https://files.pythonhosted.org/packages/44/28/b6672962639e85dc0ac36f71ab3a8f5f38e01b51343d7aa372a6b56fa3f3/pyarrow-21.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:26bfd95f6bff443ceae63c65dc7e048670b7e98bc892210acba7e4995d3d4b51", size = 42733488, upload-time = "2025-07-18T00:54:47.132Z" }, - { url = "https://files.pythonhosted.org/packages/f8/cc/de02c3614874b9089c94eac093f90ca5dfa6d5afe45de3ba847fd950fdf1/pyarrow-21.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd04ec08f7f8bd113c55868bd3fc442a9db67c27af098c5f814a3091e71cc61a", size = 43329159, upload-time = "2025-07-18T00:54:51.686Z" }, - { url = "https://files.pythonhosted.org/packages/a6/3e/99473332ac40278f196e105ce30b79ab8affab12f6194802f2593d6b0be2/pyarrow-21.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9b0b14b49ac10654332a805aedfc0147fb3469cbf8ea951b3d040dab12372594", size = 45050567, upload-time = "2025-07-18T00:54:56.679Z" }, - { url = "https://files.pythonhosted.org/packages/7b/f5/c372ef60593d713e8bfbb7e0c743501605f0ad00719146dc075faf11172b/pyarrow-21.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:9d9f8bcb4c3be7738add259738abdeddc363de1b80e3310e04067aa1ca596634", size = 26217959, upload-time = "2025-07-18T00:55:00.482Z" }, - { url = "https://files.pythonhosted.org/packages/94/dc/80564a3071a57c20b7c32575e4a0120e8a330ef487c319b122942d665960/pyarrow-21.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c077f48aab61738c237802836fc3844f85409a46015635198761b0d6a688f87b", size = 31243234, upload-time = "2025-07-18T00:55:03.812Z" }, - { url = "https://files.pythonhosted.org/packages/ea/cc/3b51cb2db26fe535d14f74cab4c79b191ed9a8cd4cbba45e2379b5ca2746/pyarrow-21.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:689f448066781856237eca8d1975b98cace19b8dd2ab6145bf49475478bcaa10", size = 32714370, upload-time = "2025-07-18T00:55:07.495Z" }, - { url = "https://files.pythonhosted.org/packages/24/11/a4431f36d5ad7d83b87146f515c063e4d07ef0b7240876ddb885e6b44f2e/pyarrow-21.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:479ee41399fcddc46159a551705b89c05f11e8b8cb8e968f7fec64f62d91985e", size = 41135424, upload-time = "2025-07-18T00:55:11.461Z" }, - { url = "https://files.pythonhosted.org/packages/74/dc/035d54638fc5d2971cbf1e987ccd45f1091c83bcf747281cf6cc25e72c88/pyarrow-21.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:40ebfcb54a4f11bcde86bc586cbd0272bac0d516cfa539c799c2453768477569", size = 42823810, upload-time = "2025-07-18T00:55:16.301Z" }, - { url = "https://files.pythonhosted.org/packages/2e/3b/89fced102448a9e3e0d4dded1f37fa3ce4700f02cdb8665457fcc8015f5b/pyarrow-21.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8d58d8497814274d3d20214fbb24abcad2f7e351474357d552a8d53bce70c70e", size = 43391538, upload-time = "2025-07-18T00:55:23.82Z" }, - { url = "https://files.pythonhosted.org/packages/fb/bb/ea7f1bd08978d39debd3b23611c293f64a642557e8141c80635d501e6d53/pyarrow-21.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:585e7224f21124dd57836b1530ac8f2df2afc43c861d7bf3d58a4870c42ae36c", size = 45120056, upload-time = "2025-07-18T00:55:28.231Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0b/77ea0600009842b30ceebc3337639a7380cd946061b620ac1a2f3cb541e2/pyarrow-21.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:555ca6935b2cbca2c0e932bedd853e9bc523098c39636de9ad4693b5b1df86d6", size = 26220568, upload-time = "2025-07-18T00:55:32.122Z" }, - { url = "https://files.pythonhosted.org/packages/ca/d4/d4f817b21aacc30195cf6a46ba041dd1be827efa4a623cc8bf39a1c2a0c0/pyarrow-21.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:3a302f0e0963db37e0a24a70c56cf91a4faa0bca51c23812279ca2e23481fccd", size = 31160305, upload-time = "2025-07-18T00:55:35.373Z" }, - { url = "https://files.pythonhosted.org/packages/a2/9c/dcd38ce6e4b4d9a19e1d36914cb8e2b1da4e6003dd075474c4cfcdfe0601/pyarrow-21.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:b6b27cf01e243871390474a211a7922bfbe3bda21e39bc9160daf0da3fe48876", size = 32684264, upload-time = "2025-07-18T00:55:39.303Z" }, - { url = "https://files.pythonhosted.org/packages/4f/74/2a2d9f8d7a59b639523454bec12dba35ae3d0a07d8ab529dc0809f74b23c/pyarrow-21.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:e72a8ec6b868e258a2cd2672d91f2860ad532d590ce94cdf7d5e7ec674ccf03d", size = 41108099, upload-time = "2025-07-18T00:55:42.889Z" }, - { url = "https://files.pythonhosted.org/packages/ad/90/2660332eeb31303c13b653ea566a9918484b6e4d6b9d2d46879a33ab0622/pyarrow-21.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b7ae0bbdc8c6674259b25bef5d2a1d6af5d39d7200c819cf99e07f7dfef1c51e", size = 42829529, upload-time = "2025-07-18T00:55:47.069Z" }, - { url = "https://files.pythonhosted.org/packages/33/27/1a93a25c92717f6aa0fca06eb4700860577d016cd3ae51aad0e0488ac899/pyarrow-21.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:58c30a1729f82d201627c173d91bd431db88ea74dcaa3885855bc6203e433b82", size = 43367883, upload-time = "2025-07-18T00:55:53.069Z" }, - { url = "https://files.pythonhosted.org/packages/05/d9/4d09d919f35d599bc05c6950095e358c3e15148ead26292dfca1fb659b0c/pyarrow-21.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:072116f65604b822a7f22945a7a6e581cfa28e3454fdcc6939d4ff6090126623", size = 45133802, upload-time = "2025-07-18T00:55:57.714Z" }, - { url = "https://files.pythonhosted.org/packages/71/30/f3795b6e192c3ab881325ffe172e526499eb3780e306a15103a2764916a2/pyarrow-21.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf56ec8b0a5c8c9d7021d6fd754e688104f9ebebf1bf4449613c9531f5346a18", size = 26203175, upload-time = "2025-07-18T00:56:01.364Z" }, - { url = "https://files.pythonhosted.org/packages/16/ca/c7eaa8e62db8fb37ce942b1ea0c6d7abfe3786ca193957afa25e71b81b66/pyarrow-21.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e99310a4ebd4479bcd1964dff9e14af33746300cb014aa4a3781738ac63baf4a", size = 31154306, upload-time = "2025-07-18T00:56:04.42Z" }, - { url = "https://files.pythonhosted.org/packages/ce/e8/e87d9e3b2489302b3a1aea709aaca4b781c5252fcb812a17ab6275a9a484/pyarrow-21.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:d2fe8e7f3ce329a71b7ddd7498b3cfac0eeb200c2789bd840234f0dc271a8efe", size = 32680622, upload-time = "2025-07-18T00:56:07.505Z" }, - { url = "https://files.pythonhosted.org/packages/84/52/79095d73a742aa0aba370c7942b1b655f598069489ab387fe47261a849e1/pyarrow-21.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:f522e5709379d72fb3da7785aa489ff0bb87448a9dc5a75f45763a795a089ebd", size = 41104094, upload-time = "2025-07-18T00:56:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/89/4b/7782438b551dbb0468892a276b8c789b8bbdb25ea5c5eb27faadd753e037/pyarrow-21.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:69cbbdf0631396e9925e048cfa5bce4e8c3d3b41562bbd70c685a8eb53a91e61", size = 42825576, upload-time = "2025-07-18T00:56:15.569Z" }, - { url = "https://files.pythonhosted.org/packages/b3/62/0f29de6e0a1e33518dec92c65be0351d32d7ca351e51ec5f4f837a9aab91/pyarrow-21.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:731c7022587006b755d0bdb27626a1a3bb004bb56b11fb30d98b6c1b4718579d", size = 43368342, upload-time = "2025-07-18T00:56:19.531Z" }, - { url = "https://files.pythonhosted.org/packages/90/c7/0fa1f3f29cf75f339768cc698c8ad4ddd2481c1742e9741459911c9ac477/pyarrow-21.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc56bc708f2d8ac71bd1dcb927e458c93cec10b98eb4120206a4091db7b67b99", size = 45131218, upload-time = "2025-07-18T00:56:23.347Z" }, - { url = "https://files.pythonhosted.org/packages/01/63/581f2076465e67b23bc5a37d4a2abff8362d389d29d8105832e82c9c811c/pyarrow-21.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:186aa00bca62139f75b7de8420f745f2af12941595bbbfa7ed3870ff63e25636", size = 26087551, upload-time = "2025-07-18T00:56:26.758Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ab/357d0d9648bb8241ee7348e564f2479d206ebe6e1c47ac5027c2e31ecd39/pyarrow-21.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:a7a102574faa3f421141a64c10216e078df467ab9576684d5cd696952546e2da", size = 31290064, upload-time = "2025-07-18T00:56:30.214Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8a/5685d62a990e4cac2043fc76b4661bf38d06efed55cf45a334b455bd2759/pyarrow-21.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:1e005378c4a2c6db3ada3ad4c217b381f6c886f0a80d6a316fe586b90f77efd7", size = 32727837, upload-time = "2025-07-18T00:56:33.935Z" }, - { url = "https://files.pythonhosted.org/packages/fc/de/c0828ee09525c2bafefd3e736a248ebe764d07d0fd762d4f0929dbc516c9/pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:65f8e85f79031449ec8706b74504a316805217b35b6099155dd7e227eef0d4b6", size = 41014158, upload-time = "2025-07-18T00:56:37.528Z" }, - { url = "https://files.pythonhosted.org/packages/6e/26/a2865c420c50b7a3748320b614f3484bfcde8347b2639b2b903b21ce6a72/pyarrow-21.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:3a81486adc665c7eb1a2bde0224cfca6ceaba344a82a971ef059678417880eb8", size = 42667885, upload-time = "2025-07-18T00:56:41.483Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f9/4ee798dc902533159250fb4321267730bc0a107d8c6889e07c3add4fe3a5/pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fc0d2f88b81dcf3ccf9a6ae17f89183762c8a94a5bdcfa09e05cfe413acf0503", size = 43276625, upload-time = "2025-07-18T00:56:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/5a/da/e02544d6997037a4b0d22d8e5f66bc9315c3671371a8b18c79ade1cefe14/pyarrow-21.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6299449adf89df38537837487a4f8d3bd91ec94354fdd2a7d30bc11c48ef6e79", size = 44951890, upload-time = "2025-07-18T00:56:52.568Z" }, - { url = "https://files.pythonhosted.org/packages/e5/4e/519c1bc1876625fe6b71e9a28287c43ec2f20f73c658b9ae1d485c0c206e/pyarrow-21.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:222c39e2c70113543982c6b34f3077962b44fca38c0bd9e68bb6781534425c10", size = 26371006, upload-time = "2025-07-18T00:56:56.379Z" }, +version = "20.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/ee/a7810cb9f3d6e9238e61d312076a9859bf3668fd21c69744de9532383912/pyarrow-20.0.0.tar.gz", hash = "sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1", size = 1125187, upload-time = "2025-04-27T12:34:23.264Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/23/77094eb8ee0dbe88441689cb6afc40ac312a1e15d3a7acc0586999518222/pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7", size = 30832591, upload-time = "2025-04-27T12:27:27.89Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d5/48cc573aff00d62913701d9fac478518f693b30c25f2c157550b0b2565cb/pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4", size = 32273686, upload-time = "2025-04-27T12:27:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/37/df/4099b69a432b5cb412dd18adc2629975544d656df3d7fda6d73c5dba935d/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae", size = 41337051, upload-time = "2025-04-27T12:27:44.4Z" }, + { url = "https://files.pythonhosted.org/packages/4c/27/99922a9ac1c9226f346e3a1e15e63dee6f623ed757ff2893f9d6994a69d3/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee", size = 42404659, upload-time = "2025-04-27T12:27:51.715Z" }, + { url = "https://files.pythonhosted.org/packages/21/d1/71d91b2791b829c9e98f1e0d85be66ed93aff399f80abb99678511847eaa/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20", size = 40695446, upload-time = "2025-04-27T12:27:59.643Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ca/ae10fba419a6e94329707487835ec721f5a95f3ac9168500bcf7aa3813c7/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9", size = 42278528, upload-time = "2025-04-27T12:28:07.297Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a6/aba40a2bf01b5d00cf9cd16d427a5da1fad0fb69b514ce8c8292ab80e968/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75", size = 42918162, upload-time = "2025-04-27T12:28:15.716Z" }, + { url = "https://files.pythonhosted.org/packages/93/6b/98b39650cd64f32bf2ec6d627a9bd24fcb3e4e6ea1873c5e1ea8a83b1a18/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8", size = 44550319, upload-time = "2025-04-27T12:28:27.026Z" }, + { url = "https://files.pythonhosted.org/packages/ab/32/340238be1eb5037e7b5de7e640ee22334417239bc347eadefaf8c373936d/pyarrow-20.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191", size = 25770759, upload-time = "2025-04-27T12:28:33.702Z" }, + { url = "https://files.pythonhosted.org/packages/47/a2/b7930824181ceadd0c63c1042d01fa4ef63eee233934826a7a2a9af6e463/pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0", size = 30856035, upload-time = "2025-04-27T12:28:40.78Z" }, + { url = "https://files.pythonhosted.org/packages/9b/18/c765770227d7f5bdfa8a69f64b49194352325c66a5c3bb5e332dfd5867d9/pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb", size = 32309552, upload-time = "2025-04-27T12:28:47.051Z" }, + { url = "https://files.pythonhosted.org/packages/44/fb/dfb2dfdd3e488bb14f822d7335653092dde150cffc2da97de6e7500681f9/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232", size = 41334704, upload-time = "2025-04-27T12:28:55.064Z" }, + { url = "https://files.pythonhosted.org/packages/58/0d/08a95878d38808051a953e887332d4a76bc06c6ee04351918ee1155407eb/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f", size = 42399836, upload-time = "2025-04-27T12:29:02.13Z" }, + { url = "https://files.pythonhosted.org/packages/f3/cd/efa271234dfe38f0271561086eedcad7bc0f2ddd1efba423916ff0883684/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab", size = 40711789, upload-time = "2025-04-27T12:29:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/46/1f/7f02009bc7fc8955c391defee5348f510e589a020e4b40ca05edcb847854/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62", size = 42301124, upload-time = "2025-04-27T12:29:17.187Z" }, + { url = "https://files.pythonhosted.org/packages/4f/92/692c562be4504c262089e86757a9048739fe1acb4024f92d39615e7bab3f/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c", size = 42916060, upload-time = "2025-04-27T12:29:24.253Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ec/9f5c7e7c828d8e0a3c7ef50ee62eca38a7de2fa6eb1b8fa43685c9414fef/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3", size = 44547640, upload-time = "2025-04-27T12:29:32.782Z" }, + { url = "https://files.pythonhosted.org/packages/54/96/46613131b4727f10fd2ffa6d0d6f02efcc09a0e7374eff3b5771548aa95b/pyarrow-20.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc", size = 25781491, upload-time = "2025-04-27T12:29:38.464Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d6/0c10e0d54f6c13eb464ee9b67a68b8c71bcf2f67760ef5b6fbcddd2ab05f/pyarrow-20.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba", size = 30815067, upload-time = "2025-04-27T12:29:44.384Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e2/04e9874abe4094a06fd8b0cbb0f1312d8dd7d707f144c2ec1e5e8f452ffa/pyarrow-20.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781", size = 32297128, upload-time = "2025-04-27T12:29:52.038Z" }, + { url = "https://files.pythonhosted.org/packages/31/fd/c565e5dcc906a3b471a83273039cb75cb79aad4a2d4a12f76cc5ae90a4b8/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199", size = 41334890, upload-time = "2025-04-27T12:29:59.452Z" }, + { url = "https://files.pythonhosted.org/packages/af/a9/3bdd799e2c9b20c1ea6dc6fa8e83f29480a97711cf806e823f808c2316ac/pyarrow-20.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd", size = 42421775, upload-time = "2025-04-27T12:30:06.875Z" }, + { url = "https://files.pythonhosted.org/packages/10/f7/da98ccd86354c332f593218101ae56568d5dcedb460e342000bd89c49cc1/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28", size = 40687231, upload-time = "2025-04-27T12:30:13.954Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1b/2168d6050e52ff1e6cefc61d600723870bf569cbf41d13db939c8cf97a16/pyarrow-20.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8", size = 42295639, upload-time = "2025-04-27T12:30:21.949Z" }, + { url = "https://files.pythonhosted.org/packages/b2/66/2d976c0c7158fd25591c8ca55aee026e6d5745a021915a1835578707feb3/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e", size = 42908549, upload-time = "2025-04-27T12:30:29.551Z" }, + { url = "https://files.pythonhosted.org/packages/31/a9/dfb999c2fc6911201dcbf348247f9cc382a8990f9ab45c12eabfd7243a38/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a", size = 44557216, upload-time = "2025-04-27T12:30:36.977Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8e/9adee63dfa3911be2382fb4d92e4b2e7d82610f9d9f668493bebaa2af50f/pyarrow-20.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b", size = 25660496, upload-time = "2025-04-27T12:30:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/9b/aa/daa413b81446d20d4dad2944110dcf4cf4f4179ef7f685dd5a6d7570dc8e/pyarrow-20.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:a15532e77b94c61efadde86d10957950392999503b3616b2ffcef7621a002893", size = 30798501, upload-time = "2025-04-27T12:30:48.351Z" }, + { url = "https://files.pythonhosted.org/packages/ff/75/2303d1caa410925de902d32ac215dc80a7ce7dd8dfe95358c165f2adf107/pyarrow-20.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:dd43f58037443af715f34f1322c782ec463a3c8a94a85fdb2d987ceb5658e061", size = 32277895, upload-time = "2025-04-27T12:30:55.238Z" }, + { url = "https://files.pythonhosted.org/packages/92/41/fe18c7c0b38b20811b73d1bdd54b1fccba0dab0e51d2048878042d84afa8/pyarrow-20.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0d288143a8585806e3cc7c39566407aab646fb9ece164609dac1cfff45f6ae", size = 41327322, upload-time = "2025-04-27T12:31:05.587Z" }, + { url = "https://files.pythonhosted.org/packages/da/ab/7dbf3d11db67c72dbf36ae63dcbc9f30b866c153b3a22ef728523943eee6/pyarrow-20.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6953f0114f8d6f3d905d98e987d0924dabce59c3cda380bdfaa25a6201563b4", size = 42411441, upload-time = "2025-04-27T12:31:15.675Z" }, + { url = "https://files.pythonhosted.org/packages/90/c3/0c7da7b6dac863af75b64e2f827e4742161128c350bfe7955b426484e226/pyarrow-20.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:991f85b48a8a5e839b2128590ce07611fae48a904cae6cab1f089c5955b57eb5", size = 40677027, upload-time = "2025-04-27T12:31:24.631Z" }, + { url = "https://files.pythonhosted.org/packages/be/27/43a47fa0ff9053ab5203bb3faeec435d43c0d8bfa40179bfd076cdbd4e1c/pyarrow-20.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:97c8dc984ed09cb07d618d57d8d4b67a5100a30c3818c2fb0b04599f0da2de7b", size = 42281473, upload-time = "2025-04-27T12:31:31.311Z" }, + { url = "https://files.pythonhosted.org/packages/bc/0b/d56c63b078876da81bbb9ba695a596eabee9b085555ed12bf6eb3b7cab0e/pyarrow-20.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9b71daf534f4745818f96c214dbc1e6124d7daf059167330b610fc69b6f3d3e3", size = 42893897, upload-time = "2025-04-27T12:31:39.406Z" }, + { url = "https://files.pythonhosted.org/packages/92/ac/7d4bd020ba9145f354012838692d48300c1b8fe5634bfda886abcada67ed/pyarrow-20.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8b88758f9303fa5a83d6c90e176714b2fd3852e776fc2d7e42a22dd6c2fb368", size = 44543847, upload-time = "2025-04-27T12:31:45.997Z" }, + { url = "https://files.pythonhosted.org/packages/9d/07/290f4abf9ca702c5df7b47739c1b2c83588641ddfa2cc75e34a301d42e55/pyarrow-20.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:30b3051b7975801c1e1d387e17c588d8ab05ced9b1e14eec57915f79869b5031", size = 25653219, upload-time = "2025-04-27T12:31:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/95/df/720bb17704b10bd69dde086e1400b8eefb8f58df3f8ac9cff6c425bf57f1/pyarrow-20.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:ca151afa4f9b7bc45bcc791eb9a89e90a9eb2772767d0b1e5389609c7d03db63", size = 30853957, upload-time = "2025-04-27T12:31:59.215Z" }, + { url = "https://files.pythonhosted.org/packages/d9/72/0d5f875efc31baef742ba55a00a25213a19ea64d7176e0fe001c5d8b6e9a/pyarrow-20.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:4680f01ecd86e0dd63e39eb5cd59ef9ff24a9d166db328679e36c108dc993d4c", size = 32247972, upload-time = "2025-04-27T12:32:05.369Z" }, + { url = "https://files.pythonhosted.org/packages/d5/bc/e48b4fa544d2eea72f7844180eb77f83f2030b84c8dad860f199f94307ed/pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f4c8534e2ff059765647aa69b75d6543f9fef59e2cd4c6d18015192565d2b70", size = 41256434, upload-time = "2025-04-27T12:32:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/c3/01/974043a29874aa2cf4f87fb07fd108828fc7362300265a2a64a94965e35b/pyarrow-20.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e1f8a47f4b4ae4c69c4d702cfbdfe4d41e18e5c7ef6f1bb1c50918c1e81c57b", size = 42353648, upload-time = "2025-04-27T12:32:20.766Z" }, + { url = "https://files.pythonhosted.org/packages/68/95/cc0d3634cde9ca69b0e51cbe830d8915ea32dda2157560dda27ff3b3337b/pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a1f60dc14658efaa927f8214734f6a01a806d7690be4b3232ba526836d216122", size = 40619853, upload-time = "2025-04-27T12:32:28.1Z" }, + { url = "https://files.pythonhosted.org/packages/29/c2/3ad40e07e96a3e74e7ed7cc8285aadfa84eb848a798c98ec0ad009eb6bcc/pyarrow-20.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:204a846dca751428991346976b914d6d2a82ae5b8316a6ed99789ebf976551e6", size = 42241743, upload-time = "2025-04-27T12:32:35.792Z" }, + { url = "https://files.pythonhosted.org/packages/eb/cb/65fa110b483339add6a9bc7b6373614166b14e20375d4daa73483755f830/pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f3b117b922af5e4c6b9a9115825726cac7d8b1421c37c2b5e24fbacc8930612c", size = 42839441, upload-time = "2025-04-27T12:32:46.64Z" }, + { url = "https://files.pythonhosted.org/packages/98/7b/f30b1954589243207d7a0fbc9997401044bf9a033eec78f6cb50da3f304a/pyarrow-20.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e724a3fd23ae5b9c010e7be857f4405ed5e679db5c93e66204db1a69f733936a", size = 44503279, upload-time = "2025-04-27T12:32:56.503Z" }, + { url = "https://files.pythonhosted.org/packages/37/40/ad395740cd641869a13bcf60851296c89624662575621968dcfafabaa7f6/pyarrow-20.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:82f1ee5133bd8f49d31be1299dc07f585136679666b502540db854968576faf9", size = 25944982, upload-time = "2025-04-27T12:33:04.72Z" }, ] [[package]] @@ -3460,104 +3644,91 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.7" +version = "2.10.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, { name = "typing-extensions" }, - { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681, upload-time = "2025-01-24T01:42:12.693Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, + { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696, upload-time = "2025-01-24T01:42:10.371Z" }, ] [[package]] name = "pydantic-core" -version = "2.33.2" +version = "2.27.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" }, - { url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" }, - { url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" }, - { url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" }, - { url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" }, - { url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" }, - { url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" }, - { url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" }, - { url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" }, - { url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" }, - { url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" }, - { url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" }, - { url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" }, - { url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" }, - { url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" }, - { url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" }, - { url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" }, - { url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" }, - { url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" }, - { url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" }, - { url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" }, - { url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" }, - { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, - { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, - { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, - { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, - { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, - { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, - { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, - { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, - { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, - { url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" }, - { url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" }, - { url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" }, - { url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" }, - { url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" }, - { url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" }, - { url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" }, - { url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" }, - { url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" }, - { url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" }, - { url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" }, - { url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" }, - { url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" }, - { url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" }, - { url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443, upload-time = "2024-12-18T11:31:54.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938, upload-time = "2024-12-18T11:27:14.406Z" }, + { url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684, upload-time = "2024-12-18T11:27:16.489Z" }, + { url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169, upload-time = "2024-12-18T11:27:22.16Z" }, + { url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227, upload-time = "2024-12-18T11:27:25.097Z" }, + { url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695, upload-time = "2024-12-18T11:27:28.656Z" }, + { url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662, upload-time = "2024-12-18T11:27:30.798Z" }, + { url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370, upload-time = "2024-12-18T11:27:33.692Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813, upload-time = "2024-12-18T11:27:37.111Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287, upload-time = "2024-12-18T11:27:40.566Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414, upload-time = "2024-12-18T11:27:43.757Z" }, + { url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301, upload-time = "2024-12-18T11:27:47.36Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685, upload-time = "2024-12-18T11:27:50.508Z" }, + { url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876, upload-time = "2024-12-18T11:27:53.54Z" }, + { url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421, upload-time = "2024-12-18T11:27:55.409Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998, upload-time = "2024-12-18T11:27:57.252Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167, upload-time = "2024-12-18T11:27:59.146Z" }, + { url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071, upload-time = "2024-12-18T11:28:02.625Z" }, + { url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244, upload-time = "2024-12-18T11:28:04.442Z" }, + { url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470, upload-time = "2024-12-18T11:28:07.679Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291, upload-time = "2024-12-18T11:28:10.297Z" }, + { url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613, upload-time = "2024-12-18T11:28:13.362Z" }, + { url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355, upload-time = "2024-12-18T11:28:16.587Z" }, + { url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661, upload-time = "2024-12-18T11:28:18.407Z" }, + { url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261, upload-time = "2024-12-18T11:28:21.471Z" }, + { url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361, upload-time = "2024-12-18T11:28:23.53Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484, upload-time = "2024-12-18T11:28:25.391Z" }, + { url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102, upload-time = "2024-12-18T11:28:28.593Z" }, + { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127, upload-time = "2024-12-18T11:28:30.346Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340, upload-time = "2024-12-18T11:28:32.521Z" }, + { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900, upload-time = "2024-12-18T11:28:34.507Z" }, + { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177, upload-time = "2024-12-18T11:28:36.488Z" }, + { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046, upload-time = "2024-12-18T11:28:39.409Z" }, + { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386, upload-time = "2024-12-18T11:28:41.221Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060, upload-time = "2024-12-18T11:28:44.709Z" }, + { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870, upload-time = "2024-12-18T11:28:46.839Z" }, + { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822, upload-time = "2024-12-18T11:28:48.896Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364, upload-time = "2024-12-18T11:28:50.755Z" }, + { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303, upload-time = "2024-12-18T11:28:54.122Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064, upload-time = "2024-12-18T11:28:56.074Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046, upload-time = "2024-12-18T11:28:58.107Z" }, + { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092, upload-time = "2024-12-18T11:29:01.335Z" }, + { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709, upload-time = "2024-12-18T11:29:03.193Z" }, + { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273, upload-time = "2024-12-18T11:29:05.306Z" }, + { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027, upload-time = "2024-12-18T11:29:07.294Z" }, + { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888, upload-time = "2024-12-18T11:29:09.249Z" }, + { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738, upload-time = "2024-12-18T11:29:11.23Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138, upload-time = "2024-12-18T11:29:16.396Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025, upload-time = "2024-12-18T11:29:20.25Z" }, + { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633, upload-time = "2024-12-18T11:29:23.877Z" }, + { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404, upload-time = "2024-12-18T11:29:25.872Z" }, + { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130, upload-time = "2024-12-18T11:29:29.252Z" }, + { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946, upload-time = "2024-12-18T11:29:31.338Z" }, + { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387, upload-time = "2024-12-18T11:29:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453, upload-time = "2024-12-18T11:29:35.533Z" }, + { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186, upload-time = "2024-12-18T11:29:37.649Z" }, + { url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159, upload-time = "2024-12-18T11:30:54.382Z" }, + { url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331, upload-time = "2024-12-18T11:30:58.178Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467, upload-time = "2024-12-18T11:31:00.6Z" }, + { url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797, upload-time = "2024-12-18T11:31:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839, upload-time = "2024-12-18T11:31:09.775Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861, upload-time = "2024-12-18T11:31:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582, upload-time = "2024-12-18T11:31:17.423Z" }, + { url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985, upload-time = "2024-12-18T11:31:19.901Z" }, + { url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715, upload-time = "2024-12-18T11:31:22.821Z" }, ] [[package]] @@ -4626,6 +4797,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ee/55/ba2546ab09a6adebc521bf3974440dc1d8c06ed342cceb30ed62a8858835/sqlalchemy-2.0.42-py3-none-any.whl", hash = "sha256:defcdff7e661f0043daa381832af65d616e060ddb54d3fe4476f51df7eaa1835", size = 1922072, upload-time = "2025-07-29T13:09:17.061Z" }, ] +[package.optional-dependencies] +mypy = [ + { name = "mypy" }, +] + [[package]] name = "sqlglot" version = "25.20.2" @@ -4718,11 +4894,11 @@ wheels = [ [[package]] name = "tenacity" -version = "9.1.2" +version = "8.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/4d/6a19536c50b849338fcbe9290d562b52cbdcf30d8963d3588a68a4107df1/tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78", size = 47309, upload-time = "2024-07-05T07:25:31.836Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687", size = 28165, upload-time = "2024-07-05T07:25:29.591Z" }, ] [[package]] @@ -4883,6 +5059,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/ea/b678e8fc87a36c003342e15c1f4ef362bdb40c5ff32573c9ec7d47e6e45b/trino-0.335.0-py3-none-any.whl", hash = "sha256:5c96d89d610ab7712ede532d2eb41beb8627339571bceff6134370a8a496f685", size = 57873, upload-time = "2025-06-17T15:22:54.84Z" }, ] +[[package]] +name = "typeguard" +version = "4.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/68/71c1a15b5f65f40e91b65da23b8224dad41349894535a97f63a52e462196/typeguard-4.4.4.tar.gz", hash = "sha256:3a7fd2dffb705d4d0efaed4306a704c89b9dee850b688f060a8b1615a79e5f74", size = 75203, upload-time = "2025-06-18T09:56:07.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/a9/e3aee762739c1d7528da1c3e06d518503f8b6c439c35549b53735ba52ead/typeguard-4.4.4-py3-none-any.whl", hash = "sha256:b5f562281b6bfa1f5492470464730ef001646128b180769880468bd84b68b09e", size = 34874, upload-time = "2025-06-18T09:56:05.999Z" }, +] + [[package]] name = "types-python-dateutil" version = "2.9.0.20250708" @@ -4980,16 +5168,72 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.35.0" +version = "0.34.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568, upload-time = "2024-12-15T13:33:30.42Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, + { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315, upload-time = "2024-12-15T13:33:27.467Z" }, +] + +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvicorn-worker" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gunicorn" }, + { name = "uvicorn" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/c0/b5df8c9a31b0516a47703a669902b362ca1e569fed4f3daa1d4299b28be0/uvicorn_worker-0.3.0.tar.gz", hash = "sha256:6baeab7b2162ea6b9612cbe149aa670a76090ad65a267ce8e27316ed13c7de7b", size = 9181, upload-time = "2024-12-26T12:13:07.591Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl", hash = "sha256:ef0fe8aad27b0290a9e602a256b03f5a5da3a9e5f942414ca587b645ec77dd52", size = 5346, upload-time = "2024-12-26T12:13:06.026Z" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741, upload-time = "2024-10-14T23:38:35.489Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/76/44a55515e8c9505aa1420aebacf4dd82552e5e15691654894e90d0bd051a/uvloop-0.21.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f", size = 1442019, upload-time = "2024-10-14T23:37:20.068Z" }, + { url = "https://files.pythonhosted.org/packages/35/5a/62d5800358a78cc25c8a6c72ef8b10851bdb8cca22e14d9c74167b7f86da/uvloop-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d", size = 801898, upload-time = "2024-10-14T23:37:22.663Z" }, + { url = "https://files.pythonhosted.org/packages/f3/96/63695e0ebd7da6c741ccd4489b5947394435e198a1382349c17b1146bb97/uvloop-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26", size = 3827735, upload-time = "2024-10-14T23:37:25.129Z" }, + { url = "https://files.pythonhosted.org/packages/61/e0/f0f8ec84979068ffae132c58c79af1de9cceeb664076beea86d941af1a30/uvloop-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb", size = 3825126, upload-time = "2024-10-14T23:37:27.59Z" }, + { url = "https://files.pythonhosted.org/packages/bf/fe/5e94a977d058a54a19df95f12f7161ab6e323ad49f4dabc28822eb2df7ea/uvloop-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f", size = 3705789, upload-time = "2024-10-14T23:37:29.385Z" }, + { url = "https://files.pythonhosted.org/packages/26/dd/c7179618e46092a77e036650c1f056041a028a35c4d76945089fcfc38af8/uvloop-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c", size = 3800523, upload-time = "2024-10-14T23:37:32.048Z" }, + { url = "https://files.pythonhosted.org/packages/57/a7/4cf0334105c1160dd6819f3297f8700fda7fc30ab4f61fbf3e725acbc7cc/uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", size = 1447410, upload-time = "2024-10-14T23:37:33.612Z" }, + { url = "https://files.pythonhosted.org/packages/8c/7c/1517b0bbc2dbe784b563d6ab54f2ef88c890fdad77232c98ed490aa07132/uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", size = 805476, upload-time = "2024-10-14T23:37:36.11Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ea/0bfae1aceb82a503f358d8d2fa126ca9dbdb2ba9c7866974faec1cb5875c/uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", size = 3960855, upload-time = "2024-10-14T23:37:37.683Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ca/0864176a649838b838f36d44bf31c451597ab363b60dc9e09c9630619d41/uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", size = 3973185, upload-time = "2024-10-14T23:37:40.226Z" }, + { url = "https://files.pythonhosted.org/packages/30/bf/08ad29979a936d63787ba47a540de2132169f140d54aa25bc8c3df3e67f4/uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", size = 3820256, upload-time = "2024-10-14T23:37:42.839Z" }, + { url = "https://files.pythonhosted.org/packages/da/e2/5cf6ef37e3daf2f06e651aae5ea108ad30df3cb269102678b61ebf1fdf42/uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", size = 3937323, upload-time = "2024-10-14T23:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284, upload-time = "2024-10-14T23:37:47.833Z" }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349, upload-time = "2024-10-14T23:37:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089, upload-time = "2024-10-14T23:37:51.703Z" }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770, upload-time = "2024-10-14T23:37:54.122Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321, upload-time = "2024-10-14T23:37:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022, upload-time = "2024-10-14T23:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123, upload-time = "2024-10-14T23:38:00.688Z" }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325, upload-time = "2024-10-14T23:38:02.309Z" }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806, upload-time = "2024-10-14T23:38:04.711Z" }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068, upload-time = "2024-10-14T23:38:06.385Z" }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428, upload-time = "2024-10-14T23:38:08.416Z" }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018, upload-time = "2024-10-14T23:38:10.888Z" }, ] [[package]] @@ -5055,6 +5299,106 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] +[[package]] +name = "watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/dd/579d1dc57f0f895426a1211c4ef3b0cb37eb9e642bb04bdcd962b5df206a/watchfiles-1.1.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:27f30e14aa1c1e91cb653f03a63445739919aef84c8d2517997a83155e7a2fcc", size = 405757, upload-time = "2025-06-15T19:04:51.058Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/7a0318cd874393344d48c34d53b3dd419466adf59a29ba5b51c88dd18b86/watchfiles-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3366f56c272232860ab45c77c3ca7b74ee819c8e1f6f35a7125556b198bbc6df", size = 397511, upload-time = "2025-06-15T19:04:52.79Z" }, + { url = "https://files.pythonhosted.org/packages/06/be/503514656d0555ec2195f60d810eca29b938772e9bfb112d5cd5ad6f6a9e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8412eacef34cae2836d891836a7fff7b754d6bcac61f6c12ba5ca9bc7e427b68", size = 450739, upload-time = "2025-06-15T19:04:54.203Z" }, + { url = "https://files.pythonhosted.org/packages/4e/0d/a05dd9e5f136cdc29751816d0890d084ab99f8c17b86f25697288ca09bc7/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df670918eb7dd719642e05979fc84704af913d563fd17ed636f7c4783003fdcc", size = 458106, upload-time = "2025-06-15T19:04:55.607Z" }, + { url = "https://files.pythonhosted.org/packages/f1/fa/9cd16e4dfdb831072b7ac39e7bea986e52128526251038eb481effe9f48e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7642b9bc4827b5518ebdb3b82698ada8c14c7661ddec5fe719f3e56ccd13c97", size = 484264, upload-time = "2025-06-15T19:04:57.009Z" }, + { url = "https://files.pythonhosted.org/packages/32/04/1da8a637c7e2b70e750a0308e9c8e662ada0cca46211fa9ef24a23937e0b/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199207b2d3eeaeb80ef4411875a6243d9ad8bc35b07fc42daa6b801cc39cc41c", size = 597612, upload-time = "2025-06-15T19:04:58.409Z" }, + { url = "https://files.pythonhosted.org/packages/30/01/109f2762e968d3e58c95731a206e5d7d2a7abaed4299dd8a94597250153c/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a479466da6db5c1e8754caee6c262cd373e6e6c363172d74394f4bff3d84d7b5", size = 477242, upload-time = "2025-06-15T19:04:59.786Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/46f58cf4969d3b7bc3ca35a98e739fa4085b0657a1540ccc29a1a0bc016f/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935f9edd022ec13e447e5723a7d14456c8af254544cefbc533f6dd276c9aa0d9", size = 453148, upload-time = "2025-06-15T19:05:01.103Z" }, + { url = "https://files.pythonhosted.org/packages/a5/cd/8267594263b1770f1eb76914940d7b2d03ee55eca212302329608208e061/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8076a5769d6bdf5f673a19d51da05fc79e2bbf25e9fe755c47595785c06a8c72", size = 626574, upload-time = "2025-06-15T19:05:02.582Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2f/7f2722e85899bed337cba715723e19185e288ef361360718973f891805be/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86b1e28d4c37e89220e924305cd9f82866bb0ace666943a6e4196c5df4d58dcc", size = 624378, upload-time = "2025-06-15T19:05:03.719Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/64c88ec43d90a568234d021ab4b2a6f42a5230d772b987c3f9c00cc27b8b/watchfiles-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d1caf40c1c657b27858f9774d5c0e232089bca9cb8ee17ce7478c6e9264d2587", size = 279829, upload-time = "2025-06-15T19:05:04.822Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/a9c1ed33de7af80935e4eac09570de679c6e21c07070aa99f74b4431f4d6/watchfiles-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a89c75a5b9bc329131115a409d0acc16e8da8dfd5867ba59f1dd66ae7ea8fa82", size = 292192, upload-time = "2025-06-15T19:05:06.348Z" }, + { url = "https://files.pythonhosted.org/packages/8b/78/7401154b78ab484ccaaeef970dc2af0cb88b5ba8a1b415383da444cdd8d3/watchfiles-1.1.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c9649dfc57cc1f9835551deb17689e8d44666315f2e82d337b9f07bd76ae3aa2", size = 405751, upload-time = "2025-06-15T19:05:07.679Z" }, + { url = "https://files.pythonhosted.org/packages/76/63/e6c3dbc1f78d001589b75e56a288c47723de28c580ad715eb116639152b5/watchfiles-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:406520216186b99374cdb58bc48e34bb74535adec160c8459894884c983a149c", size = 397313, upload-time = "2025-06-15T19:05:08.764Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a2/8afa359ff52e99af1632f90cbf359da46184207e893a5f179301b0c8d6df/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45350fd1dc75cd68d3d72c47f5b513cb0578da716df5fba02fff31c69d5f2d", size = 450792, upload-time = "2025-06-15T19:05:09.869Z" }, + { url = "https://files.pythonhosted.org/packages/1d/bf/7446b401667f5c64972a57a0233be1104157fc3abf72c4ef2666c1bd09b2/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11ee4444250fcbeb47459a877e5e80ed994ce8e8d20283857fc128be1715dac7", size = 458196, upload-time = "2025-06-15T19:05:11.91Z" }, + { url = "https://files.pythonhosted.org/packages/58/2f/501ddbdfa3fa874ea5597c77eeea3d413579c29af26c1091b08d0c792280/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bda8136e6a80bdea23e5e74e09df0362744d24ffb8cd59c4a95a6ce3d142f79c", size = 484788, upload-time = "2025-06-15T19:05:13.373Z" }, + { url = "https://files.pythonhosted.org/packages/61/1e/9c18eb2eb5c953c96bc0e5f626f0e53cfef4bd19bd50d71d1a049c63a575/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b915daeb2d8c1f5cee4b970f2e2c988ce6514aace3c9296e58dd64dc9aa5d575", size = 597879, upload-time = "2025-06-15T19:05:14.725Z" }, + { url = "https://files.pythonhosted.org/packages/8b/6c/1467402e5185d89388b4486745af1e0325007af0017c3384cc786fff0542/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed8fc66786de8d0376f9f913c09e963c66e90ced9aa11997f93bdb30f7c872a8", size = 477447, upload-time = "2025-06-15T19:05:15.775Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a1/ec0a606bde4853d6c4a578f9391eeb3684a9aea736a8eb217e3e00aa89a1/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe4371595edf78c41ef8ac8df20df3943e13defd0efcb732b2e393b5a8a7a71f", size = 453145, upload-time = "2025-06-15T19:05:17.17Z" }, + { url = "https://files.pythonhosted.org/packages/90/b9/ef6f0c247a6a35d689fc970dc7f6734f9257451aefb30def5d100d6246a5/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b7c5f6fe273291f4d414d55b2c80d33c457b8a42677ad14b4b47ff025d0893e4", size = 626539, upload-time = "2025-06-15T19:05:18.557Z" }, + { url = "https://files.pythonhosted.org/packages/34/44/6ffda5537085106ff5aaa762b0d130ac6c75a08015dd1621376f708c94de/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7738027989881e70e3723c75921f1efa45225084228788fc59ea8c6d732eb30d", size = 624472, upload-time = "2025-06-15T19:05:19.588Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e3/71170985c48028fa3f0a50946916a14055e741db11c2e7bc2f3b61f4d0e3/watchfiles-1.1.0-cp311-cp311-win32.whl", hash = "sha256:622d6b2c06be19f6e89b1d951485a232e3b59618def88dbeda575ed8f0d8dbf2", size = 279348, upload-time = "2025-06-15T19:05:20.856Z" }, + { url = "https://files.pythonhosted.org/packages/89/1b/3e39c68b68a7a171070f81fc2561d23ce8d6859659406842a0e4bebf3bba/watchfiles-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:48aa25e5992b61debc908a61ab4d3f216b64f44fdaa71eb082d8b2de846b7d12", size = 292607, upload-time = "2025-06-15T19:05:21.937Z" }, + { url = "https://files.pythonhosted.org/packages/61/9f/2973b7539f2bdb6ea86d2c87f70f615a71a1fc2dba2911795cea25968aea/watchfiles-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:00645eb79a3faa70d9cb15c8d4187bb72970b2470e938670240c7998dad9f13a", size = 285056, upload-time = "2025-06-15T19:05:23.12Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, + { url = "https://files.pythonhosted.org/packages/be/7c/a3d7c55cfa377c2f62c4ae3c6502b997186bc5e38156bafcb9b653de9a6d/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a6fd40bbb50d24976eb275ccb55cd1951dfb63dbc27cae3066a6ca5f4beabd5", size = 406748, upload-time = "2025-06-15T19:06:44.2Z" }, + { url = "https://files.pythonhosted.org/packages/38/d0/c46f1b2c0ca47f3667b144de6f0515f6d1c670d72f2ca29861cac78abaa1/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f811079d2f9795b5d48b55a37aa7773680a5659afe34b54cc1d86590a51507d", size = 398801, upload-time = "2025-06-15T19:06:45.774Z" }, + { url = "https://files.pythonhosted.org/packages/70/9c/9a6a42e97f92eeed77c3485a43ea96723900aefa3ac739a8c73f4bff2cd7/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2726d7bfd9f76158c84c10a409b77a320426540df8c35be172444394b17f7ea", size = 451528, upload-time = "2025-06-15T19:06:46.791Z" }, + { url = "https://files.pythonhosted.org/packages/51/7b/98c7f4f7ce7ff03023cf971cd84a3ee3b790021ae7584ffffa0eb2554b96/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df32d59cb9780f66d165a9a7a26f19df2c7d24e3bd58713108b41d0ff4f929c6", size = 454095, upload-time = "2025-06-15T19:06:48.211Z" }, + { url = "https://files.pythonhosted.org/packages/8c/6b/686dcf5d3525ad17b384fd94708e95193529b460a1b7bf40851f1328ec6e/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0ece16b563b17ab26eaa2d52230c9a7ae46cf01759621f4fbbca280e438267b3", size = 406910, upload-time = "2025-06-15T19:06:49.335Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d3/71c2dcf81dc1edcf8af9f4d8d63b1316fb0a2dd90cbfd427e8d9dd584a90/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:51b81e55d40c4b4aa8658427a3ee7ea847c591ae9e8b81ef94a90b668999353c", size = 398816, upload-time = "2025-06-15T19:06:50.433Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fa/12269467b2fc006f8fce4cd6c3acfa77491dd0777d2a747415f28ccc8c60/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2bcdc54ea267fe72bfc7d83c041e4eb58d7d8dc6f578dfddb52f037ce62f432", size = 451584, upload-time = "2025-06-15T19:06:51.834Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d3/254cea30f918f489db09d6a8435a7de7047f8cb68584477a515f160541d6/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923fec6e5461c42bd7e3fd5ec37492c6f3468be0499bc0707b4bbbc16ac21792", size = 454009, upload-time = "2025-06-15T19:06:52.896Z" }, +] + [[package]] name = "wcwidth" version = "0.2.13" @@ -5091,6 +5435,65 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload-time = "2024-04-23T22:16:14.422Z" }, ] +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423, upload-time = "2025-03-05T20:01:35.363Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080, upload-time = "2025-03-05T20:01:37.304Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329, upload-time = "2025-03-05T20:01:39.668Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312, upload-time = "2025-03-05T20:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319, upload-time = "2025-03-05T20:01:43.967Z" }, + { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631, upload-time = "2025-03-05T20:01:46.104Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016, upload-time = "2025-03-05T20:01:47.603Z" }, + { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426, upload-time = "2025-03-05T20:01:48.949Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360, upload-time = "2025-03-05T20:01:50.938Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388, upload-time = "2025-03-05T20:01:52.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830, upload-time = "2025-03-05T20:01:53.922Z" }, + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, + { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + [[package]] name = "xgboost" version = "3.0.3" @@ -5125,6 +5528,7 @@ dependencies = [ { name = "cryptography" }, { name = "dask", marker = "python_full_version < '4'" }, { name = "envyaml" }, + { name = "feast" }, { name = "geoarrow-types", marker = "python_full_version < '4'" }, { name = "opentelemetry-exporter-otlp" }, { name = "opentelemetry-exporter-prometheus" }, @@ -5231,16 +5635,17 @@ requires-dist = [ { name = "adbc-driver-postgresql", marker = "extra == 'postgres'", specifier = ">=1.4.0" }, { name = "adbc-driver-snowflake", marker = "extra == 'snowflake'", specifier = ">=1.5.0" }, { name = "adbc-driver-sqlite", marker = "extra == 'sqlite'", specifier = ">=1.4.0" }, - { name = "atpublic", specifier = ">=5.1" }, + { name = "atpublic", specifier = ">=3.0" }, { name = "attrs", marker = "python_full_version >= '3.10' and python_full_version < '4'", specifier = ">=24.0.0,<26" }, { name = "cityhash", marker = "python_full_version >= '3.10' and python_full_version < '4'", specifier = ">=0.4.7,<1" }, - { name = "cloudpickle", specifier = ">=3.1.1" }, + { name = "cloudpickle", specifier = ">=3.0" }, { name = "cryptography", specifier = ">=45.0.3" }, { name = "dask", marker = "python_full_version >= '3.10' and python_full_version < '4'", specifier = "==2025.1.0" }, { name = "datafusion", marker = "python_full_version >= '3.10' and python_full_version < '4' and extra == 'datafusion'", specifier = ">=0.6,<49" }, { name = "duckdb", marker = "python_full_version >= '3.10' and python_full_version < '4' and extra == 'examples'", specifier = ">=0.10.3,<2" }, { name = "duckdb", marker = "extra == 'duckdb'", specifier = ">=1.1.3" }, { name = "envyaml", specifier = ">=1.10.211231" }, + { name = "feast", specifier = ">=0.55.0" }, { name = "fsspec", marker = "python_full_version >= '3.10' and python_full_version < '4' and extra == 'examples'", specifier = ">=2024.6.1,<2025.7.1" }, { name = "geoarrow-types", marker = "python_full_version >= '3.10' and python_full_version < '4'", specifier = ">=0.2,<1" }, { name = "mcp", marker = "extra == 'examples'", specifier = ">=1.5.0" }, From b7e8b5c2ccea01b67ad7bd26c06975f331ba92b0 Mon Sep 17 00:00:00 2001 From: dlovell Date: Wed, 24 Sep 2025 08:20:12 -0400 Subject: [PATCH 2/2] wip: add feast_utils, feast_replication_utils and tests --- .../common/utils/feast_replication_utils.py | 408 ++++++++++++ python/xorq/common/utils/feast_utils.py | 586 ++++++++++++++++++ .../xorq/common/utils/tests/feast/conftest.py | 70 +++ .../feast/test_feast_replication_utils.py | 134 ++++ .../utils/tests/feast/test_feast_utils.py | 129 ++++ python/xorq/tests/fixtures/feature_repo.tgz | Bin 0 -> 30589 bytes 6 files changed, 1327 insertions(+) create mode 100644 python/xorq/common/utils/feast_replication_utils.py create mode 100644 python/xorq/common/utils/feast_utils.py create mode 100644 python/xorq/common/utils/tests/feast/conftest.py create mode 100644 python/xorq/common/utils/tests/feast/test_feast_replication_utils.py create mode 100644 python/xorq/common/utils/tests/feast/test_feast_utils.py create mode 100644 python/xorq/tests/fixtures/feature_repo.tgz diff --git a/python/xorq/common/utils/feast_replication_utils.py b/python/xorq/common/utils/feast_replication_utils.py new file mode 100644 index 000000000..6f93cfc07 --- /dev/null +++ b/python/xorq/common/utils/feast_replication_utils.py @@ -0,0 +1,408 @@ +import contextlib +import functools +import operator +from datetime import datetime +from pathlib import ( + Path, +) + +import dask +import toolz +from attr import ( + field, + frozen, +) +from attr.validators import ( + instance_of, +) + + +@dask.base.normalize_token.register(dask.utils.methodcaller) +def normalize_methodcaller(mc): + return dask.base.normalize_token( + ( + dask.utils.methodcaller, + mc.method, + ) + ) + + +@frozen +class Store: + path = field(validator=instance_of(Path), converter=Path) + + def __attrs_post_init__(self): + assert self.path.exists() + + @property + @functools.cache + def store(self): + import feast + + return feast.FeatureStore(self.path) + + @property + def config(self): + return self.store.config + + @property + def provider(self): + return self.store._get_provider() + + @property + @functools.cache + def repo_contents(self): + import feast.repo_operations + + with contextlib.chdir(self.path): + return feast.repo_operations._get_repo_contents( + self.path, self.project_name + ) + + @property + def registry(self): + return self.store._registry + + @property + def entities(self): + return self.store.list_entities() + + @property + def project_name(self): + return self.config.project + + def apply(self, skip_source_validation=False): + import feast.repo_operations + + with contextlib.chdir(self.path): + return feast.repo_operations.apply_total( + self.config, self.path, skip_source_validation=skip_source_validation + ) + + def teardown(self): + return self.store.teardown() + + def list_on_demand_feature_view_names(self): + return tuple(el.name for el in self.repo_contents.on_demand_feature_views) + + def get_on_demand_feature_view(self, on_demand_feature_view_name): + return self.registry.get_on_demand_feature_view( + on_demand_feature_view_name, self.store.project + ) + + def list_feature_view_names(self): + return tuple(el.name for el in self.repo_contents.feature_views) + + def get_feature_view(self, feature_view_name): + return self.registry.get_feature_view(feature_view_name, self.store.project) + + def get_feature_refs(self, features): + import feast.utils as utils + + return utils._get_features(self.registry, self.store.project, list(features)) + + def get_feature_views_to_use(self, features): + import feast.utils as utils + + (all_feature_views, all_on_demand_feature_views) = ( + utils._get_feature_views_to_use( + self.registry, + self.store.project, + list(features), + ) + ) + return (all_feature_views, all_on_demand_feature_views) + + def get_grouped_feature_views(self, features): + import feast.utils as utils + + feature_refs = self.get_feature_refs(features) + (all_feature_views, all_on_demand_feature_views) = ( + self.get_feature_views_to_use(features) + ) + fvs, odfvs = utils._group_feature_refs( + feature_refs, + all_feature_views, + all_on_demand_feature_views, + ) + (feature_views, on_demand_feature_views) = ( + tuple(view for view, _ in gen) for gen in (fvs, odfvs) + ) + return feature_views, on_demand_feature_views + + def validate_entity_expr(self, entity_expr, features, full_feature_names=False): + import feast.utils as utils + + (_, on_demand_feature_views) = self.get_grouped_feature_views(features) + if self.store.config.coerce_tz_aware: + # FIXME: pass entity_expr back out + # entity_df = utils.make_df_tzaware(typing.cast(pd.DataFrame, entity_df)) + pass + bad_pairs = ( + (feature_name, odfv.name) + for odfv in on_demand_feature_views + for feature_name in odfv.get_request_data_schema().keys() + if feature_name not in entity_expr.columns + ) + if pair := next(bad_pairs, None): + from feast.feature_store import RequestDatanotFoundInEntityDfException + + (feature_name, feature_view_name) = pair + raise RequestDatanotFoundInEntityDfException( + feature_name=feature_name, + feature_view_name=feature_view_name, + ) + utils._validate_feature_refs( + self.get_feature_refs(features), + full_feature_names, + ) + + def get_historical_features(self, entity_expr, features, full_feature_names=False): + self.validate_entity_expr( + entity_expr, features, full_feature_names=full_feature_names + ) + (odfv_dct, fv_dct) = group_features(self, features) + entity_expr, all_join_keys = process_all_feature_views( + self, entity_expr, fv_dct + ) + expr = process_odfvs(entity_expr, odfv_dct) + return expr + + def get_historical_features_feast( + self, entity_df, features, full_feature_names=False + ): + return self.store.get_historical_features( + entity_df=entity_df, + features=features, + full_feature_names=full_feature_names, + ) + + def get_online_features(self, features, entity_rows): + return self.store.get_online_features( + features=features, + entity_rows=entity_rows, + ).to_dict() + + def list_feature_service_names(self): + return tuple(el.name for el in self.store.list_feature_services()) + + def get_feature_service(self, feature_service_name): + return self.store.get_feature_service(feature_service_name) + + def list_data_source_names(self): + return tuple( + el.name for el in self.registry.list_data_sources(self.project_name) + ) + + def get_data_source(self, data_source_name): + return self.registry.get_data_source(data_source_name, self.project_name) + + @classmethod + def make_applied_materialized(cls, path, end_date=None): + end_date = end_date or datetime.now() + store = cls(path) + store.apply() + store.store.materialize_incremental(end_date=end_date) + return store + + +def process_one_feature_view( + entity_expr, store, feature_view, feature_names, all_join_keys +): + from feast.infra.offline_stores.offline_utils import ( + DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL, + ) + + import xorq.api as xo + + def _read_mapped( + con, + store, + feature_view, + feature_names, + right_entity_key_columns, + ets, + ts, + full_feature_names=False, + ): + def maybe_rename(expr, dct): + return ( + expr.rename({to_: from_ for from_, to_ in dct.items() if from_ in expr}) + if dct + else expr + ) + + if full_feature_names: + raise ValueError + expr = ( + xo.deferred_read_parquet( + store.config.repo_path.joinpath(feature_view.batch_source.path), con=con + ) + .pipe(maybe_rename, feature_view.batch_source.field_mapping) + .pipe(maybe_rename, feature_view.projection.join_key_map) + .select(list(right_entity_key_columns) + list(feature_names)) + ) + if ts == ets: + new_ts = f"__{ts}" + expr, ts = expr.pipe(maybe_rename, {ts: new_ts}), new_ts + return expr, ts + + def _merge(entity_expr, feature_expr, join_keys): + return entity_expr.join( + feature_expr, predicates=join_keys, how="left", rname="{name}__" + ) + + def _normalize_timestamp(expr, *tss): + casts = { + ts: xo.expr.datatypes.Timestamp(timezone="UTC") + for ts in tss + if ts in expr and expr[ts].type().timezone is None + } + return expr.cast(casts) if casts else expr + + def _filter_ttl(expr, ttl, ets, ts): + isna_condition = expr[ts].isnull() + le_condition = expr[ts] <= expr[ets] + if ttl and ttl.total_seconds() != 0: + ge_condition = ( + expr[ets] - xo.interval(seconds=ttl.total_seconds()) + ) <= expr[ts] + time_condition = ge_condition & le_condition + else: + time_condition = le_condition + condition = isna_condition | time_condition + return expr[condition] + + def _drop_duplicates(expr, join_keys, ets, ts, cts): + order_by = tuple( + expr[ts].desc(nulls_first=False) + # cts desc first: most recent update + # ts desc: closest to the event ts + for ts in (cts, ts) + if ts in expr + ) + ROW_NUM = "row_num" + expr = ( + expr.mutate( + **{ + ROW_NUM: ( + xo.row_number().over( + group_by=list(join_keys) + [ets], + order_by=order_by, + ) + ), + } + ) + .filter(xo._[ROW_NUM] == 0) + .drop(ROW_NUM) + ) + return expr + + ets = DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL + assert ets in entity_expr + con = entity_expr._find_backend() + + ts, cts = ( + feature_view.batch_source.timestamp_field, + feature_view.batch_source.created_timestamp_column, + ) + join_keys = tuple( + feature_view.projection.join_key_map.get(entity_column.name, entity_column.name) + for entity_column in feature_view.entity_columns + ) + all_join_keys = all_join_keys + [ + join_key for join_key in join_keys if join_key not in all_join_keys + ] + right_entity_key_columns = list(filter(None, [ts, cts] + list(join_keys))) + + entity_expr = _normalize_timestamp(entity_expr, ets) + + feature_expr, ts = _read_mapped( + con, store, feature_view, feature_names, right_entity_key_columns, ets, ts + ) + expr = _merge(entity_expr, feature_expr, join_keys) + expr = _normalize_timestamp(expr, ts, cts) + expr = _filter_ttl(expr, feature_view.ttl, ets, ts) + expr = _drop_duplicates(expr, all_join_keys, ets, ts, cts) + return expr, all_join_keys + + +def process_all_feature_views(store, entity_expr, fv_dct): + all_join_keys = [] + for feature_view, feature_names in fv_dct.items(): + entity_expr, all_join_keys = process_one_feature_view( + entity_expr, store, feature_view, feature_names, all_join_keys + ) + return entity_expr, all_join_keys + + +@toolz.curry +def apply_odfv_dct(df, odfv_udfs): + for other in (udf(df) for udf in odfv_udfs): + df = df.join(other) + return df + + +def make_uniform_timestamps(expr, timezone="UTC", scale=6): + import xorq.vendor.ibis.expr.datatypes as dt + + casts = { + name: dt.Timestamp(timezone=timezone, scale=scale) + for name, typ in expr.schema().items() + if isinstance(typ, dt.Timestamp) + } + return expr.cast(casts) if casts else expr + + +def calc_odfv_schema_append(odfv_dct): + fields = (field for odfv in odfv_dct for field in odfv.features) + schema_append = {field.name: field.dtype.name for field in fields} + return schema_append + + +def process_odfvs(entity_expr, odfv_dct, full_feature_names=False): + import xorq.expr.relations as rel + + if full_feature_names: + raise ValueError + entity_expr = make_uniform_timestamps(entity_expr) + odfv_udfs = tuple(odfv.feature_transformation.udf for odfv in odfv_dct.keys()) + schema_in = entity_expr.schema() + schema_append = calc_odfv_schema_append(odfv_dct) + udxf = rel.flight_udxf( + process_df=apply_odfv_dct(odfv_udfs=odfv_udfs), + maybe_schema_in=schema_in, + maybe_schema_out=schema_in | schema_append, + name="process_odfvs", + ) + return udxf(entity_expr) + + +def group_features(store, feature_names): + import feast + + splat = tuple(feature_name.split(":") for feature_name in feature_names) + if bad_feature_splats := tuple(el for el in splat if len(el) != 2): + raise ValueError( + f"got invalid feature names: {tuple(':'.join(el) for el in bad_feature_splats)}" + ) + name_to_use_to_view = { + view.projection.name_to_use(): view + for view in store.store.list_all_feature_views() + } + dct = toolz.groupby( + operator.itemgetter(0), + splat, + ) + view_to_feature_names = { + name_to_use_to_view[feature_view_name]: tuple( + feature_name for _, feature_name in pairs + ) + for feature_view_name, pairs in dct.items() + } + is_odfv = toolz.flip(isinstance)(feast.OnDemandFeatureView) + (odfv_dct, fv_dct) = ( + toolz.keyfilter(f, view_to_feature_names) + for f in (is_odfv, toolz.complement(is_odfv)) + ) + return odfv_dct, fv_dct diff --git a/python/xorq/common/utils/feast_utils.py b/python/xorq/common/utils/feast_utils.py new file mode 100644 index 000000000..05f14129e --- /dev/null +++ b/python/xorq/common/utils/feast_utils.py @@ -0,0 +1,586 @@ +import functools +from datetime import ( + datetime, + timedelta, +) +from operator import methodcaller +from pathlib import Path + +import toolz +from attrs import ( + field, + frozen, +) +from attrs.validators import ( + deep_iterable, + instance_of, + is_callable, + optional, +) +from feast import ( + Entity, + FeatureService, + FeatureView, + Field, + FileSource, + OnDemandFeatureView, + Project, + PushSource, + RequestSource, +) +from feast.data_format import FileFormat +from feast.feature_logging import ( + LoggingConfig, +) +from feast.feature_view import ( + DUMMY_ENTITY_NAME, +) +from feast.transformation.base import ( + Transformation, +) +from feast.types import ( + # this is the only "leakage" from feast classes + FeastType, + ValueType, +) + +import xorq.api as xo +import xorq.expr.datatypes as dt + + +EVENT_TIMESTAMP = "event_timestamp" + + +def dct_converter(maybe_dct): + # toolz.compose(tuple, sorted, operator.methodcaller("items"), dict) + return tuple(sorted(dict(maybe_dct).items())) + + +def gen_attr_names(has_attrs_attrs): + # toolz.compose(partial(map, operator.attrgetter("name")), operator.attrgetter("__attrs_attrs__")) + # operator.methodcaller("__getstate__") + yield from (attr.name for attr in has_attrs_attrs.__attrs_attrs__) + + +def getattrs(attrs, obj, *args): + yield from ((attr, getattr(obj, attr, *args)) for attr in attrs) + + +def apply_conversions(conversions, kwargs): + conversions = dict(conversions) + converted = {k: conversions.get(k, toolz.identity)(v) for k, v in kwargs.items()} + return converted + + +@toolz.curry +def _to_feast(feast_cls, xorq_obj, conversions=(), post_process=None): + kwargs = apply_conversions( + conversions, + dict(getattrs(gen_attr_names(xorq_obj), xorq_obj)), + ) + if post_process: + feast_obj = post_process(xorq_obj, feast_cls, kwargs) + else: + feast_obj = feast_cls(**kwargs) + return feast_obj + + +@toolz.curry +def _from_feast(xorq_cls, feast_obj, conversions=(), post_process=None): + kwargs = apply_conversions( + conversions, + dict(getattrs(gen_attr_names(xorq_cls), feast_obj, None)), + ) + if post_process: + xorq_obj = post_process(xorq_cls, feast_obj, kwargs) + else: + xorq_obj = xorq_cls(**kwargs) + return xorq_obj + + +def from_feast(obj): + match obj: + case None: + return None + case tuple() | list(): + return tuple(from_feast(el) for el in obj) + case _: + typ = next((typ for typ in typs if isinstance(obj, typ.feast_cls)), None) + if typ: + return typ.from_feast(obj) + else: + raise NotImplementedError(f"don't know how to convert type {type(obj)}") + + +list_map_to_feast = toolz.compose(list, toolz.partial(map, methodcaller("to_feast"))) + + +@frozen +class FeastProject: + name = field(validator=instance_of(str)) + description = field(validator=instance_of(str), default="") + tags = field( + validator=deep_iterable(instance_of(tuple), instance_of(tuple)), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + created_timestamp = field(validator=optional(instance_of(datetime)), default=None) + last_updated_timestamp = field( + validator=optional(instance_of(datetime)), default=None + ) + # + feast_cls = Project + + to_feast = _to_feast(feast_cls, conversions=(("tags", dict),)) + + from_feast = classmethod(_from_feast) + + +@frozen +class FeastField: + name = field(validator=instance_of(str)) + dtype = field(validator=instance_of(FeastType)) + description = field(validator=instance_of(str), default="") + tags = field( + validator=deep_iterable(instance_of(tuple), instance_of(tuple)), + converter=dct_converter, + default=(), + ) + vector_index = field(validator=instance_of(bool), default=False) + vector_length = field(validator=instance_of(int), default=0) + vector_search_metric = field(validator=optional(instance_of(str)), default=None) + # + feast_cls = Field + + def __attrs_post_init__(self): + if (self.vector_index, self.vector_length, self.vector_search_metric) != ( + False, + 0, + None, + ): + raise ValueError + + to_feast = _to_feast(feast_cls, conversions=(("tags", dict),)) + + from_feast = classmethod(_from_feast) + + +@frozen +class FeastEntity: + name = field(validator=instance_of(str)) + join_keys = field(validator=deep_iterable(instance_of(str), instance_of(tuple))) + value_type = field(validator=optional(instance_of(ValueType)), default=None) + description = field(validator=instance_of(str), default="") + tags = field( + validator=deep_iterable(instance_of(tuple), instance_of(tuple)), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + created_timestamp = field(validator=optional(instance_of(datetime)), default=None) + last_updated_timestamp = field( + validator=optional(instance_of(datetime)), default=None + ) + # + feast_cls = Entity + + def __attrs_post_init__(self): + # this is only every created once + assert len(self.join_keys) == 1 + + def to_feast_post_process(self, feast_cls, kwargs): + setattrs = ("created_timestamp", "last_updated_timestamp") + to_setattr = ((k, kwargs[k]) for k in setattrs) + feast_obj = feast_cls(**toolz.dissoc(kwargs, *setattrs)) + for k, v in to_setattr: + setattr(feast_obj, k, v) + return feast_obj + + @staticmethod + def from_feast_post_process(cls, feast_obj, kwargs): + xorq_obj = cls( + **kwargs + | { + "join_keys": (feast_obj.join_key,), + } + ) + return xorq_obj + + to_feast = _to_feast( + feast_cls, + conversions=( + ("tags", dict), + ("join_keys", list), + ), + post_process=to_feast_post_process, + ) + + from_feast = classmethod(_from_feast(post_process=from_feast_post_process)) + + +@frozen +class FeastFeatureViewProjection: + # feast_cls = FeatureViewProjection + + def __attrs_post_init__(self): + raise NotImplementedError + + +@frozen +class FeastDataSource: + # feast_cls = DataSource + + def __attrs_post_init__(self): + raise NotImplementedError("we only have FeastFileSource for now") + + +@frozen +class FeastFileSource: + path = field(validator=instance_of(Path), converter=Path) + name = field(validator=instance_of(str), default="") + event_timestamp_column = field(validator=optional(instance_of(str)), default=None) + file_format = field(validator=optional(instance_of(FileFormat)), default=None) + created_timestamp_column = field(validator=instance_of(str), default="") + s3_endpoint_override = field(validator=optional(instance_of(str)), default=None) + description = field(validator=instance_of(str), default="") + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + timestamp_field = field(validator=instance_of(str), default="") + # + feast_cls = FileSource + + def __attrs_post_init__(self): + def validate_timestamp_field(field): + if field: + assert field in self.expr.schema() + typ = type(self.expr[field].type()) + assert dt.Temporal in typ.mro() + + assert self.name + assert self.path.exists() + validate_timestamp_field(self.timestamp_field) + validate_timestamp_field(self.created_timestamp_column) + + @property + def expr(self): + match self.path.suffix: + case ".parquet": + return xo.deferred_read_parquet(self.path, xo.connect()) + case ".csv": + return xo.deferred_read_csv(self.path, xo.connect()) + case _: + raise ValueError( + f"don't know how to deal with suffix {self.path.suffix}" + ) + + to_feast = _to_feast( + feast_cls, + conversions=( + ("batch_source", methodcaller("to_feast")), + ("tags", dict), + ("path", str), + ), + ) + + from_feast = classmethod(_from_feast) + + +@frozen +class FeastPushSource: + name = field(validator=instance_of(str)) + batch_source = field(validator=instance_of((FeastDataSource, FeastFileSource))) + description = field(validator=instance_of(str), default="") + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + # + feast_cls = PushSource + + to_feast = _to_feast( + feast_cls, + conversions=( + ("batch_source", methodcaller("to_feast")), + ("tags", dict), + ), + ) + + from_feast = classmethod(_from_feast(conversions=(("batch_source", from_feast),))) + + +# every field of schema either goes into entity_columns or into features +# entity_columns if its in join keys +# features if not + + +@frozen +class FeastFeatureView: + name = field(validator=instance_of(str)) + source = field( + validator=instance_of((FeastFileSource, FeastDataSource, FeastPushSource)), + ) + schema = field( + validator=deep_iterable(instance_of(FeastField), instance_of(tuple)), + default=(), + ) + # we only get strings, but would like to have the join keys + entities = field( + # validator=deep_iterable(instance_of(FeastEntity), instance_of(tuple)), + validator=deep_iterable(instance_of(str), instance_of(tuple)), + converter=tuple, + default=(DUMMY_ENTITY_NAME,), + ) + # FIXME: default should be datetime.timedelta(0) + ttl = field(validator=optional(instance_of(timedelta)), default=None) + online = field(validator=instance_of(bool), default=False) + offline = field(validator=instance_of(bool), default=True) + description = field(validator=instance_of(str), default="") + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + # + # how we handle getitem on feature view that results in a mutation of self.projection + # do we have to inspect the FeatureView to see if its already been sliced? + # it mutates projection.{features,desired_features} + item = field( + validator=deep_iterable(instance_of(FeastField), instance_of(tuple)), + default=(), + ) + # + feast_cls = FeatureView + + def __getitem__(self, item): + return from_feast(self.instance[item]) + + @property + @functools.cache + def instance(self): + obj = self.to_feast() + if self.item: + # obj.projection.features = list(self.item) + obj = obj[list(self.item)] + return obj + + # def __attrs_post_init__(self): + # # try to attain feast order for equals testing + # object.__setattr__(self, "schema", tuple(set(self.schema))) + @staticmethod + def from_feast_post_process(cls, feast_obj, kwargs): + if feast_obj.projection.desired_features: + raise ValueError + return cls( + **kwargs + | { + "item": from_feast(feast_obj.projection.features), + } + ) + + def to_feast_post_process(self, feast_cls, kwargs): + feast_obj = feast_cls(**toolz.dissoc(kwargs, "item")) + if item := kwargs.get("item"): + # feast_obj = feast_obj[list(item)] + feast_obj.projection.features = list(el.to_feast() for el in item) + return feast_obj + + to_feast = _to_feast( + feast_cls, + conversions=( + ("schema", list_map_to_feast), + ("tags", dict), + ("entities", lambda x: [Entity(name=el, join_keys=[]) for el in x]), + ("source", methodcaller("to_feast")), + ), + post_process=to_feast_post_process, + ) + + from_feast = classmethod( + _from_feast( + conversions=( + ("source", from_feast), + ("schema", from_feast), + ), + post_process=from_feast_post_process, + ) + ) + + +@frozen +class FeastRequestSource: + name = field() + schema = field( + validator=deep_iterable(instance_of(FeastField), instance_of(tuple)), + ) + description = field(validator=instance_of(str), default="") + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + # + feast_cls = RequestSource + + to_feast = _to_feast( + feast_cls, conversions=(("schema", list_map_to_feast), ("tags", dict)) + ) + + from_feast = classmethod( + _from_feast( + conversions=(("schema", from_feast),), + ) + ) + + +@frozen +class FeastOnDemandFeatureView: + name = field(validator=instance_of(str)) + # we would like to be able to infer / retain the fields + entities = field( + # validator=deep_iterable(instance_of(FeastEntity), instance_of(tuple)), + validator=deep_iterable(instance_of(str), instance_of(tuple)), + converter=tuple, + default=(DUMMY_ENTITY_NAME,), + ) + schema = field( + validator=deep_iterable(instance_of(FeastField), instance_of(tuple)), + default=(), + ) + sources = field( + validator=deep_iterable( + instance_of( + (FeastFeatureView, FeastRequestSource, FeastFeatureViewProjection) + ), + instance_of(tuple), + ), + converter=tuple, + default=(), + ) + udf = field(validator=optional(is_callable()), default=None) + udf_string = field(validator=instance_of(str), default="") + feature_transformation = field( + validator=optional(instance_of(Transformation)), default=None + ) + mode = field(validator=instance_of(str), default="pandas") + description = field(validator=instance_of(str), default="") + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + owner = field(validator=instance_of(str), default="") + write_to_online_store = field(validator=instance_of(bool), default=False) + singleton = field(validator=instance_of(bool), default=False) + # + feast_cls = OnDemandFeatureView + + @classmethod + def on_demand_feature_view(cls, name=None, **kwargs): + def decorator(user_function): + import dill + + user_function.__module__ = "__main__" + udf_string = dill.source.getsource(user_function) + obj = cls( + name=name or user_function.__name__, + udf=user_function, + udf_string=udf_string, + **kwargs, + ) + functools.update_wrapper(wrapper=obj, wrapped=user_function) + return obj + + return decorator + + to_feast = _to_feast( + feast_cls, + conversions=( + ("schema", list_map_to_feast), + ("tags", dict), + ("entities", lambda x: [Entity(name=el, join_keys=[]) for el in x]), + # ("sources", methodcaller("to_feast")), + ("sources", list_map_to_feast), + ), + ) + + from_feast = classmethod( + _from_feast( + conversions=( + ("sources", from_feast), + ("schema", from_feast), + ), + ) + ) + + +@frozen +class FeastFeatureService: + name = field(validator=instance_of(str)) + features = field( + validator=deep_iterable( + instance_of((FeastFeatureView, FeastOnDemandFeatureView)), + instance_of(tuple), + ) + ) + tags = field( + validator=optional( + deep_iterable(instance_of(tuple), instance_of(tuple)), + ), + converter=dct_converter, + default=(), + ) + description = field(validator=instance_of(str), default="") + owner = field(validator=instance_of(str), default="") + logging_config = field(validator=optional(instance_of(LoggingConfig)), default=None) + # + feast_cls = FeatureService + + @staticmethod + def from_feast_post_process(cls, feast_obj, kwargs): + xorq_obj = cls(**kwargs | {"features": from_feast(feast_obj._features)}) + return xorq_obj + + to_feast = _to_feast( + feast_cls, + conversions=( + ("features", list_map_to_feast), + ("tags", dict), + ), + ) + + # from_feast = classmethod(_from_feast(conversions=(("features", from_feast),))) + from_feast = classmethod(_from_feast(post_process=from_feast_post_process)) + + +typs = ( + FeastProject, + FeastField, + FeastEntity, + FeastFeatureView, + # FeastFeatureViewProjection, + FeastFileSource, + # FeastDataSource, + FeastPushSource, + FeastRequestSource, + FeastOnDemandFeatureView, + FeastFeatureService, +) diff --git a/python/xorq/common/utils/tests/feast/conftest.py b/python/xorq/common/utils/tests/feast/conftest.py new file mode 100644 index 000000000..93c3b993a --- /dev/null +++ b/python/xorq/common/utils/tests/feast/conftest.py @@ -0,0 +1,70 @@ +import sys +import tarfile +from datetime import datetime, timedelta +from pathlib import Path + +import pytest + + +pytest.importorskip("feast") + + +def freshen_driver_stats( + store, end_date=None, delta=None, driver_entities=(1001, 1002, 1003, 1004, 1005) +): + from feast.driver_test_data import create_driver_hourly_stats_df + + end_date = end_date or datetime.now().replace(microsecond=0, second=0, minute=0) + delta = delta or timedelta(days=15) + driver_df = create_driver_hourly_stats_df( + list(driver_entities), + end_date - delta, + end_date, + ) + parquet_path = store.path.joinpath("data", "driver_stats.parquet") + parquet_path.parent.mkdir(exist_ok=True, parents=True) + driver_df.to_parquet(parquet_path) + + +def make_store(fixture_dir, tmpdir): + from xorq.common.utils.feast_replication_utils import ( + Store, + ) + + tgz_path = fixture_dir.joinpath("feature_repo.tgz") + with tarfile.TarFile.gzopen(tgz_path) as tfh: + tfh.extractall(tmpdir) + store = Store(tmpdir) + freshen_driver_stats(store) + return store + + +def make_store_applied(fixture_dir, tmpdir): + store_applied = make_store(fixture_dir, tmpdir) + # we must directly change sys.path + # # monkeypatch.syspath_prepend is only function scope + old_sys_path, sys.path = sys.path, [str(tmpdir)] + sys.path + store_applied.apply() + sys.path = old_sys_path + return store_applied + + +@pytest.fixture(scope="function") +def fresh_store(fixture_dir, tmpdir): + fresh_store = make_store(fixture_dir, tmpdir) + return fresh_store + + +@pytest.fixture(scope="session") +def store_applied(fixture_dir, tmpdir_factory): + tmpdir = Path(tmpdir_factory.mktemp("tmp")) + store_applied = make_store_applied(fixture_dir, tmpdir) + return store_applied + + +@pytest.fixture(scope="session") +def store_applied_materialized(fixture_dir, tmpdir_factory): + tmpdir = Path(tmpdir_factory.mktemp("tmp")) + store_applied_materialized = make_store_applied(fixture_dir, tmpdir) + store_applied_materialized.store.materialize_incremental(end_date=datetime.now()) + return store_applied_materialized diff --git a/python/xorq/common/utils/tests/feast/test_feast_replication_utils.py b/python/xorq/common/utils/tests/feast/test_feast_replication_utils.py new file mode 100644 index 000000000..3fd9592b8 --- /dev/null +++ b/python/xorq/common/utils/tests/feast/test_feast_replication_utils.py @@ -0,0 +1,134 @@ +from datetime import datetime + +import pandas as pd +import pytest + +import xorq.api as xo + + +@pytest.fixture(scope="session") +def entity_df(): + entity_df = pd.DataFrame.from_dict( + { + # entity's join key -> entity values + "driver_id": [1001, 1002, 1003], + # "event_timestamp" (reserved key) -> timestamps + "event_timestamp": [ + datetime(2021, 4, 12, 10, 59, 42), + datetime(2021, 4, 12, 8, 12, 10), + datetime(2021, 4, 12, 16, 40, 26), + ], + # (optional) label name -> label values. Feast does not process these + "label_driver_reported_satisfaction": [1, 5, 3], + # values we're using for an on-demand transformation + "val_to_add": [1, 2, 3], + "val_to_add_2": [10, 20, 30], + } + ) + return entity_df + + +@pytest.fixture(scope="session") +def historical_features(): + features = ( + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "transformed_conv_rate:conv_rate_plus_val1", + "transformed_conv_rate:conv_rate_plus_val2", + ) + return features + + +@pytest.fixture(scope="session") +def entity_rows(): + entity_rows = [ + # {join_key: entity_value} + { + "driver_id": 1001, + "val_to_add": 1000, + "val_to_add_2": 2000, + }, + { + "driver_id": 1002, + "val_to_add": 1001, + "val_to_add_2": 2002, + }, + ] + return entity_rows + + +def get_online_features(store_applied, source): + if source == "feature_service": + features_to_fetch = store_applied.store.get_feature_service( + "driver_activity_v1" + ) + elif source == "push": + features_to_fetch = store_applied.store.get_feature_service( + "driver_activity_v3" + ) + else: + features_to_fetch = [ + "driver_hourly_stats:acc_rate", + "transformed_conv_rate:conv_rate_plus_val1", + "transformed_conv_rate:conv_rate_plus_val2", + ] + return features_to_fetch + + +# contextlib.chdir doesn't exist in python3.10 + +# def test_unapplied_failures0(fresh_store, entity_df, historical_features): +# entity_expr = xo.pandas.connect({"t": entity_df}).table("t") +# features_expr = fresh_store.get_historical_features(entity_expr, historical_features) +# import pdb; pdb.set_trace() # noqa +# with pytest.raises( +# Exception, match="Feature view driver_hourly_stats does not exist in project" +# ): +# features_expr.execute() +# + + +@pytest.mark.parametrize("source", ("feature_service", "push")) +def test_unapplied_failures1(fresh_store, source): + with pytest.raises(Exception, match="Feature service .* does not exist in project"): + get_online_features(fresh_store, source) + + +@pytest.mark.parametrize("source", ("feature_service", "push")) +def test_unmaterialized_failure(store_applied, entity_rows, source): + features_to_fetch = get_online_features(store_applied, source) + actual = store_applied.get_online_features(features_to_fetch, entity_rows) + assert all(v == [None, None] for k, v in actual.items() if k != "driver_id") + + +def df_copy(df): + return pd.DataFrame(df.values, index=df.index, columns=df.columns) + + +def test_get_historical_features(store_applied, entity_df, historical_features): + entity_expr = xo.pandas.connect({"t": entity_df}).table("t") + actual = store_applied.get_historical_features( + entity_expr, historical_features + ).execute() + expected = store_applied.store.get_historical_features( + entity_df, list(historical_features) + ).to_df() + # FIXME: make reindex_like unnecessary + assert not actual.empty and df_copy(actual.reindex_like(expected)).equals( + df_copy(expected) + ) + + +@pytest.mark.parametrize("source", ("feature_service", "push", None)) +def test_get_online_features(store_applied_materialized, entity_rows, source): + features_to_fetch = get_online_features(store_applied_materialized, source) + actual = store_applied_materialized.get_online_features( + features_to_fetch, entity_rows + ) + expected = store_applied_materialized.store.get_online_features( + features=features_to_fetch, + entity_rows=entity_rows, + ).to_dict() + assert actual == expected + assert not any(v == [None, None] for k, v in actual.items() if k != "driver_id") diff --git a/python/xorq/common/utils/tests/feast/test_feast_utils.py b/python/xorq/common/utils/tests/feast/test_feast_utils.py new file mode 100644 index 000000000..e4d112e96 --- /dev/null +++ b/python/xorq/common/utils/tests/feast/test_feast_utils.py @@ -0,0 +1,129 @@ +from abc import abstractmethod +from typing import ( + Dict, + List, + Optional, +) + +import feast +import pytest +from feast import ( + Field, +) +from feast.data_source import ( + DataSource, +) +from feast.feature_view_projection import FeatureViewProjection + +from xorq.common.utils.feast_utils import ( + from_feast, +) +from xorq.common.utils.import_utils import ( + import_from_gist, +) + + +@abstractmethod +def my_base_feature_view_init( + self, + *, + name: str, + features: Optional[List[Field]] = None, + description: str = "", + tags: Optional[Dict[str, str]] = None, + owner: str = "", + source: Optional[DataSource] = None, +): + """ + Creates a BaseFeatureView object. + + Args: + name: The unique name of the base feature view. + features (optional): The list of features defined as part of this base feature view. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the base feature view, typically the email of the + primary maintainer. + source (optional): The source of data for this group of features. May be a stream source, or a batch source. + If a stream source, the source should contain a batch_source for backfills & batch materialization. + Raises: + ValueError: A field mapping conflicts with an Entity or a Feature. + """ + assert name is not None + self.name = name + self.features = features or [] + self.description = description + self.tags = tags or {} + self.owner = owner + self.created_timestamp = None + self.last_updated_timestamp = None + + if source: + self.source = source + + # above is what is in feast.base_feature_view.BaseFeatureView.__init__ + # below is things we have to modify to ensure replicability + for attr in ("features", "entities", "entity_columns"): + if value := getattr(self, attr, None): + setattr(self, attr, sorted(value)) + self.projection = FeatureViewProjection.from_definition(self) + + +def do_rountdrips(cls, instance, n=1): + for _ in range(n): + instance = cls.from_feast(instance).to_feast() + return instance + + +def assert_roundtrip(instance): + other = from_feast(instance).to_feast() + if other != instance: + diff = diff_dunder_dict(other, instance) + raise ValueError(f"roundtrip failed: {diff}") + + +def diff_dunder_dict(obj0, obj1): + import operator + + import toolz + + is_not_dunder = toolz.complement(operator.methodcaller("startswith", "__")) + dct0, dct1 = ( + toolz.keyfilter(is_not_dunder, getattr(obj, "__dict__")) for obj in (obj0, obj1) + ) + assert type(obj0) is type(obj1) and set(dct0) == set(dct1) + diff = tuple( + (k, (v0, v1)) + for ((k, v0), (_, v1)) in zip(*(sorted(dct.items()) for dct in (dct0, dct1))) + if v0 != v1 + ) + return diff + + +user, gist = "dlovell", "b719dc08a4cffb232e3f92bea3bd75aa" +fer = import_from_gist(user, gist) + + +instances = ( + fer.project, + fer.driver, + # how to materialize path to this working dir? currently just symlinked it + fer.driver_stats_source, + fer.input_request, + fer.driver_stats_fv, + fer.transformed_conv_rate, + fer.transformed_conv_rate_fresh, + fer.driver_activity_v1, +) + + +@pytest.mark.parametrize("instance", (instances)) +# as a hack, we can change into the fer dir? +def test_roundtrip(instance, store_applied, monkeypatch): + # FeastFileSource.path.exists() must be true + monkeypatch.chdir(store_applied.path) + # ordering of features must match instance + monkeypatch.setattr( + feast.feature_view.BaseFeatureView, "__init__", my_base_feature_view_init + ) + assert_roundtrip(instance) diff --git a/python/xorq/tests/fixtures/feature_repo.tgz b/python/xorq/tests/fixtures/feature_repo.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5496cb48b09b0cbc9a8a096107727eade9822572 GIT binary patch literal 30589 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 literal 0 HcmV?d00001