├── .github └── workflows │ ├── format.yml │ ├── python_publish.yml │ └── python_test.yml ├── .gitignore ├── LICENSE ├── README.md ├── examples ├── example.ipynb └── task.py ├── poetry.lock ├── pyproject.toml ├── test ├── __init__.py ├── sample.py ├── test_case │ ├── log │ │ ├── processing_time │ │ │ └── TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl │ │ ├── task_log │ │ │ └── TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl │ │ └── task_params │ │ │ └── TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl │ └── sample │ │ └── test_case_c5b4a28a606228ac23477557c774a3a0.pkl ├── test_gcs_client.py ├── test_local_cache.py ├── test_local_cache_regression.py ├── test_local_directory_client.py ├── test_s3_client.py ├── test_thunderbolt.py └── test_thunderbolt_regression.py ├── thunderbolt ├── __init__.py ├── client │ ├── __init__.py │ ├── gcs_client.py │ ├── local_cache.py │ ├── local_directory_client.py │ └── s3_client.py └── thunderbolt.py └── tox.ini /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Formatting Check 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | 8 | 9 | jobs: 10 | formatting-check: 11 | 12 | name: Formatting Check 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/setup-python@v5 18 | with: 19 | python-version: "3.12" 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | python -m pip install poetry 24 | poetry install 25 | - name: Run formatter 26 | run: | 27 | poetry run tox -e ruff 28 | -------------------------------------------------------------------------------- /.github/workflows/python_publish.yml: -------------------------------------------------------------------------------- 1 | name: Upload Python Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | deploy: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-python@v5 15 | with: 16 | python-version: '3.x' 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip 20 | pip install poetry poetry-dynamic-versioning twine 21 | - name: Build and publish 22 | env: 23 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 24 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 25 | run: | 26 | poetry publish --build --username $TWINE_USERNAME --password $TWINE_PASSWORD 27 | -------------------------------------------------------------------------------- /.github/workflows/python_test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ${{ matrix.platform }} 13 | strategy: 14 | max-parallel: 4 15 | matrix: 16 | platform: [ubuntu-latest] 17 | python-version: ["3.9", "3.10", "3.11", "3.12"] 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | - name: Set up Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v5 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | python -m pip install poetry 29 | poetry run python -m pip install tox-gh-actions 30 | poetry install 31 | - name: Test with tox 32 | run: poetry run tox 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # PyCharm 104 | .idea/ 105 | 106 | # dev 107 | sandbox/ 108 | resource/* 109 | notebook/ 110 | conf/env.list.local 111 | 112 | # luigi stuff 113 | ./data/ 114 | ./public/ 115 | 116 | # for Mac 117 | .DS_Store 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019, 6syun9 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Thunderbolt 2 | 3 | [![Test](https://github.com/m3dev/thunderbolt/workflows/Test/badge.svg)](https://github.com/m3dev/thunderbolt/actions?query=workflow%3ATest) 4 | [![Python Versions](https://img.shields.io/pypi/pyversions/thunderbolt.svg)](https://pypi.org/project/thunderbolt/) 5 | [![](https://img.shields.io/pypi/v/thunderbolt)](https://pypi.org/project/thunderbolt/) 6 | ![](https://img.shields.io/pypi/l/thunderbolt) 7 | 8 | Thunderbolt is data manager for gokart. 9 | 10 | 11 | 1. Auto loading gokart task logs 12 | 1. Check task params using pandas 13 | 1. Download data from python 14 | 15 | 16 | # Usage 17 | 18 | ### install 19 | ```shell 20 | pip install thunderbolt 21 | ``` 22 | 23 | ### Example 24 | 25 | If you specify `TASK_WORKSPACE_DIRECTORY`, thunderbolt reads the log. 26 | So making tasks pandas.DataFrame, and load dumped data. 27 | This is also possible from S3 or GCS. (s3://, gs://) 28 | 29 | Example: 30 | ```python 31 | from thunderbolt import Thunderbolt 32 | 33 | tb = Thunderbolt() 34 | print(tb.get_task_df()) 35 | print(tb.get_data('TASK_NAME')) 36 | ``` 37 | 38 | Please look here too: https://github.com/m3dev/thunderbolt/blob/master/examples/example.ipynb 39 | 40 | 41 | # Thanks 42 | 43 | - `gokart`: https://github.com/m3dev/gokart 44 | -------------------------------------------------------------------------------- /examples/example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "---\n", 8 | "# gokart task run\n", 9 | "---\n", 10 | "running sample task" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import os\n", 20 | "os.environ['TASK_WORKSPACE_DIRECTORY'] = './resources'" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 2, 26 | "metadata": {}, 27 | "outputs": [ 28 | { 29 | "name": "stdout", 30 | "output_type": "stream", 31 | "text": [ 32 | "# define tasks\n", 33 | "import gokart\n", 34 | "import luigi\n", 35 | "from luigi.util import requires\n", 36 | "from logging import getLogger\n", 37 | "\n", 38 | "logger = getLogger(__name__)\n", 39 | "\n", 40 | "\n", 41 | "class SampleTask(gokart.TaskOnKart):\n", 42 | " task_namespace = 'sample'\n", 43 | " name = luigi.Parameter()\n", 44 | " number = luigi.IntParameter()\n", 45 | " \n", 46 | " def run(self):\n", 47 | " self.dump(f'this is sample output. model number: {self.number}')\n", 48 | "\n", 49 | " \n", 50 | "@requires(SampleTask)\n", 51 | "class SecondTask(gokart.TaskOnKart):\n", 52 | " task_namespace = 'sample'\n", 53 | " param = luigi.Parameter()\n", 54 | "\n", 55 | " def run(self):\n", 56 | " sample = self.load()\n", 57 | " self.dump(sample + f'add task: {self.param}')\n", 58 | " \n", 59 | "gokart.run()" 60 | ] 61 | } 62 | ], 63 | "source": [ 64 | "!cat ./task.py" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 3, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "# sample task run\n", 74 | "!rm -rf ./resources\n", 75 | "!python task.py sample.SampleTask --name='EXAMPLE' --number=1 --local-scheduler 2> /dev/null\n", 76 | "!python task.py sample.SampleTask --name='EXAMPLE' --number=2 --local-scheduler 2> /dev/null\n", 77 | "!python task.py sample.SampleTask --name='EXAMPLE' --number=3 --local-scheduler 2> /dev/null\n", 78 | "!python task.py sample.SampleTask --name='TEMP' --number=1 --local-scheduler 2> /dev/null\n", 79 | "!python task.py sample.SampleTask --name='TEMP' --number=2 --local-scheduler 2> /dev/null\n", 80 | "!python task.py sample.SecondTask --name='TEMP' --number=2 --param='RUN' --local-scheduler --local-temporary-directory='./resource' 2> /dev/null" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 4, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "name": "stdout", 90 | "output_type": "stream", 91 | "text": [ 92 | "\u001b[34m./resources/\u001b[00m\n", 93 | "├── \u001b[34m__main__\u001b[00m\n", 94 | "│   ├── SampleTask_84b0b9c5a39bce072271599c9f730660.pkl\n", 95 | "│   ├── SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl\n", 96 | "│   ├── SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl\n", 97 | "│   ├── SampleTask_d57cff8074e2560896974850e5d3174d.pkl\n", 98 | "│   ├── SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl\n", 99 | "│   └── SecondTask_ea1806322904199b2455d6e115c525ea.pkl\n", 100 | "└── \u001b[34mlog\u001b[00m\n", 101 | " ├── \u001b[34mmodule_versions\u001b[00m\n", 102 | " │   ├── SampleTask_84b0b9c5a39bce072271599c9f730660.txt\n", 103 | " │   ├── SampleTask_944fc52ef5011b71b5839f035f4d7e48.txt\n", 104 | " │   ├── SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.txt\n", 105 | " │   ├── SampleTask_d57cff8074e2560896974850e5d3174d.txt\n", 106 | " │   ├── SampleTask_e883bcfad65f5fb68259d1cd4691f384.txt\n", 107 | " │   └── SecondTask_ea1806322904199b2455d6e115c525ea.txt\n", 108 | " ├── \u001b[34mprocessing_time\u001b[00m\n", 109 | " │   ├── SampleTask_84b0b9c5a39bce072271599c9f730660.pkl\n", 110 | " │   ├── SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl\n", 111 | " │   ├── SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl\n", 112 | " │   ├── SampleTask_d57cff8074e2560896974850e5d3174d.pkl\n", 113 | " │   ├── SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl\n", 114 | " │   └── SecondTask_ea1806322904199b2455d6e115c525ea.pkl\n", 115 | " ├── \u001b[34mtask_log\u001b[00m\n", 116 | " │   ├── SampleTask_84b0b9c5a39bce072271599c9f730660.pkl\n", 117 | " │   ├── SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl\n", 118 | " │   ├── SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl\n", 119 | " │   ├── SampleTask_d57cff8074e2560896974850e5d3174d.pkl\n", 120 | " │   ├── SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl\n", 121 | " │   └── SecondTask_ea1806322904199b2455d6e115c525ea.pkl\n", 122 | " └── \u001b[34mtask_params\u001b[00m\n", 123 | " ├── SampleTask_84b0b9c5a39bce072271599c9f730660.pkl\n", 124 | " ├── SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl\n", 125 | " ├── SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl\n", 126 | " ├── SampleTask_d57cff8074e2560896974850e5d3174d.pkl\n", 127 | " ├── SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl\n", 128 | " └── SecondTask_ea1806322904199b2455d6e115c525ea.pkl\n", 129 | "\n", 130 | "6 directories, 30 files\n" 131 | ] 132 | } 133 | ], 134 | "source": [ 135 | "!tree ./resources/" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "---\n", 143 | "# Init Thunderbolt\n", 144 | "---\n", 145 | "using thunderbolt" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 5, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "from thunderbolt import Thunderbolt" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 6, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "# 1st arg is gokart's output directory (default: $TASK_WORKSPACE_DIRECTORY)\n", 164 | "# 2nd arg is `task_filters` (for fast)\n", 165 | "\n", 166 | "tb = Thunderbolt() " 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "## Check tasks param\n", 174 | "checking thunderbolt's task_id" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 7, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "df = tb.get_task_df()" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 8, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "data": { 193 | "text/html": [ 194 | "
\n", 195 | "\n", 208 | "\n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | "
task_idtask_namelast_modifiedtask_params
00SampleTask2020-02-13 14:17:13.704206{'name': 'TEMP', 'number': '1'}
11SampleTask2020-02-13 14:17:15.728998{'name': 'TEMP', 'number': '2'}
22SecondTask2020-02-13 14:17:17.735793{'name': 'TEMP', 'number': '2', 'param': 'RUN'}
33SampleTask2020-02-13 14:17:07.787346{'name': 'EXAMPLE', 'number': '1'}
44SampleTask2020-02-13 14:17:09.776602{'name': 'EXAMPLE', 'number': '2'}
55SampleTask2020-02-13 14:17:11.699651{'name': 'EXAMPLE', 'number': '3'}
\n", 263 | "
" 264 | ], 265 | "text/plain": [ 266 | " task_id task_name last_modified \\\n", 267 | "0 0 SampleTask 2020-02-13 14:17:13.704206 \n", 268 | "1 1 SampleTask 2020-02-13 14:17:15.728998 \n", 269 | "2 2 SecondTask 2020-02-13 14:17:17.735793 \n", 270 | "3 3 SampleTask 2020-02-13 14:17:07.787346 \n", 271 | "4 4 SampleTask 2020-02-13 14:17:09.776602 \n", 272 | "5 5 SampleTask 2020-02-13 14:17:11.699651 \n", 273 | "\n", 274 | " task_params \n", 275 | "0 {'name': 'TEMP', 'number': '1'} \n", 276 | "1 {'name': 'TEMP', 'number': '2'} \n", 277 | "2 {'name': 'TEMP', 'number': '2', 'param': 'RUN'} \n", 278 | "3 {'name': 'EXAMPLE', 'number': '1'} \n", 279 | "4 {'name': 'EXAMPLE', 'number': '2'} \n", 280 | "5 {'name': 'EXAMPLE', 'number': '3'} " 281 | ] 282 | }, 283 | "execution_count": 8, 284 | "metadata": {}, 285 | "output_type": "execute_result" 286 | } 287 | ], 288 | "source": [ 289 | "import pandas as pd\n", 290 | "pd.set_option(\"display.max_colwidth\", 200)\n", 291 | "df" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "## thunderbolt filter\n", 299 | "2nd arg 'task_filters' is str or list. So fast.\n", 300 | "\n", 301 | "task_filters is partial match word for example: \n", 302 | " - 'Tag' -> HogeTag, NormalizeHogeTag, TagTask, ...\n", 303 | " - ['Train', 'Tag'] -> TrainModel, TrainData, HogeTag, NormalizeHogeTag, TagTask, ..." 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 9, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "tb = Thunderbolt(task_filters='Sample') " 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": 10, 318 | "metadata": {}, 319 | "outputs": [ 320 | { 321 | "data": { 322 | "text/html": [ 323 | "
\n", 324 | "\n", 337 | "\n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | "
task_idtask_namelast_modifiedtask_paramstask_hashtask_log
00SampleTask2020-02-13 14:17:13.704206{'name': 'TEMP', 'number': '1'}d57cff8074e2560896974850e5d3174d{'file_path': ['./resources/__main__/SampleTask_d57cff8074e2560896974850e5d3174d.pkl']}
11SampleTask2020-02-13 14:17:15.728998{'name': 'TEMP', 'number': '2'}d05a2ab961781d3d8eca3e2e5f0d608b{'file_path': ['./resources/__main__/SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl']}
23SampleTask2020-02-13 14:17:07.787346{'name': 'EXAMPLE', 'number': '1'}e883bcfad65f5fb68259d1cd4691f384{'file_path': ['./resources/__main__/SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl']}
34SampleTask2020-02-13 14:17:09.776602{'name': 'EXAMPLE', 'number': '2'}84b0b9c5a39bce072271599c9f730660{'file_path': ['./resources/__main__/SampleTask_84b0b9c5a39bce072271599c9f730660.pkl']}
45SampleTask2020-02-13 14:17:11.699651{'name': 'EXAMPLE', 'number': '3'}944fc52ef5011b71b5839f035f4d7e48{'file_path': ['./resources/__main__/SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl']}
\n", 397 | "
" 398 | ], 399 | "text/plain": [ 400 | " task_id task_name last_modified \\\n", 401 | "0 0 SampleTask 2020-02-13 14:17:13.704206 \n", 402 | "1 1 SampleTask 2020-02-13 14:17:15.728998 \n", 403 | "2 3 SampleTask 2020-02-13 14:17:07.787346 \n", 404 | "3 4 SampleTask 2020-02-13 14:17:09.776602 \n", 405 | "4 5 SampleTask 2020-02-13 14:17:11.699651 \n", 406 | "\n", 407 | " task_params task_hash \\\n", 408 | "0 {'name': 'TEMP', 'number': '1'} d57cff8074e2560896974850e5d3174d \n", 409 | "1 {'name': 'TEMP', 'number': '2'} d05a2ab961781d3d8eca3e2e5f0d608b \n", 410 | "2 {'name': 'EXAMPLE', 'number': '1'} e883bcfad65f5fb68259d1cd4691f384 \n", 411 | "3 {'name': 'EXAMPLE', 'number': '2'} 84b0b9c5a39bce072271599c9f730660 \n", 412 | "4 {'name': 'EXAMPLE', 'number': '3'} 944fc52ef5011b71b5839f035f4d7e48 \n", 413 | "\n", 414 | " task_log \n", 415 | "0 {'file_path': ['./resources/__main__/SampleTask_d57cff8074e2560896974850e5d3174d.pkl']} \n", 416 | "1 {'file_path': ['./resources/__main__/SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl']} \n", 417 | "2 {'file_path': ['./resources/__main__/SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl']} \n", 418 | "3 {'file_path': ['./resources/__main__/SampleTask_84b0b9c5a39bce072271599c9f730660.pkl']} \n", 419 | "4 {'file_path': ['./resources/__main__/SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl']} " 420 | ] 421 | }, 422 | "execution_count": 10, 423 | "metadata": {}, 424 | "output_type": "execute_result" 425 | } 426 | ], 427 | "source": [ 428 | "# example: all_data=True\n", 429 | "\n", 430 | "tb.get_task_df(all_data=True)" 431 | ] 432 | }, 433 | { 434 | "cell_type": "markdown", 435 | "metadata": {}, 436 | "source": [ 437 | "---\n", 438 | "# Data Load\n", 439 | "---\n", 440 | "using load method\n", 441 | "- arg: thunderbolt's task_id\n", 442 | "- return : data list" 443 | ] 444 | }, 445 | { 446 | "cell_type": "code", 447 | "execution_count": 11, 448 | "metadata": {}, 449 | "outputs": [ 450 | { 451 | "name": "stdout", 452 | "output_type": "stream", 453 | "text": [ 454 | "this is sample output. model number: 1\n" 455 | ] 456 | } 457 | ], 458 | "source": [ 459 | "x = tb.load(task_id=3)\n", 460 | "print(x)" 461 | ] 462 | }, 463 | { 464 | "cell_type": "markdown", 465 | "metadata": {}, 466 | "source": [ 467 | "### newest data load example" 468 | ] 469 | }, 470 | { 471 | "cell_type": "code", 472 | "execution_count": 12, 473 | "metadata": {}, 474 | "outputs": [ 475 | { 476 | "data": { 477 | "text/plain": [ 478 | "'this is sample output. model number: 2'" 479 | ] 480 | }, 481 | "execution_count": 12, 482 | "metadata": {}, 483 | "output_type": "execute_result" 484 | } 485 | ], 486 | "source": [ 487 | "tb.get_data('SampleTask')" 488 | ] 489 | } 490 | ], 491 | "metadata": { 492 | "kernelspec": { 493 | "display_name": "Python 3", 494 | "language": "python", 495 | "name": "python3" 496 | }, 497 | "language_info": { 498 | "codemirror_mode": { 499 | "name": "ipython", 500 | "version": 3 501 | }, 502 | "file_extension": ".py", 503 | "mimetype": "text/x-python", 504 | "name": "python", 505 | "nbconvert_exporter": "python", 506 | "pygments_lexer": "ipython3", 507 | "version": "3.6.8" 508 | } 509 | }, 510 | "nbformat": 4, 511 | "nbformat_minor": 4 512 | } 513 | -------------------------------------------------------------------------------- /examples/task.py: -------------------------------------------------------------------------------- 1 | # define tasks 2 | from logging import getLogger 3 | 4 | import gokart 5 | import luigi 6 | from luigi.util import requires 7 | 8 | logger = getLogger(__name__) 9 | 10 | 11 | class SampleTask(gokart.TaskOnKart): 12 | task_namespace = 'sample' 13 | name = luigi.Parameter() 14 | number = luigi.IntParameter() 15 | 16 | def run(self): 17 | self.dump(f'this is sample output. model number: {self.number}') 18 | 19 | 20 | @requires(SampleTask) 21 | class SecondTask(gokart.TaskOnKart): 22 | task_namespace = 'sample' 23 | param = luigi.Parameter() 24 | 25 | def run(self): 26 | sample = self.load() 27 | self.dump(sample + f'add task: {self.param}') 28 | 29 | 30 | gokart.run() 31 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "apscheduler" 5 | version = "3.10.4" 6 | description = "In-process task scheduler with Cron-like capabilities" 7 | optional = false 8 | python-versions = ">=3.6" 9 | groups = ["main"] 10 | files = [ 11 | {file = "APScheduler-3.10.4-py3-none-any.whl", hash = "sha256:fb91e8a768632a4756a585f79ec834e0e27aad5860bac7eaa523d9ccefd87661"}, 12 | {file = "APScheduler-3.10.4.tar.gz", hash = "sha256:e6df071b27d9be898e486bc7940a7be50b4af2e9da7c08f0744a96d4bd4cef4a"}, 13 | ] 14 | 15 | [package.dependencies] 16 | pytz = "*" 17 | six = ">=1.4.0" 18 | tzlocal = ">=2.0,<3.dev0 || >=4.dev0" 19 | 20 | [package.extras] 21 | doc = ["sphinx", "sphinx-rtd-theme"] 22 | gevent = ["gevent"] 23 | mongodb = ["pymongo (>=3.0)"] 24 | redis = ["redis (>=3.0)"] 25 | rethinkdb = ["rethinkdb (>=2.4.0)"] 26 | sqlalchemy = ["sqlalchemy (>=1.4)"] 27 | testing = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-tornado5"] 28 | tornado = ["tornado (>=4.3)"] 29 | twisted = ["twisted"] 30 | zookeeper = ["kazoo"] 31 | 32 | [[package]] 33 | name = "async-timeout" 34 | version = "4.0.3" 35 | description = "Timeout context manager for asyncio programs" 36 | optional = false 37 | python-versions = ">=3.7" 38 | groups = ["main"] 39 | markers = "python_full_version <= \"3.11.2\"" 40 | files = [ 41 | {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, 42 | {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, 43 | ] 44 | 45 | [[package]] 46 | name = "boto3" 47 | version = "1.34.44" 48 | description = "The AWS SDK for Python" 49 | optional = false 50 | python-versions = ">= 3.8" 51 | groups = ["main"] 52 | files = [ 53 | {file = "boto3-1.34.44-py3-none-any.whl", hash = "sha256:40f89fb2acee0a0879effe81badffcd801a348e715483227223241ae311c48fc"}, 54 | {file = "boto3-1.34.44.tar.gz", hash = "sha256:86bcf79a56631609a9f8023fe8f53e2869702bdd4c9047c6d9f091eb39c9b0fa"}, 55 | ] 56 | 57 | [package.dependencies] 58 | botocore = ">=1.34.44,<1.35.0" 59 | jmespath = ">=0.7.1,<2.0.0" 60 | s3transfer = ">=0.10.0,<0.11.0" 61 | 62 | [package.extras] 63 | crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] 64 | 65 | [[package]] 66 | name = "botocore" 67 | version = "1.34.44" 68 | description = "Low-level, data-driven core of boto 3." 69 | optional = false 70 | python-versions = ">= 3.8" 71 | groups = ["main"] 72 | files = [ 73 | {file = "botocore-1.34.44-py3-none-any.whl", hash = "sha256:8d9837fb33256e70b9c8955a32d3e60fa70a0b72849a909737cf105fcc3b5deb"}, 74 | {file = "botocore-1.34.44.tar.gz", hash = "sha256:b0f40c54477e8e0a5c43377a927b8959a86bb8824aaef2d28db7c9c367cdefaa"}, 75 | ] 76 | 77 | [package.dependencies] 78 | jmespath = ">=0.7.1,<2.0.0" 79 | python-dateutil = ">=2.1,<3.0.0" 80 | urllib3 = [ 81 | {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, 82 | {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""}, 83 | ] 84 | 85 | [package.extras] 86 | crt = ["awscrt (==0.19.19)"] 87 | 88 | [[package]] 89 | name = "cachetools" 90 | version = "5.3.2" 91 | description = "Extensible memoizing collections and decorators" 92 | optional = false 93 | python-versions = ">=3.7" 94 | groups = ["main", "dev"] 95 | files = [ 96 | {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, 97 | {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, 98 | ] 99 | 100 | [[package]] 101 | name = "certifi" 102 | version = "2024.7.4" 103 | description = "Python package for providing Mozilla's CA Bundle." 104 | optional = false 105 | python-versions = ">=3.6" 106 | groups = ["main"] 107 | files = [ 108 | {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, 109 | {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, 110 | ] 111 | 112 | [[package]] 113 | name = "chardet" 114 | version = "5.2.0" 115 | description = "Universal encoding detector for Python 3" 116 | optional = false 117 | python-versions = ">=3.7" 118 | groups = ["dev"] 119 | files = [ 120 | {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, 121 | {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, 122 | ] 123 | 124 | [[package]] 125 | name = "charset-normalizer" 126 | version = "3.3.2" 127 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 128 | optional = false 129 | python-versions = ">=3.7.0" 130 | groups = ["main"] 131 | files = [ 132 | {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, 133 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, 134 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, 135 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, 136 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, 137 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, 138 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, 139 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, 140 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, 141 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, 142 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, 143 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, 144 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, 145 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, 146 | {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, 147 | {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, 148 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, 149 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, 150 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, 151 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, 152 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, 153 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, 154 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, 155 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, 156 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, 157 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, 158 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, 159 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, 160 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, 161 | {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, 162 | {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, 163 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, 164 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, 165 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, 166 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, 167 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, 168 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, 169 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, 170 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, 171 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, 172 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, 173 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, 174 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, 175 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, 176 | {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, 177 | {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, 178 | {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, 179 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, 180 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, 181 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, 182 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, 183 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, 184 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, 185 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, 186 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, 187 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, 188 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, 189 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, 190 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, 191 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, 192 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, 193 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, 194 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, 195 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, 196 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, 197 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, 198 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, 199 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, 200 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, 201 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, 202 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, 203 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, 204 | {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, 205 | {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, 206 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, 207 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, 208 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, 209 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, 210 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, 211 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, 212 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, 213 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, 214 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, 215 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, 216 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, 217 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, 218 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, 219 | {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, 220 | {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, 221 | {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, 222 | ] 223 | 224 | [[package]] 225 | name = "colorama" 226 | version = "0.4.6" 227 | description = "Cross-platform colored terminal text." 228 | optional = false 229 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 230 | groups = ["main", "dev"] 231 | files = [ 232 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 233 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 234 | ] 235 | markers = {main = "platform_system == \"Windows\""} 236 | 237 | [[package]] 238 | name = "contourpy" 239 | version = "1.2.0" 240 | description = "Python library for calculating contours of 2D quadrilateral grids" 241 | optional = false 242 | python-versions = ">=3.9" 243 | groups = ["main"] 244 | files = [ 245 | {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, 246 | {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, 247 | {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, 248 | {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, 249 | {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, 250 | {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, 251 | {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, 252 | {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, 253 | {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, 254 | {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, 255 | {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, 256 | {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, 257 | {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, 258 | {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, 259 | {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, 260 | {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, 261 | {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, 262 | {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, 263 | {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, 264 | {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, 265 | {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, 266 | {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, 267 | {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, 268 | {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, 269 | {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, 270 | {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, 271 | {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, 272 | {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, 273 | {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, 274 | {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, 275 | {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, 276 | {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, 277 | {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, 278 | {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, 279 | {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, 280 | {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, 281 | {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, 282 | {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, 283 | {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, 284 | {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, 285 | {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, 286 | {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, 287 | {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, 288 | {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, 289 | ] 290 | 291 | [package.dependencies] 292 | numpy = ">=1.20,<2.0" 293 | 294 | [package.extras] 295 | bokeh = ["bokeh", "selenium"] 296 | docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] 297 | mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] 298 | test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] 299 | test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] 300 | 301 | [[package]] 302 | name = "coverage" 303 | version = "7.4.1" 304 | description = "Code coverage measurement for Python" 305 | optional = false 306 | python-versions = ">=3.8" 307 | groups = ["dev"] 308 | files = [ 309 | {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, 310 | {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, 311 | {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, 312 | {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, 313 | {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, 314 | {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, 315 | {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, 316 | {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, 317 | {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, 318 | {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, 319 | {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, 320 | {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, 321 | {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, 322 | {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, 323 | {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, 324 | {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, 325 | {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, 326 | {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, 327 | {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, 328 | {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, 329 | {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, 330 | {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, 331 | {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, 332 | {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, 333 | {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, 334 | {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, 335 | {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, 336 | {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, 337 | {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, 338 | {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, 339 | {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, 340 | {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, 341 | {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, 342 | {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, 343 | {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, 344 | {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, 345 | {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, 346 | {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, 347 | {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, 348 | {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, 349 | {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, 350 | {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, 351 | {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, 352 | {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, 353 | {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, 354 | {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, 355 | {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, 356 | {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, 357 | {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, 358 | {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, 359 | {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, 360 | {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, 361 | ] 362 | 363 | [package.extras] 364 | toml = ["tomli ; python_full_version <= \"3.11.0a6\""] 365 | 366 | [[package]] 367 | name = "cycler" 368 | version = "0.12.1" 369 | description = "Composable style cycles" 370 | optional = false 371 | python-versions = ">=3.8" 372 | groups = ["main"] 373 | files = [ 374 | {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, 375 | {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, 376 | ] 377 | 378 | [package.extras] 379 | docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] 380 | tests = ["pytest", "pytest-cov", "pytest-xdist"] 381 | 382 | [[package]] 383 | name = "distlib" 384 | version = "0.3.8" 385 | description = "Distribution utilities" 386 | optional = false 387 | python-versions = "*" 388 | groups = ["dev"] 389 | files = [ 390 | {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, 391 | {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, 392 | ] 393 | 394 | [[package]] 395 | name = "docutils" 396 | version = "0.20.1" 397 | description = "Docutils -- Python Documentation Utilities" 398 | optional = false 399 | python-versions = ">=3.7" 400 | groups = ["main"] 401 | files = [ 402 | {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, 403 | {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, 404 | ] 405 | 406 | [[package]] 407 | name = "filelock" 408 | version = "3.13.1" 409 | description = "A platform independent file lock." 410 | optional = false 411 | python-versions = ">=3.8" 412 | groups = ["dev"] 413 | files = [ 414 | {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, 415 | {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, 416 | ] 417 | 418 | [package.extras] 419 | docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] 420 | testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] 421 | typing = ["typing-extensions (>=4.8) ; python_version < \"3.11\""] 422 | 423 | [[package]] 424 | name = "fonttools" 425 | version = "4.49.0" 426 | description = "Tools to manipulate font files" 427 | optional = false 428 | python-versions = ">=3.8" 429 | groups = ["main"] 430 | files = [ 431 | {file = "fonttools-4.49.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d970ecca0aac90d399e458f0b7a8a597e08f95de021f17785fb68e2dc0b99717"}, 432 | {file = "fonttools-4.49.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac9a745b7609f489faa65e1dc842168c18530874a5f5b742ac3dd79e26bca8bc"}, 433 | {file = "fonttools-4.49.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ba0e00620ca28d4ca11fc700806fd69144b463aa3275e1b36e56c7c09915559"}, 434 | {file = "fonttools-4.49.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdee3ab220283057e7840d5fb768ad4c2ebe65bdba6f75d5d7bf47f4e0ed7d29"}, 435 | {file = "fonttools-4.49.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ce7033cb61f2bb65d8849658d3786188afd80f53dad8366a7232654804529532"}, 436 | {file = "fonttools-4.49.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:07bc5ea02bb7bc3aa40a1eb0481ce20e8d9b9642a9536cde0218290dd6085828"}, 437 | {file = "fonttools-4.49.0-cp310-cp310-win32.whl", hash = "sha256:86eef6aab7fd7c6c8545f3ebd00fd1d6729ca1f63b0cb4d621bccb7d1d1c852b"}, 438 | {file = "fonttools-4.49.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fac1b7eebfce75ea663e860e7c5b4a8831b858c17acd68263bc156125201abf"}, 439 | {file = "fonttools-4.49.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:edc0cce355984bb3c1d1e89d6a661934d39586bb32191ebff98c600f8957c63e"}, 440 | {file = "fonttools-4.49.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:83a0d9336de2cba86d886507dd6e0153df333ac787377325a39a2797ec529814"}, 441 | {file = "fonttools-4.49.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36c8865bdb5cfeec88f5028e7e592370a0657b676c6f1d84a2108e0564f90e22"}, 442 | {file = "fonttools-4.49.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33037d9e56e2562c710c8954d0f20d25b8386b397250d65581e544edc9d6b942"}, 443 | {file = "fonttools-4.49.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8fb022d799b96df3eaa27263e9eea306bd3d437cc9aa981820850281a02b6c9a"}, 444 | {file = "fonttools-4.49.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33c584c0ef7dc54f5dd4f84082eabd8d09d1871a3d8ca2986b0c0c98165f8e86"}, 445 | {file = "fonttools-4.49.0-cp311-cp311-win32.whl", hash = "sha256:cbe61b158deb09cffdd8540dc4a948d6e8f4d5b4f3bf5cd7db09bd6a61fee64e"}, 446 | {file = "fonttools-4.49.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc11e5114f3f978d0cea7e9853627935b30d451742eeb4239a81a677bdee6bf6"}, 447 | {file = "fonttools-4.49.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d647a0e697e5daa98c87993726da8281c7233d9d4ffe410812a4896c7c57c075"}, 448 | {file = "fonttools-4.49.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f3bbe672df03563d1f3a691ae531f2e31f84061724c319652039e5a70927167e"}, 449 | {file = "fonttools-4.49.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bebd91041dda0d511b0d303180ed36e31f4f54b106b1259b69fade68413aa7ff"}, 450 | {file = "fonttools-4.49.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4145f91531fd43c50f9eb893faa08399816bb0b13c425667c48475c9f3a2b9b5"}, 451 | {file = "fonttools-4.49.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ea329dafb9670ffbdf4dbc3b0e5c264104abcd8441d56de77f06967f032943cb"}, 452 | {file = "fonttools-4.49.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c076a9e548521ecc13d944b1d261ff3d7825048c338722a4bd126d22316087b7"}, 453 | {file = "fonttools-4.49.0-cp312-cp312-win32.whl", hash = "sha256:b607ea1e96768d13be26d2b400d10d3ebd1456343eb5eaddd2f47d1c4bd00880"}, 454 | {file = "fonttools-4.49.0-cp312-cp312-win_amd64.whl", hash = "sha256:a974c49a981e187381b9cc2c07c6b902d0079b88ff01aed34695ec5360767034"}, 455 | {file = "fonttools-4.49.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b85ec0bdd7bdaa5c1946398cbb541e90a6dfc51df76dfa88e0aaa41b335940cb"}, 456 | {file = "fonttools-4.49.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:af20acbe198a8a790618ee42db192eb128afcdcc4e96d99993aca0b60d1faeb4"}, 457 | {file = "fonttools-4.49.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d418b1fee41a1d14931f7ab4b92dc0bc323b490e41d7a333eec82c9f1780c75"}, 458 | {file = "fonttools-4.49.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b44a52b8e6244b6548851b03b2b377a9702b88ddc21dcaf56a15a0393d425cb9"}, 459 | {file = "fonttools-4.49.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7c7125068e04a70739dad11857a4d47626f2b0bd54de39e8622e89701836eabd"}, 460 | {file = "fonttools-4.49.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29e89d0e1a7f18bc30f197cfadcbef5a13d99806447c7e245f5667579a808036"}, 461 | {file = "fonttools-4.49.0-cp38-cp38-win32.whl", hash = "sha256:9d95fa0d22bf4f12d2fb7b07a46070cdfc19ef5a7b1c98bc172bfab5bf0d6844"}, 462 | {file = "fonttools-4.49.0-cp38-cp38-win_amd64.whl", hash = "sha256:768947008b4dc552d02772e5ebd49e71430a466e2373008ce905f953afea755a"}, 463 | {file = "fonttools-4.49.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:08877e355d3dde1c11973bb58d4acad1981e6d1140711230a4bfb40b2b937ccc"}, 464 | {file = "fonttools-4.49.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fdb54b076f25d6b0f0298dc706acee5052de20c83530fa165b60d1f2e9cbe3cb"}, 465 | {file = "fonttools-4.49.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0af65c720520710cc01c293f9c70bd69684365c6015cc3671db2b7d807fe51f2"}, 466 | {file = "fonttools-4.49.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f255ce8ed7556658f6d23f6afd22a6d9bbc3edb9b96c96682124dc487e1bf42"}, 467 | {file = "fonttools-4.49.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d00af0884c0e65f60dfaf9340e26658836b935052fdd0439952ae42e44fdd2be"}, 468 | {file = "fonttools-4.49.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:263832fae27481d48dfafcc43174644b6706639661e242902ceb30553557e16c"}, 469 | {file = "fonttools-4.49.0-cp39-cp39-win32.whl", hash = "sha256:0404faea044577a01bb82d47a8fa4bc7a54067fa7e324785dd65d200d6dd1133"}, 470 | {file = "fonttools-4.49.0-cp39-cp39-win_amd64.whl", hash = "sha256:b050d362df50fc6e38ae3954d8c29bf2da52be384649ee8245fdb5186b620836"}, 471 | {file = "fonttools-4.49.0-py3-none-any.whl", hash = "sha256:af281525e5dd7fa0b39fb1667b8d5ca0e2a9079967e14c4bfe90fd1cd13e0f18"}, 472 | {file = "fonttools-4.49.0.tar.gz", hash = "sha256:ebf46e7f01b7af7861310417d7c49591a85d99146fc23a5ba82fdb28af156321"}, 473 | ] 474 | 475 | [package.extras] 476 | all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] 477 | graphite = ["lz4 (>=1.7.4.2)"] 478 | interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] 479 | lxml = ["lxml (>=4.0)"] 480 | pathops = ["skia-pathops (>=0.5.0)"] 481 | plot = ["matplotlib"] 482 | repacker = ["uharfbuzz (>=0.23.0)"] 483 | symfont = ["sympy"] 484 | type1 = ["xattr ; sys_platform == \"darwin\""] 485 | ufo = ["fs (>=2.2.0,<3)"] 486 | unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] 487 | woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] 488 | 489 | [[package]] 490 | name = "gokart" 491 | version = "1.2.6" 492 | description = "Gokart solves reproducibility, task dependencies, constraints of good code, and ease of use for Machine Learning Pipeline. [Documentation](https://gokart.readthedocs.io/en/latest/)" 493 | optional = false 494 | python-versions = ">=3.9,<3.13" 495 | groups = ["main"] 496 | files = [ 497 | {file = "gokart-1.2.6-py3-none-any.whl", hash = "sha256:38dbc1fe3b706d95d9b5050c6711f9c67deac94e43b7386d73bc229947a961bb"}, 498 | {file = "gokart-1.2.6.tar.gz", hash = "sha256:c24793d133cfe726e38d84b0ce8cddbae1c9696ceb2f9d9a272c43bba24991d2"}, 499 | ] 500 | 501 | [package.dependencies] 502 | APScheduler = "*" 503 | boto3 = "*" 504 | google-api-python-client = "*" 505 | google-auth = "*" 506 | luigi = "*" 507 | matplotlib = "*" 508 | numpy = "*" 509 | pandas = "*" 510 | pyarrow = "*" 511 | redis = "*" 512 | slack-sdk = ">=3,<4" 513 | tqdm = "*" 514 | uritemplate = "*" 515 | 516 | [[package]] 517 | name = "google-api-core" 518 | version = "2.17.1" 519 | description = "Google API client core library" 520 | optional = false 521 | python-versions = ">=3.7" 522 | groups = ["main"] 523 | files = [ 524 | {file = "google-api-core-2.17.1.tar.gz", hash = "sha256:9df18a1f87ee0df0bc4eea2770ebc4228392d8cc4066655b320e2cfccb15db95"}, 525 | {file = "google_api_core-2.17.1-py3-none-any.whl", hash = "sha256:610c5b90092c360736baccf17bd3efbcb30dd380e7a6dc28a71059edb8bd0d8e"}, 526 | ] 527 | 528 | [package.dependencies] 529 | google-auth = ">=2.14.1,<3.0.dev0" 530 | googleapis-common-protos = ">=1.56.2,<2.0.dev0" 531 | protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" 532 | requests = ">=2.18.0,<3.0.0.dev0" 533 | 534 | [package.extras] 535 | grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev) ; python_version >= \"3.11\"", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\""] 536 | grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] 537 | grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] 538 | 539 | [[package]] 540 | name = "google-api-python-client" 541 | version = "2.118.0" 542 | description = "Google API Client Library for Python" 543 | optional = false 544 | python-versions = ">=3.7" 545 | groups = ["main"] 546 | files = [ 547 | {file = "google-api-python-client-2.118.0.tar.gz", hash = "sha256:ebf4927a3f5184096647be8f705d090e7f06d48ad82b0fa431a2fe80c2cbe182"}, 548 | {file = "google_api_python_client-2.118.0-py2.py3-none-any.whl", hash = "sha256:9d83b178496b180e058fd206ebfb70ea1afab49f235dd326f557513f56f496d5"}, 549 | ] 550 | 551 | [package.dependencies] 552 | google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" 553 | google-auth = ">=1.19.0,<3.0.0.dev0" 554 | google-auth-httplib2 = ">=0.1.0" 555 | httplib2 = ">=0.15.0,<1.dev0" 556 | uritemplate = ">=3.0.1,<5" 557 | 558 | [[package]] 559 | name = "google-auth" 560 | version = "2.28.0" 561 | description = "Google Authentication Library" 562 | optional = false 563 | python-versions = ">=3.7" 564 | groups = ["main"] 565 | files = [ 566 | {file = "google-auth-2.28.0.tar.gz", hash = "sha256:3cfc1b6e4e64797584fb53fc9bd0b7afa9b7c0dba2004fa7dcc9349e58cc3195"}, 567 | {file = "google_auth-2.28.0-py2.py3-none-any.whl", hash = "sha256:7634d29dcd1e101f5226a23cbc4a0c6cda6394253bf80e281d9c5c6797869c53"}, 568 | ] 569 | 570 | [package.dependencies] 571 | cachetools = ">=2.0.0,<6.0" 572 | pyasn1-modules = ">=0.2.1" 573 | rsa = ">=3.1.4,<5" 574 | 575 | [package.extras] 576 | aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] 577 | enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] 578 | pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] 579 | reauth = ["pyu2f (>=0.1.5)"] 580 | requests = ["requests (>=2.20.0,<3.0.0.dev0)"] 581 | 582 | [[package]] 583 | name = "google-auth-httplib2" 584 | version = "0.2.0" 585 | description = "Google Authentication Library: httplib2 transport" 586 | optional = false 587 | python-versions = "*" 588 | groups = ["main"] 589 | files = [ 590 | {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, 591 | {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, 592 | ] 593 | 594 | [package.dependencies] 595 | google-auth = "*" 596 | httplib2 = ">=0.19.0" 597 | 598 | [[package]] 599 | name = "googleapis-common-protos" 600 | version = "1.62.0" 601 | description = "Common protobufs used in Google APIs" 602 | optional = false 603 | python-versions = ">=3.7" 604 | groups = ["main"] 605 | files = [ 606 | {file = "googleapis-common-protos-1.62.0.tar.gz", hash = "sha256:83f0ece9f94e5672cced82f592d2a5edf527a96ed1794f0bab36d5735c996277"}, 607 | {file = "googleapis_common_protos-1.62.0-py2.py3-none-any.whl", hash = "sha256:4750113612205514f9f6aa4cb00d523a94f3e8c06c5ad2fee466387dc4875f07"}, 608 | ] 609 | 610 | [package.dependencies] 611 | protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" 612 | 613 | [package.extras] 614 | grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] 615 | 616 | [[package]] 617 | name = "httplib2" 618 | version = "0.22.0" 619 | description = "A comprehensive HTTP client library." 620 | optional = false 621 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 622 | groups = ["main"] 623 | files = [ 624 | {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, 625 | {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, 626 | ] 627 | 628 | [package.dependencies] 629 | pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} 630 | 631 | [[package]] 632 | name = "idna" 633 | version = "3.7" 634 | description = "Internationalized Domain Names in Applications (IDNA)" 635 | optional = false 636 | python-versions = ">=3.5" 637 | groups = ["main"] 638 | files = [ 639 | {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, 640 | {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, 641 | ] 642 | 643 | [[package]] 644 | name = "importlib-resources" 645 | version = "6.1.1" 646 | description = "Read resources from Python packages" 647 | optional = false 648 | python-versions = ">=3.8" 649 | groups = ["main"] 650 | markers = "python_version < \"3.10\"" 651 | files = [ 652 | {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, 653 | {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, 654 | ] 655 | 656 | [package.dependencies] 657 | zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} 658 | 659 | [package.extras] 660 | docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] 661 | testing = ["pytest (>=6)", "pytest-black (>=0.3.7) ; platform_python_implementation != \"PyPy\"", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1) ; platform_python_implementation != \"PyPy\"", "pytest-ruff", "zipp (>=3.17)"] 662 | 663 | [[package]] 664 | name = "jmespath" 665 | version = "1.0.1" 666 | description = "JSON Matching Expressions" 667 | optional = false 668 | python-versions = ">=3.7" 669 | groups = ["main"] 670 | files = [ 671 | {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, 672 | {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, 673 | ] 674 | 675 | [[package]] 676 | name = "kiwisolver" 677 | version = "1.4.5" 678 | description = "A fast implementation of the Cassowary constraint solver" 679 | optional = false 680 | python-versions = ">=3.7" 681 | groups = ["main"] 682 | files = [ 683 | {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, 684 | {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, 685 | {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, 686 | {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, 687 | {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, 688 | {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, 689 | {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, 690 | {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, 691 | {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, 692 | {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, 693 | {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, 694 | {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, 695 | {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, 696 | {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, 697 | {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, 698 | {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, 699 | {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, 700 | {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, 701 | {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, 702 | {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, 703 | {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, 704 | {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, 705 | {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, 706 | {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, 707 | {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, 708 | {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, 709 | {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, 710 | {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, 711 | {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, 712 | {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, 713 | {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, 714 | {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, 715 | {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, 716 | {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, 717 | {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, 718 | {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, 719 | {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, 720 | {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, 721 | {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, 722 | {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, 723 | {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, 724 | {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, 725 | {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, 726 | {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, 727 | {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, 728 | {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, 729 | {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, 730 | {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, 731 | {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, 732 | {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, 733 | {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, 734 | {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, 735 | {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, 736 | {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, 737 | {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, 738 | {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, 739 | {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, 740 | {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, 741 | {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, 742 | {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, 743 | {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, 744 | {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, 745 | {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, 746 | {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, 747 | {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, 748 | {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, 749 | {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, 750 | {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, 751 | {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, 752 | {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, 753 | {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, 754 | {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, 755 | {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, 756 | {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, 757 | {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, 758 | {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, 759 | {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, 760 | {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, 761 | {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, 762 | {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, 763 | {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, 764 | {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, 765 | {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, 766 | {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, 767 | {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, 768 | {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, 769 | {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, 770 | {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, 771 | {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, 772 | {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, 773 | {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, 774 | {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, 775 | {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, 776 | {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, 777 | {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, 778 | {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, 779 | {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, 780 | {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, 781 | {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, 782 | {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, 783 | {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, 784 | {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, 785 | {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, 786 | {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, 787 | ] 788 | 789 | [[package]] 790 | name = "lockfile" 791 | version = "0.12.2" 792 | description = "Platform-independent file locking module" 793 | optional = false 794 | python-versions = "*" 795 | groups = ["main"] 796 | files = [ 797 | {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, 798 | {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, 799 | ] 800 | 801 | [[package]] 802 | name = "luigi" 803 | version = "3.6.0" 804 | description = "Workflow mgmgt + task scheduling + dependency resolution." 805 | optional = false 806 | python-versions = "*" 807 | groups = ["main"] 808 | files = [ 809 | {file = "luigi-3.6.0.tar.gz", hash = "sha256:41b14850223c619d9006b30acda733e756b883fc7e60814205576647190c96e3"}, 810 | ] 811 | 812 | [package.dependencies] 813 | python-daemon = "*" 814 | python-dateutil = ">=2.7.5,<3" 815 | tenacity = ">=8,<9" 816 | tornado = ">=5.0,<7" 817 | 818 | [package.extras] 819 | jsonschema = ["jsonschema"] 820 | prometheus = ["prometheus-client (>=0.5,<0.15)"] 821 | toml = ["toml (<2.0.0)"] 822 | 823 | [[package]] 824 | name = "matplotlib" 825 | version = "3.8.3" 826 | description = "Python plotting package" 827 | optional = false 828 | python-versions = ">=3.9" 829 | groups = ["main"] 830 | files = [ 831 | {file = "matplotlib-3.8.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cf60138ccc8004f117ab2a2bad513cc4d122e55864b4fe7adf4db20ca68a078f"}, 832 | {file = "matplotlib-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f557156f7116be3340cdeef7f128fa99b0d5d287d5f41a16e169819dcf22357"}, 833 | {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f386cf162b059809ecfac3bcc491a9ea17da69fa35c8ded8ad154cd4b933d5ec"}, 834 | {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c5f96f57b0369c288bf6f9b5274ba45787f7e0589a34d24bdbaf6d3344632f"}, 835 | {file = "matplotlib-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:83e0f72e2c116ca7e571c57aa29b0fe697d4c6425c4e87c6e994159e0c008635"}, 836 | {file = "matplotlib-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:1c5c8290074ba31a41db1dc332dc2b62def469ff33766cbe325d32a3ee291aea"}, 837 | {file = "matplotlib-3.8.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900"}, 838 | {file = "matplotlib-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e"}, 839 | {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7"}, 840 | {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65"}, 841 | {file = "matplotlib-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0"}, 842 | {file = "matplotlib-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407"}, 843 | {file = "matplotlib-3.8.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4"}, 844 | {file = "matplotlib-3.8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa"}, 845 | {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5"}, 846 | {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1"}, 847 | {file = "matplotlib-3.8.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7"}, 848 | {file = "matplotlib-3.8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39"}, 849 | {file = "matplotlib-3.8.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c4af3f7317f8a1009bbb2d0bf23dfaba859eb7dd4ccbd604eba146dccaaaf0a4"}, 850 | {file = "matplotlib-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4c6e00a65d017d26009bac6808f637b75ceade3e1ff91a138576f6b3065eeeba"}, 851 | {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7b49ab49a3bea17802df6872f8d44f664ba8f9be0632a60c99b20b6db2165b7"}, 852 | {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6728dde0a3997396b053602dbd907a9bd64ec7d5cf99e728b404083698d3ca01"}, 853 | {file = "matplotlib-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:813925d08fb86aba139f2d31864928d67511f64e5945ca909ad5bc09a96189bb"}, 854 | {file = "matplotlib-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:cd3a0c2be76f4e7be03d34a14d49ded6acf22ef61f88da600a18a5cd8b3c5f3c"}, 855 | {file = "matplotlib-3.8.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e"}, 856 | {file = "matplotlib-3.8.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc"}, 857 | {file = "matplotlib-3.8.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26"}, 858 | {file = "matplotlib-3.8.3.tar.gz", hash = "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161"}, 859 | ] 860 | 861 | [package.dependencies] 862 | contourpy = ">=1.0.1" 863 | cycler = ">=0.10" 864 | fonttools = ">=4.22.0" 865 | importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} 866 | kiwisolver = ">=1.3.1" 867 | numpy = ">=1.21,<2" 868 | packaging = ">=20.0" 869 | pillow = ">=8" 870 | pyparsing = ">=2.3.1" 871 | python-dateutil = ">=2.7" 872 | 873 | [[package]] 874 | name = "mock" 875 | version = "5.1.0" 876 | description = "Rolling backport of unittest.mock for all Pythons" 877 | optional = false 878 | python-versions = ">=3.6" 879 | groups = ["dev"] 880 | files = [ 881 | {file = "mock-5.1.0-py3-none-any.whl", hash = "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744"}, 882 | {file = "mock-5.1.0.tar.gz", hash = "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d"}, 883 | ] 884 | 885 | [package.extras] 886 | build = ["blurb", "twine", "wheel"] 887 | docs = ["sphinx"] 888 | test = ["pytest", "pytest-cov"] 889 | 890 | [[package]] 891 | name = "numpy" 892 | version = "1.26.4" 893 | description = "Fundamental package for array computing in Python" 894 | optional = false 895 | python-versions = ">=3.9" 896 | groups = ["main"] 897 | files = [ 898 | {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, 899 | {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, 900 | {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, 901 | {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, 902 | {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, 903 | {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, 904 | {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, 905 | {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, 906 | {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, 907 | {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, 908 | {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, 909 | {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, 910 | {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, 911 | {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, 912 | {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, 913 | {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, 914 | {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, 915 | {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, 916 | {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, 917 | {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, 918 | {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, 919 | {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, 920 | {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, 921 | {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, 922 | {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, 923 | {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, 924 | {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, 925 | {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, 926 | {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, 927 | {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, 928 | {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, 929 | {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, 930 | {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, 931 | {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, 932 | {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, 933 | {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, 934 | ] 935 | 936 | [[package]] 937 | name = "packaging" 938 | version = "23.2" 939 | description = "Core utilities for Python packages" 940 | optional = false 941 | python-versions = ">=3.7" 942 | groups = ["main", "dev"] 943 | files = [ 944 | {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, 945 | {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, 946 | ] 947 | 948 | [[package]] 949 | name = "pandas" 950 | version = "2.2.0" 951 | description = "Powerful data structures for data analysis, time series, and statistics" 952 | optional = false 953 | python-versions = ">=3.9" 954 | groups = ["main"] 955 | files = [ 956 | {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"}, 957 | {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"}, 958 | {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"}, 959 | {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"}, 960 | {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"}, 961 | {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"}, 962 | {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"}, 963 | {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"}, 964 | {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"}, 965 | {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"}, 966 | {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"}, 967 | {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"}, 968 | {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"}, 969 | {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"}, 970 | {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"}, 971 | {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"}, 972 | {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"}, 973 | {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"}, 974 | {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"}, 975 | {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"}, 976 | {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"}, 977 | {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"}, 978 | {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"}, 979 | {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"}, 980 | {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"}, 981 | {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"}, 982 | {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"}, 983 | {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"}, 984 | {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"}, 985 | ] 986 | 987 | [package.dependencies] 988 | numpy = [ 989 | {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, 990 | {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, 991 | {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, 992 | ] 993 | python-dateutil = ">=2.8.2" 994 | pytz = ">=2020.1" 995 | tzdata = ">=2022.7" 996 | 997 | [package.extras] 998 | 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)"] 999 | aws = ["s3fs (>=2022.11.0)"] 1000 | clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] 1001 | compression = ["zstandard (>=0.19.0)"] 1002 | computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] 1003 | consortium-standard = ["dataframe-api-compat (>=0.1.7)"] 1004 | 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)"] 1005 | feather = ["pyarrow (>=10.0.1)"] 1006 | fss = ["fsspec (>=2022.11.0)"] 1007 | gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] 1008 | hdf5 = ["tables (>=3.8.0)"] 1009 | html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] 1010 | mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] 1011 | output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] 1012 | parquet = ["pyarrow (>=10.0.1)"] 1013 | performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] 1014 | plot = ["matplotlib (>=3.6.3)"] 1015 | postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] 1016 | spss = ["pyreadstat (>=1.2.0)"] 1017 | sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] 1018 | test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] 1019 | xml = ["lxml (>=4.9.2)"] 1020 | 1021 | [[package]] 1022 | name = "pillow" 1023 | version = "10.3.0" 1024 | description = "Python Imaging Library (Fork)" 1025 | optional = false 1026 | python-versions = ">=3.8" 1027 | groups = ["main"] 1028 | files = [ 1029 | {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, 1030 | {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, 1031 | {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, 1032 | {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, 1033 | {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, 1034 | {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, 1035 | {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, 1036 | {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, 1037 | {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, 1038 | {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, 1039 | {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, 1040 | {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, 1041 | {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, 1042 | {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, 1043 | {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, 1044 | {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, 1045 | {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, 1046 | {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, 1047 | {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, 1048 | {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, 1049 | {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, 1050 | {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, 1051 | {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, 1052 | {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, 1053 | {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, 1054 | {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, 1055 | {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, 1056 | {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, 1057 | {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, 1058 | {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, 1059 | {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, 1060 | {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, 1061 | {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, 1062 | {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, 1063 | {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, 1064 | {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, 1065 | {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, 1066 | {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, 1067 | {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, 1068 | {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, 1069 | {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, 1070 | {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, 1071 | {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, 1072 | {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, 1073 | {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, 1074 | {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, 1075 | {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, 1076 | {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, 1077 | {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, 1078 | {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, 1079 | {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, 1080 | {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, 1081 | {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, 1082 | {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, 1083 | {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, 1084 | {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, 1085 | {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, 1086 | {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, 1087 | {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, 1088 | {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, 1089 | {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, 1090 | {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, 1091 | {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, 1092 | {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, 1093 | {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, 1094 | {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, 1095 | {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, 1096 | {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, 1097 | {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, 1098 | ] 1099 | 1100 | [package.extras] 1101 | docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] 1102 | fpx = ["olefile"] 1103 | mic = ["olefile"] 1104 | tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] 1105 | typing = ["typing-extensions ; python_version < \"3.10\""] 1106 | xmp = ["defusedxml"] 1107 | 1108 | [[package]] 1109 | name = "platformdirs" 1110 | version = "4.2.0" 1111 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 1112 | optional = false 1113 | python-versions = ">=3.8" 1114 | groups = ["dev"] 1115 | files = [ 1116 | {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, 1117 | {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, 1118 | ] 1119 | 1120 | [package.extras] 1121 | docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] 1122 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] 1123 | 1124 | [[package]] 1125 | name = "pluggy" 1126 | version = "1.4.0" 1127 | description = "plugin and hook calling mechanisms for python" 1128 | optional = false 1129 | python-versions = ">=3.8" 1130 | groups = ["dev"] 1131 | files = [ 1132 | {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, 1133 | {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, 1134 | ] 1135 | 1136 | [package.extras] 1137 | dev = ["pre-commit", "tox"] 1138 | testing = ["pytest", "pytest-benchmark"] 1139 | 1140 | [[package]] 1141 | name = "protobuf" 1142 | version = "4.25.3" 1143 | description = "" 1144 | optional = false 1145 | python-versions = ">=3.8" 1146 | groups = ["main"] 1147 | files = [ 1148 | {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, 1149 | {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, 1150 | {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, 1151 | {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, 1152 | {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, 1153 | {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, 1154 | {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, 1155 | {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, 1156 | {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, 1157 | {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, 1158 | {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, 1159 | ] 1160 | 1161 | [[package]] 1162 | name = "pyarrow" 1163 | version = "15.0.0" 1164 | description = "Python library for Apache Arrow" 1165 | optional = false 1166 | python-versions = ">=3.8" 1167 | groups = ["main"] 1168 | files = [ 1169 | {file = "pyarrow-15.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0a524532fd6dd482edaa563b686d754c70417c2f72742a8c990b322d4c03a15d"}, 1170 | {file = "pyarrow-15.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:60a6bdb314affa9c2e0d5dddf3d9cbb9ef4a8dddaa68669975287d47ece67642"}, 1171 | {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66958fd1771a4d4b754cd385835e66a3ef6b12611e001d4e5edfcef5f30391e2"}, 1172 | {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f500956a49aadd907eaa21d4fff75f73954605eaa41f61cb94fb008cf2e00c6"}, 1173 | {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6f87d9c4f09e049c2cade559643424da84c43a35068f2a1c4653dc5b1408a929"}, 1174 | {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85239b9f93278e130d86c0e6bb455dcb66fc3fd891398b9d45ace8799a871a1e"}, 1175 | {file = "pyarrow-15.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b8d43e31ca16aa6e12402fcb1e14352d0d809de70edd185c7650fe80e0769e3"}, 1176 | {file = "pyarrow-15.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:fa7cd198280dbd0c988df525e50e35b5d16873e2cdae2aaaa6363cdb64e3eec5"}, 1177 | {file = "pyarrow-15.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8780b1a29d3c8b21ba6b191305a2a607de2e30dab399776ff0aa09131e266340"}, 1178 | {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0ec198ccc680f6c92723fadcb97b74f07c45ff3fdec9dd765deb04955ccf19"}, 1179 | {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036a7209c235588c2f07477fe75c07e6caced9b7b61bb897c8d4e52c4b5f9555"}, 1180 | {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2bd8a0e5296797faf9a3294e9fa2dc67aa7f10ae2207920dbebb785c77e9dbe5"}, 1181 | {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e8ebed6053dbe76883a822d4e8da36860f479d55a762bd9e70d8494aed87113e"}, 1182 | {file = "pyarrow-15.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:17d53a9d1b2b5bd7d5e4cd84d018e2a45bc9baaa68f7e6e3ebed45649900ba99"}, 1183 | {file = "pyarrow-15.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9950a9c9df24090d3d558b43b97753b8f5867fb8e521f29876aa021c52fda351"}, 1184 | {file = "pyarrow-15.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:003d680b5e422d0204e7287bb3fa775b332b3fce2996aa69e9adea23f5c8f970"}, 1185 | {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f75fce89dad10c95f4bf590b765e3ae98bcc5ba9f6ce75adb828a334e26a3d40"}, 1186 | {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca9cb0039923bec49b4fe23803807e4ef39576a2bec59c32b11296464623dc2"}, 1187 | {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ed5a78ed29d171d0acc26a305a4b7f83c122d54ff5270810ac23c75813585e4"}, 1188 | {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6eda9e117f0402dfcd3cd6ec9bfee89ac5071c48fc83a84f3075b60efa96747f"}, 1189 | {file = "pyarrow-15.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a3a6180c0e8f2727e6f1b1c87c72d3254cac909e609f35f22532e4115461177"}, 1190 | {file = "pyarrow-15.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19a8918045993349b207de72d4576af0191beef03ea655d8bdb13762f0cd6eac"}, 1191 | {file = "pyarrow-15.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0ec076b32bacb6666e8813a22e6e5a7ef1314c8069d4ff345efa6246bc38593"}, 1192 | {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5db1769e5d0a77eb92344c7382d6543bea1164cca3704f84aa44e26c67e320fb"}, 1193 | {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2617e3bf9df2a00020dd1c1c6dce5cc343d979efe10bc401c0632b0eef6ef5b"}, 1194 | {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:d31c1d45060180131caf10f0f698e3a782db333a422038bf7fe01dace18b3a31"}, 1195 | {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:c8c287d1d479de8269398b34282e206844abb3208224dbdd7166d580804674b7"}, 1196 | {file = "pyarrow-15.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:07eb7f07dc9ecbb8dace0f58f009d3a29ee58682fcdc91337dfeb51ea618a75b"}, 1197 | {file = "pyarrow-15.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:47af7036f64fce990bb8a5948c04722e4e3ea3e13b1007ef52dfe0aa8f23cf7f"}, 1198 | {file = "pyarrow-15.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93768ccfff85cf044c418bfeeafce9a8bb0cee091bd8fd19011aff91e58de540"}, 1199 | {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ee87fd6892700960d90abb7b17a72a5abb3b64ee0fe8db6c782bcc2d0dc0b4"}, 1200 | {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:001fca027738c5f6be0b7a3159cc7ba16a5c52486db18160909a0831b063c4e4"}, 1201 | {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:d1c48648f64aec09accf44140dccb92f4f94394b8d79976c426a5b79b11d4fa7"}, 1202 | {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:972a0141be402bb18e3201448c8ae62958c9c7923dfaa3b3d4530c835ac81aed"}, 1203 | {file = "pyarrow-15.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:f01fc5cf49081426429127aa2d427d9d98e1cb94a32cb961d583a70b7c4504e6"}, 1204 | {file = "pyarrow-15.0.0.tar.gz", hash = "sha256:876858f549d540898f927eba4ef77cd549ad8d24baa3207cf1b72e5788b50e83"}, 1205 | ] 1206 | 1207 | [package.dependencies] 1208 | numpy = ">=1.16.6,<2" 1209 | 1210 | [[package]] 1211 | name = "pyasn1" 1212 | version = "0.5.1" 1213 | description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" 1214 | optional = false 1215 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 1216 | groups = ["main"] 1217 | files = [ 1218 | {file = "pyasn1-0.5.1-py2.py3-none-any.whl", hash = "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58"}, 1219 | {file = "pyasn1-0.5.1.tar.gz", hash = "sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c"}, 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "pyasn1-modules" 1224 | version = "0.3.0" 1225 | description = "A collection of ASN.1-based protocols modules" 1226 | optional = false 1227 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 1228 | groups = ["main"] 1229 | files = [ 1230 | {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, 1231 | {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, 1232 | ] 1233 | 1234 | [package.dependencies] 1235 | pyasn1 = ">=0.4.6,<0.6.0" 1236 | 1237 | [[package]] 1238 | name = "pyparsing" 1239 | version = "3.1.1" 1240 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 1241 | optional = false 1242 | python-versions = ">=3.6.8" 1243 | groups = ["main"] 1244 | files = [ 1245 | {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, 1246 | {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, 1247 | ] 1248 | 1249 | [package.extras] 1250 | diagrams = ["jinja2", "railroad-diagrams"] 1251 | 1252 | [[package]] 1253 | name = "pyproject-api" 1254 | version = "1.6.1" 1255 | description = "API to interact with the python pyproject.toml based projects" 1256 | optional = false 1257 | python-versions = ">=3.8" 1258 | groups = ["dev"] 1259 | files = [ 1260 | {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, 1261 | {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, 1262 | ] 1263 | 1264 | [package.dependencies] 1265 | packaging = ">=23.1" 1266 | tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} 1267 | 1268 | [package.extras] 1269 | docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] 1270 | testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] 1271 | 1272 | [[package]] 1273 | name = "python-daemon" 1274 | version = "3.0.1" 1275 | description = "Library to implement a well-behaved Unix daemon process." 1276 | optional = false 1277 | python-versions = ">=3" 1278 | groups = ["main"] 1279 | files = [ 1280 | {file = "python-daemon-3.0.1.tar.gz", hash = "sha256:6c57452372f7eaff40934a1c03ad1826bf5e793558e87fef49131e6464b4dae5"}, 1281 | {file = "python_daemon-3.0.1-py3-none-any.whl", hash = "sha256:42bb848a3260a027fa71ad47ecd959e471327cb34da5965962edd5926229f341"}, 1282 | ] 1283 | 1284 | [package.dependencies] 1285 | docutils = "*" 1286 | lockfile = ">=0.10" 1287 | setuptools = ">=62.4.0" 1288 | 1289 | [package.extras] 1290 | devel = ["coverage", "docutils", "isort", "testscenarios (>=0.4)", "testtools", "twine"] 1291 | test = ["coverage", "docutils", "testscenarios (>=0.4)", "testtools"] 1292 | 1293 | [[package]] 1294 | name = "python-dateutil" 1295 | version = "2.8.2" 1296 | description = "Extensions to the standard Python datetime module" 1297 | optional = false 1298 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 1299 | groups = ["main"] 1300 | files = [ 1301 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 1302 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 1303 | ] 1304 | 1305 | [package.dependencies] 1306 | six = ">=1.5" 1307 | 1308 | [[package]] 1309 | name = "pytz" 1310 | version = "2024.1" 1311 | description = "World timezone definitions, modern and historical" 1312 | optional = false 1313 | python-versions = "*" 1314 | groups = ["main"] 1315 | files = [ 1316 | {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, 1317 | {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "redis" 1322 | version = "5.0.1" 1323 | description = "Python client for Redis database and key-value store" 1324 | optional = false 1325 | python-versions = ">=3.7" 1326 | groups = ["main"] 1327 | files = [ 1328 | {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, 1329 | {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, 1330 | ] 1331 | 1332 | [package.dependencies] 1333 | async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} 1334 | 1335 | [package.extras] 1336 | hiredis = ["hiredis (>=1.0.0)"] 1337 | ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] 1338 | 1339 | [[package]] 1340 | name = "requests" 1341 | version = "2.32.2" 1342 | description = "Python HTTP for Humans." 1343 | optional = false 1344 | python-versions = ">=3.8" 1345 | groups = ["main"] 1346 | files = [ 1347 | {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, 1348 | {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, 1349 | ] 1350 | 1351 | [package.dependencies] 1352 | certifi = ">=2017.4.17" 1353 | charset-normalizer = ">=2,<4" 1354 | idna = ">=2.5,<4" 1355 | urllib3 = ">=1.21.1,<3" 1356 | 1357 | [package.extras] 1358 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 1359 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 1360 | 1361 | [[package]] 1362 | name = "rsa" 1363 | version = "4.9" 1364 | description = "Pure-Python RSA implementation" 1365 | optional = false 1366 | python-versions = ">=3.6,<4" 1367 | groups = ["main"] 1368 | files = [ 1369 | {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, 1370 | {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, 1371 | ] 1372 | 1373 | [package.dependencies] 1374 | pyasn1 = ">=0.1.3" 1375 | 1376 | [[package]] 1377 | name = "ruff" 1378 | version = "0.2.2" 1379 | description = "An extremely fast Python linter and code formatter, written in Rust." 1380 | optional = false 1381 | python-versions = ">=3.7" 1382 | groups = ["dev"] 1383 | files = [ 1384 | {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"}, 1385 | {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"}, 1386 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"}, 1387 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"}, 1388 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"}, 1389 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"}, 1390 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"}, 1391 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"}, 1392 | {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"}, 1393 | {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"}, 1394 | {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"}, 1395 | {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"}, 1396 | {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"}, 1397 | {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"}, 1398 | {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"}, 1399 | {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"}, 1400 | {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"}, 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "s3transfer" 1405 | version = "0.10.0" 1406 | description = "An Amazon S3 Transfer Manager" 1407 | optional = false 1408 | python-versions = ">= 3.8" 1409 | groups = ["main"] 1410 | files = [ 1411 | {file = "s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e"}, 1412 | {file = "s3transfer-0.10.0.tar.gz", hash = "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b"}, 1413 | ] 1414 | 1415 | [package.dependencies] 1416 | botocore = ">=1.33.2,<2.0a.0" 1417 | 1418 | [package.extras] 1419 | crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] 1420 | 1421 | [[package]] 1422 | name = "setuptools" 1423 | version = "78.1.1" 1424 | description = "Easily download, build, install, upgrade, and uninstall Python packages" 1425 | optional = false 1426 | python-versions = ">=3.9" 1427 | groups = ["main"] 1428 | files = [ 1429 | {file = "setuptools-78.1.1-py3-none-any.whl", hash = "sha256:c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561"}, 1430 | {file = "setuptools-78.1.1.tar.gz", hash = "sha256:fcc17fd9cd898242f6b4adfaca46137a9edef687f43e6f78469692a5e70d851d"}, 1431 | ] 1432 | 1433 | [package.extras] 1434 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] 1435 | core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] 1436 | cover = ["pytest-cov"] 1437 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] 1438 | enabler = ["pytest-enabler (>=2.2)"] 1439 | test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] 1440 | type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] 1441 | 1442 | [[package]] 1443 | name = "six" 1444 | version = "1.16.0" 1445 | description = "Python 2 and 3 compatibility utilities" 1446 | optional = false 1447 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 1448 | groups = ["main"] 1449 | files = [ 1450 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1451 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1452 | ] 1453 | 1454 | [[package]] 1455 | name = "slack-sdk" 1456 | version = "3.27.0" 1457 | description = "The Slack API Platform SDK for Python" 1458 | optional = false 1459 | python-versions = ">=3.6" 1460 | groups = ["main"] 1461 | files = [ 1462 | {file = "slack_sdk-3.27.0-py2.py3-none-any.whl", hash = "sha256:a901c68cb5547d5459cdefd81343d116db56d65f6b33f4081ddf1cdd243bf07e"}, 1463 | {file = "slack_sdk-3.27.0.tar.gz", hash = "sha256:811472ce598db855ab3c02f098fa430323ccb253cfe17ba20c7b05ab206d984d"}, 1464 | ] 1465 | 1466 | [package.extras] 1467 | optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=10,<11) ; python_version > \"3.6\"", "websockets (>=9.1,<10) ; python_version == \"3.6\""] 1468 | 1469 | [[package]] 1470 | name = "tenacity" 1471 | version = "8.2.3" 1472 | description = "Retry code until it succeeds" 1473 | optional = false 1474 | python-versions = ">=3.7" 1475 | groups = ["main"] 1476 | files = [ 1477 | {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, 1478 | {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, 1479 | ] 1480 | 1481 | [package.extras] 1482 | doc = ["reno", "sphinx", "tornado (>=4.5)"] 1483 | 1484 | [[package]] 1485 | name = "tomli" 1486 | version = "2.0.1" 1487 | description = "A lil' TOML parser" 1488 | optional = false 1489 | python-versions = ">=3.7" 1490 | groups = ["dev"] 1491 | markers = "python_version <= \"3.10\"" 1492 | files = [ 1493 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1494 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1495 | ] 1496 | 1497 | [[package]] 1498 | name = "tornado" 1499 | version = "6.5.1" 1500 | description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 1501 | optional = false 1502 | python-versions = ">=3.9" 1503 | groups = ["main"] 1504 | files = [ 1505 | {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7"}, 1506 | {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6"}, 1507 | {file = "tornado-6.5.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888"}, 1508 | {file = "tornado-6.5.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331"}, 1509 | {file = "tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e"}, 1510 | {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401"}, 1511 | {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692"}, 1512 | {file = "tornado-6.5.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a"}, 1513 | {file = "tornado-6.5.1-cp39-abi3-win32.whl", hash = "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365"}, 1514 | {file = "tornado-6.5.1-cp39-abi3-win_amd64.whl", hash = "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b"}, 1515 | {file = "tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7"}, 1516 | {file = "tornado-6.5.1.tar.gz", hash = "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c"}, 1517 | ] 1518 | 1519 | [[package]] 1520 | name = "tox" 1521 | version = "4.13.0" 1522 | description = "tox is a generic virtualenv management and test command line tool" 1523 | optional = false 1524 | python-versions = ">=3.8" 1525 | groups = ["dev"] 1526 | files = [ 1527 | {file = "tox-4.13.0-py3-none-any.whl", hash = "sha256:1143c7e2489c68026a55d3d4ae84c02c449f073b28e62f80e3e440a3b72a4afa"}, 1528 | {file = "tox-4.13.0.tar.gz", hash = "sha256:dd789a554c16c4b532924ba393c92fc8991323c4b3d466712bfecc8c9b9f24f7"}, 1529 | ] 1530 | 1531 | [package.dependencies] 1532 | cachetools = ">=5.3.2" 1533 | chardet = ">=5.2" 1534 | colorama = ">=0.4.6" 1535 | filelock = ">=3.13.1" 1536 | packaging = ">=23.2" 1537 | platformdirs = ">=4.1" 1538 | pluggy = ">=1.3" 1539 | pyproject-api = ">=1.6.1" 1540 | tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} 1541 | virtualenv = ">=20.25" 1542 | 1543 | [package.extras] 1544 | docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] 1545 | testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13) ; implementation_name != \"pypy\"", "wheel (>=0.42)"] 1546 | 1547 | [[package]] 1548 | name = "tqdm" 1549 | version = "4.66.3" 1550 | description = "Fast, Extensible Progress Meter" 1551 | optional = false 1552 | python-versions = ">=3.7" 1553 | groups = ["main"] 1554 | files = [ 1555 | {file = "tqdm-4.66.3-py3-none-any.whl", hash = "sha256:4f41d54107ff9a223dca80b53efe4fb654c67efaba7f47bada3ee9d50e05bd53"}, 1556 | {file = "tqdm-4.66.3.tar.gz", hash = "sha256:23097a41eba115ba99ecae40d06444c15d1c0c698d527a01c6c8bd1c5d0647e5"}, 1557 | ] 1558 | 1559 | [package.dependencies] 1560 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 1561 | 1562 | [package.extras] 1563 | dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] 1564 | notebook = ["ipywidgets (>=6)"] 1565 | slack = ["slack-sdk"] 1566 | telegram = ["requests"] 1567 | 1568 | [[package]] 1569 | name = "tzdata" 1570 | version = "2024.1" 1571 | description = "Provider of IANA time zone data" 1572 | optional = false 1573 | python-versions = ">=2" 1574 | groups = ["main"] 1575 | files = [ 1576 | {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, 1577 | {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, 1578 | ] 1579 | 1580 | [[package]] 1581 | name = "tzlocal" 1582 | version = "5.2" 1583 | description = "tzinfo object for the local timezone" 1584 | optional = false 1585 | python-versions = ">=3.8" 1586 | groups = ["main"] 1587 | files = [ 1588 | {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, 1589 | {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, 1590 | ] 1591 | 1592 | [package.dependencies] 1593 | tzdata = {version = "*", markers = "platform_system == \"Windows\""} 1594 | 1595 | [package.extras] 1596 | devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] 1597 | 1598 | [[package]] 1599 | name = "uritemplate" 1600 | version = "4.1.1" 1601 | description = "Implementation of RFC 6570 URI Templates" 1602 | optional = false 1603 | python-versions = ">=3.6" 1604 | groups = ["main"] 1605 | files = [ 1606 | {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, 1607 | {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, 1608 | ] 1609 | 1610 | [[package]] 1611 | name = "urllib3" 1612 | version = "1.26.19" 1613 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1614 | optional = false 1615 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 1616 | groups = ["main"] 1617 | files = [ 1618 | {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, 1619 | {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, 1620 | ] 1621 | 1622 | [package.extras] 1623 | brotli = ["brotli (==1.0.9) ; os_name != \"nt\" and python_version < \"3\" and platform_python_implementation == \"CPython\"", "brotli (>=1.0.9) ; python_version >= \"3\" and platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; (os_name != \"nt\" or python_version >= \"3\") and platform_python_implementation != \"CPython\"", "brotlipy (>=0.6.0) ; os_name == \"nt\" and python_version < \"3\""] 1624 | secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress ; python_version == \"2.7\"", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] 1625 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 1626 | 1627 | [[package]] 1628 | name = "virtualenv" 1629 | version = "20.26.6" 1630 | description = "Virtual Python Environment builder" 1631 | optional = false 1632 | python-versions = ">=3.7" 1633 | groups = ["dev"] 1634 | files = [ 1635 | {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"}, 1636 | {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"}, 1637 | ] 1638 | 1639 | [package.dependencies] 1640 | distlib = ">=0.3.7,<1" 1641 | filelock = ">=3.12.2,<4" 1642 | platformdirs = ">=3.9.1,<5" 1643 | 1644 | [package.extras] 1645 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] 1646 | test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] 1647 | 1648 | [[package]] 1649 | name = "zipp" 1650 | version = "3.19.1" 1651 | description = "Backport of pathlib-compatible object wrapper for zip files" 1652 | optional = false 1653 | python-versions = ">=3.8" 1654 | groups = ["main"] 1655 | markers = "python_version < \"3.10\"" 1656 | files = [ 1657 | {file = "zipp-3.19.1-py3-none-any.whl", hash = "sha256:2828e64edb5386ea6a52e7ba7cdb17bb30a73a858f5eb6eb93d8d36f5ea26091"}, 1658 | {file = "zipp-3.19.1.tar.gz", hash = "sha256:35427f6d5594f4acf82d25541438348c26736fa9b3afa2754bcd63cdb99d8e8f"}, 1659 | ] 1660 | 1661 | [package.extras] 1662 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 1663 | test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] 1664 | 1665 | [metadata] 1666 | lock-version = "2.1" 1667 | python-versions = ">=3.9,<3.13" 1668 | content-hash = "4576bfb1be801782d43ed194269cba253e1fa8086e6a1e0acc51e42be085e0af" 1669 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "thunderbolt" 3 | version = "0.0.0" # using poetry-dynamic-versioning 4 | description="gokart file downloader" 5 | authors = ["vaaaaanquish <6syun9@gmail.com>"] 6 | license = "MIT" 7 | readme = "README.md" 8 | homepage = "https://github.com/m3dev/thunderbolt" 9 | repository = "https://github.com/m3dev/thunderbolt" 10 | 11 | [tool.poetry-dynamic-versioning] 12 | enable = true 13 | style = "pep440" 14 | pattern = "^(?P\\d+\\.\\d+\\.\\d+)" 15 | 16 | [tool.poetry.dependencies] 17 | python = ">=3.9,<3.13" 18 | gokart = "*" 19 | boto3 = "*" 20 | tqdm = "*" 21 | 22 | [tool.poetry.group.dev.dependencies] 23 | ruff = "*" 24 | tox = "*" 25 | coverage = "*" 26 | mock = "*" 27 | 28 | [tool.ruff] 29 | line-length = 160 30 | exclude = ["venv/*", "tox/*"] 31 | 32 | [tool.ruff.lint] 33 | # All the rules are listed on https://docs.astral.sh/ruff/rules/ 34 | extend-select = [ 35 | "B", # bugbear 36 | "I" # isort 37 | ] 38 | 39 | # B006: Do not use mutable data structures for argument defaults. They are created during function definition time. All calls to the function reuse this one instance of that data structure, persisting changes between them. 40 | # B008 Do not perform function calls in argument defaults. The call is performed only once at function definition time. All calls to your function will reuse the result of that definition-time function call. If this is intended, assign the function call to a module-level variable and use that variable as a default value. 41 | ignore = ["B006", "B008"] 42 | 43 | # Avoid automatically removing unused imports in __init__.py files. 44 | ignore-init-module-imports = true 45 | 46 | [tool.ruff.lint.per-file-ignores] 47 | "__init__.py" = ["F401"] 48 | 49 | [tool.ruff.format] 50 | quote-style = "single" 51 | 52 | [build-system] 53 | requires = ["poetry"] 54 | build-backend = "poetry.masonry.api" 55 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m3dev/thunderbolt/c4f6d3e809debde2c90ae79fcf49a7eeeb82dceb/test/__init__.py -------------------------------------------------------------------------------- /test/sample.py: -------------------------------------------------------------------------------- 1 | # define tasks 2 | from logging import getLogger 3 | 4 | import gokart 5 | import luigi 6 | 7 | logger = getLogger(__name__) 8 | 9 | 10 | class TestCaseTask(gokart.TaskOnKart): 11 | task_namespace = 'test' 12 | param = luigi.Parameter() 13 | number = luigi.IntParameter() 14 | 15 | def require(self): 16 | return 17 | 18 | def output(self): 19 | return self.make_target(f'{self.param}/test_case.pkl') 20 | 21 | def run(self): 22 | self.dump(f'test number: {self.number}') 23 | 24 | 25 | gokart.run() 26 | -------------------------------------------------------------------------------- /test/test_case/log/processing_time/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m3dev/thunderbolt/c4f6d3e809debde2c90ae79fcf49a7eeeb82dceb/test/test_case/log/processing_time/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl -------------------------------------------------------------------------------- /test/test_case/log/task_log/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m3dev/thunderbolt/c4f6d3e809debde2c90ae79fcf49a7eeeb82dceb/test/test_case/log/task_log/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl -------------------------------------------------------------------------------- /test/test_case/log/task_params/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m3dev/thunderbolt/c4f6d3e809debde2c90ae79fcf49a7eeeb82dceb/test/test_case/log/task_params/TestCaseTask_c5b4a28a606228ac23477557c774a3a0.pkl -------------------------------------------------------------------------------- /test/test_case/sample/test_case_c5b4a28a606228ac23477557c774a3a0.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m3dev/thunderbolt/c4f6d3e809debde2c90ae79fcf49a7eeeb82dceb/test/test_case/sample/test_case_c5b4a28a606228ac23477557c774a3a0.pkl -------------------------------------------------------------------------------- /test/test_gcs_client.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from thunderbolt.client.gcs_client import GCSClient 4 | 5 | 6 | class TestGCSClient(unittest.TestCase): 7 | def setUp(self): 8 | self.base_path = 'gs://bucket/prefix/' 9 | self.client = GCSClient(self.base_path, None, None, use_cache=False) 10 | 11 | def test_to_absolute_path(self): 12 | source = 'gs://bucket/prefix/hoge/piyo' 13 | target = self.base_path + 'hoge/piyo' 14 | output = self.client.to_absolute_path(source) 15 | self.assertEqual(output, target) 16 | -------------------------------------------------------------------------------- /test/test_local_cache.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from pathlib import Path 4 | 5 | from thunderbolt.client.local_cache import LocalCache 6 | 7 | 8 | class TestLocalCache(unittest.TestCase): 9 | def setUp(self): 10 | self.base_path = './resources' 11 | self.local_cache = LocalCache(self.base_path, True) 12 | 13 | def test_init(self): 14 | self.assertTrue(os.path.exists('./thunderbolt')) 15 | 16 | def test_dump_and_get(self): 17 | target = {'foo': 'bar'} 18 | self.local_cache.dump('test.pkl', target) 19 | output = self.local_cache.get('test.pkl') 20 | self.assertDictEqual(target, output) 21 | 22 | def test_convert_file_path(self): 23 | output = self.local_cache._convert_file_path('test.pkl') 24 | target = Path(os.path.join(os.getcwd(), '.thunderbolt', self.base_path.split('/')[-1], 'test.pkl')) 25 | self.assertEqual(target, output) 26 | 27 | def tearDown(self): 28 | self.local_cache.clear() 29 | -------------------------------------------------------------------------------- /test/test_local_cache_regression.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import path 3 | 4 | from thunderbolt import Thunderbolt 5 | 6 | """ 7 | requires: 8 | python sample.py test.TestCaseTask --param=sample --number=1 --workspace-directory=./test_case --local-scheduler 9 | """ 10 | 11 | 12 | class LocalCacheTest(unittest.TestCase): 13 | def test_running(self): 14 | target = Thunderbolt(self._get_test_case_path(), use_cache=False) 15 | _ = Thunderbolt(self._get_test_case_path()) 16 | output = Thunderbolt(self._get_test_case_path()) 17 | 18 | for k, v in target.tasks.items(): 19 | if k == 'last_modified': # cache file 20 | continue 21 | self.assertEqual(v, output.tasks[k]) 22 | 23 | output.client.local_cache.clear() 24 | 25 | def _get_test_case_path(self, file_name: str = ''): 26 | p = path.abspath(path.join(path.dirname(__file__), 'test_case')) 27 | if file_name: 28 | return path.join(p, file_name) 29 | return p 30 | -------------------------------------------------------------------------------- /test/test_local_directory_client.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | 4 | from thunderbolt.client.local_directory_client import LocalDirectoryClient 5 | 6 | 7 | class TestLocalDirectoryClient(unittest.TestCase): 8 | def setUp(self): 9 | self.client = LocalDirectoryClient('.', None, None, use_cache=False) 10 | 11 | def test_to_absolute_path(self): 12 | source = './hoge/hoge/piyo' 13 | self.client.workspace_directory = '../hoge/' 14 | target = os.path.abspath('../hoge') + '/hoge/piyo' 15 | 16 | output = self.client.to_absolute_path(source) 17 | self.assertEqual(output, target) 18 | -------------------------------------------------------------------------------- /test/test_s3_client.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from thunderbolt.client.s3_client import S3Client 4 | 5 | 6 | class TestS3Client(unittest.TestCase): 7 | def setUp(self): 8 | self.base_path = 's3://bucket/prefix/' 9 | self.client = S3Client(self.base_path, None, None, use_cache=False) 10 | 11 | def test_to_absolute_path(self): 12 | source = 's3://bucket/prefix/hoge/piyo' 13 | target = self.base_path + 'hoge/piyo' 14 | output = self.client.to_absolute_path(source) 15 | self.assertEqual(output, target) 16 | -------------------------------------------------------------------------------- /test/test_thunderbolt.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from contextlib import ExitStack 3 | from unittest.mock import patch 4 | 5 | import pandas as pd 6 | from mock import MagicMock 7 | 8 | import thunderbolt 9 | from thunderbolt.client.gcs_client import GCSClient 10 | from thunderbolt.client.local_directory_client import LocalDirectoryClient 11 | from thunderbolt.client.s3_client import S3Client 12 | 13 | 14 | class TestThunderbolt(unittest.TestCase): 15 | def setUp(self): 16 | def get_tasks(): 17 | return [] 18 | 19 | module_path = 'thunderbolt.client' 20 | with ExitStack() as stack: 21 | for module in ['local_directory_client.LocalDirectoryClient', 'gcs_client.GCSClient', 's3_client.S3Client']: 22 | stack.enter_context(patch('.'.join([module_path, module, 'get_tasks']), side_effect=get_tasks)) 23 | self.tb = thunderbolt.Thunderbolt(None, use_cache=False) 24 | 25 | def test_get_client(self): 26 | source_workspace_directory = ['s3://', 'gs://', 'gcs://', './local', 'hoge'] 27 | source_filters = [] 28 | source_tqdm_disable = False 29 | target = [S3Client, GCSClient, GCSClient, LocalDirectoryClient, LocalDirectoryClient] 30 | 31 | for s, t in zip(source_workspace_directory, target): 32 | output = self.tb._get_client(s, source_filters, source_tqdm_disable, False) 33 | self.assertEqual(type(output), t) 34 | 35 | def test_get_tasks_dic(self): 36 | tasks_list = [ 37 | {'task_name': 'task', 'last_modified': 'last_modified_2', 'task_params': 'task_params_1', 'task_hash': 'task_hash_1', 'task_log': 'task_log_1'}, 38 | {'task_name': 'task', 'last_modified': 'last_modified_1', 'task_params': 'task_params_1', 'task_hash': 'task_hash_1', 'task_log': 'task_log_1'}, 39 | ] 40 | 41 | target = { 42 | 0: {'task_name': 'task', 'last_modified': 'last_modified_1', 'task_params': 'task_params_1', 'task_hash': 'task_hash_1', 'task_log': 'task_log_1'}, 43 | 1: {'task_name': 'task', 'last_modified': 'last_modified_2', 'task_params': 'task_params_1', 'task_hash': 'task_hash_1', 'task_log': 'task_log_1'}, 44 | } 45 | output = self.tb._get_tasks_dic(tasks_list=tasks_list) 46 | self.assertDictEqual(output, target) 47 | 48 | def test_get_task_df(self): 49 | self.tb.tasks = {} 50 | 51 | target = pd.DataFrame(columns=['task_id', 'task_name', 'last_modified', 'task_params', 'task_hash', 'task_log']) 52 | output = self.tb.get_task_df(all_data=True) 53 | pd.testing.assert_frame_equal(output, target) 54 | 55 | target = pd.DataFrame(columns=['task_id', 'task_name', 'last_modified', 'task_params']) 56 | output = self.tb.get_task_df(all_data=False) 57 | pd.testing.assert_frame_equal(output, target) 58 | 59 | self.tb.tasks = { 60 | 'Task1': { 61 | 'task_name': 'task_name_1', 62 | 'last_modified': 'last_modified_1', 63 | 'task_params': 'task_params_1', 64 | 'task_hash': 'task_hash_1', 65 | 'task_log': 'task_log_1', 66 | } 67 | } 68 | 69 | target = pd.DataFrame( 70 | { 71 | 'task_id': ['Task1'], 72 | 'task_name': ['task_name_1'], 73 | 'last_modified': ['last_modified_1'], 74 | 'task_params': ['task_params_1'], 75 | 'task_hash': ['task_hash_1'], 76 | 'task_log': ['task_log_1'], 77 | } 78 | ) 79 | output = self.tb.get_task_df(all_data=True) 80 | pd.testing.assert_frame_equal(output, target) 81 | 82 | target = pd.DataFrame( 83 | { 84 | 'task_id': ['Task1'], 85 | 'task_name': ['task_name_1'], 86 | 'last_modified': ['last_modified_1'], 87 | 'task_params': ['task_params_1'], 88 | } 89 | ) 90 | output = self.tb.get_task_df(all_data=False) 91 | pd.testing.assert_frame_equal(output, target) 92 | 93 | def test_get_data(self): 94 | self.tb.tasks = { 95 | 'Task1': { 96 | 'task_name': 'task', 97 | 'last_modified': 'last_modified_1', 98 | 'task_params': 'task_params_1', 99 | 'task_hash': 'task_hash_1', 100 | 'task_log': 'task_log_1', 101 | }, 102 | 'Task2': { 103 | 'task_name': 'task', 104 | 'last_modified': 'last_modified_2', 105 | 'task_params': 'task_params_2', 106 | 'task_hash': 'task_hash_2', 107 | 'task_log': 'task_log_2', 108 | }, 109 | } 110 | target = 'Task2' 111 | 112 | with patch('thunderbolt.Thunderbolt.load', side_effect=lambda x: x): 113 | output = self.tb.get_data('task') 114 | self.assertEqual(output, target) 115 | 116 | def test_get_data_top_k(self): 117 | self.tb.tasks = { 118 | 'Task1': { 119 | 'task_name': 'task', 120 | 'last_modified': 'last_modified_1', 121 | 'task_params': 'task_params_1', 122 | 'task_hash': 'task_hash_1', 123 | 'task_log': 'task_log_1', 124 | }, 125 | 'Task2': { 126 | 'task_name': 'task', 127 | 'last_modified': 'last_modified_2', 128 | 'task_params': 'task_params_2', 129 | 'task_hash': 'task_hash_2', 130 | 'task_log': 'task_log_2', 131 | }, 132 | 'Task3': { 133 | 'task_name': 'task', 134 | 'last_modified': 'last_modified_3', 135 | 'task_params': 'task_params_3', 136 | 'task_hash': 'task_hash_3', 137 | 'task_log': 'task_log_3', 138 | }, 139 | } 140 | target = ['Task3', 'Task2'] 141 | 142 | with patch('thunderbolt.Thunderbolt.load', side_effect=lambda x: x): 143 | output = self.tb.get_data('task', 2) 144 | self.assertEqual(output, target) 145 | 146 | def test_load(self): 147 | self.tb.tasks = { 148 | 'Task1': {'task_log': {'file_path': ['./hoge', './piyo']}}, 149 | 'Task2': {'task_log': {'file_path': ['./hoge']}}, 150 | } 151 | 152 | source = 'Task1' 153 | target = ['./hoge', './piyo'] 154 | with patch('thunderbolt.Thunderbolt._target_load', side_effect=lambda x: x): 155 | output = self.tb.load(source) 156 | self.assertListEqual(output, target) 157 | 158 | source = 'Task2' 159 | target = './hoge' 160 | with patch('thunderbolt.Thunderbolt._target_load', side_effect=lambda x: x): 161 | output = self.tb.load(source) 162 | self.assertEqual(output, target) 163 | 164 | def test_target_load(self): 165 | source = 'hoge' 166 | target = 'hoge' 167 | 168 | def make_target(file_path): 169 | class mock: 170 | def __init__(self, file_path): 171 | self.file_path = file_path 172 | 173 | def load(self): 174 | return file_path 175 | 176 | return mock(file_path) 177 | 178 | self.tb.client.to_absolute_path = MagicMock(side_effect=lambda x: x) 179 | with patch('gokart.target.make_target', side_effect=make_target): 180 | output = self.tb._target_load(source) 181 | self.assertEqual(output, target) 182 | -------------------------------------------------------------------------------- /test/test_thunderbolt_regression.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import unittest 3 | from os import path 4 | 5 | import pandas as pd 6 | 7 | import thunderbolt 8 | 9 | """ 10 | requires: 11 | python sample.py test.TestCaseTask --param=sample --number=1 --workspace-directory=./test_case --local-scheduler 12 | 13 | running: 14 | python -m unittest discover -s ./ 15 | """ 16 | 17 | 18 | class SimpleLocalTest(unittest.TestCase): 19 | def setUp(self): 20 | self.tb = thunderbolt.Thunderbolt(self.get_test_case_path(), use_cache=False) 21 | 22 | def test_init(self): 23 | self.assertEqual(self.tb.client.workspace_directory, self.get_test_case_path()) 24 | task = self.tb.tasks[0] 25 | self.assertEqual(task['task_name'], 'TestCaseTask') 26 | self.assertEqual(task['task_hash'], 'c5b4a28a606228ac23477557c774a3a0') 27 | self.assertListEqual(task['task_log']['file_path'], ['./test_case/sample/test_case_c5b4a28a606228ac23477557c774a3a0.pkl']) 28 | self.assertDictEqual(task['task_params'], {'param': 'sample', 'number': '1'}) 29 | 30 | def get_test_case_path(self, file_name: str = ''): 31 | p = path.abspath(path.join(path.dirname(__file__), 'test_case')) 32 | if file_name: 33 | return path.join(p, file_name) 34 | return p 35 | 36 | def test_get_task_df(self): 37 | df = self.tb.get_task_df(all_data=True) 38 | df = df.drop('last_modified', axis=1) 39 | target_df = pd.DataFrame( 40 | [ 41 | { 42 | 'task_id': 0, 43 | 'task_name': 'TestCaseTask', 44 | 'task_params': {'param': 'sample', 'number': '1'}, 45 | 'task_hash': 'c5b4a28a606228ac23477557c774a3a0', 46 | 'task_log': {'file_path': ['./test_case/sample/test_case_c5b4a28a606228ac23477557c774a3a0.pkl']}, 47 | } 48 | ] 49 | ) 50 | pd.testing.assert_frame_equal(df, target_df) 51 | 52 | def test_load(self): 53 | x = self.tb.load(0) 54 | with open(self.get_test_case_path('sample/test_case_c5b4a28a606228ac23477557c774a3a0.pkl'), 'rb') as f: 55 | target = pickle.load(f) 56 | self.assertEqual(x, target) 57 | -------------------------------------------------------------------------------- /thunderbolt/__init__.py: -------------------------------------------------------------------------------- 1 | from thunderbolt.thunderbolt import Thunderbolt 2 | -------------------------------------------------------------------------------- /thunderbolt/client/__init__.py: -------------------------------------------------------------------------------- 1 | from thunderbolt.client.gcs_client import GCSClient 2 | from thunderbolt.client.local_directory_client import LocalDirectoryClient 3 | from thunderbolt.client.s3_client import S3Client 4 | -------------------------------------------------------------------------------- /thunderbolt/client/gcs_client.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import warnings 4 | from datetime import datetime 5 | from typing import Any, Dict, List 6 | 7 | from gokart.gcs_config import GCSConfig 8 | from tqdm import tqdm 9 | 10 | from thunderbolt.client.local_cache import LocalCache 11 | 12 | 13 | class GCSClient: 14 | def __init__(self, workspace_directory: str = '', task_filters: List[str] = [], tqdm_disable: bool = False, use_cache: bool = True): 15 | """must set $GCS_CREDENTIAL""" 16 | self.workspace_directory = workspace_directory 17 | self.task_filters = task_filters 18 | self.tqdm_disable = tqdm_disable 19 | self.gcs_client = GCSConfig().get_gcs_client() 20 | self.local_cache = LocalCache(workspace_directory, use_cache) 21 | self.use_cache = use_cache 22 | 23 | def get_tasks(self) -> List[Dict[str, Any]]: 24 | """Load all task_log from GCS""" 25 | files = self._get_gcs_objects() 26 | tasks_list = list() 27 | for x in tqdm(files, disable=self.tqdm_disable): 28 | n = x.split('/')[-1] 29 | if self.task_filters and not [f for f in self.task_filters if f in n]: 30 | continue 31 | n = n.split('_') 32 | 33 | if self.use_cache: 34 | cache = self.local_cache.get(x) 35 | if cache: 36 | tasks_list.append(cache) 37 | continue 38 | 39 | try: 40 | meta = self._get_gcs_object_info(x) 41 | params = { 42 | 'task_name': '_'.join(n[:-1]), 43 | 'task_params': pickle.load(self.gcs_client.download(x.replace('task_log', 'task_params'))), 44 | 'task_log': pickle.load(self.gcs_client.download(x)), 45 | 'last_modified': datetime.strptime(meta['updated'].split('.')[0], '%Y-%m-%dT%H:%M:%S'), 46 | 'task_hash': n[-1].split('.')[0], 47 | } 48 | tasks_list.append(params) 49 | if self.use_cache: 50 | self.local_cache.dump(x, params) 51 | except Exception: 52 | continue 53 | 54 | if len(tasks_list) != len(list(files)): 55 | warnings.warn(f'[NOT FOUND LOGS] target file: {len(list(files))}, found log file: {len(tasks_list)}', stacklevel=2) 56 | 57 | return tasks_list 58 | 59 | def _get_gcs_objects(self) -> List[str]: 60 | """get GCS objects""" 61 | return self.gcs_client.listdir(os.path.join(self.workspace_directory, 'log/task_log')) 62 | 63 | def _get_gcs_object_info(self, x: str) -> Dict[str, str]: 64 | """get GCS object meta data""" 65 | bucket, obj = self.gcs_client._path_to_bucket_and_key(x) 66 | return self.gcs_client.client.objects().get(bucket=bucket, object=obj).execute() 67 | 68 | def to_absolute_path(self, x: str) -> str: 69 | """get GCS file path""" 70 | x = x.lstrip('.').lstrip('/') 71 | if self.workspace_directory.rstrip('/').split('/')[-1] == x.split('/')[0]: 72 | x = '/'.join(x.split('/')[1:]) 73 | return x 74 | -------------------------------------------------------------------------------- /thunderbolt/client/local_cache.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import shutil 4 | from pathlib import Path 5 | from typing import Optional 6 | 7 | 8 | class LocalCache: 9 | def __init__(self, workspace_directory: str, use_cache: bool): 10 | """Log file cache. 11 | 12 | dump file: ./.thunderbolt/resources/{task_hash}.pkl 13 | """ 14 | self.cache_dir = Path(os.path.join(os.getcwd(), '.thunderbolt', workspace_directory.split('/')[-1])) 15 | if use_cache: 16 | self.cache_dir.mkdir(parents=True, exist_ok=True) 17 | 18 | def get(self, file_name: str) -> Optional[dict]: 19 | cache_file_path = self._convert_file_path(file_name) 20 | if cache_file_path.exists(): 21 | with cache_file_path.open(mode='rb') as f: 22 | params = pickle.load(f) 23 | return params 24 | return None 25 | 26 | def dump(self, file_name: str, params: dict): 27 | cache_file_path = self._convert_file_path(file_name) 28 | with cache_file_path.open(mode='wb') as f: 29 | pickle.dump(params, f) 30 | 31 | def clear(self): 32 | shutil.rmtree(os.path.join(os.getcwd(), '.thunderbolt')) 33 | 34 | def _convert_file_path(self, file_name: str) -> Path: 35 | file_name = file_name.split('/')[-1] 36 | cache_file_path = self.cache_dir.joinpath(file_name) 37 | return cache_file_path.with_suffix('.pkl') 38 | -------------------------------------------------------------------------------- /thunderbolt/client/local_directory_client.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import warnings 4 | from datetime import datetime 5 | from pathlib import Path 6 | from typing import Any, Dict, List 7 | 8 | from tqdm import tqdm 9 | 10 | from thunderbolt.client.local_cache import LocalCache 11 | 12 | 13 | class LocalDirectoryClient: 14 | def __init__(self, workspace_directory: str = '', task_filters: List[str] = [], tqdm_disable: bool = False, use_cache: bool = True): 15 | self.workspace_directory = os.path.abspath(workspace_directory) 16 | self.task_filters = task_filters 17 | self.tqdm_disable = tqdm_disable 18 | self.local_cache = LocalCache(workspace_directory, use_cache) 19 | self.use_cache = use_cache 20 | 21 | def get_tasks(self) -> List[Dict[str, Any]]: 22 | """Load all task_log from workspace_directory.""" 23 | files = {str(path) for path in Path(os.path.join(self.workspace_directory, 'log/task_log')).rglob('*')} 24 | tasks_list = list() 25 | for x in tqdm(files, disable=self.tqdm_disable): 26 | n = x.split('/')[-1] 27 | if self.task_filters and not [x for x in self.task_filters if x in n]: 28 | continue 29 | n = n.split('_') 30 | 31 | if self.use_cache: 32 | cache = self.local_cache.get(x) 33 | if cache: 34 | tasks_list.append(cache) 35 | continue 36 | 37 | try: 38 | modified = datetime.fromtimestamp(os.stat(x).st_mtime) 39 | with open(x, 'rb') as f: 40 | task_log = pickle.load(f) 41 | with open(x.replace('task_log', 'task_params'), 'rb') as f: 42 | task_params = pickle.load(f) 43 | 44 | params = { 45 | 'task_name': '_'.join(n[:-1]), 46 | 'task_params': task_params, 47 | 'task_log': task_log, 48 | 'last_modified': modified, 49 | 'task_hash': n[-1].split('.')[0], 50 | } 51 | tasks_list.append(params) 52 | if self.use_cache: 53 | self.local_cache.dump(x, params) 54 | except Exception: 55 | continue 56 | 57 | if len(tasks_list) != len(files): 58 | warnings.warn(f'[NOT FOUND LOGS] target file: {len(files)}, found log file: {len(tasks_list)}', stacklevel=2) 59 | 60 | return tasks_list 61 | 62 | def to_absolute_path(self, x: str) -> str: 63 | """get file path""" 64 | x = x.lstrip('.').lstrip('/') 65 | if self.workspace_directory.rstrip('/').split('/')[-1] == x.split('/')[0]: 66 | x = '/'.join(x.split('/')[1:]) 67 | x = os.path.join(self.workspace_directory, x) 68 | return os.path.abspath(x) 69 | -------------------------------------------------------------------------------- /thunderbolt/client/s3_client.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import warnings 4 | from typing import Any, Dict, List 5 | 6 | import boto3 7 | from boto3 import Session 8 | from tqdm import tqdm 9 | 10 | from thunderbolt.client.local_cache import LocalCache 11 | 12 | 13 | class S3Client: 14 | def __init__(self, workspace_directory: str = '', task_filters: List[str] = [], tqdm_disable: bool = False, use_cache: bool = True): 15 | self.workspace_directory = workspace_directory 16 | self.task_filters = task_filters 17 | self.tqdm_disable = tqdm_disable 18 | self.bucket_name = workspace_directory.replace('s3://', '').split('/')[0] 19 | self.prefix = '/'.join(workspace_directory.replace('s3://', '').split('/')[1:]) 20 | self.resource = boto3.resource('s3') 21 | self.s3client = Session().client('s3') 22 | self.local_cache = LocalCache(workspace_directory, use_cache) 23 | self.use_cache = use_cache 24 | 25 | def get_tasks(self) -> List[Dict[str, Any]]: 26 | """Load all task_log from S3""" 27 | files = self._get_s3_keys([], '') 28 | tasks_list = list() 29 | for x in tqdm(files, disable=self.tqdm_disable): 30 | n = x['Key'].split('/')[-1] 31 | if self.task_filters and not [x for x in self.task_filters if x in n]: 32 | continue 33 | n = n.split('_') 34 | 35 | if self.use_cache: 36 | cache = self.local_cache.get(x['Key']) 37 | if cache: 38 | tasks_list.append(cache) 39 | continue 40 | 41 | try: 42 | params = { 43 | 'task_name': '_'.join(n[:-1]), 44 | 'task_params': pickle.loads(self.resource.Object(self.bucket_name, x['Key'].replace('task_log', 'task_params')).get()['Body'].read()), 45 | 'task_log': pickle.loads(self.resource.Object(self.bucket_name, x['Key']).get()['Body'].read()), 46 | 'last_modified': x['LastModified'], 47 | 'task_hash': n[-1].split('.')[0], 48 | } 49 | tasks_list.append(params) 50 | if self.use_cache: 51 | self.local_cache.dump(x['Key'], params) 52 | except Exception: 53 | continue 54 | 55 | if len(tasks_list) != len(files): 56 | warnings.warn(f'[NOT FOUND LOGS] target file: {len(files)}, found log file: {len(tasks_list)}', stacklevel=2) 57 | 58 | return tasks_list 59 | 60 | def _get_s3_keys(self, keys: List[Dict[str, Any]] = [], marker: str = '') -> List[Dict[str, Any]]: 61 | """Recursively get Key from S3. 62 | 63 | Using s3client api by boto module. 64 | Reference: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html 65 | 66 | Args: 67 | keys: The object key to get. Increases with recursion. 68 | marker: S3 marker. The recursion ends when this is gone. 69 | 70 | Returns: 71 | Object keys from S3. For example: ['hoge', 'piyo', ...] 72 | """ 73 | response = self.s3client.list_objects(Bucket=self.bucket_name, Prefix=os.path.join(self.prefix, 'log/task_log'), Marker=marker) 74 | if 'Contents' in response: 75 | keys.extend([{'Key': content['Key'], 'LastModified': content['LastModified']} for content in response['Contents']]) 76 | if 'Contents' in response and 'IsTruncated' in response: 77 | return self._get_s3_keys(keys=keys, marker=keys[-1]['Key']) 78 | return keys 79 | 80 | def to_absolute_path(self, x: str) -> str: 81 | """get S3 file path""" 82 | x = x.lstrip('.').lstrip('/') 83 | if self.workspace_directory.rstrip('/').split('/')[-1] == x.split('/')[0]: 84 | x = '/'.join(x.split('/')[1:]) 85 | return x 86 | -------------------------------------------------------------------------------- /thunderbolt/thunderbolt.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from typing import Any, Dict, List, Union 4 | 5 | import gokart 6 | import pandas as pd 7 | 8 | from thunderbolt.client.gcs_client import GCSClient 9 | from thunderbolt.client.local_directory_client import LocalDirectoryClient 10 | from thunderbolt.client.s3_client import S3Client 11 | 12 | 13 | class Thunderbolt: 14 | def __init__( 15 | self, workspace_directory: str = '', task_filters: Union[str, List[str]] = '', use_tqdm: bool = False, tmp_path: str = './tmp', use_cache: bool = True 16 | ): 17 | """Thunderbolt init. 18 | 19 | Set the path to the directory or S3. 20 | 21 | Args: 22 | workspace_directory: Gokart's TASK_WORKSPACE_DIRECTORY. If None, use $TASK_WORKSPACE_DIRECTORY in os.env. 23 | task_filters: Filter for task name. 24 | Load only tasks that contain the specified string here. We can also specify the number of copies. 25 | use_tqdm: Flag of using tdqm. If False, tqdm not be displayed (default=False). 26 | tmp_path: Temporary directory when use external load function. 27 | use_cache: Flag of using Log Cache. 28 | """ 29 | self.tmp_path = tmp_path 30 | if not workspace_directory: 31 | env = os.getenv('TASK_WORKSPACE_DIRECTORY') 32 | workspace_directory = env if env else '' 33 | self.client = self._get_client(workspace_directory, [task_filters] if isinstance(type(task_filters), str) else task_filters, not use_tqdm, use_cache) 34 | self.tasks = self._get_tasks_dic(tasks_list=self.client.get_tasks()) 35 | 36 | def _get_client(self, workspace_directory, filters, tqdm_disable, use_cache): 37 | if workspace_directory.startswith('s3://'): 38 | return S3Client(workspace_directory, filters, tqdm_disable, use_cache) 39 | elif workspace_directory.startswith('gs://') or workspace_directory.startswith('gcs://'): 40 | return GCSClient(workspace_directory, filters, tqdm_disable, use_cache) 41 | return LocalDirectoryClient(workspace_directory, filters, tqdm_disable, use_cache) 42 | 43 | def _get_tasks_dic(self, tasks_list: List[Dict]) -> Dict[int, Dict]: 44 | return {i: task for i, task in enumerate(sorted(tasks_list, key=lambda x: x['last_modified']))} 45 | 46 | def get_task_df(self, all_data: bool = False) -> pd.DataFrame: 47 | """Get task's pandas DataFrame. 48 | 49 | Args: 50 | all_data: If True, add `task unique hash` and `task log data` to DataFrame. 51 | 52 | Returns: 53 | All gokart task infomation pandas.DataFrame. 54 | """ 55 | if self.tasks: 56 | df = pd.DataFrame( 57 | [ 58 | { 59 | 'task_id': k, 60 | 'task_name': v['task_name'], 61 | 'last_modified': v['last_modified'], 62 | 'task_params': v['task_params'], 63 | 'task_hash': v['task_hash'], 64 | 'task_log': v['task_log'], 65 | } 66 | for k, v in self.tasks.items() 67 | ] 68 | ) 69 | else: 70 | df = pd.DataFrame(columns=['task_id', 'task_name', 'last_modified', 'task_params', 'task_hash', 'task_log']) 71 | 72 | if all_data: 73 | return df 74 | return df[['task_id', 'task_name', 'last_modified', 'task_params']] 75 | 76 | def get_data(self, task_name: str, top_k: int = 1) -> Union[list, Any]: 77 | """Load newest task output data. 78 | 79 | Args: 80 | task_name: gokart's task name. 81 | top_k: top-k of newest output data. 82 | 83 | Returns: 84 | The return value is newest data or data list. 85 | """ 86 | df = self.get_task_df() 87 | df = df.sort_values(by='last_modified', ascending=False) 88 | 89 | data = [self.load(df.query(f'task_name=="{task_name}"')['task_id'].iloc[i]) for i in range(top_k)] 90 | if len(data) == 1: 91 | return data[0] 92 | return data 93 | 94 | def load(self, task_id: int) -> Union[list, Any]: 95 | """Load File using gokart.load. 96 | 97 | Args: 98 | task_id: Specify the ID given by Thunderbolt, Read data into memory. 99 | Please check `task_id` by using Thunderbolt.get_task_df. 100 | 101 | Returns: 102 | The return value is data or data list. This is because it may be divided when dumping by gokart. 103 | """ 104 | data = [self._target_load(x) for x in self.tasks[task_id]['task_log']['file_path']] 105 | data = data[0] if len(data) == 1 else data 106 | return data 107 | 108 | def _target_load(self, file_name: str) -> Any: 109 | """Select gokart load_function and load model. 110 | 111 | Args: 112 | file_name: Path to gokart's output file. 113 | 114 | Returns: 115 | Loaded data. 116 | """ 117 | file_path = self.client.to_absolute_path(file_name) 118 | if file_path.endswith('.zip'): 119 | tmp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.abspath(self.tmp_path)) 120 | zip_client = gokart.zip_client_util.make_zip_client(file_path, tmp_path) 121 | zip_client.unpack_archive() 122 | load_function_path = os.path.join(tmp_path, 'load_function.pkl') 123 | load_function = gokart.target.make_target(load_function_path).load() 124 | model = load_function(os.path.join(tmp_path, 'model.pkl')) 125 | shutil.rmtree(tmp_path) 126 | return model 127 | return gokart.target.make_target(file_path=file_path).load() 128 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py{39,310,311,312},ruff 3 | isolated_build = true 4 | 5 | [testenv] 6 | allowlist_externals = coverage 7 | skip_install = true 8 | commands = coverage run -m unittest discover -s test 9 | 10 | [testenv:ruff] 11 | allowlist_externals = ruff 12 | skip_install = true 13 | commands = 14 | ruff check {posargs} 15 | ruff format --check {posargs} 16 | 17 | [gh-actions] 18 | python = 19 | 3.9: py39 20 | 3.10: py310 21 | 3.11: py311 22 | 3.12: py312 23 | --------------------------------------------------------------------------------