├── .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 | [](https://github.com/m3dev/thunderbolt/actions?query=workflow%3ATest)
4 | [](https://pypi.org/project/thunderbolt/)
5 | [](https://pypi.org/project/thunderbolt/)
6 | 
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 | " task_id | \n",
213 | " task_name | \n",
214 | " last_modified | \n",
215 | " task_params | \n",
216 | "
\n",
217 | " \n",
218 | " \n",
219 | " \n",
220 | " 0 | \n",
221 | " 0 | \n",
222 | " SampleTask | \n",
223 | " 2020-02-13 14:17:13.704206 | \n",
224 | " {'name': 'TEMP', 'number': '1'} | \n",
225 | "
\n",
226 | " \n",
227 | " 1 | \n",
228 | " 1 | \n",
229 | " SampleTask | \n",
230 | " 2020-02-13 14:17:15.728998 | \n",
231 | " {'name': 'TEMP', 'number': '2'} | \n",
232 | "
\n",
233 | " \n",
234 | " 2 | \n",
235 | " 2 | \n",
236 | " SecondTask | \n",
237 | " 2020-02-13 14:17:17.735793 | \n",
238 | " {'name': 'TEMP', 'number': '2', 'param': 'RUN'} | \n",
239 | "
\n",
240 | " \n",
241 | " 3 | \n",
242 | " 3 | \n",
243 | " SampleTask | \n",
244 | " 2020-02-13 14:17:07.787346 | \n",
245 | " {'name': 'EXAMPLE', 'number': '1'} | \n",
246 | "
\n",
247 | " \n",
248 | " 4 | \n",
249 | " 4 | \n",
250 | " SampleTask | \n",
251 | " 2020-02-13 14:17:09.776602 | \n",
252 | " {'name': 'EXAMPLE', 'number': '2'} | \n",
253 | "
\n",
254 | " \n",
255 | " 5 | \n",
256 | " 5 | \n",
257 | " SampleTask | \n",
258 | " 2020-02-13 14:17:11.699651 | \n",
259 | " {'name': 'EXAMPLE', 'number': '3'} | \n",
260 | "
\n",
261 | " \n",
262 | "
\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 | " task_id | \n",
342 | " task_name | \n",
343 | " last_modified | \n",
344 | " task_params | \n",
345 | " task_hash | \n",
346 | " task_log | \n",
347 | "
\n",
348 | " \n",
349 | " \n",
350 | " \n",
351 | " 0 | \n",
352 | " 0 | \n",
353 | " SampleTask | \n",
354 | " 2020-02-13 14:17:13.704206 | \n",
355 | " {'name': 'TEMP', 'number': '1'} | \n",
356 | " d57cff8074e2560896974850e5d3174d | \n",
357 | " {'file_path': ['./resources/__main__/SampleTask_d57cff8074e2560896974850e5d3174d.pkl']} | \n",
358 | "
\n",
359 | " \n",
360 | " 1 | \n",
361 | " 1 | \n",
362 | " SampleTask | \n",
363 | " 2020-02-13 14:17:15.728998 | \n",
364 | " {'name': 'TEMP', 'number': '2'} | \n",
365 | " d05a2ab961781d3d8eca3e2e5f0d608b | \n",
366 | " {'file_path': ['./resources/__main__/SampleTask_d05a2ab961781d3d8eca3e2e5f0d608b.pkl']} | \n",
367 | "
\n",
368 | " \n",
369 | " 2 | \n",
370 | " 3 | \n",
371 | " SampleTask | \n",
372 | " 2020-02-13 14:17:07.787346 | \n",
373 | " {'name': 'EXAMPLE', 'number': '1'} | \n",
374 | " e883bcfad65f5fb68259d1cd4691f384 | \n",
375 | " {'file_path': ['./resources/__main__/SampleTask_e883bcfad65f5fb68259d1cd4691f384.pkl']} | \n",
376 | "
\n",
377 | " \n",
378 | " 3 | \n",
379 | " 4 | \n",
380 | " SampleTask | \n",
381 | " 2020-02-13 14:17:09.776602 | \n",
382 | " {'name': 'EXAMPLE', 'number': '2'} | \n",
383 | " 84b0b9c5a39bce072271599c9f730660 | \n",
384 | " {'file_path': ['./resources/__main__/SampleTask_84b0b9c5a39bce072271599c9f730660.pkl']} | \n",
385 | "
\n",
386 | " \n",
387 | " 4 | \n",
388 | " 5 | \n",
389 | " SampleTask | \n",
390 | " 2020-02-13 14:17:11.699651 | \n",
391 | " {'name': 'EXAMPLE', 'number': '3'} | \n",
392 | " 944fc52ef5011b71b5839f035f4d7e48 | \n",
393 | " {'file_path': ['./resources/__main__/SampleTask_944fc52ef5011b71b5839f035f4d7e48.pkl']} | \n",
394 | "
\n",
395 | " \n",
396 | "
\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 |
--------------------------------------------------------------------------------