├── .gitattributes ├── .gitignore ├── Dockerfile.workspace ├── LICENSE ├── README.md ├── assets ├── examples │ └── example-instacart │ │ ├── create_features.ipynb │ │ ├── explore_data.ipynb │ │ ├── load_data.ipynb │ │ └── train_model.ipynb └── static │ ├── boson-logo-animated-fast.gif │ ├── boson-logo-animated.gif │ ├── boson-logo-cropped.PNG │ ├── boson-logo-cropped.ico │ ├── boson-logo-cropped.svg │ ├── boson-logo.png │ ├── boson-logo.psd │ ├── boson-logo.svg │ ├── classification-matrix.png │ ├── delta-explorer-example.png │ ├── delta-explorer.png │ ├── delta-exporer.png │ ├── experiment-tracker-button.png │ ├── experiment-tracker-example.png │ ├── experiment-tracker.png │ ├── explore-data.png │ ├── file-browser.png │ ├── inline-table.png │ ├── load-data.png │ └── main-screenshot.png ├── create-workspace.sh ├── delta-explorer ├── Dockerfile ├── app.py ├── poetry.lock ├── pyproject.toml └── scan_deltalake.py ├── docker-compose.base.yml ├── docs ├── builtins.md ├── concepts.md └── example-instacart.md ├── kernel ├── Dockerfile ├── README.md ├── jupyter-lab-ext │ ├── delta-explorer │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── webpack.config.js │ ├── experiment-tracker │ │ ├── package.json │ │ ├── src │ │ │ └── index.ts │ │ ├── tsconfig.json │ │ └── webpack.config.js │ ├── favicon.ico │ └── theme │ │ ├── package.json │ │ ├── src │ │ ├── custom.d.ts │ │ └── index.ts │ │ ├── style │ │ ├── base.css │ │ ├── boson-logo-animated-fast.gif │ │ └── index.js │ │ ├── tsconfig.json │ │ └── webpack.config.js ├── jupyter_notebook_config.py ├── kernel │ ├── __init__.py │ └── globals.py ├── mount-cloud-storage.sh └── pyproject.toml ├── nginx └── default.conf ├── storage └── config.json ├── workspace-entrypoint.sh └── workspaces └── example-instacart ├── .env ├── docker-compose.override.yml └── pyproject.toml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce LF endings for common text-based file types 2 | *.sh text eol=lf 3 | *.py text eol=lf 4 | *.yml text eol=lf 5 | *.yaml text eol=lf 6 | *.md text eol=lf 7 | *.json text eol=lf 8 | *.txt text eol=lf 9 | *.toml text eol=lf 10 | boson text eol=lf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/.gitignore -------------------------------------------------------------------------------- /Dockerfile.workspace: -------------------------------------------------------------------------------- 1 | FROM kernel:latest AS base 2 | 3 | FROM base 4 | 5 | COPY ./ ./ 6 | 7 | # Configure Jupyter 8 | ARG WORKSPACE_NAME 9 | RUN echo "{\"appName\": \"Boson (${WORKSPACE_NAME})\"}" > /usr/local/share/jupyter/lab/settings/page_config.json 10 | 11 | COPY --from=base /root/.jupyter/jupyter_notebook_config.py /root/.jupyter/jupyter_notebook_config.py 12 | 13 | RUN jupyter lab clean 14 | RUN jupyter lab build --name "Boson (${WORKSPACE_NAME})" 15 | 16 | # Install workspace dependencies 17 | RUN poetry config virtualenvs.create false 18 | RUN poetry install --no-root 19 | RUN poetry run python -m ipykernel install --user 20 | 21 | # Mount storage 22 | COPY --from=base /root/.mount-cloud-storage.sh /root/.mount-cloud-storage.sh 23 | RUN chmod +x /bin/fusermount 24 | 25 | CMD ["bash"] 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Business Source License 1.1 2 | 3 | Parameters 4 | 5 | Licensor: MYNT LABS PTY. LTD. 6 | Licensed Work: Boson 7 | The Licensed Work is (c) 2025 MYNT LABS PTY. LTD. 8 | Additional Use Grant: You may make production use of the Licensed Work, 9 | provided that You may NOT use the Licensed Work for a 10 | Machine Learning Research Platform unless You have 11 | obtained a separate commercial license that expressly 12 | permits such use. 13 | 14 | A "Machine Learning Research Platform" is a COMMERCIAL 15 | offering that allows third parties (other than Your 16 | direct employees and contractors) to access the 17 | functionality of the Licensed Work by building, 18 | training, experimenting-with or managing 19 | machine-learning or data-science workloads where the 20 | Licensed Work is either hosted or embedded. 21 | 22 | Change Date: 2029-09-17 23 | 24 | Change License: Apache License, Version 2.0 25 | 26 | Notice 27 | 28 | The Business Source License (this document, or the "License") is not an Open 29 | Source license. However, the Licensed Work will eventually be made available 30 | under an Open Source License, as stated in this License. 31 | 32 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. 33 | "Business Source License" is a trademark of MariaDB Corporation Ab. 34 | 35 | ----------------------------------------------------------------------------- 36 | 37 | Business Source License 1.1 38 | 39 | Terms 40 | 41 | The Licensor hereby grants you the right to copy, modify, create derivative 42 | works, redistribute, and make non-production use of the Licensed Work. The 43 | Licensor may make an Additional Use Grant, above, permitting limited 44 | production use. 45 | 46 | Effective on the Change Date, or the fourth anniversary of the first publicly 47 | available distribution of a specific version of the Licensed Work under this 48 | License, whichever comes first, the Licensor hereby grants you rights under 49 | the terms of the Change License, and the rights granted in the paragraph 50 | above terminate. 51 | 52 | If your use of the Licensed Work does not comply with the requirements 53 | currently in effect as described in this License, you must purchase a 54 | commercial license from the Licensor, its affiliated entities, or authorized 55 | resellers, or you must refrain from using the Licensed Work. 56 | 57 | All copies of the original and modified Licensed Work, and derivative works 58 | of the Licensed Work, are subject to this License. This License applies 59 | separately for each version of the Licensed Work and the Change Date may vary 60 | for each version of the Licensed Work released by Licensor. 61 | 62 | You must conspicuously display this License on each original or modified copy 63 | of the Licensed Work. If you receive the Licensed Work in original or 64 | modified form from a third party, the terms and conditions set forth in this 65 | License apply to your use of that work. 66 | 67 | Any use of the Licensed Work in violation of this License will automatically 68 | terminate your rights under this License for the current and all other 69 | versions of the Licensed Work. 70 | 71 | This License does not grant you any right in any trademark or logo of 72 | Licensor or its affiliates (provided that you may use a trademark or logo of 73 | Licensor as expressly required by this License). 74 | 75 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON 76 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, 77 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF 78 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND 79 | TITLE. 80 | 81 | MariaDB hereby grants you permission to use this License's text to license 82 | your works, and to refer to it using the trademark "Business Source License", 83 | as long as you comply with the Covenants of Licensor below. 84 | 85 | Covenants of Licensor 86 | 87 | In consideration of the right to use this License's text and the "Business 88 | Source License" name and trademark, Licensor covenants to MariaDB, and to all 89 | other recipients of the licensed work to be provided by Licensor: 90 | 91 | 1. To specify as the Change License the GPL Version 2.0 or any later version, 92 | or a license that is compatible with GPL Version 2.0 or a later version, 93 | where "compatible" means that software provided under the Change License can 94 | be included in a program with software provided under GPL Version 2.0 or a 95 | later version. Licensor may specify additional Change Licenses without 96 | limitation. 97 | 98 | 2. To either: (a) specify an additional grant of rights to use that does not 99 | impose any additional restriction on the right granted in this License, as 100 | the Additional Use Grant; or (b) insert the text "None". 101 | 102 | 3. To specify a Change Date. 103 | 104 | 4. Not to modify this License in any other way. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boson 2 | 3 | **Boson** is a lightweight, fully containerized, and feature-rich machine learning research platform. It centralizes essential tools to help teams keep projects lean, organized, and reproducible—while reducing overhead and boosting productivity. Think Databricks/Sagemaker but local and free. 4 | 5 | Boson enables engineers and researchers to iterate faster without getting bogged down by infrastructure or tooling complexity. 6 | 7 | ![Boson Interface](assets/static/main-screenshot.png) 8 | 9 | --- 10 | 11 | ## Contents 12 | - [Key Features](#-key-features) 13 | - [Quickstart](#-quickstart) 14 | - [Quick Look](#-quick-look) 15 | - [Creating a Workspace](#-creating-a-workspace) 16 | - Documentation 17 | - [Example - Instacart](docs/example-instacart.md) 18 | - [Concepts](docs/concepts.md) 19 | - [Builtins](docs/builtins.md) 20 | - [Contributing](#-contributing) 21 | 22 | ## 🔑 Key Features 23 | 24 | - **Out-of-the-Box Data Lake Integration** 25 | Boson uses [Delta Lake](https://github.com/delta-io/delta) to store datasets and features, making it easy to save and load dataframes as versioned tables. A built-in Delta Explorer lets you visually inspect your lake in real time. 26 | 27 | - **Lazy Data Processing with Polars** 28 | Boson supports efficient, memory-conscious data workflows using [Polars](https://github.com/pola-rs/polars). This makes large, expensive transformations performant and scalable—even on local hardware. 29 | 30 | - **Integrated Experiment Tracking** 31 | Powered by [Aim](https://github.com/aimhubio/aim) Boson offers a seamless tracking experience—log metrics, compare experiments, and visualize performance over time with zero setup. 32 | 33 | - **Cloud-Like Notebook Development** 34 | All data, notebooks, artifacts, and metrics are stored in internal cloud storage. This keeps your local environment clean and every workspace fully self-contained. 35 | 36 | - **Composable, Declarative Infrastructure** 37 | Built on layered Docker Compose files, Boson enables isolated, customizable workspaces per project—without sacrificing reproducibility or maintainability. 38 | 39 | --- 40 | 41 | ## 🚀 Quickstart 42 | 43 | **Boson currently only supports AMD64 (i.e. no Mac). ARM support is a high priority.** 44 | 45 | Boson requires that `docker` be installed. 46 | 47 | After cloning, navigate to the project root and run: 48 | 49 | ```bash 50 | docker compose -f docker-compose.base.yml -f workspaces/example-instacart/docker-compose.override.yml --env-file workspaces/example-instacart/.env up 51 | ``` 52 | 53 | This will spin up the `example-instacart` workspace. You can open this workspace in Boson by visitng `http://localhost:8889` in your browser. 54 | 55 | Follow the [walkthrough](/docs/example-instacart.md) of this example. 56 | 57 | ## 🔎 Quick Look 58 | 59 | Write Polars df to Delta Table: 60 | ```python 61 | write_delta(my_df, "my_table_name") 62 | ``` 63 | 64 | Read Delta Table to Polars df: 65 | ```python 66 | df_materialised = read_delta("my_table_name") 67 | df_lazy = scan_delta("my_table_name") 68 | ``` 69 | 70 | Display inline Polars df: 71 | ```python 72 | display(my_df) 73 | ``` 74 | ![inline-table](assets/static/inline-table.png) 75 | 76 | Create Aim experiment for tracking: 77 | ```python 78 | run = new_run(experiment="my-experiment-name") 79 | ``` 80 | 81 | View Delta Tables: 82 | 83 | ![delta-explorer](assets/static/delta-exporer.png) 84 | 85 | ## ⚙️ Creating a Workspace 86 | Boson is deployed by instantiating a *workspace*. A *workspace* is an instance of the **Boson Kernel** but with its own isolated dependencies and configuration. 87 | 88 | The below instructions will create a new custom workspace with isolated storage. 89 | 90 | Create a workspace by running: 91 | 92 | ```bash 93 | ./create-workspace.sh 94 | ``` 95 | 96 | Navigate to the workspace directory with: 97 | 98 | ```bash 99 | cd workspaces/ 100 | ``` 101 | 102 | Change Python dependencies via [Poetry](https://python-poetry.org/), for example: 103 | 104 | ```bash 105 | poetry remove xgboost 106 | poetry add plotly 107 | ``` 108 | 109 | If you do not have Poetry installed, you can follow the above link to set it up or manually update the `[tool.poetry.dependencies]` section of the `pyproject.toml`. 110 | 111 | Spin up the Boson workspace with: 112 | 113 | ```bash 114 | docker compose -f docker-compose.base.yml -f workspaces//docker-compose.override.yml --env-file workspaces//.env up 115 | ``` 116 | 117 | ## 🤝 Contributing 118 | 119 | We would be stoked for you to get involved with Boson development! If you'd like to get more involved, please contact Harry at harry@myntlabs.io. 120 | 121 | - 💬 [Start a discussion](https://github.com/bosonstack/boson/discussions) 122 | - 🛠️ [Fix a bug](https://github.com/bosonstack/boson/issues/new) 123 | - 🧠 [Request a feature](https://github.com/bosonstack/boson/issues/new) 124 | 125 | ### Future tickets 126 | 127 | - ARM support 128 | - Improve linting - especially of custom builtins 129 | - Introduce table schemas/scoping 130 | - Nice CLI wrapper 131 | - Various UI improvements -------------------------------------------------------------------------------- /assets/examples/example-instacart/create_features.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "07d2e8e8-9165-4c8e-8238-3250b337c166", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import polars as pl" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "id": "228e3ab0-7adb-471d-9689-2021f40c2d6c", 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# Lazy load all tables\n", 21 | "aisles = scan_delta(\"aisles\")\n", 22 | "departments = scan_delta(\"departments\")\n", 23 | "prior = scan_delta(\"order_products__prior\")\n", 24 | "train = scan_delta(\"order_products__train\")\n", 25 | "orders = scan_delta(\"orders\")\n", 26 | "products = scan_delta(\"products\")" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "id": "f04f7e42-5b6b-4191-9c9d-03189b101248", 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "# Join prior orders with order metadata\n", 37 | "prior_full = (\n", 38 | " prior\n", 39 | " .join(orders, on=\"order_id\", how=\"inner\")\n", 40 | ")" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "id": "e1aa2bbe-6b38-46b5-a894-31d14ff7d30d", 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "# Aggregate user-product interaction history\n", 51 | "user_product_features = (\n", 52 | " prior_full\n", 53 | " .group_by([\"user_id\", \"product_id\"])\n", 54 | " .agg([\n", 55 | " pl.len().alias(\"times_ordered\"),\n", 56 | " pl.mean(\"add_to_cart_order\").alias(\"avg_cart_position\"),\n", 57 | " pl.max(\"order_number\").alias(\"last_order_number\"),\n", 58 | " pl.mean(\"reordered\").alias(\"reorder_rate\"),\n", 59 | " ])\n", 60 | ")" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "id": "bcd4d2d5-49b8-4fe5-837b-2372de636fc5", 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "# Add product-level info\n", 71 | "product_features = (\n", 72 | " products\n", 73 | " .join(departments.lazy(), on=\"department_id\", how=\"left\")\n", 74 | " .join(aisles.lazy(), on=\"aisle_id\", how=\"left\")\n", 75 | ")\n", 76 | "\n", 77 | "user_product_with_meta = (\n", 78 | " user_product_features\n", 79 | " .join(product_features.select([\"product_id\", \"product_name\", \"department\", \"aisle\"]), on=\"product_id\", how=\"left\")\n", 80 | ")" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "id": "57ef60f1-2a4c-4dd2-bed2-d381ccf63b60", 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "# Join with training set (labels)\n", 91 | "\n", 92 | "train_orders = (\n", 93 | " orders\n", 94 | " .filter(pl.col(\"eval_set\") == \"train\")\n", 95 | " .select([\"order_id\", \"user_id\"])\n", 96 | ")\n", 97 | "\n", 98 | "train_labels = (\n", 99 | " train_orders\n", 100 | " .join(train, on=\"order_id\", how=\"inner\")\n", 101 | " .select([\"user_id\", \"product_id\", \"reordered\"])\n", 102 | ")" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "id": "21701f65-0a00-4fb5-b0d4-507c0e586cb3", 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "# Compute final dataset\n", 113 | "\n", 114 | "final_features_df = (\n", 115 | " user_product_with_meta\n", 116 | " .join(train_labels, on=[\"user_id\", \"product_id\"], how=\"left\")\n", 117 | " .with_columns(pl.col(\"reordered\").fill_null(0))\n", 118 | " .collect()\n", 119 | ")" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "id": "22f5a8db-7cb0-4506-9f4f-892cf664f684", 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "# Write final dataset to delta table\n", 130 | "\n", 131 | "write_delta(final_features_df, \"final_features\", mode=\"overwrite\")" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "id": "b456c063-7729-48c3-a6ac-52c98506fe46", 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [] 141 | } 142 | ], 143 | "metadata": { 144 | "kernelspec": { 145 | "display_name": "Python 3 (ipykernel)", 146 | "language": "python", 147 | "name": "python3" 148 | }, 149 | "language_info": { 150 | "codemirror_mode": { 151 | "name": "ipython", 152 | "version": 3 153 | }, 154 | "file_extension": ".py", 155 | "mimetype": "text/x-python", 156 | "name": "python", 157 | "nbconvert_exporter": "python", 158 | "pygments_lexer": "ipython3", 159 | "version": "3.12.10" 160 | } 161 | }, 162 | "nbformat": 4, 163 | "nbformat_minor": 5 164 | } 165 | -------------------------------------------------------------------------------- /assets/examples/example-instacart/explore_data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "d3589711-d1d6-4a37-bd21-97c588b27dd0", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import seaborn as sns\n", 11 | "import matplotlib.pyplot as plt\n", 12 | "import polars as pl" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": null, 18 | "id": "ff7fb27f-5e04-46d8-8061-6a7a4f7dc5b5", 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "# Lazy load table\n", 23 | "order_products_prior = scan_delta(\"order_products__prior\")\n", 24 | "products = scan_delta(\"products\")" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "id": "c33c83be-7d40-449f-a81b-0a60674f52c2", 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "top_products = (\n", 35 | " order_products_prior\n", 36 | " .group_by(\"product_id\")\n", 37 | " .agg(pl.len().alias(\"order_count\"))\n", 38 | " .sort(\"order_count\", descending=True)\n", 39 | " .limit(10)\n", 40 | " .join(products.select([\"product_id\", \"product_name\"]), on=\"product_id\", how=\"left\")\n", 41 | ")\n", 42 | "\n", 43 | "sns.set(style=\"whitegrid\")\n", 44 | "plt.figure(figsize=(10, 6))\n", 45 | "sns.barplot(data=top_products.collect(), x=\"order_count\", y=\"product_name\")\n", 46 | "plt.title(\"Top 10 Most Frequently Ordered Products\", fontsize=14)\n", 47 | "plt.xlabel(\"Order Count\")\n", 48 | "plt.ylabel(\"Product Name\")\n", 49 | "plt.tight_layout()\n", 50 | "plt.show()" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "id": "153400db-1e0f-4b9c-a78a-96c096eebdda", 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "display(top_products)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "id": "cba828f3-9346-421f-a658-0f5f5c729fd9", 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [] 70 | } 71 | ], 72 | "metadata": { 73 | "kernelspec": { 74 | "display_name": "Python 3 (ipykernel)", 75 | "language": "python", 76 | "name": "python3" 77 | }, 78 | "language_info": { 79 | "codemirror_mode": { 80 | "name": "ipython", 81 | "version": 3 82 | }, 83 | "file_extension": ".py", 84 | "mimetype": "text/x-python", 85 | "name": "python", 86 | "nbconvert_exporter": "python", 87 | "pygments_lexer": "ipython3", 88 | "version": "3.12.10" 89 | } 90 | }, 91 | "nbformat": 4, 92 | "nbformat_minor": 5 93 | } 94 | -------------------------------------------------------------------------------- /assets/examples/example-instacart/load_data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "f7ba157d-31e4-4cd6-91d7-975a76d05b9c", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "%pip install kagglehub" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "id": "c08f1d52-a598-4f85-8ae3-b354b53adaef", 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "import kagglehub\n", 21 | "import shutil\n", 22 | "import os\n", 23 | "\n", 24 | "# Download latest version\n", 25 | "download_cache_path = kagglehub.dataset_download(\n", 26 | " \"yasserh/instacart-online-grocery-basket-analysis-dataset\"\n", 27 | ")\n", 28 | "\n", 29 | "target_path = \"instacart-data\"\n", 30 | "shutil.copytree(download_cache_path, target_path, dirs_exist_ok=True)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "id": "02c950fd-5713-4c6c-9304-662ffd27cbd8", 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "import os\n", 41 | "import polars as pl\n", 42 | "\n", 43 | "folder_path = \"instacart-data\"\n", 44 | "\n", 45 | "# Load and save csvs as delta tables\n", 46 | "for filename in os.listdir(folder_path):\n", 47 | " if filename.endswith(\".csv\"):\n", 48 | " file_path = os.path.join(folder_path, filename)\n", 49 | " df = pl.read_csv(file_path)\n", 50 | " \n", 51 | " table_name = filename[:-4]\n", 52 | " write_delta(df, table_name, mode=\"overwrite\")" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "id": "dd95e77f-61a0-4fd6-8a5d-63c2fc189a59", 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "display(read_delta(\"orders\"))" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "id": "b676a8d9-b3ae-47ca-9521-d9d09b35aeab", 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [] 72 | } 73 | ], 74 | "metadata": { 75 | "kernelspec": { 76 | "display_name": "Python 3 (ipykernel)", 77 | "language": "python", 78 | "name": "python3" 79 | }, 80 | "language_info": { 81 | "codemirror_mode": { 82 | "name": "ipython", 83 | "version": 3 84 | }, 85 | "file_extension": ".py", 86 | "mimetype": "text/x-python", 87 | "name": "python", 88 | "nbconvert_exporter": "python", 89 | "pygments_lexer": "ipython3", 90 | "version": "3.12.10" 91 | } 92 | }, 93 | "nbformat": 4, 94 | "nbformat_minor": 5 95 | } 96 | -------------------------------------------------------------------------------- /assets/examples/example-instacart/train_model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "cb034548-1520-4a03-bd99-9a4d05f47431", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import polars as pl\n", 11 | "import xgboost as xgb\n", 12 | "from sklearn.model_selection import train_test_split\n", 13 | "from sklearn.preprocessing import LabelEncoder\n", 14 | "from sklearn.metrics import classification_report, accuracy_score" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "id": "4daf9d36-ba31-4cb1-a14b-d6c8013be765", 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "# Load dataset\n", 25 | "df = read_delta(\"final_features\")\n", 26 | "df = df.drop([\"product_name\"])" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "id": "f6ac31f5-1b6e-456d-a463-465d0a9d93dc", 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "# Encode categorical columns\n", 37 | "for col in [\"department\", \"aisle\"]:\n", 38 | " encoder = LabelEncoder()\n", 39 | " encoded = encoder.fit_transform(df[col].to_list())\n", 40 | " df = df.with_columns(pl.Series(name=col, values=encoded))" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "id": "a7963060-aaf8-47db-8fea-5b287e463218", 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "# Define hypothesis variables\n", 51 | "X = df.drop([\"user_id\", \"product_id\", \"reordered\"])\n", 52 | "y = df[\"reordered\"]" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "id": "6f9657bd-235a-408c-830f-1c90cdd2dc2b", 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "# Create dataset splits\n", 63 | "X_train, X_test, y_train, y_test = train_test_split(\n", 64 | " X, y,\n", 65 | " test_size=0.2,\n", 66 | " random_state=42,\n", 67 | " stratify=y\n", 68 | ")" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "id": "e341fa04-1e3e-4948-839a-eec99d939d73", 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "# Calculate class imbalance\n", 79 | "neg, pos = (df[\"reordered\"] == 0).sum(), (df[\"reordered\"] == 1).sum()\n", 80 | "ratio = neg / pos" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "id": "62440b6f-f87d-4739-8263-8e3a7b835d6e", 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "# Initialise Aim run\n", 91 | "run = new_run(experiment=\"xgb-reorder-predictor\")\n", 92 | "run[\"hparams\"] = {\n", 93 | " \"scale_pos_weight\": ratio,\n", 94 | " \"n_estimators\": 100,\n", 95 | " \"learning_rate\": 0.1,\n", 96 | " \"max_depth\": 6,\n", 97 | "}" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "id": "72ae7787-2034-48ee-81a1-81329db3b0d0", 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "# Define model\n", 108 | "model = xgb.XGBClassifier(\n", 109 | " objective=\"binary:logistic\",\n", 110 | " scale_pos_weight=ratio,\n", 111 | " eval_metric=\"logloss\",\n", 112 | " use_label_encoder=False,\n", 113 | " n_estimators=100,\n", 114 | " learning_rate=0.1,\n", 115 | " max_depth=6,\n", 116 | " random_state=42\n", 117 | ")" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "id": "6eff3ac7-1a2a-4e59-95d7-1a1aadc01b4a", 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "# Train model\n", 128 | "eval_set = [(\"train\", X_train, y_train), (\"val\", X_test, y_test)]\n", 129 | "model.fit(\n", 130 | " X_train,\n", 131 | " y_train,\n", 132 | " eval_set=[(X_train, y_train), (X_test, y_test)],\n", 133 | " verbose=False\n", 134 | ")" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "id": "ffa06868-1ece-490c-b4d8-dc5b0e4da0a7", 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "# Retroactively log metrics to Aim\n", 145 | "results = model.evals_result()\n", 146 | "train_losses = results[\"validation_0\"][\"logloss\"]\n", 147 | "val_losses = results[\"validation_1\"][\"logloss\"]\n", 148 | "\n", 149 | "for i, (train_loss, val_loss) in enumerate(zip(train_losses, val_losses)):\n", 150 | " run.track(train_loss, name=\"train_loss\", step=i)\n", 151 | " run.track(val_loss, name=\"val_loss\", step=i)" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "id": "1c7de14e-9114-4649-8725-bf9484c9c7ee", 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "# Final evaluation\n", 162 | "y_pred = model.predict(X_test)\n", 163 | "acc = accuracy_score(y_test, y_pred)\n", 164 | "\n", 165 | "print(\"Accuracy:\", acc)\n", 166 | "print(classification_report(y_test, y_pred))\n", 167 | "\n", 168 | "run.track(acc, name=\"final_accuracy\")" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "id": "7d1c1ccb-ac91-4eca-aa2e-f7f074c57c1a", 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [] 178 | } 179 | ], 180 | "metadata": { 181 | "kernelspec": { 182 | "display_name": "Python 3 (ipykernel)", 183 | "language": "python", 184 | "name": "python3" 185 | }, 186 | "language_info": { 187 | "codemirror_mode": { 188 | "name": "ipython", 189 | "version": 3 190 | }, 191 | "file_extension": ".py", 192 | "mimetype": "text/x-python", 193 | "name": "python", 194 | "nbconvert_exporter": "python", 195 | "pygments_lexer": "ipython3", 196 | "version": "3.12.10" 197 | } 198 | }, 199 | "nbformat": 4, 200 | "nbformat_minor": 5 201 | } 202 | -------------------------------------------------------------------------------- /assets/static/boson-logo-animated-fast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo-animated-fast.gif -------------------------------------------------------------------------------- /assets/static/boson-logo-animated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo-animated.gif -------------------------------------------------------------------------------- /assets/static/boson-logo-cropped.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo-cropped.PNG -------------------------------------------------------------------------------- /assets/static/boson-logo-cropped.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo-cropped.ico -------------------------------------------------------------------------------- /assets/static/boson-logo-cropped.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/static/boson-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo.png -------------------------------------------------------------------------------- /assets/static/boson-logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/boson-logo.psd -------------------------------------------------------------------------------- /assets/static/boson-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/static/classification-matrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/classification-matrix.png -------------------------------------------------------------------------------- /assets/static/delta-explorer-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/delta-explorer-example.png -------------------------------------------------------------------------------- /assets/static/delta-explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/delta-explorer.png -------------------------------------------------------------------------------- /assets/static/delta-exporer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/delta-exporer.png -------------------------------------------------------------------------------- /assets/static/experiment-tracker-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/experiment-tracker-button.png -------------------------------------------------------------------------------- /assets/static/experiment-tracker-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/experiment-tracker-example.png -------------------------------------------------------------------------------- /assets/static/experiment-tracker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/experiment-tracker.png -------------------------------------------------------------------------------- /assets/static/explore-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/explore-data.png -------------------------------------------------------------------------------- /assets/static/file-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/file-browser.png -------------------------------------------------------------------------------- /assets/static/inline-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/inline-table.png -------------------------------------------------------------------------------- /assets/static/load-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/load-data.png -------------------------------------------------------------------------------- /assets/static/main-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/assets/static/main-screenshot.png -------------------------------------------------------------------------------- /create-workspace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Validate arguments 4 | if [ $# -ne 2 ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | WORKSPACE_NAME="$1" 10 | PORT="$2" 11 | 12 | # Check for invalid characters in the workspace name 13 | if [[ "$WORKSPACE_NAME" == *"-"* || "$WORKSPACE_NAME" == *"_"* ]]; then 14 | echo "Error: Workspace name cannot contain hyphens (-) or underscores (_)." 15 | exit 1 16 | fi 17 | 18 | SRC_WORKSPACE="example-instacart" 19 | SRC_DIR="workspaces/$SRC_WORKSPACE" 20 | DEST_DIR="workspaces/$WORKSPACE_NAME" 21 | 22 | # Step 1: Copy workspace 23 | if [ -d "$DEST_DIR" ]; then 24 | echo "Error: Destination workspace '$DEST_DIR' already exists." 25 | exit 1 26 | fi 27 | 28 | cp -r "$SRC_DIR" "$DEST_DIR" 29 | 30 | # Step 2: Replace in docker-compose.override.yml 31 | DOCKER_COMPOSE="$DEST_DIR/docker-compose.override.yml" 32 | sed -i "s/example-instacart/$WORKSPACE_NAME/g" "$DOCKER_COMPOSE" 33 | sed -i "s/example_instacart/${WORKSPACE_NAME}/g" "$DOCKER_COMPOSE" 34 | sed -i "s/Example - Instacart/$WORKSPACE_NAME/g" "$DOCKER_COMPOSE" 35 | 36 | # Step 3: Replace in pyproject.toml 37 | PYPROJECT="$DEST_DIR/pyproject.toml" 38 | sed -i "s/example-instacart/$WORKSPACE_NAME/g" "$PYPROJECT" 39 | sed -i "s/Example - Instacart/$WORKSPACE_NAME/g" "$PYPROJECT" 40 | 41 | # Step 4: Set port in .env 42 | ENV_FILE="$DEST_DIR/.env" 43 | if grep -q "^PORT=" "$ENV_FILE"; then 44 | sed -i "s/^PORT=.*/PORT=$PORT/" "$ENV_FILE" 45 | else 46 | echo "PORT=$PORT" >> "$ENV_FILE" 47 | fi 48 | 49 | echo "Workspace '$WORKSPACE_NAME' created with port $PORT." 50 | -------------------------------------------------------------------------------- /delta-explorer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim 2 | 3 | # Set workdir 4 | WORKDIR /app 5 | 6 | # Install Poetry 7 | RUN pip install --no-cache-dir poetry 8 | 9 | # Copy project files 10 | COPY . . 11 | 12 | # Install dependencies 13 | RUN poetry config virtualenvs.create false 14 | RUN poetry install --no-root -------------------------------------------------------------------------------- /delta-explorer/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import streamlit as st 3 | from dotenv import load_dotenv 4 | from datetime import datetime 5 | from streamlit_autorefresh import st_autorefresh 6 | from scan_deltalake import scan_deltalake, DeltaLake 7 | 8 | st.set_page_config("Delta Table Browser", layout="wide") 9 | 10 | # 🔧 Custom styling 11 | st.markdown(""" 12 | 35 | """, unsafe_allow_html=True) 36 | 37 | st_autorefresh(interval=5000, key="autorefresh") 38 | 39 | with st.container(): 40 | st.markdown("### Delta Explorer") 41 | if st.button("🔄 Refresh"): 42 | st.session_state["_refresh"] = not st.session_state.get("_refresh", False) 43 | 44 | search = st.text_input( 45 | label="Search", 46 | placeholder="🔍 Search tables or columns...", 47 | label_visibility="collapsed" 48 | ).strip().lower() 49 | 50 | lake: DeltaLake = scan_deltalake() 51 | 52 | def matches(table): 53 | if search in table.name.lower(): 54 | return True 55 | for col in table.schema: 56 | if search in col.lower(): 57 | return True 58 | return False 59 | 60 | filtered_tables = [t for t in lake.delta_tables if matches(t)] 61 | 62 | def format_ts(ts) -> str: 63 | if ts is None: 64 | return "-" 65 | if isinstance(ts, int): 66 | try: 67 | ts = datetime.fromtimestamp(ts / 1000) 68 | except Exception: 69 | return str(ts) 70 | return ts.astimezone().strftime("%Y-%m-%d %H:%M:%S") 71 | 72 | if not filtered_tables: 73 | st.info("No tables match your search.") 74 | else: 75 | st.success(f"Found `{len(filtered_tables)}` matching Delta table(s):") 76 | 77 | for table in filtered_tables: 78 | with st.expander(f"📊 **{table.name}**", expanded=False): 79 | st.code(table.path) 80 | 81 | # 🧾 Metadata (clean vertical display) 82 | st.markdown(f""" 83 | **Latest Version:** {table.latest_version} 84 | **Created:** {format_ts(table.created_time)} 85 | **Last Updated:** {format_ts(table.last_updated_time)} 86 | """) 87 | 88 | # 📐 Schema Table 89 | st.dataframe( 90 | [{"Column": col, "Type": typ} for col, typ in table.schema.items()], 91 | hide_index=True, 92 | use_container_width=True, 93 | ) 94 | -------------------------------------------------------------------------------- /delta-explorer/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "altair" 5 | version = "5.5.0" 6 | description = "Vega-Altair: A declarative statistical visualization library for Python." 7 | optional = false 8 | python-versions = ">=3.9" 9 | groups = ["main"] 10 | files = [ 11 | {file = "altair-5.5.0-py3-none-any.whl", hash = "sha256:91a310b926508d560fe0148d02a194f38b824122641ef528113d029fcd129f8c"}, 12 | {file = "altair-5.5.0.tar.gz", hash = "sha256:d960ebe6178c56de3855a68c47b516be38640b73fb3b5111c2a9ca90546dd73d"}, 13 | ] 14 | 15 | [package.dependencies] 16 | jinja2 = "*" 17 | jsonschema = ">=3.0" 18 | narwhals = ">=1.14.2" 19 | packaging = "*" 20 | typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.14\""} 21 | 22 | [package.extras] 23 | all = ["altair-tiles (>=0.3.0)", "anywidget (>=0.9.0)", "numpy", "pandas (>=1.1.3)", "pyarrow (>=11)", "vega-datasets (>=0.9.0)", "vegafusion[embed] (>=1.6.6)", "vl-convert-python (>=1.7.0)"] 24 | dev = ["duckdb (>=1.0)", "geopandas", "hatch (>=1.13.0)", "ipython[kernel]", "mistune", "mypy", "pandas (>=1.1.3)", "pandas-stubs", "polars (>=0.20.3)", "pyarrow-stubs", "pytest", "pytest-cov", "pytest-xdist[psutil] (>=3.5,<4.0)", "ruff (>=0.6.0)", "types-jsonschema", "types-setuptools"] 25 | doc = ["docutils", "jinja2", "myst-parser", "numpydoc", "pillow (>=9,<10)", "pydata-sphinx-theme (>=0.14.1)", "scipy", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinxext-altair"] 26 | save = ["vl-convert-python (>=1.7.0)"] 27 | 28 | [[package]] 29 | name = "attrs" 30 | version = "25.3.0" 31 | description = "Classes Without Boilerplate" 32 | optional = false 33 | python-versions = ">=3.8" 34 | groups = ["main"] 35 | files = [ 36 | {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, 37 | {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, 38 | ] 39 | 40 | [package.extras] 41 | benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] 42 | cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] 43 | dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] 44 | docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] 45 | tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] 46 | tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] 47 | 48 | [[package]] 49 | name = "blinker" 50 | version = "1.9.0" 51 | description = "Fast, simple object-to-object and broadcast signaling" 52 | optional = false 53 | python-versions = ">=3.9" 54 | groups = ["main"] 55 | files = [ 56 | {file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"}, 57 | {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, 58 | ] 59 | 60 | [[package]] 61 | name = "boto3" 62 | version = "1.37.37" 63 | description = "The AWS SDK for Python" 64 | optional = false 65 | python-versions = ">=3.8" 66 | groups = ["main"] 67 | files = [ 68 | {file = "boto3-1.37.37-py3-none-any.whl", hash = "sha256:d125cb11e22817f7a2581bade4bf7b75247b401888890239ceb5d3e902ccaf38"}, 69 | {file = "boto3-1.37.37.tar.gz", hash = "sha256:752d31105a45e3e01c8c68471db14ae439990b75a35e72b591ca528e2575b28f"}, 70 | ] 71 | 72 | [package.dependencies] 73 | botocore = ">=1.37.37,<1.38.0" 74 | jmespath = ">=0.7.1,<2.0.0" 75 | s3transfer = ">=0.11.0,<0.12.0" 76 | 77 | [package.extras] 78 | crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] 79 | 80 | [[package]] 81 | name = "botocore" 82 | version = "1.37.37" 83 | description = "Low-level, data-driven core of boto 3." 84 | optional = false 85 | python-versions = ">=3.8" 86 | groups = ["main"] 87 | files = [ 88 | {file = "botocore-1.37.37-py3-none-any.whl", hash = "sha256:eb730ff978f47c02f0c8ed07bccdc0db6d8fa098ed32ac31bee1da0e9be480d1"}, 89 | {file = "botocore-1.37.37.tar.gz", hash = "sha256:3eadde6fed95c4cb469cc39d1c3558528b7fa76d23e7e16d4bddc77250431a64"}, 90 | ] 91 | 92 | [package.dependencies] 93 | jmespath = ">=0.7.1,<2.0.0" 94 | python-dateutil = ">=2.1,<3.0.0" 95 | urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} 96 | 97 | [package.extras] 98 | crt = ["awscrt (==0.23.8)"] 99 | 100 | [[package]] 101 | name = "cachetools" 102 | version = "5.5.2" 103 | description = "Extensible memoizing collections and decorators" 104 | optional = false 105 | python-versions = ">=3.7" 106 | groups = ["main"] 107 | files = [ 108 | {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, 109 | {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, 110 | ] 111 | 112 | [[package]] 113 | name = "certifi" 114 | version = "2025.1.31" 115 | description = "Python package for providing Mozilla's CA Bundle." 116 | optional = false 117 | python-versions = ">=3.6" 118 | groups = ["main"] 119 | files = [ 120 | {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, 121 | {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, 122 | ] 123 | 124 | [[package]] 125 | name = "charset-normalizer" 126 | version = "3.4.1" 127 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 128 | optional = false 129 | python-versions = ">=3.7" 130 | groups = ["main"] 131 | files = [ 132 | {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, 133 | {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, 134 | {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, 135 | {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, 136 | {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, 137 | {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, 138 | {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, 139 | {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, 140 | {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, 141 | {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, 142 | {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, 143 | {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, 144 | {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, 145 | {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, 146 | {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, 147 | {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, 148 | {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, 149 | {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, 150 | {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, 151 | {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, 152 | {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, 153 | {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, 154 | {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, 155 | {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, 156 | {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, 157 | {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, 158 | {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, 159 | {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, 160 | {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, 161 | {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, 162 | {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, 163 | {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, 164 | {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, 165 | {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, 166 | {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, 167 | {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, 168 | {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, 169 | {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, 170 | {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, 171 | {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, 172 | {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, 173 | {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, 174 | {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, 175 | {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, 176 | {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, 177 | {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, 178 | {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, 179 | {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, 180 | {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, 181 | {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, 182 | {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, 183 | {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, 184 | {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, 185 | {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, 186 | {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, 187 | {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, 188 | {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, 189 | {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, 190 | {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, 191 | {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, 192 | {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, 193 | {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, 194 | {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, 195 | {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, 196 | {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, 197 | {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, 198 | {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, 199 | {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, 200 | {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, 201 | {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, 202 | {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, 203 | {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, 204 | {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, 205 | {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, 206 | {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, 207 | {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, 208 | {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, 209 | {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, 210 | {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, 211 | {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, 212 | {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, 213 | {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, 214 | {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, 215 | {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, 216 | {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, 217 | {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, 218 | {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, 219 | {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, 220 | {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, 221 | {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, 222 | {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, 223 | {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, 224 | ] 225 | 226 | [[package]] 227 | name = "click" 228 | version = "8.1.8" 229 | description = "Composable command line interface toolkit" 230 | optional = false 231 | python-versions = ">=3.7" 232 | groups = ["main"] 233 | files = [ 234 | {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, 235 | {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, 236 | ] 237 | 238 | [package.dependencies] 239 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 240 | 241 | [[package]] 242 | name = "colorama" 243 | version = "0.4.6" 244 | description = "Cross-platform colored terminal text." 245 | optional = false 246 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 247 | groups = ["main"] 248 | markers = "platform_system == \"Windows\"" 249 | files = [ 250 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 251 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 252 | ] 253 | 254 | [[package]] 255 | name = "deltalake" 256 | version = "0.25.5" 257 | description = "Native Delta Lake Python binding based on delta-rs with Pandas integration" 258 | optional = false 259 | python-versions = ">=3.9" 260 | groups = ["main"] 261 | files = [ 262 | {file = "deltalake-0.25.5-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:76be7e1ed8d13f2dc933361057a44a47a89e6112d4f5ea0a73fb510bedd96efc"}, 263 | {file = "deltalake-0.25.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:e8f0d24bf64455f702da8402307b22e01f91e0f76694f7c5e33c9513011e8d29"}, 264 | {file = "deltalake-0.25.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1c7e826fd7c3bdd3676c7471d3b551e1a3674e44cd8e3747a0017a2c0292b7"}, 265 | {file = "deltalake-0.25.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b36afba5936f74c42920c06d140535e6efc8361f659770014944d8e69fbca09"}, 266 | {file = "deltalake-0.25.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0ca70e824fd7bcd16aeaaf9a43800eb9dc6c5d05b7854328c4cb4a240643ef78"}, 267 | {file = "deltalake-0.25.5-cp39-abi3-win_amd64.whl", hash = "sha256:4ea62150f9d7d37dce0d973e833b91b07139031cc416ba72ebddbdd1a748f270"}, 268 | {file = "deltalake-0.25.5.tar.gz", hash = "sha256:173e4b83fcff10f26474ae117161c3f2bdd5f44c30c20463c24b6b8b520e7656"}, 269 | ] 270 | 271 | [package.dependencies] 272 | pyarrow = ">=16,<19.0.0 || >19.0.0" 273 | 274 | [package.extras] 275 | devel = ["azure-storage-blob (==12.20.0)", "mypy (==1.10.1)", "packaging (>=20)", "pip (>=24.0)", "pytest", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-timeout", "ruff (==0.5.2)", "sphinx (<=4.5)", "sphinx-rtd-theme", "toml", "wheel"] 276 | lakefs = ["lakefs (==0.8.0)"] 277 | pandas = ["pandas"] 278 | polars = ["polars (==1.17.1)"] 279 | pyspark = ["delta-spark", "numpy (==1.26.4)", "pyspark"] 280 | 281 | [[package]] 282 | name = "dotenv" 283 | version = "0.9.9" 284 | description = "Deprecated package" 285 | optional = false 286 | python-versions = "*" 287 | groups = ["main"] 288 | files = [ 289 | {file = "dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9"}, 290 | ] 291 | 292 | [package.dependencies] 293 | python-dotenv = "*" 294 | 295 | [[package]] 296 | name = "gitdb" 297 | version = "4.0.12" 298 | description = "Git Object Database" 299 | optional = false 300 | python-versions = ">=3.7" 301 | groups = ["main"] 302 | files = [ 303 | {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, 304 | {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, 305 | ] 306 | 307 | [package.dependencies] 308 | smmap = ">=3.0.1,<6" 309 | 310 | [[package]] 311 | name = "gitpython" 312 | version = "3.1.44" 313 | description = "GitPython is a Python library used to interact with Git repositories" 314 | optional = false 315 | python-versions = ">=3.7" 316 | groups = ["main"] 317 | files = [ 318 | {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, 319 | {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, 320 | ] 321 | 322 | [package.dependencies] 323 | gitdb = ">=4.0.1,<5" 324 | 325 | [package.extras] 326 | doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] 327 | test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] 328 | 329 | [[package]] 330 | name = "idna" 331 | version = "3.10" 332 | description = "Internationalized Domain Names in Applications (IDNA)" 333 | optional = false 334 | python-versions = ">=3.6" 335 | groups = ["main"] 336 | files = [ 337 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 338 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 339 | ] 340 | 341 | [package.extras] 342 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 343 | 344 | [[package]] 345 | name = "jinja2" 346 | version = "3.1.6" 347 | description = "A very fast and expressive template engine." 348 | optional = false 349 | python-versions = ">=3.7" 350 | groups = ["main"] 351 | files = [ 352 | {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, 353 | {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, 354 | ] 355 | 356 | [package.dependencies] 357 | MarkupSafe = ">=2.0" 358 | 359 | [package.extras] 360 | i18n = ["Babel (>=2.7)"] 361 | 362 | [[package]] 363 | name = "jmespath" 364 | version = "1.0.1" 365 | description = "JSON Matching Expressions" 366 | optional = false 367 | python-versions = ">=3.7" 368 | groups = ["main"] 369 | files = [ 370 | {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, 371 | {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, 372 | ] 373 | 374 | [[package]] 375 | name = "jsonschema" 376 | version = "4.23.0" 377 | description = "An implementation of JSON Schema validation for Python" 378 | optional = false 379 | python-versions = ">=3.8" 380 | groups = ["main"] 381 | files = [ 382 | {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, 383 | {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, 384 | ] 385 | 386 | [package.dependencies] 387 | attrs = ">=22.2.0" 388 | jsonschema-specifications = ">=2023.03.6" 389 | referencing = ">=0.28.4" 390 | rpds-py = ">=0.7.1" 391 | 392 | [package.extras] 393 | format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] 394 | format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] 395 | 396 | [[package]] 397 | name = "jsonschema-specifications" 398 | version = "2024.10.1" 399 | description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" 400 | optional = false 401 | python-versions = ">=3.9" 402 | groups = ["main"] 403 | files = [ 404 | {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, 405 | {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, 406 | ] 407 | 408 | [package.dependencies] 409 | referencing = ">=0.31.0" 410 | 411 | [[package]] 412 | name = "markupsafe" 413 | version = "3.0.2" 414 | description = "Safely add untrusted strings to HTML/XML markup." 415 | optional = false 416 | python-versions = ">=3.9" 417 | groups = ["main"] 418 | files = [ 419 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, 420 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, 421 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, 422 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, 423 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, 424 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, 425 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, 426 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, 427 | {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, 428 | {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, 429 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, 430 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, 431 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, 432 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, 433 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, 434 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, 435 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, 436 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, 437 | {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, 438 | {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, 439 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, 440 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, 441 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, 442 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, 443 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, 444 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, 445 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, 446 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, 447 | {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, 448 | {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, 449 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, 450 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, 451 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, 452 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, 453 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, 454 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, 455 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, 456 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, 457 | {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, 458 | {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, 459 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, 460 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, 461 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, 462 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, 463 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, 464 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, 465 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, 466 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, 467 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, 468 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, 469 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, 470 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, 471 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, 472 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, 473 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, 474 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, 475 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, 476 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, 477 | {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, 478 | {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, 479 | {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, 480 | ] 481 | 482 | [[package]] 483 | name = "narwhals" 484 | version = "1.35.0" 485 | description = "Extremely lightweight compatibility layer between dataframe libraries" 486 | optional = false 487 | python-versions = ">=3.8" 488 | groups = ["main"] 489 | files = [ 490 | {file = "narwhals-1.35.0-py3-none-any.whl", hash = "sha256:7562af132fa3f8aaaf34dc96d7ec95bdca29d1c795e8fcf14e01edf1d32122bc"}, 491 | {file = "narwhals-1.35.0.tar.gz", hash = "sha256:07477d18487fbc940243b69818a177ed7119b737910a8a254fb67688b48a7c96"}, 492 | ] 493 | 494 | [package.extras] 495 | cudf = ["cudf (>=24.10.0)"] 496 | dask = ["dask[dataframe] (>=2024.8)"] 497 | duckdb = ["duckdb (>=1.0)"] 498 | ibis = ["ibis-framework (>=6.0.0)", "packaging", "pyarrow-hotfix", "rich"] 499 | modin = ["modin"] 500 | pandas = ["pandas (>=0.25.3)"] 501 | polars = ["polars (>=0.20.3)"] 502 | pyarrow = ["pyarrow (>=11.0.0)"] 503 | pyspark = ["pyspark (>=3.5.0)"] 504 | sqlframe = ["sqlframe (>=3.22.0)"] 505 | 506 | [[package]] 507 | name = "numpy" 508 | version = "2.2.4" 509 | description = "Fundamental package for array computing in Python" 510 | optional = false 511 | python-versions = ">=3.10" 512 | groups = ["main"] 513 | files = [ 514 | {file = "numpy-2.2.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8146f3550d627252269ac42ae660281d673eb6f8b32f113538e0cc2a9aed42b9"}, 515 | {file = "numpy-2.2.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e642d86b8f956098b564a45e6f6ce68a22c2c97a04f5acd3f221f57b8cb850ae"}, 516 | {file = "numpy-2.2.4-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:a84eda42bd12edc36eb5b53bbcc9b406820d3353f1994b6cfe453a33ff101775"}, 517 | {file = "numpy-2.2.4-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:4ba5054787e89c59c593a4169830ab362ac2bee8a969249dc56e5d7d20ff8df9"}, 518 | {file = "numpy-2.2.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7716e4a9b7af82c06a2543c53ca476fa0b57e4d760481273e09da04b74ee6ee2"}, 519 | {file = "numpy-2.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf8c1d66f432ce577d0197dceaac2ac00c0759f573f28516246351c58a85020"}, 520 | {file = "numpy-2.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:218f061d2faa73621fa23d6359442b0fc658d5b9a70801373625d958259eaca3"}, 521 | {file = "numpy-2.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:df2f57871a96bbc1b69733cd4c51dc33bea66146b8c63cacbfed73eec0883017"}, 522 | {file = "numpy-2.2.4-cp310-cp310-win32.whl", hash = "sha256:a0258ad1f44f138b791327961caedffbf9612bfa504ab9597157806faa95194a"}, 523 | {file = "numpy-2.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:0d54974f9cf14acf49c60f0f7f4084b6579d24d439453d5fc5805d46a165b542"}, 524 | {file = "numpy-2.2.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e9e0a277bb2eb5d8a7407e14688b85fd8ad628ee4e0c7930415687b6564207a4"}, 525 | {file = "numpy-2.2.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9eeea959168ea555e556b8188da5fa7831e21d91ce031e95ce23747b7609f8a4"}, 526 | {file = "numpy-2.2.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bd3ad3b0a40e713fc68f99ecfd07124195333f1e689387c180813f0e94309d6f"}, 527 | {file = "numpy-2.2.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cf28633d64294969c019c6df4ff37f5698e8326db68cc2b66576a51fad634880"}, 528 | {file = "numpy-2.2.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fa8fa7697ad1646b5c93de1719965844e004fcad23c91228aca1cf0800044a1"}, 529 | {file = "numpy-2.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4162988a360a29af158aeb4a2f4f09ffed6a969c9776f8f3bdee9b06a8ab7e5"}, 530 | {file = "numpy-2.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:892c10d6a73e0f14935c31229e03325a7b3093fafd6ce0af704be7f894d95687"}, 531 | {file = "numpy-2.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db1f1c22173ac1c58db249ae48aa7ead29f534b9a948bc56828337aa84a32ed6"}, 532 | {file = "numpy-2.2.4-cp311-cp311-win32.whl", hash = "sha256:ea2bb7e2ae9e37d96835b3576a4fa4b3a97592fbea8ef7c3587078b0068b8f09"}, 533 | {file = "numpy-2.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:f7de08cbe5551911886d1ab60de58448c6df0f67d9feb7d1fb21e9875ef95e91"}, 534 | {file = "numpy-2.2.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a7b9084668aa0f64e64bd00d27ba5146ef1c3a8835f3bd912e7a9e01326804c4"}, 535 | {file = "numpy-2.2.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dbe512c511956b893d2dacd007d955a3f03d555ae05cfa3ff1c1ff6df8851854"}, 536 | {file = "numpy-2.2.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bb649f8b207ab07caebba230d851b579a3c8711a851d29efe15008e31bb4de24"}, 537 | {file = "numpy-2.2.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:f34dc300df798742b3d06515aa2a0aee20941c13579d7a2f2e10af01ae4901ee"}, 538 | {file = "numpy-2.2.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3f7ac96b16955634e223b579a3e5798df59007ca43e8d451a0e6a50f6bfdfba"}, 539 | {file = "numpy-2.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f92084defa704deadd4e0a5ab1dc52d8ac9e8a8ef617f3fbb853e79b0ea3592"}, 540 | {file = "numpy-2.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4e84a6283b36632e2a5b56e121961f6542ab886bc9e12f8f9818b3c266bfbb"}, 541 | {file = "numpy-2.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:11c43995255eb4127115956495f43e9343736edb7fcdb0d973defd9de14cd84f"}, 542 | {file = "numpy-2.2.4-cp312-cp312-win32.whl", hash = "sha256:65ef3468b53269eb5fdb3a5c09508c032b793da03251d5f8722b1194f1790c00"}, 543 | {file = "numpy-2.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:2aad3c17ed2ff455b8eaafe06bcdae0062a1db77cb99f4b9cbb5f4ecb13c5146"}, 544 | {file = "numpy-2.2.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cf4e5c6a278d620dee9ddeb487dc6a860f9b199eadeecc567f777daace1e9e7"}, 545 | {file = "numpy-2.2.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1974afec0b479e50438fc3648974268f972e2d908ddb6d7fb634598cdb8260a0"}, 546 | {file = "numpy-2.2.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:79bd5f0a02aa16808fcbc79a9a376a147cc1045f7dfe44c6e7d53fa8b8a79392"}, 547 | {file = "numpy-2.2.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:3387dd7232804b341165cedcb90694565a6015433ee076c6754775e85d86f1fc"}, 548 | {file = "numpy-2.2.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f527d8fdb0286fd2fd97a2a96c6be17ba4232da346931d967a0630050dfd298"}, 549 | {file = "numpy-2.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bce43e386c16898b91e162e5baaad90c4b06f9dcbe36282490032cec98dc8ae7"}, 550 | {file = "numpy-2.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31504f970f563d99f71a3512d0c01a645b692b12a63630d6aafa0939e52361e6"}, 551 | {file = "numpy-2.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81413336ef121a6ba746892fad881a83351ee3e1e4011f52e97fba79233611fd"}, 552 | {file = "numpy-2.2.4-cp313-cp313-win32.whl", hash = "sha256:f486038e44caa08dbd97275a9a35a283a8f1d2f0ee60ac260a1790e76660833c"}, 553 | {file = "numpy-2.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:207a2b8441cc8b6a2a78c9ddc64d00d20c303d79fba08c577752f080c4007ee3"}, 554 | {file = "numpy-2.2.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8120575cb4882318c791f839a4fd66161a6fa46f3f0a5e613071aae35b5dd8f8"}, 555 | {file = "numpy-2.2.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a761ba0fa886a7bb33c6c8f6f20213735cb19642c580a931c625ee377ee8bd39"}, 556 | {file = "numpy-2.2.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ac0280f1ba4a4bfff363a99a6aceed4f8e123f8a9b234c89140f5e894e452ecd"}, 557 | {file = "numpy-2.2.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:879cf3a9a2b53a4672a168c21375166171bc3932b7e21f622201811c43cdd3b0"}, 558 | {file = "numpy-2.2.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f05d4198c1bacc9124018109c5fba2f3201dbe7ab6e92ff100494f236209c960"}, 559 | {file = "numpy-2.2.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f085ce2e813a50dfd0e01fbfc0c12bbe5d2063d99f8b29da30e544fb6483b8"}, 560 | {file = "numpy-2.2.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:92bda934a791c01d6d9d8e038363c50918ef7c40601552a58ac84c9613a665bc"}, 561 | {file = "numpy-2.2.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ee4d528022f4c5ff67332469e10efe06a267e32f4067dc76bb7e2cddf3cd25ff"}, 562 | {file = "numpy-2.2.4-cp313-cp313t-win32.whl", hash = "sha256:05c076d531e9998e7e694c36e8b349969c56eadd2cdcd07242958489d79a7286"}, 563 | {file = "numpy-2.2.4-cp313-cp313t-win_amd64.whl", hash = "sha256:188dcbca89834cc2e14eb2f106c96d6d46f200fe0200310fc29089657379c58d"}, 564 | {file = "numpy-2.2.4-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7051ee569db5fbac144335e0f3b9c2337e0c8d5c9fee015f259a5bd70772b7e8"}, 565 | {file = "numpy-2.2.4-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:ab2939cd5bec30a7430cbdb2287b63151b77cf9624de0532d629c9a1c59b1d5c"}, 566 | {file = "numpy-2.2.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0f35b19894a9e08639fd60a1ec1978cb7f5f7f1eace62f38dd36be8aecdef4d"}, 567 | {file = "numpy-2.2.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b4adfbbc64014976d2f91084915ca4e626fbf2057fb81af209c1a6d776d23e3d"}, 568 | {file = "numpy-2.2.4.tar.gz", hash = "sha256:9ba03692a45d3eef66559efe1d1096c4b9b75c0986b5dff5530c378fb8331d4f"}, 569 | ] 570 | 571 | [[package]] 572 | name = "packaging" 573 | version = "24.2" 574 | description = "Core utilities for Python packages" 575 | optional = false 576 | python-versions = ">=3.8" 577 | groups = ["main"] 578 | files = [ 579 | {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, 580 | {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, 581 | ] 582 | 583 | [[package]] 584 | name = "pandas" 585 | version = "2.2.3" 586 | description = "Powerful data structures for data analysis, time series, and statistics" 587 | optional = false 588 | python-versions = ">=3.9" 589 | groups = ["main"] 590 | files = [ 591 | {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, 592 | {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, 593 | {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, 594 | {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, 595 | {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, 596 | {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, 597 | {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, 598 | {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, 599 | {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, 600 | {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, 601 | {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, 602 | {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, 603 | {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, 604 | {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, 605 | {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, 606 | {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, 607 | {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, 608 | {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, 609 | {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, 610 | {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, 611 | {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, 612 | {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, 613 | {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, 614 | {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, 615 | {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, 616 | {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, 617 | {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, 618 | {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, 619 | {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, 620 | {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, 621 | {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, 622 | {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, 623 | {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, 624 | {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, 625 | {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, 626 | {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, 627 | {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, 628 | {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, 629 | {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, 630 | {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, 631 | {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, 632 | {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, 633 | ] 634 | 635 | [package.dependencies] 636 | numpy = {version = ">=1.26.0", markers = "python_version >= \"3.12\""} 637 | python-dateutil = ">=2.8.2" 638 | pytz = ">=2020.1" 639 | tzdata = ">=2022.7" 640 | 641 | [package.extras] 642 | all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] 643 | aws = ["s3fs (>=2022.11.0)"] 644 | clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] 645 | compression = ["zstandard (>=0.19.0)"] 646 | computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] 647 | consortium-standard = ["dataframe-api-compat (>=0.1.7)"] 648 | excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] 649 | feather = ["pyarrow (>=10.0.1)"] 650 | fss = ["fsspec (>=2022.11.0)"] 651 | gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] 652 | hdf5 = ["tables (>=3.8.0)"] 653 | html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] 654 | mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] 655 | output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] 656 | parquet = ["pyarrow (>=10.0.1)"] 657 | performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] 658 | plot = ["matplotlib (>=3.6.3)"] 659 | postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] 660 | pyarrow = ["pyarrow (>=10.0.1)"] 661 | spss = ["pyreadstat (>=1.2.0)"] 662 | sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] 663 | test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] 664 | xml = ["lxml (>=4.9.2)"] 665 | 666 | [[package]] 667 | name = "pillow" 668 | version = "11.2.1" 669 | description = "Python Imaging Library (Fork)" 670 | optional = false 671 | python-versions = ">=3.9" 672 | groups = ["main"] 673 | files = [ 674 | {file = "pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047"}, 675 | {file = "pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95"}, 676 | {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61"}, 677 | {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1"}, 678 | {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c"}, 679 | {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d"}, 680 | {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97"}, 681 | {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579"}, 682 | {file = "pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d"}, 683 | {file = "pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad"}, 684 | {file = "pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2"}, 685 | {file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"}, 686 | {file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"}, 687 | {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"}, 688 | {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"}, 689 | {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"}, 690 | {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"}, 691 | {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"}, 692 | {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"}, 693 | {file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"}, 694 | {file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"}, 695 | {file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"}, 696 | {file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"}, 697 | {file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"}, 698 | {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"}, 699 | {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"}, 700 | {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"}, 701 | {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"}, 702 | {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"}, 703 | {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"}, 704 | {file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"}, 705 | {file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"}, 706 | {file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"}, 707 | {file = "pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28"}, 708 | {file = "pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830"}, 709 | {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0"}, 710 | {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1"}, 711 | {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f"}, 712 | {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155"}, 713 | {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14"}, 714 | {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b"}, 715 | {file = "pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2"}, 716 | {file = "pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691"}, 717 | {file = "pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c"}, 718 | {file = "pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22"}, 719 | {file = "pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7"}, 720 | {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16"}, 721 | {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b"}, 722 | {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406"}, 723 | {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91"}, 724 | {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751"}, 725 | {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9"}, 726 | {file = "pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd"}, 727 | {file = "pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e"}, 728 | {file = "pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681"}, 729 | {file = "pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8"}, 730 | {file = "pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909"}, 731 | {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928"}, 732 | {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79"}, 733 | {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35"}, 734 | {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb"}, 735 | {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a"}, 736 | {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36"}, 737 | {file = "pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67"}, 738 | {file = "pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1"}, 739 | {file = "pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e"}, 740 | {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156"}, 741 | {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772"}, 742 | {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363"}, 743 | {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0"}, 744 | {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01"}, 745 | {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193"}, 746 | {file = "pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013"}, 747 | {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"}, 748 | {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"}, 749 | {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"}, 750 | {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"}, 751 | {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"}, 752 | {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"}, 753 | {file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"}, 754 | {file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"}, 755 | ] 756 | 757 | [package.extras] 758 | docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] 759 | fpx = ["olefile"] 760 | mic = ["olefile"] 761 | test-arrow = ["pyarrow"] 762 | tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"] 763 | typing = ["typing-extensions ; python_version < \"3.10\""] 764 | xmp = ["defusedxml"] 765 | 766 | [[package]] 767 | name = "polars" 768 | version = "1.27.1" 769 | description = "Blazingly fast DataFrame library" 770 | optional = false 771 | python-versions = ">=3.9" 772 | groups = ["main"] 773 | files = [ 774 | {file = "polars-1.27.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ba7ad4f8046d00dd97c1369e46a4b7e00ffcff5d38c0f847ee4b9b1bb182fb18"}, 775 | {file = "polars-1.27.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:339e3948748ad6fa7a42e613c3fb165b497ed797e93fce1aa2cddf00fbc16cac"}, 776 | {file = "polars-1.27.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f801e0d9da198eb97cfb4e8af4242b8396878ff67b655c71570b7e333102b72b"}, 777 | {file = "polars-1.27.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:4d18a29c65222451818b63cd397b2e95c20412ea0065d735a20a4a79a7b26e8a"}, 778 | {file = "polars-1.27.1-cp39-abi3-win_amd64.whl", hash = "sha256:a4f832cf478b282d97f8bf86eeae2df66fa1384de1c49bc61f7224a10cc6a5df"}, 779 | {file = "polars-1.27.1-cp39-abi3-win_arm64.whl", hash = "sha256:4f238ee2e3c5660345cb62c0f731bbd6768362db96c058098359ecffa42c3c6c"}, 780 | {file = "polars-1.27.1.tar.gz", hash = "sha256:94fcb0216b56cd0594aa777db1760a41ad0dfffed90d2ca446cf9294d2e97f02"}, 781 | ] 782 | 783 | [package.extras] 784 | adbc = ["adbc-driver-manager[dbapi]", "adbc-driver-sqlite[dbapi]"] 785 | all = ["polars[async,cloudpickle,database,deltalake,excel,fsspec,graph,iceberg,numpy,pandas,plot,pyarrow,pydantic,style,timezone]"] 786 | async = ["gevent"] 787 | calamine = ["fastexcel (>=0.9)"] 788 | cloudpickle = ["cloudpickle"] 789 | connectorx = ["connectorx (>=0.3.2)"] 790 | database = ["polars[adbc,connectorx,sqlalchemy]"] 791 | deltalake = ["deltalake (>=0.19.0)"] 792 | excel = ["polars[calamine,openpyxl,xlsx2csv,xlsxwriter]"] 793 | fsspec = ["fsspec"] 794 | gpu = ["cudf-polars-cu12"] 795 | graph = ["matplotlib"] 796 | iceberg = ["pyiceberg (>=0.7.1)"] 797 | numpy = ["numpy (>=1.16.0)"] 798 | openpyxl = ["openpyxl (>=3.0.0)"] 799 | pandas = ["pandas", "polars[pyarrow]"] 800 | plot = ["altair (>=5.4.0)"] 801 | polars-cloud = ["polars-cloud (>=0.0.1a1)"] 802 | pyarrow = ["pyarrow (>=7.0.0)"] 803 | pydantic = ["pydantic"] 804 | sqlalchemy = ["polars[pandas]", "sqlalchemy"] 805 | style = ["great-tables (>=0.8.0)"] 806 | timezone = ["tzdata ; platform_system == \"Windows\""] 807 | xlsx2csv = ["xlsx2csv (>=0.8.0)"] 808 | xlsxwriter = ["xlsxwriter"] 809 | 810 | [[package]] 811 | name = "protobuf" 812 | version = "5.29.4" 813 | description = "" 814 | optional = false 815 | python-versions = ">=3.8" 816 | groups = ["main"] 817 | files = [ 818 | {file = "protobuf-5.29.4-cp310-abi3-win32.whl", hash = "sha256:13eb236f8eb9ec34e63fc8b1d6efd2777d062fa6aaa68268fb67cf77f6839ad7"}, 819 | {file = "protobuf-5.29.4-cp310-abi3-win_amd64.whl", hash = "sha256:bcefcdf3976233f8a502d265eb65ea740c989bacc6c30a58290ed0e519eb4b8d"}, 820 | {file = "protobuf-5.29.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:307ecba1d852ec237e9ba668e087326a67564ef83e45a0189a772ede9e854dd0"}, 821 | {file = "protobuf-5.29.4-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:aec4962f9ea93c431d5714ed1be1c93f13e1a8618e70035ba2b0564d9e633f2e"}, 822 | {file = "protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:d7d3f7d1d5a66ed4942d4fefb12ac4b14a29028b209d4bfb25c68ae172059922"}, 823 | {file = "protobuf-5.29.4-cp38-cp38-win32.whl", hash = "sha256:1832f0515b62d12d8e6ffc078d7e9eb06969aa6dc13c13e1036e39d73bebc2de"}, 824 | {file = "protobuf-5.29.4-cp38-cp38-win_amd64.whl", hash = "sha256:476cb7b14914c780605a8cf62e38c2a85f8caff2e28a6a0bad827ec7d6c85d68"}, 825 | {file = "protobuf-5.29.4-cp39-cp39-win32.whl", hash = "sha256:fd32223020cb25a2cc100366f1dedc904e2d71d9322403224cdde5fdced0dabe"}, 826 | {file = "protobuf-5.29.4-cp39-cp39-win_amd64.whl", hash = "sha256:678974e1e3a9b975b8bc2447fca458db5f93a2fb6b0c8db46b6675b5b5346812"}, 827 | {file = "protobuf-5.29.4-py3-none-any.whl", hash = "sha256:3fde11b505e1597f71b875ef2fc52062b6a9740e5f7c8997ce878b6009145862"}, 828 | {file = "protobuf-5.29.4.tar.gz", hash = "sha256:4f1dfcd7997b31ef8f53ec82781ff434a28bf71d9102ddde14d076adcfc78c99"}, 829 | ] 830 | 831 | [[package]] 832 | name = "pyarrow" 833 | version = "19.0.1" 834 | description = "Python library for Apache Arrow" 835 | optional = false 836 | python-versions = ">=3.9" 837 | groups = ["main"] 838 | files = [ 839 | {file = "pyarrow-19.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:fc28912a2dc924dddc2087679cc8b7263accc71b9ff025a1362b004711661a69"}, 840 | {file = "pyarrow-19.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:fca15aabbe9b8355800d923cc2e82c8ef514af321e18b437c3d782aa884eaeec"}, 841 | {file = "pyarrow-19.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad76aef7f5f7e4a757fddcdcf010a8290958f09e3470ea458c80d26f4316ae89"}, 842 | {file = "pyarrow-19.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d03c9d6f2a3dffbd62671ca070f13fc527bb1867b4ec2b98c7eeed381d4f389a"}, 843 | {file = "pyarrow-19.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:65cf9feebab489b19cdfcfe4aa82f62147218558d8d3f0fc1e9dea0ab8e7905a"}, 844 | {file = "pyarrow-19.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:41f9706fbe505e0abc10e84bf3a906a1338905cbbcf1177b71486b03e6ea6608"}, 845 | {file = "pyarrow-19.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6cb2335a411b713fdf1e82a752162f72d4a7b5dbc588e32aa18383318b05866"}, 846 | {file = "pyarrow-19.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:cc55d71898ea30dc95900297d191377caba257612f384207fe9f8293b5850f90"}, 847 | {file = "pyarrow-19.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:7a544ec12de66769612b2d6988c36adc96fb9767ecc8ee0a4d270b10b1c51e00"}, 848 | {file = "pyarrow-19.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0148bb4fc158bfbc3d6dfe5001d93ebeed253793fff4435167f6ce1dc4bddeae"}, 849 | {file = "pyarrow-19.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f24faab6ed18f216a37870d8c5623f9c044566d75ec586ef884e13a02a9d62c5"}, 850 | {file = "pyarrow-19.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:4982f8e2b7afd6dae8608d70ba5bd91699077323f812a0448d8b7abdff6cb5d3"}, 851 | {file = "pyarrow-19.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:49a3aecb62c1be1d822f8bf629226d4a96418228a42f5b40835c1f10d42e4db6"}, 852 | {file = "pyarrow-19.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:008a4009efdb4ea3d2e18f05cd31f9d43c388aad29c636112c2966605ba33466"}, 853 | {file = "pyarrow-19.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:80b2ad2b193e7d19e81008a96e313fbd53157945c7be9ac65f44f8937a55427b"}, 854 | {file = "pyarrow-19.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:ee8dec072569f43835932a3b10c55973593abc00936c202707a4ad06af7cb294"}, 855 | {file = "pyarrow-19.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d5d1ec7ec5324b98887bdc006f4d2ce534e10e60f7ad995e7875ffa0ff9cb14"}, 856 | {file = "pyarrow-19.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ad4c0eb4e2a9aeb990af6c09e6fa0b195c8c0e7b272ecc8d4d2b6574809d34"}, 857 | {file = "pyarrow-19.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d383591f3dcbe545f6cc62daaef9c7cdfe0dff0fb9e1c8121101cabe9098cfa6"}, 858 | {file = "pyarrow-19.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b4c4156a625f1e35d6c0b2132635a237708944eb41df5fbe7d50f20d20c17832"}, 859 | {file = "pyarrow-19.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:5bd1618ae5e5476b7654c7b55a6364ae87686d4724538c24185bbb2952679960"}, 860 | {file = "pyarrow-19.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e45274b20e524ae5c39d7fc1ca2aa923aab494776d2d4b316b49ec7572ca324c"}, 861 | {file = "pyarrow-19.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:d9dedeaf19097a143ed6da37f04f4051aba353c95ef507764d344229b2b740ae"}, 862 | {file = "pyarrow-19.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ebfb5171bb5f4a52319344ebbbecc731af3f021e49318c74f33d520d31ae0c4"}, 863 | {file = "pyarrow-19.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a21d39fbdb948857f67eacb5bbaaf36802de044ec36fbef7a1c8f0dd3a4ab2"}, 864 | {file = "pyarrow-19.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:99bc1bec6d234359743b01e70d4310d0ab240c3d6b0da7e2a93663b0158616f6"}, 865 | {file = "pyarrow-19.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1b93ef2c93e77c442c979b0d596af45e4665d8b96da598db145b0fec014b9136"}, 866 | {file = "pyarrow-19.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:d9d46e06846a41ba906ab25302cf0fd522f81aa2a85a71021826f34639ad31ef"}, 867 | {file = "pyarrow-19.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c0fe3dbbf054a00d1f162fda94ce236a899ca01123a798c561ba307ca38af5f0"}, 868 | {file = "pyarrow-19.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:96606c3ba57944d128e8a8399da4812f56c7f61de8c647e3470b417f795d0ef9"}, 869 | {file = "pyarrow-19.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f04d49a6b64cf24719c080b3c2029a3a5b16417fd5fd7c4041f94233af732f3"}, 870 | {file = "pyarrow-19.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a9137cf7e1640dce4c190551ee69d478f7121b5c6f323553b319cac936395f6"}, 871 | {file = "pyarrow-19.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:7c1bca1897c28013db5e4c83944a2ab53231f541b9e0c3f4791206d0c0de389a"}, 872 | {file = "pyarrow-19.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:58d9397b2e273ef76264b45531e9d552d8ec8a6688b7390b5be44c02a37aade8"}, 873 | {file = "pyarrow-19.0.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:b9766a47a9cb56fefe95cb27f535038b5a195707a08bf61b180e642324963b46"}, 874 | {file = "pyarrow-19.0.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:6c5941c1aac89a6c2f2b16cd64fe76bcdb94b2b1e99ca6459de4e6f07638d755"}, 875 | {file = "pyarrow-19.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd44d66093a239358d07c42a91eebf5015aa54fccba959db899f932218ac9cc8"}, 876 | {file = "pyarrow-19.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:335d170e050bcc7da867a1ed8ffb8b44c57aaa6e0843b156a501298657b1e972"}, 877 | {file = "pyarrow-19.0.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:1c7556165bd38cf0cd992df2636f8bcdd2d4b26916c6b7e646101aff3c16f76f"}, 878 | {file = "pyarrow-19.0.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:699799f9c80bebcf1da0983ba86d7f289c5a2a5c04b945e2f2bcf7e874a91911"}, 879 | {file = "pyarrow-19.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:8464c9fbe6d94a7fe1599e7e8965f350fd233532868232ab2596a71586c5a429"}, 880 | {file = "pyarrow-19.0.1.tar.gz", hash = "sha256:3bf266b485df66a400f282ac0b6d1b500b9d2ae73314a153dbe97d6d5cc8a99e"}, 881 | ] 882 | 883 | [package.extras] 884 | test = ["cffi", "hypothesis", "pandas", "pytest", "pytz"] 885 | 886 | [[package]] 887 | name = "pydeck" 888 | version = "0.9.1" 889 | description = "Widget for deck.gl maps" 890 | optional = false 891 | python-versions = ">=3.8" 892 | groups = ["main"] 893 | files = [ 894 | {file = "pydeck-0.9.1-py2.py3-none-any.whl", hash = "sha256:b3f75ba0d273fc917094fa61224f3f6076ca8752b93d46faf3bcfd9f9d59b038"}, 895 | {file = "pydeck-0.9.1.tar.gz", hash = "sha256:f74475ae637951d63f2ee58326757f8d4f9cd9f2a457cf42950715003e2cb605"}, 896 | ] 897 | 898 | [package.dependencies] 899 | jinja2 = ">=2.10.1" 900 | numpy = ">=1.16.4" 901 | 902 | [package.extras] 903 | carto = ["pydeck-carto"] 904 | jupyter = ["ipykernel (>=5.1.2) ; python_version >= \"3.4\"", "ipython (>=5.8.0) ; python_version < \"3.4\"", "ipywidgets (>=7,<8)", "traitlets (>=4.3.2)"] 905 | 906 | [[package]] 907 | name = "python-dateutil" 908 | version = "2.9.0.post0" 909 | description = "Extensions to the standard Python datetime module" 910 | optional = false 911 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 912 | groups = ["main"] 913 | files = [ 914 | {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, 915 | {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, 916 | ] 917 | 918 | [package.dependencies] 919 | six = ">=1.5" 920 | 921 | [[package]] 922 | name = "python-dotenv" 923 | version = "1.1.0" 924 | description = "Read key-value pairs from a .env file and set them as environment variables" 925 | optional = false 926 | python-versions = ">=3.9" 927 | groups = ["main"] 928 | files = [ 929 | {file = "python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"}, 930 | {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, 931 | ] 932 | 933 | [package.extras] 934 | cli = ["click (>=5.0)"] 935 | 936 | [[package]] 937 | name = "pytz" 938 | version = "2025.2" 939 | description = "World timezone definitions, modern and historical" 940 | optional = false 941 | python-versions = "*" 942 | groups = ["main"] 943 | files = [ 944 | {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, 945 | {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, 946 | ] 947 | 948 | [[package]] 949 | name = "referencing" 950 | version = "0.36.2" 951 | description = "JSON Referencing + Python" 952 | optional = false 953 | python-versions = ">=3.9" 954 | groups = ["main"] 955 | files = [ 956 | {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, 957 | {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, 958 | ] 959 | 960 | [package.dependencies] 961 | attrs = ">=22.2.0" 962 | rpds-py = ">=0.7.0" 963 | typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} 964 | 965 | [[package]] 966 | name = "requests" 967 | version = "2.32.3" 968 | description = "Python HTTP for Humans." 969 | optional = false 970 | python-versions = ">=3.8" 971 | groups = ["main"] 972 | files = [ 973 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, 974 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, 975 | ] 976 | 977 | [package.dependencies] 978 | certifi = ">=2017.4.17" 979 | charset-normalizer = ">=2,<4" 980 | idna = ">=2.5,<4" 981 | urllib3 = ">=1.21.1,<3" 982 | 983 | [package.extras] 984 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 985 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 986 | 987 | [[package]] 988 | name = "rpds-py" 989 | version = "0.24.0" 990 | description = "Python bindings to Rust's persistent data structures (rpds)" 991 | optional = false 992 | python-versions = ">=3.9" 993 | groups = ["main"] 994 | files = [ 995 | {file = "rpds_py-0.24.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724"}, 996 | {file = "rpds_py-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b"}, 997 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727"}, 998 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964"}, 999 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5"}, 1000 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664"}, 1001 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc"}, 1002 | {file = "rpds_py-0.24.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0"}, 1003 | {file = "rpds_py-0.24.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f"}, 1004 | {file = "rpds_py-0.24.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f"}, 1005 | {file = "rpds_py-0.24.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875"}, 1006 | {file = "rpds_py-0.24.0-cp310-cp310-win32.whl", hash = "sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07"}, 1007 | {file = "rpds_py-0.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052"}, 1008 | {file = "rpds_py-0.24.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef"}, 1009 | {file = "rpds_py-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97"}, 1010 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e"}, 1011 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d"}, 1012 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586"}, 1013 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4"}, 1014 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae"}, 1015 | {file = "rpds_py-0.24.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc"}, 1016 | {file = "rpds_py-0.24.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c"}, 1017 | {file = "rpds_py-0.24.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c"}, 1018 | {file = "rpds_py-0.24.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718"}, 1019 | {file = "rpds_py-0.24.0-cp311-cp311-win32.whl", hash = "sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a"}, 1020 | {file = "rpds_py-0.24.0-cp311-cp311-win_amd64.whl", hash = "sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6"}, 1021 | {file = "rpds_py-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205"}, 1022 | {file = "rpds_py-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7"}, 1023 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9"}, 1024 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e"}, 1025 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda"}, 1026 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e"}, 1027 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029"}, 1028 | {file = "rpds_py-0.24.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9"}, 1029 | {file = "rpds_py-0.24.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7"}, 1030 | {file = "rpds_py-0.24.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91"}, 1031 | {file = "rpds_py-0.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56"}, 1032 | {file = "rpds_py-0.24.0-cp312-cp312-win32.whl", hash = "sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30"}, 1033 | {file = "rpds_py-0.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034"}, 1034 | {file = "rpds_py-0.24.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c"}, 1035 | {file = "rpds_py-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c"}, 1036 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240"}, 1037 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8"}, 1038 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8"}, 1039 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b"}, 1040 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d"}, 1041 | {file = "rpds_py-0.24.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7"}, 1042 | {file = "rpds_py-0.24.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad"}, 1043 | {file = "rpds_py-0.24.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120"}, 1044 | {file = "rpds_py-0.24.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9"}, 1045 | {file = "rpds_py-0.24.0-cp313-cp313-win32.whl", hash = "sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143"}, 1046 | {file = "rpds_py-0.24.0-cp313-cp313-win_amd64.whl", hash = "sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a"}, 1047 | {file = "rpds_py-0.24.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114"}, 1048 | {file = "rpds_py-0.24.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405"}, 1049 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47"}, 1050 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272"}, 1051 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd"}, 1052 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a"}, 1053 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d"}, 1054 | {file = "rpds_py-0.24.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7"}, 1055 | {file = "rpds_py-0.24.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d"}, 1056 | {file = "rpds_py-0.24.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797"}, 1057 | {file = "rpds_py-0.24.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c"}, 1058 | {file = "rpds_py-0.24.0-cp313-cp313t-win32.whl", hash = "sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba"}, 1059 | {file = "rpds_py-0.24.0-cp313-cp313t-win_amd64.whl", hash = "sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350"}, 1060 | {file = "rpds_py-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d"}, 1061 | {file = "rpds_py-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e"}, 1062 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65"}, 1063 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b"}, 1064 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791"}, 1065 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9"}, 1066 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c"}, 1067 | {file = "rpds_py-0.24.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58"}, 1068 | {file = "rpds_py-0.24.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124"}, 1069 | {file = "rpds_py-0.24.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149"}, 1070 | {file = "rpds_py-0.24.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45"}, 1071 | {file = "rpds_py-0.24.0-cp39-cp39-win32.whl", hash = "sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103"}, 1072 | {file = "rpds_py-0.24.0-cp39-cp39-win_amd64.whl", hash = "sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f"}, 1073 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a"}, 1074 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399"}, 1075 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098"}, 1076 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d"}, 1077 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e"}, 1078 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1"}, 1079 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb"}, 1080 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44"}, 1081 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33"}, 1082 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164"}, 1083 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc"}, 1084 | {file = "rpds_py-0.24.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5"}, 1085 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d"}, 1086 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a"}, 1087 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5"}, 1088 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d"}, 1089 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793"}, 1090 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba"}, 1091 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea"}, 1092 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032"}, 1093 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d"}, 1094 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25"}, 1095 | {file = "rpds_py-0.24.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba"}, 1096 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6"}, 1097 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb"}, 1098 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1"}, 1099 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83"}, 1100 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046"}, 1101 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391"}, 1102 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3"}, 1103 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78"}, 1104 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3"}, 1105 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd"}, 1106 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796"}, 1107 | {file = "rpds_py-0.24.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f"}, 1108 | {file = "rpds_py-0.24.0.tar.gz", hash = "sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e"}, 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "s3transfer" 1113 | version = "0.11.5" 1114 | description = "An Amazon S3 Transfer Manager" 1115 | optional = false 1116 | python-versions = ">=3.8" 1117 | groups = ["main"] 1118 | files = [ 1119 | {file = "s3transfer-0.11.5-py3-none-any.whl", hash = "sha256:757af0f2ac150d3c75bc4177a32355c3862a98d20447b69a0161812992fe0bd4"}, 1120 | {file = "s3transfer-0.11.5.tar.gz", hash = "sha256:8c8aad92784779ab8688a61aefff3e28e9ebdce43142808eaa3f0b0f402f68b7"}, 1121 | ] 1122 | 1123 | [package.dependencies] 1124 | botocore = ">=1.37.4,<2.0a.0" 1125 | 1126 | [package.extras] 1127 | crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] 1128 | 1129 | [[package]] 1130 | name = "six" 1131 | version = "1.17.0" 1132 | description = "Python 2 and 3 compatibility utilities" 1133 | optional = false 1134 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 1135 | groups = ["main"] 1136 | files = [ 1137 | {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, 1138 | {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, 1139 | ] 1140 | 1141 | [[package]] 1142 | name = "smmap" 1143 | version = "5.0.2" 1144 | description = "A pure Python implementation of a sliding window memory map manager" 1145 | optional = false 1146 | python-versions = ">=3.7" 1147 | groups = ["main"] 1148 | files = [ 1149 | {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, 1150 | {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, 1151 | ] 1152 | 1153 | [[package]] 1154 | name = "streamlit" 1155 | version = "1.44.1" 1156 | description = "A faster way to build and share data apps" 1157 | optional = false 1158 | python-versions = "!=3.9.7,>=3.9" 1159 | groups = ["main"] 1160 | files = [ 1161 | {file = "streamlit-1.44.1-py3-none-any.whl", hash = "sha256:9fe355f58b11f4eb71e74f115ce1f38c4c9eaff2733e6bcffb510ac1298a5990"}, 1162 | {file = "streamlit-1.44.1.tar.gz", hash = "sha256:c6914ed6d5b76870b461510476806db370f36425ae0e6654d227c988288198d3"}, 1163 | ] 1164 | 1165 | [package.dependencies] 1166 | altair = ">=4.0,<6" 1167 | blinker = ">=1.0.0,<2" 1168 | cachetools = ">=4.0,<6" 1169 | click = ">=7.0,<9" 1170 | gitpython = ">=3.0.7,<3.1.19 || >3.1.19,<4" 1171 | numpy = ">=1.23,<3" 1172 | packaging = ">=20,<25" 1173 | pandas = ">=1.4.0,<3" 1174 | pillow = ">=7.1.0,<12" 1175 | protobuf = ">=3.20,<6" 1176 | pyarrow = ">=7.0" 1177 | pydeck = ">=0.8.0b4,<1" 1178 | requests = ">=2.27,<3" 1179 | tenacity = ">=8.1.0,<10" 1180 | toml = ">=0.10.1,<2" 1181 | tornado = ">=6.0.3,<7" 1182 | typing-extensions = ">=4.4.0,<5" 1183 | watchdog = {version = ">=2.1.5,<7", markers = "platform_system != \"Darwin\""} 1184 | 1185 | [package.extras] 1186 | snowflake = ["snowflake-connector-python (>=3.3.0) ; python_version < \"3.12\"", "snowflake-snowpark-python[modin] (>=1.17.0) ; python_version < \"3.12\""] 1187 | 1188 | [[package]] 1189 | name = "streamlit-autorefresh" 1190 | version = "1.0.1" 1191 | description = "Simple way to autorefresh your Streamlit apps" 1192 | optional = false 1193 | python-versions = ">=3.6" 1194 | groups = ["main"] 1195 | files = [ 1196 | {file = "streamlit-autorefresh-1.0.1.tar.gz", hash = "sha256:a89abf23f2c4e52d37be442115cd5566b41f382e3c09ff08817e17a25f50b8ed"}, 1197 | {file = "streamlit_autorefresh-1.0.1-py3-none-any.whl", hash = "sha256:8f0a772eff9d56807d19dc422e44ef92d900bbb22b1b85de31d8d82ea7d875f1"}, 1198 | ] 1199 | 1200 | [package.dependencies] 1201 | streamlit = ">=0.75" 1202 | 1203 | [[package]] 1204 | name = "tenacity" 1205 | version = "9.1.2" 1206 | description = "Retry code until it succeeds" 1207 | optional = false 1208 | python-versions = ">=3.9" 1209 | groups = ["main"] 1210 | files = [ 1211 | {file = "tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138"}, 1212 | {file = "tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb"}, 1213 | ] 1214 | 1215 | [package.extras] 1216 | doc = ["reno", "sphinx"] 1217 | test = ["pytest", "tornado (>=4.5)", "typeguard"] 1218 | 1219 | [[package]] 1220 | name = "toml" 1221 | version = "0.10.2" 1222 | description = "Python Library for Tom's Obvious, Minimal Language" 1223 | optional = false 1224 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 1225 | groups = ["main"] 1226 | files = [ 1227 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1228 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1229 | ] 1230 | 1231 | [[package]] 1232 | name = "tornado" 1233 | version = "6.4.2" 1234 | description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 1235 | optional = false 1236 | python-versions = ">=3.8" 1237 | groups = ["main"] 1238 | files = [ 1239 | {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"}, 1240 | {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"}, 1241 | {file = "tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec"}, 1242 | {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946"}, 1243 | {file = "tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf"}, 1244 | {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634"}, 1245 | {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73"}, 1246 | {file = "tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c"}, 1247 | {file = "tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482"}, 1248 | {file = "tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38"}, 1249 | {file = "tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b"}, 1250 | ] 1251 | 1252 | [[package]] 1253 | name = "typing-extensions" 1254 | version = "4.13.2" 1255 | description = "Backported and Experimental Type Hints for Python 3.8+" 1256 | optional = false 1257 | python-versions = ">=3.8" 1258 | groups = ["main"] 1259 | files = [ 1260 | {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, 1261 | {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "tzdata" 1266 | version = "2025.2" 1267 | description = "Provider of IANA time zone data" 1268 | optional = false 1269 | python-versions = ">=2" 1270 | groups = ["main"] 1271 | files = [ 1272 | {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, 1273 | {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, 1274 | ] 1275 | 1276 | [[package]] 1277 | name = "urllib3" 1278 | version = "2.4.0" 1279 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1280 | optional = false 1281 | python-versions = ">=3.9" 1282 | groups = ["main"] 1283 | files = [ 1284 | {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, 1285 | {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, 1286 | ] 1287 | 1288 | [package.extras] 1289 | brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] 1290 | h2 = ["h2 (>=4,<5)"] 1291 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 1292 | zstd = ["zstandard (>=0.18.0)"] 1293 | 1294 | [[package]] 1295 | name = "watchdog" 1296 | version = "6.0.0" 1297 | description = "Filesystem events monitoring" 1298 | optional = false 1299 | python-versions = ">=3.9" 1300 | groups = ["main"] 1301 | markers = "platform_system != \"Darwin\"" 1302 | files = [ 1303 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, 1304 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, 1305 | {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, 1306 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, 1307 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, 1308 | {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, 1309 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, 1310 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, 1311 | {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, 1312 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, 1313 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, 1314 | {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, 1315 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, 1316 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, 1317 | {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, 1318 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, 1319 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, 1320 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, 1321 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, 1322 | {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, 1323 | {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, 1324 | {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, 1325 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, 1326 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, 1327 | {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, 1328 | {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, 1329 | {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, 1330 | {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, 1331 | {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, 1332 | {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, 1333 | ] 1334 | 1335 | [package.extras] 1336 | watchmedo = ["PyYAML (>=3.10)"] 1337 | 1338 | [metadata] 1339 | lock-version = "2.1" 1340 | python-versions = ">=3.12" 1341 | content-hash = "afdd5253a4af01ff133e010297557f88404fdba15d5531d3f5853f2d890fea0a" 1342 | -------------------------------------------------------------------------------- /delta-explorer/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "streamlit-demo" 3 | version = "0.1.0" 4 | description = "" 5 | authors = [ 6 | {name = "Harry",email = "harry@myntlabs.io"} 7 | ] 8 | readme = "README.md" 9 | requires-python = ">=3.12" 10 | dependencies = [ 11 | "streamlit (>=1.44.1,<2.0.0)", 12 | "deltalake (>=0.25.5,<0.26.0)", 13 | "boto3 (>=1.37.37,<2.0.0)", 14 | "dotenv (>=0.9.9,<0.10.0)", 15 | "polars (>=1.27.1,<2.0.0)", 16 | "streamlit-autorefresh (>=1.0.1,<2.0.0)" 17 | ] 18 | 19 | 20 | [build-system] 21 | requires = ["poetry-core>=2.0.0,<3.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | -------------------------------------------------------------------------------- /delta-explorer/scan_deltalake.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import List, Optional, Dict 3 | from datetime import datetime 4 | import os 5 | from deltalake import DeltaTable 6 | from dotenv import load_dotenv 7 | import boto3 8 | from botocore.config import Config 9 | 10 | @dataclass 11 | class DeltaTableInfo: 12 | name: str 13 | path: str 14 | schema: Dict[str, str] 15 | created_time: Optional[datetime] 16 | last_updated_time: Optional[datetime] 17 | latest_version: int 18 | 19 | @dataclass 20 | class DeltaLake: 21 | delta_tables: List[DeltaTableInfo] 22 | 23 | def scan_deltalake() -> DeltaLake: 24 | bucket = "metastore" 25 | delta_prefix = f"delta/" 26 | endpoint_url = f"http://storage:{os.environ.get("STORAGE_PORT")}" 27 | storage_key = os.environ.get("STORAGE_USER") 28 | storage_password = os.environ.get("STORAGE_PASSWORD") 29 | 30 | storage_options = { 31 | "AWS_ACCESS_KEY_ID": storage_key, 32 | "AWS_SECRET_ACCESS_KEY": storage_password, 33 | "AWS_ENDPOINT_URL": endpoint_url, 34 | "AWS_REGION": "us-east-1", 35 | "AWS_ALLOW_HTTP": "true", 36 | } 37 | 38 | s3 = boto3.client( 39 | "s3", 40 | endpoint_url=endpoint_url, 41 | aws_access_key_id=storage_key, 42 | aws_secret_access_key=storage_password, 43 | config=Config(signature_version="s3v4"), 44 | ) 45 | 46 | tables = [] 47 | paginator = s3.get_paginator("list_objects_v2") 48 | result = paginator.paginate(Bucket=bucket, Prefix=delta_prefix, Delimiter="/") 49 | 50 | for page in result: 51 | for prefix in page.get("CommonPrefixes", []): 52 | table_name = prefix["Prefix"].replace(delta_prefix, "").strip("/") 53 | s3_path = f"s3://{bucket}/{delta_prefix}{table_name}" 54 | 55 | dt = DeltaTable(s3_path, storage_options=storage_options) 56 | metadata = dt.metadata() 57 | schema = {f.name: str(f.type) for f in dt.schema().fields} 58 | history = dt.history() 59 | latest_version = dt.version() 60 | 61 | last_updated_time = history[0].get("timestamp") if history else None 62 | 63 | table_info = DeltaTableInfo( 64 | name=table_name, 65 | path=s3_path, 66 | schema=schema, 67 | created_time=metadata.created_time, 68 | last_updated_time=last_updated_time, 69 | latest_version=latest_version, 70 | ) 71 | tables.append(table_info) 72 | 73 | return DeltaLake(delta_tables=tables) -------------------------------------------------------------------------------- /docker-compose.base.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | storage: 5 | image: zenko/cloudserver:latest 6 | environment: 7 | - SCALITY_ACCESS_KEY_ID=${STORAGE_USER} 8 | - SCALITY_SECRET_ACCESS_KEY=${STORAGE_PASSWORD} 9 | - S3DATA=multiple 10 | - REMOTE_MANAGEMENT_DISABLE=true 11 | volumes: 12 | - ./storage/config.json:/usr/src/app/config.json:ro 13 | 14 | storage-init: 15 | image: amazon/aws-cli 16 | depends_on: 17 | - storage 18 | entrypoint: > 19 | /bin/sh -c " 20 | sleep 5; 21 | aws --endpoint-url http://storage:8000 s3api create-bucket --bucket metastore; 22 | aws --endpoint-url http://storage:8000 s3api put-bucket-versioning --bucket metastore --versioning-configuration Status=Enabled; 23 | " 24 | environment: 25 | AWS_ACCESS_KEY_ID: ${STORAGE_USER} 26 | AWS_SECRET_ACCESS_KEY: ${STORAGE_PASSWORD} 27 | 28 | kernel: 29 | build: 30 | context: ./kernel 31 | image: kernel:latest 32 | working_dir: /kernel 33 | 34 | workspace: 35 | depends_on: 36 | kernel: 37 | condition: service_completed_successfully 38 | storage-init: 39 | condition: service_completed_successfully 40 | build: 41 | dockerfile: ../../Dockerfile.workspace 42 | environment: 43 | STORAGE_USER: ${STORAGE_USER} 44 | STORAGE_PASSWORD: ${STORAGE_PASSWORD} 45 | STORAGE_PORT: 8000 46 | cap_add: 47 | - SYS_ADMIN 48 | devices: 49 | - /dev/fuse 50 | security_opt: 51 | - apparmor:unconfined 52 | volumes: 53 | - ./workspace-entrypoint.sh:/root/.workspace-entrypoint.sh 54 | entrypoint: 55 | [/root/.workspace-entrypoint.sh] 56 | 57 | aim-init: 58 | image: aimstack/aim 59 | entrypoint: ["/bin/sh", "-c", 60 | 'if [ ! -d "/repo/.aim" ]; then aim init --repo /repo; else echo "AIM repo already exists at /repo, skipping init"; fi' 61 | ] 62 | 63 | aim-ui: 64 | image: aimstack/aim 65 | depends_on: 66 | aim-init: 67 | condition: service_completed_successfully 68 | entrypoint: [ 69 | "aim", "up", "--repo", 70 | "/repo", "--host", "0.0.0.0", "--port", 71 | "43800", "--base-path", "/aim" 72 | ] 73 | 74 | delta-explorer: 75 | build: 76 | context: ./delta-explorer 77 | depends_on: 78 | - storage-init 79 | environment: 80 | STORAGE_USER: ${STORAGE_USER} 81 | STORAGE_PASSWORD: ${STORAGE_PASSWORD} 82 | STORAGE_PORT: 8000 83 | command: 84 | - poetry 85 | - run 86 | - streamlit 87 | - run 88 | - app.py 89 | - --server.port=8501 90 | - --server.address=0.0.0.0 91 | - --server.enableCORS=false 92 | - --server.enableXsrfProtection=false 93 | - --server.baseUrlPath=/delta/ 94 | 95 | nginx: 96 | image: nginx:alpine 97 | ports: 98 | - "${BOSON_PORT}:80" 99 | depends_on: 100 | - workspace 101 | - aim-ui 102 | volumes: 103 | - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro -------------------------------------------------------------------------------- /docs/builtins.md: -------------------------------------------------------------------------------- 1 | # Builtins 2 | 3 | Boson simplifies usage by abstracting repetitive implemention details into convenient builtin functions. These functions are automatically installed in the Jupyter kernel and require no manual imports to be made available. 4 | 5 | For the full reference, please see [globals.py](../kernel/kernel/globals.py) 6 | 7 | ### `write_delta(df: polars.DataFrame, table_name: str, *args, **kwargs)` 8 | 9 | ```python 10 | write_delta(my_df, "my_table") 11 | ``` 12 | 13 | Save a Polars DataFrame to a Delta Table in blob storage. 14 | 15 | ### `read_delta(table_name: str, *args, **kwargs) -> polars.DataFrame` 16 | 17 | ```python 18 | df = read_delta("my_table") 19 | ``` 20 | 21 | Read a Delta Table from blob storage via Polars. 22 | 23 | ### `scan_delta(table_name: str, *args, **kwargs) -> polars.LazyFrame` 24 | 25 | ```python 26 | lf = scan_delta("my_table") 27 | ``` 28 | 29 | Lazily scan a Delta Table from blob storage via Polars. 30 | 31 | ### `drop_delta(table_name: str)` 32 | 33 | ```python 34 | drop_delta("my_table") 35 | ``` 36 | 37 | Drop (delete) a Delta Table from cloud storage by removing all underlying files. 38 | 39 | ### `display(df: polars.DataFrame | polars.LazyFrame)` 40 | 41 | ```python 42 | display(my_df) 43 | ``` 44 | 45 | Drop (delete) a Delta Table from cloud storage by removing all underlying files. 46 | 47 | ### `new_run(*args, **kwargs) -> Run` 48 | 49 | ```python 50 | run = new_run() 51 | ``` 52 | 53 | Creates an Aim Run at the default repository location. -------------------------------------------------------------------------------- /docs/concepts.md: -------------------------------------------------------------------------------- 1 | # Concepts 2 | 3 | ## Architecture 4 | 5 | The Boson platform is a single-node-optimized, lightweight ML research platform that achieves fast, reproducible experimentation by separating concerns across a modular data and compute plane. It is designed to simplify the ML research lifecycle without the operational overhead of distributed systems and can be self-hosted. 6 | 7 | ### Core Architectural Principles 8 | 9 | **Data Plane (Storage + Versioning)** 10 | - Built on Delta Lake for ACID-compliant, versioned datasets 11 | - Enables reproducible data access across experiments 12 | - **Boson Metastore** (internal blob cloud storage) contains Delta Lake, notebooks and all local files 13 | - Metastore is mounted to local Compute Plane location for seamless compute access 14 | 15 | **Compute Plane (Experiment and Pipeline Execution)** 16 | - Fully containerized execution via Docker Compose 17 | - Optimized for single-node environments using Polars for ultra-fast data pipeline execution 18 | - Notebook development environment 19 | 20 | ## Workspaces 21 | Boson achieves multi-tenancy through the use of a composable service architecture (with Docker Compose.) The **Boson kernel** is the base image used across all tenants and is preinstalled with common dependencies and integration logic. The kernel cannot be spun up by itself and instead, needs to be *instanced* with an overriding workspace Docker Compose file. 22 | 23 | This standardises the developer experience and abstracts away architectural and platform overhead, while allowing for full workspace isolation, including: 24 | - Independent Docker volumes 25 | - Independent Python dependencies 26 | - Tailored compute allocations 27 | - Independent environment variables 28 | - Individually deployable workspaces 29 | 30 | ### Analysing Example - Instacart Workspace 31 | 32 | A workspace installs the **Boson Kernel**, its own Python dependencies and sets up any additional configuration defined it its Docker Compose file. A workspace is defined by a subfolder of `workspaces/`. The contents of this folder are copied into the workspace container during Docker build-time. In this instance, the workspace is defined at, `workspaces/example-instacart/`. 33 | 34 | This workspace has three files: 35 | 36 | #### `docker-compose.override.yml` 37 | 38 | **Mandatory** - a workspace overrides the base stack. 39 | 40 | ```yml 41 | version: "3.8" 42 | 43 | services: 44 | storage: 45 | volumes: 46 | - example_instacart_storage_data:/usr/src/app/localData 47 | - example_instacart_storage_meta:/usr/src/app/localMetadata 48 | 49 | workspace: 50 | build: 51 | context: ./workspaces/example-instacart 52 | args: 53 | WORKSPACE_NAME: "Example - Instacart" 54 | volumes: 55 | - example_instacart_aim_data:/aim-repo 56 | 57 | aim-init: 58 | volumes: 59 | - example_instacart_aim_data:/repo 60 | 61 | aim-ui: 62 | volumes: 63 | - example_instacart_aim_data:/repo 64 | 65 | volumes: 66 | example_instacart_storage_data: 67 | example_instacart_storage_meta: 68 | example_instacart_aim_data: 69 | ``` 70 | 71 | These overrides ensure that this workspace has its own Docker volumes for data isolation. 72 | 73 | #### `pyproject.toml` 74 | 75 | **Mandatory** - a workspace must define a Python project. 76 | 77 | ```toml 78 | [tool.poetry] 79 | name = "example-instacart" 80 | version = "0.1.0" 81 | description = "Example - Instacart" 82 | authors = ["Harry harry@myntlabs.io"] 83 | 84 | [tool.poetry.dependencies] 85 | python = "^3.12" 86 | seaborn = "^0.13.2" 87 | pandas = "^2.2.2" 88 | xgboost = "^3.0.0" 89 | scikit-learn = "^1.6.1" 90 | 91 | [build-system] 92 | requires = ["poetry-core"] 93 | build-backend = "poetry.core.masonry.api" 94 | ``` 95 | 96 | The Python project file defines its dependencies. 97 | 98 | #### `.env` 99 | 100 | Boson must be provided a `.env` file with the below environment variables, but it does not have to be scoped to a workspace. 101 | 102 | ```.env 103 | STORAGE_USER=admin 104 | STORAGE_PASSWORD=password 105 | BOSON_PORT=8889 106 | ``` 107 | 108 | Please ensure that the `BOSON_PORT` differs from any other workspaces currently running. `STORAGE_USER` and `STORAGE_PASSWORD` are only used by internal services but can be configured. 109 | 110 | ## Modular Components 111 | 112 | ### Aim Experiment Tracking 113 | 114 | Boson incorporates [Aim](https://github.com/aimhubio/aim) for model experiment tracking. Aim is a powerful yet simple mechanism to track metrics, store configuration, monitor performance and log artifacts during ML research and development. Please refer to the Aim docs for usage instructions. 115 | 116 | To instantiate an Aim run, refer to the built in [new_run](builtins#new_runargs-kwargs---run) function. 117 | 118 | The Aim UI can be accessed clicking on the first button (conical flask icon) in the left sidebar: 119 | 120 | ![experiment-tracker-icon](../assets/static/experiment-tracker-button.png) 121 | 122 | Clicking this button will open up the Aim UI in a new JupyterLab tab: 123 | 124 | ![experiment-tracker](../assets/static/experiment-tracker.png) 125 | 126 | ### Delta Explorer 127 | 128 | The Delta Explorer is a Boson Tool that constantly scans the internal Delta Lake for Delta Tables, retrieves associated metadata and visually displays these tables - avoiding the need to manually query the Delta Lake constantly during development. 129 | 130 | The Delta Explorer can be opened by clicking on the second button (database search icon) in the left sidebar: 131 | 132 | ![delta-explorer](../assets/static/delta-explorer.png) -------------------------------------------------------------------------------- /docs/example-instacart.md: -------------------------------------------------------------------------------- 1 | # Instacart Example Walkthrough 2 | 3 | This example explores the [Kaggle Instacart](https://www.kaggle.com/datasets/yasserh/instacart-online-grocery-basket-analysis-dataset) prediction problem. This walkthrough covers: 4 | 5 | - Data loading 6 | - Lazily executed data transformations 7 | - Reading/writing Delta Tables 8 | - Model training 9 | - Model experiment tracking and evaluation 10 | - Delta Explorer and Experiment Tracker 11 | 12 | ## Setting up 13 | Firstly, follow the [Quickstart](../README.md#-quickstart) 14 | 15 | Next, drag and drop the contents of `assets/examples/example-instacart/` into the File Browser: 16 | 17 | ![file-browser](../assets/static/file-browser.png) 18 | 19 | ## Follow-along 20 | 21 | ### 1. Load data 22 | 23 | Run all cells in the `load_data.ipynb` notebook. 24 | 25 | A new folder, `instacart-data` should be created with six csvs inside. 26 | 27 | The `orders` table should be displayed at the bottom of the notebook: 28 | 29 | ![load-data](../assets/static/load-data.png) 30 | 31 | ### 2. Explore data 32 | 33 | Run all cells in the `explore_data.ipynb` notebook. 34 | 35 | The `top_products` dataframe should be displayed at the bottom of the notebook: 36 | 37 | ![explore-data](../assets/static/explore-data.png) 38 | 39 | ### 3. Create features 40 | 41 | Run all cells in the `create_features.ipynb` notebook. 42 | 43 | The newly created Delta Table, `final_features`, should be visible in the Delta Explorer: 44 | 45 | ![delta-explorer-example](../assets/static/delta-explorer-example.png) 46 | 47 | ### 4. Train model 48 | 49 | Run all cells in the `train_model.ipynb` notebook. This may take a few minutes. 50 | 51 | The classification matrix should be printed at the bottom of the notebook: 52 | 53 | ![decision-matrix](../assets/static/classification-matrix.png) 54 | 55 | ### 5. Inspect experiment 56 | 57 | Click on the Experiment Tracker button (conical flask icon) at the top of the left sidebar. The Experiment Tracker should be opened in a new tab. 58 | 59 | Click on "Runs" in the top left corner of the Experiment Tracker tab. 60 | Click on the name of the first run (should be similar to `Run: eb716e6a66854516863724c3`.) 61 | Click on "Metrics" in the top tool bar. 62 | 63 | Multiple training iteration metrics should be visible: 64 | 65 | ![experiment-tracker-example](../assets/static/experiment-tracker-example.png) -------------------------------------------------------------------------------- /kernel/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim 2 | 3 | # System dependencies 4 | RUN apt-get update && apt-get install -y \ 5 | build-essential \ 6 | curl \ 7 | jq \ 8 | s3fs \ 9 | fuse \ 10 | git && \ 11 | curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ 12 | apt-get install -y nodejs && \ 13 | apt-get clean 14 | 15 | # Install Poetry 16 | RUN pip install --no-cache-dir poetry 17 | RUN pip install aim 18 | 19 | COPY README.md README.md 20 | COPY pyproject.toml pyproject.toml 21 | COPY kernel/ kernel/ 22 | RUN poetry config virtualenvs.create false 23 | RUN poetry install 24 | 25 | # Inject local dependencies 26 | COPY jupyter_notebook_config.py /root/.jupyter/jupyter_notebook_config.py 27 | 28 | RUN mkdir -p /root/.jupyter 29 | RUN mkdir -p /root/.ipython/profile_default/startup 30 | COPY kernel/globals.py /root/.ipython/profile_default/startup/00-load-globals.py 31 | 32 | # Install Jupyter extensions 33 | 34 | COPY jupyter-lab-ext/experiment-tracker /root/.jupyter-extensions/experiment-tracker 35 | WORKDIR /root/.jupyter-extensions/experiment-tracker 36 | RUN npm install && \ 37 | npm run build && \ 38 | jupyter labextension install . 39 | 40 | COPY jupyter-lab-ext/delta-explorer /root/.jupyter-extensions/delta-explorer 41 | WORKDIR /root/.jupyter-extensions/delta-explorer 42 | RUN npm install && \ 43 | npm run build && \ 44 | jupyter labextension install . 45 | 46 | 47 | RUN jupyter labextension disable @jupyterlab/apputils-extension:splash 48 | 49 | COPY jupyter-lab-ext/theme /root/.jupyter-extensions/theme 50 | WORKDIR /root/.jupyter-extensions/theme 51 | RUN npm install && \ 52 | npm run build && \ 53 | jupyter labextension install . 54 | 55 | # Override Jupyter source 56 | COPY jupyter-lab-ext/favicon.ico /usr/local/lib/python3.12/site-packages/jupyter_server/static/favicons/favicon.ico 57 | COPY jupyter-lab-ext/favicon.ico /usr/local/lib/python3.12/site-packages/jupyter_server/static/favicons/favicon-busy-1.ico 58 | 59 | # Inject mount instructions 60 | COPY mount-cloud-storage.sh /root/.mount-cloud-storage.sh 61 | 62 | WORKDIR /workspace -------------------------------------------------------------------------------- /kernel/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/kernel/README.md -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/delta-explorer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "delta-explorer", 3 | "version": "0.1.0", 4 | "description": "A Jupyterlab extension that embeds a Delta Lake explorer.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "watch": "webpack --watch" 9 | }, 10 | "devDependencies": { 11 | "webpack": "^5.0.0", 12 | "webpack-cli": "^4.0.0", 13 | "ts-loader": "^9.0.0", 14 | "typescript": "^4.0.0" 15 | }, 16 | "dependencies": { 17 | "@jupyterlab/application": "^4.0.0", 18 | "@jupyterlab/apputils": "^4.0.0", 19 | "@lumino/widgets": "^2.0.0" 20 | }, 21 | "jupyterlab": { 22 | "extension": "lib/index.js" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/delta-explorer/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JupyterFrontEnd, 3 | JupyterFrontEndPlugin 4 | } from '@jupyterlab/application'; 5 | 6 | import { IFrame } from '@jupyterlab/apputils'; 7 | import { LabIcon } from '@jupyterlab/ui-components'; 8 | import { PanelLayout, Widget } from '@lumino/widgets'; 9 | 10 | // Database Search Material Icon SVG (inlined) 11 | const searchIcon = new LabIcon({ 12 | name: 'delta-explorer:search', 13 | svgstr: ` 14 | 15 | 16 | 17 | ` 18 | }); 19 | 20 | const plugin: JupyterFrontEndPlugin = { 21 | id: 'delta-explorer', 22 | autoStart: true, 23 | activate: (app: JupyterFrontEnd) => { 24 | // Create an IFrame to load external content 25 | const content = new IFrame(); 26 | content.url = '/delta/'; 27 | content.id = 'delta-explorer-iframe'; 28 | content.title.label = 'Delta Explorer'; 29 | content.title.closable = true; 30 | content.addClass('delta-explorer-iframe'); 31 | content.sandbox = ['allow-scripts', 'allow-same-origin', 'allow-forms', 'allow-popups']; 32 | 33 | // Wrap the iframe in a widget for the sidebar 34 | const widget = new Widget(); 35 | widget.id = 'delta-explorer-panel'; 36 | widget.title.icon = searchIcon; 37 | widget.title.caption = 'Delta Explorer'; 38 | widget.addClass('delta-explorer-panel'); 39 | 40 | const layout = new PanelLayout(); 41 | layout.addWidget(content); 42 | widget.layout = layout; 43 | 44 | // Add to the left sidebar at the top 45 | app.shell.add(widget, 'left', { rank: 0 }); 46 | } 47 | }; 48 | 49 | export default plugin; 50 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/delta-explorer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": ["ES2020", "DOM"], 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "skipLibCheck": true, 11 | "outDir": "lib" 12 | }, 13 | "include": ["src/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/delta-explorer/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.ts', 5 | output: { 6 | filename: 'index.js', 7 | path: path.resolve(__dirname, 'lib'), 8 | libraryTarget: 'amd', 9 | publicPath: '' 10 | }, 11 | resolve: { 12 | extensions: ['.ts', '.js'] 13 | }, 14 | module: { 15 | rules: [{ test: /\.ts$/, use: 'ts-loader' }] 16 | }, 17 | externals: [ 18 | /^@jupyterlab\/.+/, 19 | /^@lumino\/.+/ 20 | ], 21 | mode: 'development' 22 | }; 23 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/experiment-tracker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aim-ui", 3 | "version": "0.1.0", 4 | "description": "A Jupyterlab extension that embeds Aim experiment tracker.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "watch": "webpack --watch" 9 | }, 10 | "devDependencies": { 11 | "webpack": "^5.0.0", 12 | "webpack-cli": "^4.0.0", 13 | "ts-loader": "^9.0.0", 14 | "typescript": "^4.0.0" 15 | }, 16 | "dependencies": { 17 | "@jupyterlab/application": "^4.0.0", 18 | "@jupyterlab/apputils": "^4.0.0", 19 | "@lumino/widgets": "^2.0.0" 20 | }, 21 | "jupyterlab": { 22 | "extension": "lib/index.js" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/experiment-tracker/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JupyterFrontEnd, 3 | JupyterFrontEndPlugin 4 | } from '@jupyterlab/application'; 5 | 6 | import { 7 | MainAreaWidget, 8 | IFrame, 9 | WidgetTracker 10 | } from '@jupyterlab/apputils'; 11 | 12 | const plugin: JupyterFrontEndPlugin = { 13 | id: 'experiment-tracker', 14 | autoStart: true, 15 | activate: (app: JupyterFrontEnd) => { 16 | const tracker = new WidgetTracker({ namespace: 'experiment-tracker' }); 17 | 18 | const openTab = async () => { 19 | let widget = tracker.find(() => true); 20 | if (widget) { 21 | app.shell.activateById(widget.id); 22 | return; 23 | } 24 | 25 | const iframe = new IFrame(); 26 | iframe.url = '/aim/'; 27 | iframe.title.label = 'Experiment Tracker'; 28 | iframe.title.closable = true; 29 | iframe.id = 'experiment-tracker-frame'; 30 | iframe.sandbox = ['allow-scripts', 'allow-same-origin']; 31 | 32 | widget = new MainAreaWidget({ content: iframe }); 33 | await tracker.add(widget); 34 | app.shell.add(widget, 'main'); 35 | app.shell.activateById(widget.id); 36 | }; 37 | 38 | const inject = () => { 39 | const sidebar = document.querySelector('.jp-SideBar.jp-mod-left'); 40 | if (!sidebar) { 41 | requestAnimationFrame(inject); 42 | return; 43 | } 44 | 45 | if (sidebar.querySelector('.experiment-tracker-static-icon')) return; 46 | 47 | const container = document.createElement('div'); 48 | container.className = 'experiment-tracker-static-icon'; 49 | container.title = 'Experiment Tracker'; 50 | container.style.display = 'flex'; 51 | container.style.alignItems = 'center'; 52 | container.style.justifyContent = 'center'; 53 | container.style.height = '52px'; 54 | container.style.cursor = 'pointer'; 55 | container.style.opacity = '0.9'; 56 | 57 | const icon = document.createElement('div'); 58 | icon.innerHTML = ` 59 | 60 | `; 61 | 62 | container.appendChild(icon); 63 | 64 | container.addEventListener('click', () => { 65 | openTab(); 66 | }); 67 | 68 | sidebar.insertBefore(container, sidebar.firstChild); 69 | }; 70 | 71 | app.restored.then(() => { 72 | requestAnimationFrame(inject); 73 | }); 74 | } 75 | }; 76 | 77 | export default plugin; -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/experiment-tracker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": ["ES2020", "DOM"], 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "skipLibCheck": true, 11 | "outDir": "lib" 12 | }, 13 | "include": ["src/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/experiment-tracker/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.ts', 5 | output: { 6 | filename: 'index.js', 7 | path: path.resolve(__dirname, 'lib'), 8 | libraryTarget: 'amd', 9 | publicPath: '' 10 | }, 11 | resolve: { 12 | extensions: ['.ts', '.js'] 13 | }, 14 | module: { 15 | rules: [{ test: /\.ts$/, use: 'ts-loader' }] 16 | }, 17 | externals: [ 18 | /^@jupyterlab\/.+/, 19 | /^@lumino\/.+/ 20 | ], 21 | mode: 'development' 22 | }; 23 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/kernel/jupyter-lab-ext/favicon.ico -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theme", 3 | "version": "0.1.0", 4 | "description": "A Jupyterlab extension that embeds a Delta Lake explorer.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "watch": "webpack --watch" 9 | }, 10 | "devDependencies": { 11 | "webpack": "^5.0.0", 12 | "webpack-cli": "^4.0.0", 13 | "ts-loader": "^9.0.0", 14 | "typescript": "^4.0.0", 15 | "style-loader": "^3.3.1", 16 | "css-loader": "^6.7.1" 17 | }, 18 | "dependencies": { 19 | "@jupyterlab/application": "^4.0.0", 20 | "@jupyterlab/apputils": "^4.0.0", 21 | "@lumino/widgets": "^2.0.0" 22 | }, 23 | "jupyterlab": { 24 | "extension": "lib/index.js" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/src/custom.d.ts: -------------------------------------------------------------------------------- 1 | // src/custom.d.ts 2 | declare module '*.gif'; 3 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JupyterFrontEnd, 3 | JupyterFrontEndPlugin 4 | } from '@jupyterlab/application'; 5 | 6 | import { IDisposable, DisposableDelegate } from '@lumino/disposable'; 7 | import { ISplashScreen } from '@jupyterlab/apputils'; 8 | import { Widget } from '@lumino/widgets'; 9 | 10 | import splashGif from '../style/boson-logo-animated-fast.gif'; 11 | import '../style/base.css'; 12 | 13 | // Jupyter reference 14 | 15 | const poweredByPlugin: JupyterFrontEndPlugin = { 16 | id: 'custom-powered-by-label', 17 | autoStart: true, 18 | activate: (app: JupyterFrontEnd) => { 19 | const topBarObserver = new MutationObserver(() => { 20 | const topBar = document.getElementById('jp-top-bar'); 21 | if (!topBar) { 22 | return; 23 | } 24 | const container = new Widget(); 25 | container.node.innerHTML = ` 26 | 40 | 45 | 46 | 47 | 48 | Powered by JupyterLab 49 | 50 | `; 51 | container.id = 'custom-powered-by-label'; 52 | topBar.appendChild(container.node); 53 | topBarObserver.disconnect(); 54 | }); 55 | topBarObserver.observe(document.body, { childList: true, subtree: true }); 56 | } 57 | }; 58 | 59 | // Splash 60 | 61 | const customSplashPlugin: JupyterFrontEndPlugin = { 62 | id: 'myorg:custom-splash', 63 | autoStart: true, 64 | provides: ISplashScreen, 65 | activate: () => ({ 66 | show: (light = true) => Private.showSplash(light) 67 | }) 68 | }; 69 | 70 | namespace Private { 71 | function createSplash(light: boolean): HTMLElement { 72 | const splash = document.createElement('div'); 73 | splash.id = 'jp-CustomSplash'; 74 | splash.classList.toggle('light', light); 75 | splash.classList.toggle('dark', !light); 76 | 77 | const img = document.createElement('img'); 78 | // Just use the inlined data: URI directly: 79 | img.src = splashGif; 80 | img.alt = 'Loading…'; 81 | img.style.width = '400px'; 82 | 83 | splash.appendChild(img); 84 | return splash; 85 | } 86 | 87 | /** 88 | * Show until JLab calls `.dispose()`. Enforces a 0.8s minimum 89 | * hold, then fade‑out & removal. 90 | */ 91 | export function showSplash(light: boolean): IDisposable { 92 | const element = createSplash(light); 93 | document.body.appendChild(element); 94 | 95 | const start = Date.now(); 96 | return new DisposableDelegate(() => { 97 | const elapsed = Date.now() - start; 98 | const toWait = Math.max(0, 800 - elapsed); 99 | 100 | setTimeout(() => { 101 | element.classList.add('splash-fade'); 102 | setTimeout(() => { 103 | element.remove(); 104 | }, 100); 105 | }, toWait); 106 | }); 107 | } 108 | } 109 | 110 | const plugins: JupyterFrontEndPlugin[] = [ 111 | poweredByPlugin, 112 | customSplashPlugin 113 | ]; 114 | export default plugins; -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/style/base.css: -------------------------------------------------------------------------------- 1 | /* 2 | See the JupyterLab Developer Guide for useful CSS Patterns: 3 | 4 | https://jupyterlab.readthedocs.io/en/stable/developer/css.html 5 | */ 6 | 7 | /* Theme */ 8 | 9 | .lm-DockPanel-tabBar .lm-TabBar-tab.jp-mod-current::before { 10 | background: #4831a7 !important; 11 | } 12 | 13 | .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser { 14 | background: #4831a7 !important; 15 | } 16 | 17 | .jp-Notebook .jp-Cell .jp-InputPrompt { 18 | color: #4831a7 !important; 19 | } 20 | 21 | .jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor { 22 | border: var(--jp-border-width) solid #4831a7 !important; 23 | } 24 | 25 | #jp-MainLogo { 26 | width: 21px; 27 | height: 21px; 28 | margin-top: 4px; 29 | margin-left: 4px; 30 | background-image: url("data:image/svg+xml,%3Csvg viewBox='262.144 266.24 483.328 487.424' xmlns='http://www.w3.org/2000/svg' version='1.2' style='max-height: 500px' width='483.328' height='487.424'%3E%3Cstyle%3E.a%7Bfill:%234831a7%7D.b%7Bfill:%23febc18%7D%3C/style%3E%3Cpath d='m663.8 645.2c-9 7.7-9.6 7.4-20.2 12.9-11.8 6.2-12 6.2-24.7 10-14 4.1-14.3 4-28.9 5.4-13.7 1.3-13.8-0.1-27.6 0.2-1.5 0.1-2.7-0.2-2.9 0.2-0.8 1.4 4.4 3.1 9.2 5.3 14.9 6.9 15.3 7 31.3 10.2 21.1 4.1 21.9 4.3 43.3 2.1 14.8-1.5 28-7 29.4-6.4 1.8 0.7-17.1 9.1-35.4 12.5-8.7 1.6-8.9 1.1-17.7 1.3-9.8 0.3-9.9 0.4-19.6-0.5-12.4-1-12.5-1.1-24.7-3.9-21.3-4.9-21.5-5.3-41.5-13.9-21.9-9.4-22-9.9-42.1-22.7-13-8.2-13-8.3-25.1-17.8-11.2-8.8-11.3-8.8-21.6-18.6-9.9-9.4-9.8-9.6-19-19.9-13.1-14.8-13.1-14.9-24.9-30.9-10.1-13.7-10.4-13.5-19.1-28.1-10.9-18.2-10.8-18.5-19.3-37.9-10.3-23.4-11.4-23.4-17.4-48.1-5.2-21.3-7.6-42.2-6.3-43.6 1.5-1.6 5.3 26.6 14.3 48.3 9.6 23.1 24.6 44.7 24.6 44.7l-1.7-192.5 206.8 1.5c0 0 40.6 4.9 69 27 10.7 8.3 10.9 9.4 18.2 21.2 4.3 6.8 4.5 7 7 14.7 2.8 8.3 2.5 8.6 3.3 17.3 1.4 16 2.3 17-1.6 32.3-5.1 19.6-6.4 21.2-19.9 36.5-6.2 7-6.8 6.7-14.6 12.2-6.7 4.7-15.4 4.6-14.1 8.3 0.5 1.3 2.6 1.2 5.1 2.4 12.4 6.2 13.3 4.9 24.5 12.9 10.9 7.8 11.9 7.8 19.8 18.6 5.8 8 5.9 8.5 9.2 17.8 7.1 20.3 7 22 5.4 43.3-1.6 22.5-1.6 24.7-12.8 44.3-6.8 11.8-7.4 12.3-17.7 21.4zm-205.8-123.2v88h108c0 0 24.4-1.5 36-14.9 9.4-10.9 10.5-15.3 10-30.1-0.6-16.4-2.3-21.4-14.3-32.2-11.4-10.2-31.7-10.8-31.7-10.8zm0-144v82h94c0 0 24.4-0.5 36.1-13.5 9.1-10.1 10.4-14.4 9.9-28.5-0.6-14.2-2.1-18.3-12.3-28.1-10.3-9.7-28.7-10.9-28.7-10.9z' class='a' fill-rule='evenodd'/%3E%3Cpath d='m422.6 275.4c-0.2 0.4-4.4 0.5-5.6 0.6-1.2 0-2.7-0.1-7.8 0.6-8.1 1.2-19.7 4.2-27.9 7.6-19.1 8.1-31.3 22.8-31.3 22.8 0 0-8.7 10.6-15.5 25.8-4 8.9-6.5 19.4-8.5 30.2-2.3 12-1.3 19.5-1.2 26.1 0.2 9.5 0.6 17.3 3.2 34.9 3.7 25.1 7.2 39.1 11 51.6 4.2 13.6 9 25.5 21 50.4 11.2 23.2 18.3 34.4 25.7 45.4 6.8 10 13.6 20.7 29.2 38.2 21.8 24.4 33.1 34.6 46.7 45.2 10.6 8.1 22.2 17.4 44.7 28.2 24.8 12 39.4 16.5 54.5 19.5 6.1 1.2 11.6 2.3 19.1 3 4.5 0.4 9.7 1 16.1 0.5 11.6-0.9 24.2-1.5 36-4 13.8-2.9 26.6-7.9 37.1-14.3 10.2-6.3 19-12.5 25.4-19.4 10.6-11.3 15.5-22.3 15.5-22.3 0 0 8.4-23.6 9.1-46.8 0.5-13.4-0.9-26.3-2.1-34.7-0.8-5.3-2.2-9.2-1-9.5 1.3-0.4 1.7 2 2.9 4.7 0.9 2.2 2.1 5 3.3 8.5 2.1 5.8 5.3 11.9 7.6 20.7 4.6 17.7 11 41.1 8.2 62.1-2.5 18.1-6.1 28.5-10.6 38.4-4.1 9.2-8.6 18.1-20.4 29.6-14.1 13.7-26 19.7-37.7 23.8-9.8 3.6-19.4 6.4-31.9 7.1-8.5 0.4-10.1 0.2-21.9 0.1-5.3-0.1-23.2-3.7-27.9-4.7-12.9-2.5-19-4.9-27.4-7.2-7.3-2-13.2-3.8-19.7-6.3-5-2-11.3-4.7-16.5-7.4-10.1-5.2-20.4-11.2-37.5-21-9.7-5.6-16.8-10.5-22.9-14.9-7.4-5.3-13.2-10-18.7-14.4-11.5-9-22.8-17.3-42.9-37.1-27.9-27.5-42-44.3-54.8-60.3-7.2-8.8-13.8-18-20.7-28.7-8.2-12.5-16.9-27.6-27.7-50.6-15.4-33-22-46.7-26.3-67.7-1.4-7.1-3.7-12.6-4.5-22.5-0.4-4.3-1.8-22.1-1.5-27.2 0.6-12.4 0.4-6.2 1.1-14.3 1.1-11.2 4-24.4 8.6-34 5.9-12.1 16.8-28.7 32.6-41.1 19.6-15.4 37.2-19.5 61.1-20.7 13.8-0.7 16.3-0.2 26.7 1 4.2 0.5 9 1.5 14.7 2.3 2.5 0.4 6.8 1 8.8 1.3 1.3 0.2 2.7 0.5 2.5 0.9zm0 0c-0.2 0.4-4.4 0.5-5.6 0.6-1.2 0-2.7-0.1-7.8 0.6-8.1 1.2-19.7 4.2-27.9 7.6-19.1 8.1-31.3 22.8-31.3 22.8 0 0-8.7 10.6-15.5 25.8-4 8.9-6.5 19.4-8.5 30.2-2.3 12-1.3 19.5-1.2 26.1 0.2 9.5 0.6 17.3 3.2 34.9 3.7 25.1 7.2 39.1 11 51.6 4.2 13.6 9 25.5 21 50.4 11.2 23.2 18.3 34.4 25.7 45.4 6.8 10 13.6 20.7 29.2 38.2 21.8 24.4 33.1 34.6 46.7 45.2 10.6 8.1 22.2 17.4 44.7 28.2 24.8 12 39.4 16.5 54.5 19.5 6.1 1.2 11.6 2.3 19.1 3 4.5 0.4 9.7 1 16.1 0.5 11.6-0.9 24.2-1.5 36-4 13.8-2.9 26.6-7.9 37.1-14.3 10.2-6.3 19-12.5 25.4-19.4 10.6-11.3 15.5-22.3 15.5-22.3 0 0 8.4-23.6 9.1-46.8 0.5-13.4-0.9-26.3-2.1-34.7-0.8-5.3-2.2-9.2-1-9.5 1.3-0.4 1.7 2 2.9 4.7 0.9 2.2 2.1 5 3.3 8.5 2.1 5.8 5.3 11.9 7.6 20.7 4.6 17.7 11 41.1 8.2 62.1-2.5 18.1-6.1 28.5-10.6 38.4-4.1 9.2-8.6 18.1-20.4 29.6-14.1 13.7-26 19.7-37.7 23.8-9.8 3.6-19.4 6.4-31.9 7.1-8.5 0.4-10.1 0.2-21.9 0.1-5.3-0.1-23.2-3.7-27.9-4.7-12.9-2.5-19-4.9-27.4-7.2-7.3-2-13.2-3.8-19.7-6.3-5-2-11.3-4.7-16.5-7.4-10.1-5.2-20.4-11.2-37.5-21-9.7-5.6-16.8-10.5-22.9-14.9-7.4-5.3-13.2-10-18.7-14.4-11.5-9-22.8-17.3-42.9-37.1-27.9-27.5-42-44.3-54.8-60.3-7.2-8.8-13.8-18-20.7-28.7-8.2-12.5-16.9-27.6-27.7-50.6-15.4-33-22-46.7-26.3-67.7-1.4-7.1-3.7-12.6-4.5-22.5-0.4-4.3-1.8-22.1-1.5-27.2 0.6-12.4 0.4-6.2 1.1-14.3 1.1-11.2 4-24.4 8.6-34 5.9-12.1 16.8-28.7 32.6-41.1 19.6-15.4 37.2-19.5 61.1-20.7 13.8-0.7 16.3-0.2 26.7 1 4.2 0.5 9 1.5 14.7 2.3 2.5 0.4 6.8 1 8.8 1.3 1.3 0.2 2.7 0.5 2.5 0.9zm0 0c-0.2 0.4-4.4 0.5-5.6 0.6-1.2 0-2.7-0.1-7.8 0.6-8.1 1.2-19.7 4.2-27.9 7.6-19.1 8.1-31.3 22.8-31.3 22.8 0 0-8.7 10.6-15.5 25.8-4 8.9-6.5 19.4-8.5 30.2-2.3 12-1.3 19.5-1.2 26.1 0.2 9.5 0.6 17.3 3.2 34.9 3.7 25.1 7.2 39.1 11 51.6 4.2 13.6 9 25.5 21 50.4 11.2 23.2 18.3 34.4 25.7 45.4 6.8 10 13.6 20.7 29.2 38.2 21.8 24.4 33.1 34.6 46.7 45.2 10.6 8.1 22.2 17.4 44.7 28.2 24.8 12 39.4 16.5 54.5 19.5 6.1 1.2 11.6 2.3 19.1 3 4.5 0.4 9.7 1 16.1 0.5 11.6-0.9 24.2-1.5 36-4 13.8-2.9 26.6-7.9 37.1-14.3 10.2-6.3 19-12.5 25.4-19.4 10.6-11.3 15.5-22.3 15.5-22.3 0 0 8.4-23.6 9.1-46.8 0.5-13.4-0.9-26.3-2.1-34.7-0.8-5.3-2.2-9.2-1-9.5 1.3-0.4 1.7 2 2.9 4.7 0.9 2.2 2.1 5 3.3 8.5 2.1 5.8 5.3 11.9 7.6 20.7 4.6 17.7 11 41.1 8.2 62.1-2.5 18.1-6.1 28.5-10.6 38.4-4.1 9.2-8.6 18.1-20.4 29.6-14.1 13.7-26 19.7-37.7 23.8-9.8 3.6-19.4 6.4-31.9 7.1-8.5 0.4-10.1 0.2-21.9 0.1-5.3-0.1-23.2-3.7-27.9-4.7-12.9-2.5-19-4.9-27.4-7.2-7.3-2-13.2-3.8-19.7-6.3-5-2-11.3-4.7-16.5-7.4-10.1-5.2-20.4-11.2-37.5-21-9.7-5.6-16.8-10.5-22.9-14.9-7.4-5.3-13.2-10-18.7-14.4-11.5-9-22.8-17.3-42.9-37.1-27.9-27.5-42-44.3-54.8-60.3-7.2-8.8-13.8-18-20.7-28.7-8.2-12.5-16.9-27.6-27.7-50.6-15.4-33-22-46.7-26.3-67.7-1.4-7.1-3.7-12.6-4.5-22.5-0.4-4.3-1.8-22.1-1.5-27.2 0.6-12.4 0.4-6.2 1.1-14.3 1.1-11.2 4-24.4 8.6-34 5.9-12.1 16.8-28.7 32.6-41.1 19.6-15.4 37.2-19.5 61.1-20.7 13.8-0.7 16.3-0.2 26.7 1 4.2 0.5 9 1.5 14.7 2.3 2.5 0.4 6.8 1 8.8 1.3 1.3 0.2 2.7 0.5 2.5 0.9z' class='b'/%3E%3C/svg%3E"); 31 | background-size: cover; 32 | background-repeat: no-repeat; 33 | background-position: center; 34 | } 35 | 36 | #jp-MainLogo > svg { 37 | visibility: hidden; 38 | } 39 | 40 | .jp-notebook-icon-color[fill] { 41 | fill: #febc18 !important; 42 | } 43 | 44 | jp-button[data-command="launcher:create"] { 45 | background-color: #4831a7 !important; 46 | } 47 | 48 | .jp-DirListing-item.jp-mod-selected { 49 | background-color: #4831a7 !important; 50 | } 51 | 52 | 53 | /* Splash */ 54 | 55 | 56 | #jp-CustomSplash { 57 | position: fixed; 58 | inset: 0; 59 | background-color: #fff; 60 | z-index: 9999; 61 | display: flex; 62 | align-items: center; 63 | justify-content: center; 64 | 65 | /* start fully visible */ 66 | opacity: 1; 67 | transition: opacity 0.1s ease; 68 | } 69 | 70 | /* fade‑out both backdrop & GIF */ 71 | #jp-CustomSplash.splash-fade { 72 | opacity: 0; 73 | } -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/style/boson-logo-animated-fast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/kernel/jupyter-lab-ext/theme/style/boson-logo-animated-fast.gif -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/style/index.js: -------------------------------------------------------------------------------- 1 | import './base.css'; -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": ["ES2020", "DOM"], 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "skipLibCheck": true, 11 | "outDir": "lib" 12 | }, 13 | "include": ["src/**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /kernel/jupyter-lab-ext/theme/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.ts', 5 | output: { 6 | filename: 'index.js', 7 | path: path.resolve(__dirname, 'lib'), 8 | libraryTarget: 'amd', 9 | publicPath: '' 10 | }, 11 | resolve: { 12 | extensions: ['.ts', '.js'] 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.ts$/, 18 | use: 'ts-loader' 19 | }, 20 | { 21 | test: /\.css$/, 22 | use: ['style-loader', 'css-loader'] 23 | }, 24 | { 25 | test: /\.gif$/i, 26 | type: 'asset/inline' 27 | }, 28 | { 29 | test: /\.(png|jpe?g|svg)$/i, 30 | type: 'asset/resource', 31 | generator: { 32 | filename: 'static/[name][ext]' 33 | } 34 | } 35 | ] 36 | }, 37 | externals: [ 38 | /^@jupyterlab\/.+/, 39 | /^@lumino\/.+/ 40 | ], 41 | mode: 'development' 42 | }; 43 | -------------------------------------------------------------------------------- /kernel/jupyter_notebook_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | def set_doc_manager_settings(): 5 | settings_file = os.path.expanduser( 6 | "~/.jupyter/lab/user-settings/@jupyterlab/docmanager-extension/plugin.jupyterlab-settings" 7 | ) 8 | 9 | os.makedirs(os.path.dirname(settings_file), exist_ok=True) 10 | 11 | settings = {} 12 | settings["defaultViewers"] = {} 13 | settings["defaultViewers"]["csv"] = "editor" 14 | 15 | with open(settings_file, "w") as f: 16 | json.dump(settings, f, indent=4) 17 | 18 | set_doc_manager_settings() 19 | 20 | 21 | c = get_config() 22 | 23 | c.ServerApp.allow_origin = '*' 24 | c.ServerApp.token = '' 25 | c.ServerApp.base_url = '/' 26 | c.ServerApp.default_url = '/lab' 27 | 28 | c.ServerApp.root_dir = "/mnt/metastore/workspace" 29 | 30 | c.Completer.use_jedi = False 31 | 32 | c.LanguageServerManager.language_servers = { 33 | "pylsp": { 34 | "argv": ["pylsp"], 35 | "languages": ["python"], 36 | "mime_types": ["text/x-python"], 37 | "version": 2, 38 | "languageId": "python", 39 | "workspace_configuration": { 40 | "pylsp.plugins.pydocstyle.enabled": False, 41 | "pylsp.plugins.pyflakes.enabled": False, 42 | "pylsp.plugins.mccabe.enabled": False, 43 | "pylsp.plugins.pylint.enabled": False, 44 | "pylsp.plugins.pycodestyle.enabled": False, 45 | "pylsp.plugins.ruff.enabled": True 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /kernel/kernel/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flintml/flint/0a67205272a07ae71c9d546e982d8804b1304692/kernel/kernel/__init__.py -------------------------------------------------------------------------------- /kernel/kernel/globals.py: -------------------------------------------------------------------------------- 1 | import os 2 | import polars as pl 3 | from perspective.widget import PerspectiveWidget 4 | from aim import Run 5 | import boto3 6 | 7 | def write_delta(df: pl.DataFrame, table_name: str, *args, **kwargs): 8 | """ 9 | Save a Polars DataFrame to a Delta Lake table in blob storage. 10 | """ 11 | s3_uri = f"s3://metastore/delta/{table_name}" 12 | 13 | storage_options = { 14 | "AWS_REGION": "us-east-1", 15 | "AWS_ACCESS_KEY_ID": os.environ.get("STORAGE_USER"), 16 | "AWS_SECRET_ACCESS_KEY": os.environ.get("STORAGE_PASSWORD"), 17 | "AWS_ALLOW_HTTP": "true", 18 | "AWS_ENDPOINT_URL": f"http://storage:{os.environ.get("STORAGE_PORT")}" 19 | } 20 | 21 | # Force storage_options + target, pass everything else through 22 | kwargs["storage_options"] = storage_options 23 | 24 | df.write_delta(s3_uri, *args, **kwargs) 25 | 26 | def read_delta(table_name: str, *args, **kwargs) -> pl.DataFrame: 27 | """ 28 | Read a Delta Lake table from blob storage via Polars. 29 | """ 30 | s3_uri = f"s3://metastore/delta/{table_name}" 31 | 32 | storage_options = { 33 | "AWS_REGION": "us-east-1", 34 | "AWS_ACCESS_KEY_ID": os.environ.get("STORAGE_USER"), 35 | "AWS_SECRET_ACCESS_KEY": os.environ.get("STORAGE_PASSWORD"), 36 | "AWS_ALLOW_HTTP": "true", 37 | "AWS_ENDPOINT_URL": f"http://storage:{os.environ.get("STORAGE_PORT")}" 38 | } 39 | 40 | kwargs["storage_options"] = storage_options 41 | 42 | df = pl.read_delta(s3_uri, *args, **kwargs) 43 | return df 44 | 45 | def scan_delta(table_name: str, *args, **kwargs) -> pl.LazyFrame: 46 | """ 47 | Lazily scan a Delta Lake table from blob storage via Polars. 48 | """ 49 | s3_uri = f"s3://metastore/delta/{table_name}" 50 | 51 | storage_options = { 52 | "AWS_REGION": "us-east-1", 53 | "AWS_ACCESS_KEY_ID": os.environ.get("STORAGE_USER"), 54 | "AWS_SECRET_ACCESS_KEY": os.environ.get("STORAGE_PASSWORD"), 55 | "AWS_ALLOW_HTTP": "true", 56 | "AWS_ENDPOINT_URL": f"http://storage:{os.environ.get("STORAGE_PORT")}" 57 | } 58 | 59 | kwargs["storage_options"] = storage_options 60 | 61 | lf = pl.scan_delta(s3_uri, *args, **kwargs) 62 | return lf 63 | 64 | def drop_delta(table_name: str): 65 | """ 66 | Drop (delete) a Delta Lake table from cloud storage by removing all underlying files. 67 | """ 68 | bucket = "metastore" 69 | prefix = f"delta/{table_name}" 70 | 71 | access_key = os.environ.get("STORAGE_USER") 72 | secret_key = os.environ.get("STORAGE_PASSWORD") 73 | endpoint_url = f"http://storage:{os.environ.get('STORAGE_PORT')}" 74 | 75 | # Initialize S3 client 76 | s3 = boto3.resource( 77 | "s3", 78 | endpoint_url=endpoint_url, 79 | aws_access_key_id=access_key, 80 | aws_secret_access_key=secret_key 81 | ) 82 | 83 | bucket_obj = s3.Bucket(bucket) 84 | 85 | deleted = bucket_obj.objects.filter(Prefix=prefix).delete() 86 | return deleted 87 | 88 | def display(df: pl.DataFrame | pl.LazyFrame): 89 | """ 90 | Displays a Polars df or lf inline with notebook. 91 | """ 92 | return PerspectiveWidget( 93 | df, 94 | plugin="Datagrid", 95 | theme="Monokai" 96 | ) 97 | 98 | def new_run(*args, **kwargs) -> Run: 99 | """Creates an Aim Run at default repository location.""" 100 | 101 | return Run(repo="/aim-repo", *args, **kwargs) 102 | 103 | import builtins 104 | builtins.write_delta = write_delta 105 | builtins.read_delta = read_delta 106 | builtins.scan_delta = scan_delta 107 | builtins.drop_delta = drop_delta 108 | builtins.display = display 109 | builtins.new_run = new_run -------------------------------------------------------------------------------- /kernel/mount-cloud-storage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | mkdir -p /mnt/metastore 5 | 6 | echo "${STORAGE_USER}:${STORAGE_PASSWORD}" > /root/.passwd-s3fs 7 | chmod 600 /root/.passwd-s3fs 8 | 9 | s3fs metastore /mnt/metastore \ 10 | -o url=http://storage:${STORAGE_PORT} \ 11 | -o use_path_request_style \ 12 | -o passwd_file=/root/.passwd-s3fs \ 13 | -o nonempty \ 14 | -o allow_other \ 15 | -o endpoint=storage 16 | 17 | mkdir -p /mnt/metastore/workspace 18 | -------------------------------------------------------------------------------- /kernel/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "kernel" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Harry "] 6 | readme = "README.md" 7 | packages = [ 8 | { include = "kernel" } 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = "^3.12" 13 | jupyterlab = "^4.4.0" 14 | ipykernel = "^6.29.5" 15 | boto3 = ">=1.0.0,<1.36.0" 16 | s3contents = "^0.11.2" 17 | polars = "^1.27.1" 18 | deltalake = "^0.25.5" 19 | ipydatagrid = "^1.4.0" 20 | jupyterlab-widgets = "^3.0.14" 21 | ipywidgets = "^8.1.6" 22 | jupyterlab-lsp = "^5.1.0" 23 | python-lsp-server = { version = "^1.12.2", extras = ["all"] } 24 | python-lsp-ruff = "^2.2.2" 25 | perspective-python = "^3.5.1" 26 | fsspec = "^2025.3.2" 27 | s3fs = "^2025.3.2" 28 | 29 | 30 | [build-system] 31 | requires = ["poetry-core"] 32 | build-backend = "poetry.core.masonry.api" 33 | 34 | [tool.ruff] 35 | builtins = ["write_delta", "read_delta", "scan_delta", "drop_delta", "display", "new_run", "WORKSPACE_NAME"] -------------------------------------------------------------------------------- /nginx/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | 4 | # Reverse proxy to JupyterLab 5 | location / { 6 | proxy_pass http://workspace:8888; 7 | proxy_set_header Host $host; 8 | # WebSocket support: 9 | proxy_http_version 1.1; 10 | proxy_set_header Upgrade $http_upgrade; 11 | proxy_set_header Connection "upgrade"; 12 | } 13 | 14 | # Reverse proxy /aim-ui to aim-ui service 15 | location /aim/ { 16 | proxy_pass http://aim-ui:43800/aim/; 17 | proxy_set_header Host $host; 18 | # WebSocket support: 19 | proxy_http_version 1.1; 20 | proxy_set_header Upgrade $http_upgrade; 21 | proxy_set_header Connection "upgrade"; 22 | } 23 | 24 | # Reverse proxy /delta to delta-explorer service 25 | location /delta/ { 26 | proxy_pass http://delta-explorer:8501/delta/; 27 | proxy_set_header Host $host; 28 | # WebSocket support 29 | proxy_http_version 1.1; 30 | proxy_set_header Upgrade $http_upgrade; 31 | proxy_set_header Connection "upgrade"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /storage/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 8000, 3 | "listenOn": [], 4 | "replicationGroupId": "RG001", 5 | "restEndpoints": { 6 | "localhost": "us-east-1", 7 | "127.0.0.1": "us-east-1", 8 | "cloudserver-front": "us-east-1", 9 | "s3.docker.test": "us-east-1", 10 | "127.0.0.2": "us-east-1", 11 | "s3.amazonaws.com": "us-east-1", 12 | "zenko-cloudserver-replicator": "us-east-1", 13 | "lb": "us-east-1", 14 | "storage": "us-east-1" 15 | }, 16 | "websiteEndpoints": ["s3-website-us-east-1.amazonaws.com", 17 | "s3-website.us-east-2.amazonaws.com", 18 | "s3-website-us-west-1.amazonaws.com", 19 | "s3-website-us-west-2.amazonaws.com", 20 | "s3-website.ap-south-1.amazonaws.com", 21 | "s3-website.ap-northeast-2.amazonaws.com", 22 | "s3-website-ap-southeast-1.amazonaws.com", 23 | "s3-website-ap-southeast-2.amazonaws.com", 24 | "s3-website-ap-northeast-1.amazonaws.com", 25 | "s3-website.eu-central-1.amazonaws.com", 26 | "s3-website-eu-west-1.amazonaws.com", 27 | "s3-website-sa-east-1.amazonaws.com", 28 | "s3-website.localhost", 29 | "s3-website.scality.test", 30 | "zenkoazuretest.blob.core.windows.net"], 31 | "replicationEndpoints": [{ 32 | "site": "zenko", 33 | "servers": ["127.0.0.1:8000"], 34 | "default": true 35 | }, { 36 | "site": "us-east-2", 37 | "type": "aws_s3" 38 | }], 39 | "backbeat": { 40 | "host": "localhost", 41 | "port": 8900 42 | }, 43 | "workflowEngineOperator": { 44 | "host": "localhost", 45 | "port": 3001 46 | }, 47 | "cdmi": { 48 | "host": "localhost", 49 | "port": 81, 50 | "path": "/dewpoint", 51 | "readonly": true 52 | }, 53 | "bucketd": { 54 | "bootstrap": ["localhost:9000"] 55 | }, 56 | "vaultd": { 57 | "host": "localhost", 58 | "port": 8500 59 | }, 60 | "clusters": 1, 61 | "log": { 62 | "logLevel": "info", 63 | "dumpLevel": "error" 64 | }, 65 | "healthChecks": { 66 | "allowFrom": ["127.0.0.1/8", "::1"] 67 | }, 68 | "metadataClient": { 69 | "host": "localhost", 70 | "port": 9990 71 | }, 72 | "dataClient": { 73 | "host": "localhost", 74 | "port": 9991 75 | }, 76 | "pfsClient": { 77 | "host": "localhost", 78 | "port": 9992 79 | }, 80 | "metadataDaemon": { 81 | "bindAddress": "localhost", 82 | "port": 9990 83 | }, 84 | "dataDaemon": { 85 | "bindAddress": "localhost", 86 | "port": 9991 87 | }, 88 | "pfsDaemon": { 89 | "bindAddress": "localhost", 90 | "port": 9992 91 | }, 92 | "recordLog": { 93 | "enabled": true, 94 | "recordLogName": "s3-recordlog" 95 | }, 96 | "mongodb": { 97 | "replicaSetHosts": "localhost:27018,localhost:27019,localhost:27020", 98 | "writeConcern": "majority", 99 | "replicaSet": "rs0", 100 | "readPreference": "primary", 101 | "database": "metadata" 102 | }, 103 | "externalBackends": { 104 | "aws_s3": { 105 | "httpAgent": { 106 | "keepAlive": false, 107 | "keepAliveMsecs": 1000, 108 | "maxFreeSockets": 256, 109 | "maxSockets": null 110 | } 111 | }, 112 | "gcp": { 113 | "httpAgent": { 114 | "keepAlive": true, 115 | "keepAliveMsecs": 1000, 116 | "maxFreeSockets": 256, 117 | "maxSockets": null 118 | } 119 | } 120 | }, 121 | "requests": { 122 | "viaProxy": false, 123 | "trustedProxyCIDRs": [], 124 | "extractClientIPFromHeader": "" 125 | }, 126 | "bucketNotificationDestinations": [ 127 | { 128 | "resource": "target1", 129 | "type": "dummy", 130 | "host": "localhost:6000" 131 | } 132 | ], 133 | "disablePayloadChecksumValidation": true 134 | } -------------------------------------------------------------------------------- /workspace-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Mount S3 5 | echo "🔧 Mounting cloud storage..." 6 | /root/.mount-cloud-storage.sh 7 | 8 | # Wait for target dir to appear 9 | echo "⏳ Waiting for /mnt/metastore/workspace..." 10 | while [ ! -d "/mnt/metastore/workspace" ]; do 11 | sleep 0.5 12 | done 13 | 14 | echo "🚀 Launching Jupyter..." 15 | exec poetry run jupyter server --config=/root/.jupyter/jupyter_notebook_config.py --ip=0.0.0.0 --port=8888 --no-browser --allow-root 16 | -------------------------------------------------------------------------------- /workspaces/example-instacart/.env: -------------------------------------------------------------------------------- 1 | STORAGE_USER=admin 2 | STORAGE_PASSWORD=password 3 | BOSON_PORT=8889 -------------------------------------------------------------------------------- /workspaces/example-instacart/docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | storage: 5 | volumes: 6 | - example_instacart_storage_data:/usr/src/app/localData 7 | - example_instacart_storage_meta:/usr/src/app/localMetadata 8 | 9 | workspace: 10 | build: 11 | context: ./workspaces/example-instacart 12 | args: 13 | WORKSPACE_NAME: "Example - Instacart" 14 | volumes: 15 | - example_instacart_aim_data:/aim-repo 16 | 17 | aim-init: 18 | volumes: 19 | - example_instacart_aim_data:/repo 20 | 21 | aim-ui: 22 | volumes: 23 | - example_instacart_aim_data:/repo 24 | 25 | volumes: 26 | example_instacart_storage_data: 27 | example_instacart_storage_meta: 28 | example_instacart_aim_data: -------------------------------------------------------------------------------- /workspaces/example-instacart/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "example-instacart" 3 | version = "0.1.0" 4 | description = "Example - Instacart" 5 | 6 | [tool.poetry.dependencies] 7 | python = "^3.12" 8 | seaborn = "^0.13.2" 9 | pandas = "^2.2.2" 10 | xgboost = "^3.0.0" 11 | scikit-learn = "^1.6.1" 12 | 13 | [build-system] 14 | requires = ["poetry-core"] 15 | build-backend = "poetry.core.masonry.api" --------------------------------------------------------------------------------