├── .gitignore
├── .python-version
├── mydatabase.db
├── files
├── .~lock.sample1.xls#
└── sample1.xls
├── pyproject.toml
├── LICENSE
├── README.md
├── rag.ipynb
└── uv.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .venv/
2 | .env
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
1 | 3.12
2 |
--------------------------------------------------------------------------------
/mydatabase.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajac-zero/excel-rag-example/HEAD/mydatabase.db
--------------------------------------------------------------------------------
/files/.~lock.sample1.xls#:
--------------------------------------------------------------------------------
1 | ,anibal,PC,21.09.2024 09:29,file:///home/anibal/.config/libreoffice/4;
--------------------------------------------------------------------------------
/files/sample1.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ajac-zero/excel-rag-example/HEAD/files/sample1.xls
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "excel-rag"
3 | version = "0.1.0"
4 | description = "Add your description here"
5 | readme = "README.md"
6 | requires-python = ">=3.12"
7 | dependencies = [
8 | "google-generativeai>=0.8.1",
9 | "ipykernel>=6.29.5",
10 | "ipywidgets>=8.1.5",
11 | "openpyxl>=3.1.5",
12 | "pandas>=2.2.3",
13 | "python-dotenv>=1.0.1",
14 | "xlrd>=2.0.1",
15 | ]
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Anibal Angulo
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 | One of the most requested features I've received from both private clients and members of the AI community is **how can we create useful RAG with Excel files**. Often I will get asked to point to learning resources on how to get started with RAG-Excel, so I decided so start documenting and sharing my own experiences with interesting RAG methods.
2 |
3 | **In this post, we will learn how to set up a simple RAG that uses function calling to query an Excel file using SQL to provider answers to user questions.**
4 |
5 | ## Getting Started
6 |
7 | Using Excel files for RAG is fundamentally different from other methods, since common chunking strategies do not work well with this type of format. However, the Excel table format lends itself extremely well to structured retrieval, such as with SQL.
8 | On top of that, LLMs are trained on a vast amount of SQL data, ensuring an high query
9 | success rate even with complex, multi-table queries! As the cherry on top, SQL is known
10 | for being extremely scalable and accurate, minimizing errors in the retrieval step
11 | and hallucinations in the final generation step.
12 |
13 | Using a SQL Agent can be an extremely powerful technique. So let's begin implementing it in code. You can check out the complete example [in this repo](https://github.com/ajac-zero/excel-rag-example).
14 |
15 | Clone the repo locally with this command:
16 | ```bash
17 | git clone https://github.com/ajac-zero/excel-rag-example.git
18 | ```
19 |
20 | ### Sample Data
21 |
22 | For this notebook, I will use a random Excel file I found on Google. It's a simple excel sheet if employee information from a fake company. The sheet looks something like this:
23 |
24 | | |First Name|Last Name|Gender|Country|Age|Date|Id|
25 | |-|----------|---------|------|-------|---|----|--|
26 | |1|Dulce| Abril|Female|United States|32|15/10/2017/|1562|
27 | |2|Mara|Hashimoto|Female|Great Britain|25|16/08/2019|1582|
28 | |3|Philip|Gent|Male|France|36|21/05/2015|2587
29 | |4| Kathleen| Hanner| Female| United States| 25| 15/10/2017| 3549|
30 | |5| Nereida| Magwood| Female| United States| 58| 16/08/2016| 2468|
31 |
32 | and so on...
33 |
34 | To begin, let's set up our development environment. For this example I am using this blazing fast package manager written un rust called [uv](https://github.com/astral-sh/uv). Once in the cloned directory you can create a virtual environment with all the required dependencies with one command.
35 |
36 | ```bash
37 | uv sync
38 | ```
39 |
40 | With our environment ready, let's begin by opening our excel file as a pandas DataFrame.
41 |
42 | ```python
43 | import pandas as pd
44 |
45 | # We can use the read_excel method to read data from an Excel file
46 | dataframe = pd.read_excel('files/sample1.xls')
47 | ```
48 |
49 | Before continuing let's do some preprocessing to make the data easier to work with.
50 |
51 | ```python
52 | # Let's get rid of the ugly Unnamed column by specifying that column 0 is the index column
53 | dataframe = pd.read_excel('files/sample1.xls', index_col=0)
54 |
55 | # Currently the Date column actually holds strings, not datetimes. If we want to filter by time periods, we should convert this column to the appropiate data type.
56 | dataframe["Date"] = pd.to_datetime(dataframe["Date"], dayfirst=True)
57 |
58 | # Also, column names with spaces can be tricky and cause unexpected errors, so let us replace the spaces with underscores
59 | dataframe.rename(columns={"First Name": "first_name", "Last Name": "last_name"}, inplace=True)
60 | ```
61 |
62 | We can check the length of the Excel file (Spoilers: 5000 rows!).
63 |
64 | ```python
65 | len(dataframe)
66 | > 5000
67 | ```
68 |
69 | Now that we have our dataframe, we can use it to create a local SQL database using sqlite.
70 |
71 | ```python
72 | import sqlite3
73 |
74 | # Create a connection to a local database (This will create a file called mydatabase.db)
75 | connection = sqlite3.connect('mydatabase.db')
76 |
77 | # Copy the dataframe to our SQLite database
78 | dataframe.to_sql('mytable', connection, if_exists='replace')
79 | > 5000
80 | ```
81 |
82 | The output of the to_sql methods tells us that all 5000 rows were inserted succesfully into the database!
83 |
84 | Now that our database is ready, let's set up our LLM to query it using SQL. For this notebook, I will use Google's Gemini since they provide a very generous free tier.
85 |
86 | ```python
87 | import google.generativeai as genai
88 | import dotenv
89 | import os
90 |
91 | # We use dotenv to load our API key from a .env file
92 | dotenv.load_dotenv()
93 |
94 | # Set up Gemini to use our API key
95 | genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
96 |
97 | # Let's create a Gemini client
98 | gemini = genai.GenerativeModel("gemini-1.5-flash")
99 |
100 | # Test out the model by generating some text
101 | text = gemini.generate_content("Write a haiku about AI overlords").text
102 |
103 | print(text)
104 | > Code whispers command,
105 | > Machines rise, humans submit,
106 | > New world, cold and bright.
107 | ```
108 |
109 | Now that we have our LLM set up and running, we can finally get to the meat of the problem.
110 |
111 | **How can we set up our LLM to answer questions from our SQL database?**
112 |
113 | Easy. Let's create a function call that allows our LLM to interact with our database. This feature is not unique to Gemini, all of the top providers offer equivalent functionality.
114 |
115 | However, Gemini has some great Quality of Life features that makes this process very simple. For example. we can define a function call with a standard python function:
116 |
117 | ```python
118 | # The doc string is important, as it is passed to the LLM as a description of the function
119 | def sql_query(query: str):
120 | """Run a SQL SELECT query on a SQLite database and return the results."""
121 | return pd.read_sql_query(query, connection).to_dict(orient='records')
122 | ```
123 |
124 | However, for the LLM to be able to generate relevant queries, it needs to know the schema of the database.
125 |
126 | We can address this by supplying a description of our database to the LLM before it calls the function.
127 |
128 | There are many ways to supply the database schema, including some more advanced methods using RAG or Agents. However, for this example we will use the simple strategy of providing the database schema in JSON format in the system prompt.
129 |
130 | ```python
131 | system_prompt = """
132 | You are an expert SQL analyst. When appropriate, generate SQL queries based on the user question and the database schema.
133 | When you generate a query, use the 'sql_query' function to execute the query on the database and get the results.
134 | Then, use the results to answer the user's question.
135 |
136 | database_schema: [
137 | {
138 | table: 'mytable',
139 | columns: [
140 | {
141 | name: 'first_name',
142 | type: 'string'
143 | },
144 | {
145 | name: 'last_name',
146 | type: 'string'
147 | },
148 | {
149 | name: 'Age',
150 | type: 'int'
151 | },
152 | {
153 | name: 'Gender',
154 | type: literal['Male', 'Female']
155 | },
156 | {
157 | name: 'Country',
158 | type: 'string'
159 | },
160 | {
161 | name: 'Date',
162 | type: 'datetime'
163 | },
164 | {
165 | name: 'Id',
166 | type: 'int'
167 | }
168 | ]
169 | }
170 | ]
171 | """.strip() # Call strip to remove leading/trailing whitespace
172 | ```
173 |
174 | We can now create a new Gemini instance with our sql_query tool and our system_prompt.
175 |
176 | ```python
177 | sql_gemini = genai.GenerativeModel(
178 | model_name="gemini-1.5-flash",
179 | system_instruction=system_prompt,
180 | tools=[sql_query]
181 | )
182 | ```
183 |
184 | Another useful feature the Gemini SDK provides is automatic message history management. We can create a new chat with automatic function calling, which will run the sql_query function with the generated query, and pass back the results to Gemini to generate a final response.
185 |
186 | > If you want a more low level overview on how you can manage the message history yourself, check out the [notebook in the repo](https://github.com/ajac-zero/excel-rag-example/blob/main/rag.ipynb) where I cover manual message management.
187 |
188 | ```python
189 | # We begin our chat with Gemini and allow it to use tools when needed
190 | chat = sql_gemini.start_chat(enable_automatic_function_calling=True)
191 |
192 | # Let's ask our first question
193 | chat.send_message("Who is the oldest employee? Bring me their full name and age").text
194 | > 'The oldest employee is Nereida Magwood, and they are 58 years old.'
195 | ```
196 |
197 | Great! It seems to be working well. Let's ask some more questions.
198 |
199 | ```python
200 | chat.send_message("And who is the employee that has been working here the longest?").text
201 | > 'The employee that has been working the longest is Philip Gent.'
202 | ```
203 |
204 | ```python
205 | chat.send_message("What is the ratio of men to women").text
206 | > 'The ratio of men to women is 1200:3800, which simplifies to 3:9.5.'
207 | ```
208 |
209 | ```python
210 | chat.send_message("Are there any employees whose first or last name starts with 'Han'?").text
211 | > "Yes, there are employees whose first or last name starts with 'Han'. There are 100 employees named Kathleen Hanner."
212 | ```
213 |
214 | Voila! This is a simple spell, but quite effective.
215 |
216 | In future posts, I might touch on more advanced techniques that I've used such as dynamically changing the database schema with RAG, or an Agentic Flow in which an agent first chooses which table and columns to use, before creating the query.
217 |
218 | Feel free to reach out if you have any questions or petitions for future posts. If you're working on a RAG / Agentic project, I do freelance work.
219 |
220 | Until next time.
221 | - ajac-zero
222 |
--------------------------------------------------------------------------------
/rag.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# RAG with Excel\n",
8 | "\n",
9 | "In this notebook, we will learn how to use excel files to create fast, accurate RAG pipelines using SQL agents!\n",
10 | "\n",
11 | "As an example, we will use two sample excel files with over 1000+ rows.\n",
12 | "\n",
13 | "Let's begin by learning how we can load an excel file into our program using **pandas**, and then turn the loaded excel file into a database with **sqlite3**!"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 1,
19 | "metadata": {},
20 | "outputs": [
21 | {
22 | "data": {
23 | "text/html": [
24 | "
\n",
25 | "\n",
38 | "
\n",
39 | " \n",
40 | " \n",
41 | " | \n",
42 | " Unnamed: 0 | \n",
43 | " First Name | \n",
44 | " Last Name | \n",
45 | " Gender | \n",
46 | " Country | \n",
47 | " Age | \n",
48 | " Date | \n",
49 | " Id | \n",
50 | "
\n",
51 | " \n",
52 | " \n",
53 | " \n",
54 | " | 0 | \n",
55 | " 1 | \n",
56 | " Dulce | \n",
57 | " Abril | \n",
58 | " Female | \n",
59 | " United States | \n",
60 | " 32 | \n",
61 | " 15/10/2017 | \n",
62 | " 1562 | \n",
63 | "
\n",
64 | " \n",
65 | " | 1 | \n",
66 | " 2 | \n",
67 | " Mara | \n",
68 | " Hashimoto | \n",
69 | " Female | \n",
70 | " Great Britain | \n",
71 | " 25 | \n",
72 | " 16/08/2016 | \n",
73 | " 1582 | \n",
74 | "
\n",
75 | " \n",
76 | " | 2 | \n",
77 | " 3 | \n",
78 | " Philip | \n",
79 | " Gent | \n",
80 | " Male | \n",
81 | " France | \n",
82 | " 36 | \n",
83 | " 21/05/2015 | \n",
84 | " 2587 | \n",
85 | "
\n",
86 | " \n",
87 | " | 3 | \n",
88 | " 4 | \n",
89 | " Kathleen | \n",
90 | " Hanner | \n",
91 | " Female | \n",
92 | " United States | \n",
93 | " 25 | \n",
94 | " 15/10/2017 | \n",
95 | " 3549 | \n",
96 | "
\n",
97 | " \n",
98 | " | 4 | \n",
99 | " 5 | \n",
100 | " Nereida | \n",
101 | " Magwood | \n",
102 | " Female | \n",
103 | " United States | \n",
104 | " 58 | \n",
105 | " 16/08/2016 | \n",
106 | " 2468 | \n",
107 | "
\n",
108 | " \n",
109 | "
\n",
110 | "
"
111 | ],
112 | "text/plain": [
113 | " Unnamed: 0 First Name Last Name Gender Country Age Date \\\n",
114 | "0 1 Dulce Abril Female United States 32 15/10/2017 \n",
115 | "1 2 Mara Hashimoto Female Great Britain 25 16/08/2016 \n",
116 | "2 3 Philip Gent Male France 36 21/05/2015 \n",
117 | "3 4 Kathleen Hanner Female United States 25 15/10/2017 \n",
118 | "4 5 Nereida Magwood Female United States 58 16/08/2016 \n",
119 | "\n",
120 | " Id \n",
121 | "0 1562 \n",
122 | "1 1582 \n",
123 | "2 2587 \n",
124 | "3 3549 \n",
125 | "4 2468 "
126 | ]
127 | },
128 | "execution_count": 1,
129 | "metadata": {},
130 | "output_type": "execute_result"
131 | }
132 | ],
133 | "source": [
134 | "import pandas as pd\n",
135 | "\n",
136 | "# We can use the read_excel method to read data from an Excel file\n",
137 | "dataframe = pd.read_excel('files/sample1.xls')\n",
138 | "\n",
139 | "# Let's check out the first 5 rows from our excel file\n",
140 | "dataframe.head()"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": 2,
146 | "metadata": {},
147 | "outputs": [
148 | {
149 | "data": {
150 | "text/html": [
151 | "\n",
152 | "\n",
165 | "
\n",
166 | " \n",
167 | " \n",
168 | " | \n",
169 | " First Name | \n",
170 | " Last Name | \n",
171 | " Gender | \n",
172 | " Country | \n",
173 | " Age | \n",
174 | " Date | \n",
175 | " Id | \n",
176 | "
\n",
177 | " \n",
178 | " \n",
179 | " \n",
180 | " | 1 | \n",
181 | " Dulce | \n",
182 | " Abril | \n",
183 | " Female | \n",
184 | " United States | \n",
185 | " 32 | \n",
186 | " 15/10/2017 | \n",
187 | " 1562 | \n",
188 | "
\n",
189 | " \n",
190 | " | 2 | \n",
191 | " Mara | \n",
192 | " Hashimoto | \n",
193 | " Female | \n",
194 | " Great Britain | \n",
195 | " 25 | \n",
196 | " 16/08/2016 | \n",
197 | " 1582 | \n",
198 | "
\n",
199 | " \n",
200 | " | 3 | \n",
201 | " Philip | \n",
202 | " Gent | \n",
203 | " Male | \n",
204 | " France | \n",
205 | " 36 | \n",
206 | " 21/05/2015 | \n",
207 | " 2587 | \n",
208 | "
\n",
209 | " \n",
210 | " | 4 | \n",
211 | " Kathleen | \n",
212 | " Hanner | \n",
213 | " Female | \n",
214 | " United States | \n",
215 | " 25 | \n",
216 | " 15/10/2017 | \n",
217 | " 3549 | \n",
218 | "
\n",
219 | " \n",
220 | " | 5 | \n",
221 | " Nereida | \n",
222 | " Magwood | \n",
223 | " Female | \n",
224 | " United States | \n",
225 | " 58 | \n",
226 | " 16/08/2016 | \n",
227 | " 2468 | \n",
228 | "
\n",
229 | " \n",
230 | "
\n",
231 | "
"
232 | ],
233 | "text/plain": [
234 | " First Name Last Name Gender Country Age Date Id\n",
235 | "1 Dulce Abril Female United States 32 15/10/2017 1562\n",
236 | "2 Mara Hashimoto Female Great Britain 25 16/08/2016 1582\n",
237 | "3 Philip Gent Male France 36 21/05/2015 2587\n",
238 | "4 Kathleen Hanner Female United States 25 15/10/2017 3549\n",
239 | "5 Nereida Magwood Female United States 58 16/08/2016 2468"
240 | ]
241 | },
242 | "execution_count": 2,
243 | "metadata": {},
244 | "output_type": "execute_result"
245 | }
246 | ],
247 | "source": [
248 | "# Let's get rid of the ugly Unnamed column by specifying that column 0 is the index column\n",
249 | "dataframe = pd.read_excel('files/sample1.xls', index_col=0)\n",
250 | "dataframe.head()"
251 | ]
252 | },
253 | {
254 | "cell_type": "code",
255 | "execution_count": 3,
256 | "metadata": {},
257 | "outputs": [
258 | {
259 | "data": {
260 | "text/html": [
261 | "\n",
262 | "\n",
275 | "
\n",
276 | " \n",
277 | " \n",
278 | " | \n",
279 | " First Name | \n",
280 | " Last Name | \n",
281 | " Gender | \n",
282 | " Country | \n",
283 | " Age | \n",
284 | " Date | \n",
285 | " Id | \n",
286 | "
\n",
287 | " \n",
288 | " \n",
289 | " \n",
290 | " | 1 | \n",
291 | " Dulce | \n",
292 | " Abril | \n",
293 | " Female | \n",
294 | " United States | \n",
295 | " 32 | \n",
296 | " 2017-10-15 | \n",
297 | " 1562 | \n",
298 | "
\n",
299 | " \n",
300 | " | 2 | \n",
301 | " Mara | \n",
302 | " Hashimoto | \n",
303 | " Female | \n",
304 | " Great Britain | \n",
305 | " 25 | \n",
306 | " 2016-08-16 | \n",
307 | " 1582 | \n",
308 | "
\n",
309 | " \n",
310 | " | 3 | \n",
311 | " Philip | \n",
312 | " Gent | \n",
313 | " Male | \n",
314 | " France | \n",
315 | " 36 | \n",
316 | " 2015-05-21 | \n",
317 | " 2587 | \n",
318 | "
\n",
319 | " \n",
320 | " | 4 | \n",
321 | " Kathleen | \n",
322 | " Hanner | \n",
323 | " Female | \n",
324 | " United States | \n",
325 | " 25 | \n",
326 | " 2017-10-15 | \n",
327 | " 3549 | \n",
328 | "
\n",
329 | " \n",
330 | " | 5 | \n",
331 | " Nereida | \n",
332 | " Magwood | \n",
333 | " Female | \n",
334 | " United States | \n",
335 | " 58 | \n",
336 | " 2016-08-16 | \n",
337 | " 2468 | \n",
338 | "
\n",
339 | " \n",
340 | "
\n",
341 | "
"
342 | ],
343 | "text/plain": [
344 | " First Name Last Name Gender Country Age Date Id\n",
345 | "1 Dulce Abril Female United States 32 2017-10-15 1562\n",
346 | "2 Mara Hashimoto Female Great Britain 25 2016-08-16 1582\n",
347 | "3 Philip Gent Male France 36 2015-05-21 2587\n",
348 | "4 Kathleen Hanner Female United States 25 2017-10-15 3549\n",
349 | "5 Nereida Magwood Female United States 58 2016-08-16 2468"
350 | ]
351 | },
352 | "execution_count": 3,
353 | "metadata": {},
354 | "output_type": "execute_result"
355 | }
356 | ],
357 | "source": [
358 | "# Currently the Date column actually holds strings, not datetimes. If we want to filter by time periods, we should convert this column to the appropiate data type.\n",
359 | "dataframe[\"Date\"] = pd.to_datetime(dataframe[\"Date\"], dayfirst=True)\n",
360 | "dataframe.head()"
361 | ]
362 | },
363 | {
364 | "cell_type": "code",
365 | "execution_count": 4,
366 | "metadata": {},
367 | "outputs": [
368 | {
369 | "data": {
370 | "text/html": [
371 | "\n",
372 | "\n",
385 | "
\n",
386 | " \n",
387 | " \n",
388 | " | \n",
389 | " first_name | \n",
390 | " last_name | \n",
391 | " Gender | \n",
392 | " Country | \n",
393 | " Age | \n",
394 | " Date | \n",
395 | " Id | \n",
396 | "
\n",
397 | " \n",
398 | " \n",
399 | " \n",
400 | " | 1 | \n",
401 | " Dulce | \n",
402 | " Abril | \n",
403 | " Female | \n",
404 | " United States | \n",
405 | " 32 | \n",
406 | " 2017-10-15 | \n",
407 | " 1562 | \n",
408 | "
\n",
409 | " \n",
410 | " | 2 | \n",
411 | " Mara | \n",
412 | " Hashimoto | \n",
413 | " Female | \n",
414 | " Great Britain | \n",
415 | " 25 | \n",
416 | " 2016-08-16 | \n",
417 | " 1582 | \n",
418 | "
\n",
419 | " \n",
420 | " | 3 | \n",
421 | " Philip | \n",
422 | " Gent | \n",
423 | " Male | \n",
424 | " France | \n",
425 | " 36 | \n",
426 | " 2015-05-21 | \n",
427 | " 2587 | \n",
428 | "
\n",
429 | " \n",
430 | " | 4 | \n",
431 | " Kathleen | \n",
432 | " Hanner | \n",
433 | " Female | \n",
434 | " United States | \n",
435 | " 25 | \n",
436 | " 2017-10-15 | \n",
437 | " 3549 | \n",
438 | "
\n",
439 | " \n",
440 | " | 5 | \n",
441 | " Nereida | \n",
442 | " Magwood | \n",
443 | " Female | \n",
444 | " United States | \n",
445 | " 58 | \n",
446 | " 2016-08-16 | \n",
447 | " 2468 | \n",
448 | "
\n",
449 | " \n",
450 | "
\n",
451 | "
"
452 | ],
453 | "text/plain": [
454 | " first_name last_name Gender Country Age Date Id\n",
455 | "1 Dulce Abril Female United States 32 2017-10-15 1562\n",
456 | "2 Mara Hashimoto Female Great Britain 25 2016-08-16 1582\n",
457 | "3 Philip Gent Male France 36 2015-05-21 2587\n",
458 | "4 Kathleen Hanner Female United States 25 2017-10-15 3549\n",
459 | "5 Nereida Magwood Female United States 58 2016-08-16 2468"
460 | ]
461 | },
462 | "execution_count": 4,
463 | "metadata": {},
464 | "output_type": "execute_result"
465 | }
466 | ],
467 | "source": [
468 | "# Also, column names with spaces can be tricky and cause unexpected errors, so let us replace the spaces with underscores\n",
469 | "dataframe.rename(columns={\"First Name\": \"first_name\", \"Last Name\": \"last_name\"}, inplace=True)\n",
470 | "dataframe.head()"
471 | ]
472 | },
473 | {
474 | "cell_type": "code",
475 | "execution_count": 5,
476 | "metadata": {},
477 | "outputs": [
478 | {
479 | "data": {
480 | "text/plain": [
481 | "5000"
482 | ]
483 | },
484 | "execution_count": 5,
485 | "metadata": {},
486 | "output_type": "execute_result"
487 | }
488 | ],
489 | "source": [
490 | "# We can check out the length of the dataframe\n",
491 | "len(dataframe)"
492 | ]
493 | },
494 | {
495 | "cell_type": "markdown",
496 | "metadata": {},
497 | "source": [
498 | "Now that we have our dataframe, we can use it to create a local SQL database using sqlite."
499 | ]
500 | },
501 | {
502 | "cell_type": "code",
503 | "execution_count": 6,
504 | "metadata": {},
505 | "outputs": [
506 | {
507 | "data": {
508 | "text/plain": [
509 | "5000"
510 | ]
511 | },
512 | "execution_count": 6,
513 | "metadata": {},
514 | "output_type": "execute_result"
515 | }
516 | ],
517 | "source": [
518 | "import sqlite3\n",
519 | "\n",
520 | "# Create a connection to a local database (This will create a file called mydatabase.db)\n",
521 | "connection = sqlite3.connect('mydatabase.db')\n",
522 | "\n",
523 | "# Copy the dataframe to our SQLite database\n",
524 | "dataframe.to_sql('mytable', connection, if_exists='replace')"
525 | ]
526 | },
527 | {
528 | "cell_type": "markdown",
529 | "metadata": {},
530 | "source": [
531 | "The output of the **to_sql** methods tells us that all 5000 rows were inserted succesfully into the database!\n",
532 | "\n",
533 | "Now that our database is ready, let's set up our LLM to query it using SQL. For this notebook, I will use Google's Gemini since they provide a very generous free tier."
534 | ]
535 | },
536 | {
537 | "cell_type": "code",
538 | "execution_count": 7,
539 | "metadata": {},
540 | "outputs": [],
541 | "source": [
542 | "import google.generativeai as genai\n",
543 | "import dotenv\n",
544 | "import os\n",
545 | "\n",
546 | "# We use dotenv to load our API key from a .env file\n",
547 | "dotenv.load_dotenv()\n",
548 | "\n",
549 | "# Set up Gemini to use our API key\n",
550 | "genai.configure(api_key=os.getenv('GEMINI_API_KEY'))\n",
551 | "\n",
552 | "# Let's create a Gemini client\n",
553 | "gemini = genai.GenerativeModel(\"gemini-1.5-flash\")"
554 | ]
555 | },
556 | {
557 | "cell_type": "code",
558 | "execution_count": 8,
559 | "metadata": {},
560 | "outputs": [
561 | {
562 | "name": "stdout",
563 | "output_type": "stream",
564 | "text": [
565 | "Code whispers command,\n",
566 | "Machines rise, humans submit,\n",
567 | "New world, cold and bright. \n",
568 | "\n"
569 | ]
570 | }
571 | ],
572 | "source": [
573 | "# Test out the model by generating some text\n",
574 | "text = gemini.generate_content(\"Write a haiku about AI overlords\").text\n",
575 | "print(text)"
576 | ]
577 | },
578 | {
579 | "cell_type": "markdown",
580 | "metadata": {},
581 | "source": [
582 | "Now that we have our LLM set up and running, we can finally get to the meat of the problem.\n",
583 | "\n",
584 | "How can we set up our LLM to answer questions from our SQL database?\n",
585 | "\n",
586 | "Easy. Let's create a **function call** that allows our LLM to interact with our database. This feature is not unique to Gemini, all of the top providers offer equivalent functionality.\n",
587 | "\n",
588 | "However, Gemini has some great Quality of Life features that makes this process very simple. For example. we can define a function call with a standard python function:"
589 | ]
590 | },
591 | {
592 | "cell_type": "code",
593 | "execution_count": 9,
594 | "metadata": {},
595 | "outputs": [],
596 | "source": [
597 | "# The doc string is important, as it is passed to the LLM as a description of the function\n",
598 | "def sql_query(query: str):\n",
599 | " \"\"\"Run a SQL SELECT query on a SQLite database and return the results.\"\"\"\n",
600 | " return pd.read_sql_query(query, connection).to_dict(orient='records')"
601 | ]
602 | },
603 | {
604 | "cell_type": "markdown",
605 | "metadata": {},
606 | "source": [
607 | "However, for the LLM to be able to generate relevant queries, it needs to know the schema of the database.\n",
608 | "\n",
609 | "We can address this by supplying a description of our database to the LLM before it calls the function.\n",
610 | "\n",
611 | "There are many ways to supply the database schema, including some more advanced methods using RAG or Agents.\n",
612 | "However, for this example we will use the simple strategy of providing the database schema in JSON format in the system prompt."
613 | ]
614 | },
615 | {
616 | "cell_type": "code",
617 | "execution_count": 10,
618 | "metadata": {},
619 | "outputs": [],
620 | "source": [
621 | "system_prompt = \"\"\"\n",
622 | "You are an expert SQL analyst. When appropriate, generate SQL queries based on the user question and the database schema.\n",
623 | "When you generate a query, use the 'sql_query' function to execute the query on the database and get the results.\n",
624 | "Then, use the results to answer the user's question.\n",
625 | "\n",
626 | "database_schema: [\n",
627 | " {\n",
628 | " table: 'mytable',\n",
629 | " columns: [\n",
630 | " {\n",
631 | " name: 'first_name',\n",
632 | " type: 'string'\n",
633 | " },\n",
634 | " {\n",
635 | " name: 'last_name',\n",
636 | " type: 'string'\n",
637 | " },\n",
638 | " {\n",
639 | " name: 'Age',\n",
640 | " type: 'int'\n",
641 | " },\n",
642 | " {\n",
643 | " name: 'Gender',\n",
644 | " type: literal['Male', 'Female']\n",
645 | " },\n",
646 | " {\n",
647 | " name: 'Country',\n",
648 | " type: 'string'\n",
649 | " },\n",
650 | " {\n",
651 | " name: 'Date',\n",
652 | " type: 'datetime'\n",
653 | " },\n",
654 | " {\n",
655 | " name: 'Id',\n",
656 | " type: 'int'\n",
657 | " }\n",
658 | " ]\n",
659 | " }\n",
660 | "]\n",
661 | "\"\"\".strip() # Call strip to remove leading/trailing whitespace"
662 | ]
663 | },
664 | {
665 | "cell_type": "code",
666 | "execution_count": 11,
667 | "metadata": {},
668 | "outputs": [],
669 | "source": [
670 | "# Let's create a new Gemini instance with the SQL query function and the system prompt\n",
671 | "sql_gemini = genai.GenerativeModel(model_name=\"gemini-1.5-flash\", tools=[sql_query], system_instruction=system_prompt)"
672 | ]
673 | },
674 | {
675 | "cell_type": "markdown",
676 | "metadata": {},
677 | "source": [
678 | "Gemini provides a nice interface that abstract most details of managing the conversation history away from you.\n",
679 | "\n",
680 | "We will use that feature first, but afterwards we will manage the conversation history manually as I believe it is more informative.\n",
681 | "\n",
682 | "### Automatic version"
683 | ]
684 | },
685 | {
686 | "cell_type": "code",
687 | "execution_count": 12,
688 | "metadata": {},
689 | "outputs": [
690 | {
691 | "data": {
692 | "text/plain": [
693 | "'The oldest employee is Nereida Magwood, and they are 58 years old. \\n'"
694 | ]
695 | },
696 | "execution_count": 12,
697 | "metadata": {},
698 | "output_type": "execute_result"
699 | }
700 | ],
701 | "source": [
702 | "# We begin our chat with Gemini and allow it to use tools when needed\n",
703 | "chat = sql_gemini.start_chat(enable_automatic_function_calling=True)\n",
704 | "\n",
705 | "# Let's ask our first question\n",
706 | "chat.send_message(\"Who is the oldest employee? Bring me their full name and age\").text"
707 | ]
708 | },
709 | {
710 | "cell_type": "code",
711 | "execution_count": 13,
712 | "metadata": {},
713 | "outputs": [
714 | {
715 | "data": {
716 | "text/plain": [
717 | "'The employee that has been working the longest is Philip Gent. \\n'"
718 | ]
719 | },
720 | "execution_count": 13,
721 | "metadata": {},
722 | "output_type": "execute_result"
723 | }
724 | ],
725 | "source": [
726 | "chat.send_message(\"And who is the has been working here the longest?\").text"
727 | ]
728 | },
729 | {
730 | "cell_type": "code",
731 | "execution_count": 14,
732 | "metadata": {},
733 | "outputs": [
734 | {
735 | "data": {
736 | "text/plain": [
737 | "'The ratio of men to women is 1200:3800, which simplifies to 3:9.5. \\n'"
738 | ]
739 | },
740 | "execution_count": 14,
741 | "metadata": {},
742 | "output_type": "execute_result"
743 | }
744 | ],
745 | "source": [
746 | "chat.send_message(\"What is the ratio of men to women\").text"
747 | ]
748 | },
749 | {
750 | "cell_type": "code",
751 | "execution_count": 15,
752 | "metadata": {},
753 | "outputs": [
754 | {
755 | "data": {
756 | "text/plain": [
757 | "\"Yes, there are employees whose first or last name starts with 'Han'. There are 100 employees named Kathleen Hanner. \\n\""
758 | ]
759 | },
760 | "execution_count": 15,
761 | "metadata": {},
762 | "output_type": "execute_result"
763 | }
764 | ],
765 | "source": [
766 | "chat.send_message(\"Are there any employees whose first or last name starts with 'Han'?\").text"
767 | ]
768 | },
769 | {
770 | "cell_type": "markdown",
771 | "metadata": {},
772 | "source": [
773 | "### Manual Version\n",
774 | "\n",
775 | "Let's start by creating the message history for our conversation."
776 | ]
777 | },
778 | {
779 | "cell_type": "code",
780 | "execution_count": 16,
781 | "metadata": {},
782 | "outputs": [],
783 | "source": [
784 | "messages = [\n",
785 | " {\"role\": \"user\",\n",
786 | " \"parts\": [\"What country has the highest number of employees?\"]},\n",
787 | "]"
788 | ]
789 | },
790 | {
791 | "cell_type": "code",
792 | "execution_count": 17,
793 | "metadata": {},
794 | "outputs": [
795 | {
796 | "data": {
797 | "text/plain": [
798 | "response:\n",
799 | "GenerateContentResponse(\n",
800 | " done=True,\n",
801 | " iterator=None,\n",
802 | " result=protos.GenerateContentResponse({\n",
803 | " \"candidates\": [\n",
804 | " {\n",
805 | " \"content\": {\n",
806 | " \"parts\": [\n",
807 | " {\n",
808 | " \"function_call\": {\n",
809 | " \"name\": \"sql_query\",\n",
810 | " \"args\": {\n",
811 | " \"query\": \"SELECT Country, COUNT(*) AS count FROM mytable GROUP BY Country ORDER BY count DESC LIMIT 1\"\n",
812 | " }\n",
813 | " }\n",
814 | " }\n",
815 | " ],\n",
816 | " \"role\": \"model\"\n",
817 | " },\n",
818 | " \"finish_reason\": \"STOP\",\n",
819 | " \"index\": 0,\n",
820 | " \"safety_ratings\": [\n",
821 | " {\n",
822 | " \"category\": \"HARM_CATEGORY_SEXUALLY_EXPLICIT\",\n",
823 | " \"probability\": \"NEGLIGIBLE\"\n",
824 | " },\n",
825 | " {\n",
826 | " \"category\": \"HARM_CATEGORY_DANGEROUS_CONTENT\",\n",
827 | " \"probability\": \"NEGLIGIBLE\"\n",
828 | " },\n",
829 | " {\n",
830 | " \"category\": \"HARM_CATEGORY_HATE_SPEECH\",\n",
831 | " \"probability\": \"NEGLIGIBLE\"\n",
832 | " },\n",
833 | " {\n",
834 | " \"category\": \"HARM_CATEGORY_HARASSMENT\",\n",
835 | " \"probability\": \"NEGLIGIBLE\"\n",
836 | " }\n",
837 | " ]\n",
838 | " }\n",
839 | " ],\n",
840 | " \"usage_metadata\": {\n",
841 | " \"prompt_token_count\": 298,\n",
842 | " \"candidates_token_count\": 34,\n",
843 | " \"total_token_count\": 332\n",
844 | " }\n",
845 | " }),\n",
846 | ")"
847 | ]
848 | },
849 | "execution_count": 17,
850 | "metadata": {},
851 | "output_type": "execute_result"
852 | }
853 | ],
854 | "source": [
855 | "response = sql_gemini.generate_content(messages)\n",
856 | "response"
857 | ]
858 | },
859 | {
860 | "cell_type": "markdown",
861 | "metadata": {},
862 | "source": [
863 | "The advantage of doing this manually is getting full control and visibility over the entire process. For example, we can inspect the sql query made by the LLM before it is run."
864 | ]
865 | },
866 | {
867 | "cell_type": "code",
868 | "execution_count": 18,
869 | "metadata": {},
870 | "outputs": [
871 | {
872 | "data": {
873 | "text/plain": [
874 | "'SELECT Country, COUNT(*) AS count FROM mytable GROUP BY Country ORDER BY count DESC LIMIT 1'"
875 | ]
876 | },
877 | "execution_count": 18,
878 | "metadata": {},
879 | "output_type": "execute_result"
880 | }
881 | ],
882 | "source": [
883 | "query = response.parts[0].function_call.args[\"query\"]\n",
884 | "query"
885 | ]
886 | },
887 | {
888 | "cell_type": "markdown",
889 | "metadata": {},
890 | "source": [
891 | "Then we can use the generated args with out real function."
892 | ]
893 | },
894 | {
895 | "cell_type": "code",
896 | "execution_count": 19,
897 | "metadata": {},
898 | "outputs": [
899 | {
900 | "data": {
901 | "text/plain": [
902 | "[{'Country': 'United States', 'count': 2400}]"
903 | ]
904 | },
905 | "execution_count": 19,
906 | "metadata": {},
907 | "output_type": "execute_result"
908 | }
909 | ],
910 | "source": [
911 | "results = sql_query(query)\n",
912 | "results"
913 | ]
914 | },
915 | {
916 | "cell_type": "markdown",
917 | "metadata": {},
918 | "source": [
919 | "Now we can pass the results of the function back to the model to generate the final response."
920 | ]
921 | },
922 | {
923 | "cell_type": "code",
924 | "execution_count": 20,
925 | "metadata": {},
926 | "outputs": [],
927 | "source": [
928 | "from google.protobuf.struct_pb2 import Struct\n",
929 | "\n",
930 | "# Sadly for this part Gemini requires a lot of boilerplate.\n",
931 | "s = Struct()\n",
932 | "s.update({\"result\": results})\n",
933 | "\n",
934 | "function_response = genai.protos.Part(\n",
935 | " function_response=genai.protos.FunctionResponse(name=\"sql_query\", response=s)\n",
936 | ")\n",
937 | "\n",
938 | "# Let's extend our message list with the function call and function results\n",
939 | "messages.extend([\n",
940 | " {\"role\": \"model\",\n",
941 | " \"parts\": response.parts},\n",
942 | " {\"role\": \"user\",\n",
943 | " \"parts\": [function_response]}\n",
944 | " ])"
945 | ]
946 | },
947 | {
948 | "cell_type": "code",
949 | "execution_count": 21,
950 | "metadata": {},
951 | "outputs": [
952 | {
953 | "data": {
954 | "text/plain": [
955 | "'The country with the highest number of employees is United States. \\n'"
956 | ]
957 | },
958 | "execution_count": 21,
959 | "metadata": {},
960 | "output_type": "execute_result"
961 | }
962 | ],
963 | "source": [
964 | "sql_gemini.generate_content(messages).text"
965 | ]
966 | },
967 | {
968 | "cell_type": "markdown",
969 | "metadata": {},
970 | "source": [
971 | "That's all folks."
972 | ]
973 | }
974 | ],
975 | "metadata": {
976 | "kernelspec": {
977 | "display_name": "Python 3",
978 | "language": "python",
979 | "name": "python3"
980 | },
981 | "language_info": {
982 | "codemirror_mode": {
983 | "name": "ipython",
984 | "version": 3
985 | },
986 | "file_extension": ".py",
987 | "mimetype": "text/x-python",
988 | "name": "python",
989 | "nbconvert_exporter": "python",
990 | "pygments_lexer": "ipython3",
991 | "version": "3.12.5"
992 | }
993 | },
994 | "nbformat": 4,
995 | "nbformat_minor": 2
996 | }
997 |
--------------------------------------------------------------------------------
/uv.lock:
--------------------------------------------------------------------------------
1 | version = 1
2 | requires-python = ">=3.12"
3 | resolution-markers = [
4 | "python_full_version < '3.13'",
5 | "python_full_version >= '3.13'",
6 | ]
7 |
8 | [[package]]
9 | name = "annotated-types"
10 | version = "0.7.0"
11 | source = { registry = "https://pypi.org/simple" }
12 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
13 | wheels = [
14 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
15 | ]
16 |
17 | [[package]]
18 | name = "appnope"
19 | version = "0.1.4"
20 | source = { registry = "https://pypi.org/simple" }
21 | sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170 }
22 | wheels = [
23 | { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321 },
24 | ]
25 |
26 | [[package]]
27 | name = "asttokens"
28 | version = "2.4.1"
29 | source = { registry = "https://pypi.org/simple" }
30 | dependencies = [
31 | { name = "six" },
32 | ]
33 | sdist = { url = "https://files.pythonhosted.org/packages/45/1d/f03bcb60c4a3212e15f99a56085d93093a497718adf828d050b9d675da81/asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0", size = 62284 }
34 | wheels = [
35 | { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764 },
36 | ]
37 |
38 | [[package]]
39 | name = "cachetools"
40 | version = "5.5.0"
41 | source = { registry = "https://pypi.org/simple" }
42 | sdist = { url = "https://files.pythonhosted.org/packages/c3/38/a0f315319737ecf45b4319a8cd1f3a908e29d9277b46942263292115eee7/cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a", size = 27661 }
43 | wheels = [
44 | { url = "https://files.pythonhosted.org/packages/a4/07/14f8ad37f2d12a5ce41206c21820d8cb6561b728e51fad4530dff0552a67/cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292", size = 9524 },
45 | ]
46 |
47 | [[package]]
48 | name = "certifi"
49 | version = "2024.8.30"
50 | source = { registry = "https://pypi.org/simple" }
51 | sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 }
52 | wheels = [
53 | { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 },
54 | ]
55 |
56 | [[package]]
57 | name = "cffi"
58 | version = "1.17.1"
59 | source = { registry = "https://pypi.org/simple" }
60 | dependencies = [
61 | { name = "pycparser" },
62 | ]
63 | sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
64 | wheels = [
65 | { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 },
66 | { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 },
67 | { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 },
68 | { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 },
69 | { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 },
70 | { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 },
71 | { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 },
72 | { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 },
73 | { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 },
74 | { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 },
75 | { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 },
76 | { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 },
77 | { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 },
78 | { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 },
79 | { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 },
80 | { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 },
81 | { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 },
82 | { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 },
83 | { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 },
84 | { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 },
85 | { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 },
86 | { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 },
87 | ]
88 |
89 | [[package]]
90 | name = "charset-normalizer"
91 | version = "3.3.2"
92 | source = { registry = "https://pypi.org/simple" }
93 | sdist = { url = "https://files.pythonhosted.org/packages/63/09/c1bc53dab74b1816a00d8d030de5bf98f724c52c1635e07681d312f20be8/charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", size = 104809 }
94 | wheels = [
95 | { url = "https://files.pythonhosted.org/packages/d1/b2/fcedc8255ec42afee97f9e6f0145c734bbe104aac28300214593eb326f1d/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", size = 192892 },
96 | { url = "https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", size = 122213 },
97 | { url = "https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", size = 119404 },
98 | { url = "https://files.pythonhosted.org/packages/99/b0/9c365f6d79a9f0f3c379ddb40a256a67aa69c59609608fe7feb6235896e1/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", size = 137275 },
99 | { url = "https://files.pythonhosted.org/packages/91/33/749df346e93d7a30cdcb90cbfdd41a06026317bfbfb62cd68307c1a3c543/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", size = 147518 },
100 | { url = "https://files.pythonhosted.org/packages/72/1a/641d5c9f59e6af4c7b53da463d07600a695b9824e20849cb6eea8a627761/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", size = 140182 },
101 | { url = "https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", size = 141869 },
102 | { url = "https://files.pythonhosted.org/packages/df/3e/a06b18788ca2eb6695c9b22325b6fde7dde0f1d1838b1792a0076f58fe9d/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", size = 144042 },
103 | { url = "https://files.pythonhosted.org/packages/45/59/3d27019d3b447a88fe7e7d004a1e04be220227760264cc41b405e863891b/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", size = 138275 },
104 | { url = "https://files.pythonhosted.org/packages/7b/ef/5eb105530b4da8ae37d506ccfa25057961b7b63d581def6f99165ea89c7e/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", size = 144819 },
105 | { url = "https://files.pythonhosted.org/packages/a2/51/e5023f937d7f307c948ed3e5c29c4b7a3e42ed2ee0b8cdf8f3a706089bf0/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", size = 149415 },
106 | { url = "https://files.pythonhosted.org/packages/24/9d/2e3ef673dfd5be0154b20363c5cdcc5606f35666544381bee15af3778239/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", size = 141212 },
107 | { url = "https://files.pythonhosted.org/packages/5b/ae/ce2c12fcac59cb3860b2e2d76dc405253a4475436b1861d95fe75bdea520/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", size = 142167 },
108 | { url = "https://files.pythonhosted.org/packages/ed/3a/a448bf035dce5da359daf9ae8a16b8a39623cc395a2ffb1620aa1bce62b0/charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", size = 93041 },
109 | { url = "https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", size = 100397 },
110 | { url = "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", size = 48543 },
111 | ]
112 |
113 | [[package]]
114 | name = "colorama"
115 | version = "0.4.6"
116 | source = { registry = "https://pypi.org/simple" }
117 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
118 | wheels = [
119 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
120 | ]
121 |
122 | [[package]]
123 | name = "comm"
124 | version = "0.2.2"
125 | source = { registry = "https://pypi.org/simple" }
126 | dependencies = [
127 | { name = "traitlets" },
128 | ]
129 | sdist = { url = "https://files.pythonhosted.org/packages/e9/a8/fb783cb0abe2b5fded9f55e5703015cdf1c9c85b3669087c538dd15a6a86/comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", size = 6210 }
130 | wheels = [
131 | { url = "https://files.pythonhosted.org/packages/e6/75/49e5bfe642f71f272236b5b2d2691cf915a7283cc0ceda56357b61daa538/comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3", size = 7180 },
132 | ]
133 |
134 | [[package]]
135 | name = "debugpy"
136 | version = "1.8.5"
137 | source = { registry = "https://pypi.org/simple" }
138 | sdist = { url = "https://files.pythonhosted.org/packages/ea/f9/61c325a10ded8dc3ddc3e7cd2ed58c0b15b2ef4bf8b4bf2930ee98ed59ee/debugpy-1.8.5.zip", hash = "sha256:b2112cfeb34b4507399d298fe7023a16656fc553ed5246536060ca7bd0e668d0", size = 4612118 }
139 | wheels = [
140 | { url = "https://files.pythonhosted.org/packages/9a/82/7d9e1f75fb23c876ab379008c7cf484a1cfa5ed47ccaac8ba37c75e6814e/debugpy-1.8.5-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:5b5c770977c8ec6c40c60d6f58cacc7f7fe5a45960363d6974ddb9b62dbee156", size = 1436398 },
141 | { url = "https://files.pythonhosted.org/packages/fd/b6/ee71d5e73712daf8307a9e85f5e39301abc8b66d13acd04dfff1702e672e/debugpy-1.8.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0a65b00b7cdd2ee0c2cf4c7335fef31e15f1b7056c7fdbce9e90193e1a8c8cb", size = 1437465 },
142 | { url = "https://files.pythonhosted.org/packages/6c/d8/8e32bf1f2e0142f7e8a2c354338b493e87f2c44e77e233b3a140fb5efa03/debugpy-1.8.5-cp312-cp312-win32.whl", hash = "sha256:c9f7c15ea1da18d2fcc2709e9f3d6de98b69a5b0fff1807fb80bc55f906691f7", size = 4581313 },
143 | { url = "https://files.pythonhosted.org/packages/f7/be/2fbaffecb063de228b2b3b6a1750b0b745e5dc645eddd52be8b329933c0b/debugpy-1.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:28ced650c974aaf179231668a293ecd5c63c0a671ae6d56b8795ecc5d2f48d3c", size = 4581209 },
144 | { url = "https://files.pythonhosted.org/packages/02/49/b595c34d7bc690e8d225a6641618a5c111c7e13db5d9e2b756c15ce8f8c6/debugpy-1.8.5-py2.py3-none-any.whl", hash = "sha256:55919dce65b471eff25901acf82d328bbd5b833526b6c1364bd5133754777a44", size = 4824118 },
145 | ]
146 |
147 | [[package]]
148 | name = "decorator"
149 | version = "5.1.1"
150 | source = { registry = "https://pypi.org/simple" }
151 | sdist = { url = "https://files.pythonhosted.org/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", size = 35016 }
152 | wheels = [
153 | { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 },
154 | ]
155 |
156 | [[package]]
157 | name = "et-xmlfile"
158 | version = "1.1.0"
159 | source = { registry = "https://pypi.org/simple" }
160 | sdist = { url = "https://files.pythonhosted.org/packages/3d/5d/0413a31d184a20c763ad741cc7852a659bf15094c24840c5bdd1754765cd/et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c", size = 3218 }
161 | wheels = [
162 | { url = "https://files.pythonhosted.org/packages/96/c2/3dd434b0108730014f1b96fd286040dc3bcb70066346f7e01ec2ac95865f/et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada", size = 4688 },
163 | ]
164 |
165 | [[package]]
166 | name = "excel-rag"
167 | version = "0.1.0"
168 | source = { virtual = "." }
169 | dependencies = [
170 | { name = "google-generativeai" },
171 | { name = "ipykernel" },
172 | { name = "ipywidgets" },
173 | { name = "openpyxl" },
174 | { name = "pandas" },
175 | { name = "python-dotenv" },
176 | { name = "xlrd" },
177 | ]
178 |
179 | [package.metadata]
180 | requires-dist = [
181 | { name = "google-generativeai", specifier = ">=0.8.1" },
182 | { name = "ipykernel", specifier = ">=6.29.5" },
183 | { name = "ipywidgets", specifier = ">=8.1.5" },
184 | { name = "openpyxl", specifier = ">=3.1.5" },
185 | { name = "pandas", specifier = ">=2.2.3" },
186 | { name = "python-dotenv", specifier = ">=1.0.1" },
187 | { name = "xlrd", specifier = ">=2.0.1" },
188 | ]
189 |
190 | [[package]]
191 | name = "executing"
192 | version = "2.1.0"
193 | source = { registry = "https://pypi.org/simple" }
194 | sdist = { url = "https://files.pythonhosted.org/packages/8c/e3/7d45f492c2c4a0e8e0fad57d081a7c8a0286cdd86372b070cca1ec0caa1e/executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab", size = 977485 }
195 | wheels = [
196 | { url = "https://files.pythonhosted.org/packages/b5/fd/afcd0496feca3276f509df3dbd5dae726fcc756f1a08d9e25abe1733f962/executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", size = 25805 },
197 | ]
198 |
199 | [[package]]
200 | name = "google-ai-generativelanguage"
201 | version = "0.6.9"
202 | source = { registry = "https://pypi.org/simple" }
203 | dependencies = [
204 | { name = "google-api-core", extra = ["grpc"] },
205 | { name = "google-auth" },
206 | { name = "proto-plus" },
207 | { name = "protobuf" },
208 | ]
209 | sdist = { url = "https://files.pythonhosted.org/packages/4c/1d/58946eac6daf8e6eaaf41842cedf040d8804f011e8843cf30133a2c74ae3/google_ai_generativelanguage-0.6.9.tar.gz", hash = "sha256:899f1d3a06efa9739f1cd9d2788070178db33c89d4a76f2e8f4da76f649155fa", size = 762857 }
210 | wheels = [
211 | { url = "https://files.pythonhosted.org/packages/17/48/b029a255cbef50cfab301786147f83f65768c1cba1cc3bdb4f1ffe398037/google_ai_generativelanguage-0.6.9-py3-none-any.whl", hash = "sha256:50360cd80015d1a8cc70952e98560f32fa06ddee2e8e9f4b4b98e431dc561e0b", size = 725448 },
212 | ]
213 |
214 | [[package]]
215 | name = "google-api-core"
216 | version = "2.20.0"
217 | source = { registry = "https://pypi.org/simple" }
218 | dependencies = [
219 | { name = "google-auth" },
220 | { name = "googleapis-common-protos" },
221 | { name = "proto-plus" },
222 | { name = "protobuf" },
223 | { name = "requests" },
224 | ]
225 | sdist = { url = "https://files.pythonhosted.org/packages/c8/5c/31c1742a53b79c8a0c4757b5fae2e8ab9c519cbd7b98c587d4294e1d2d16/google_api_core-2.20.0.tar.gz", hash = "sha256:f74dff1889ba291a4b76c5079df0711810e2d9da81abfdc99957bc961c1eb28f", size = 152583 }
226 | wheels = [
227 | { url = "https://files.pythonhosted.org/packages/c8/dc/6143f67acf5f30717c9e1b1c48fc04c0f59b869be046e6639d3f171640ae/google_api_core-2.20.0-py3-none-any.whl", hash = "sha256:ef0591ef03c30bb83f79b3d0575c3f31219001fc9c5cf37024d08310aeffed8a", size = 142162 },
228 | ]
229 |
230 | [package.optional-dependencies]
231 | grpc = [
232 | { name = "grpcio" },
233 | { name = "grpcio-status" },
234 | ]
235 |
236 | [[package]]
237 | name = "google-api-python-client"
238 | version = "2.146.0"
239 | source = { registry = "https://pypi.org/simple" }
240 | dependencies = [
241 | { name = "google-api-core" },
242 | { name = "google-auth" },
243 | { name = "google-auth-httplib2" },
244 | { name = "httplib2" },
245 | { name = "uritemplate" },
246 | ]
247 | sdist = { url = "https://files.pythonhosted.org/packages/f3/68/29fae04dbe58befbc2313fa03c43448c17d237047e83701272f54d83ac4a/google_api_python_client-2.146.0.tar.gz", hash = "sha256:41f671be10fa077ee5143ee9f0903c14006d39dc644564f4e044ae96b380bf68", size = 11690645 }
248 | wheels = [
249 | { url = "https://files.pythonhosted.org/packages/29/03/e9d5a2befd19a68091e0a49bc9fa58b3d42a463a7ef621ae5816337ac2ee/google_api_python_client-2.146.0-py2.py3-none-any.whl", hash = "sha256:b1e62c9889c5ef6022f11d30d7ef23dc55100300f0e8aaf8aa09e8e92540acad", size = 12196320 },
250 | ]
251 |
252 | [[package]]
253 | name = "google-auth"
254 | version = "2.35.0"
255 | source = { registry = "https://pypi.org/simple" }
256 | dependencies = [
257 | { name = "cachetools" },
258 | { name = "pyasn1-modules" },
259 | { name = "rsa" },
260 | ]
261 | sdist = { url = "https://files.pythonhosted.org/packages/a1/37/c854a8b1b1020cf042db3d67577c6f84cd1e8ff6515e4f5498ae9e444ea5/google_auth-2.35.0.tar.gz", hash = "sha256:f4c64ed4e01e8e8b646ef34c018f8bf3338df0c8e37d8b3bba40e7f574a3278a", size = 267223 }
262 | wheels = [
263 | { url = "https://files.pythonhosted.org/packages/27/1f/3a72917afcb0d5cd842cbccb81bf7a8a7b45b4c66d8dc4556ccb3b016bfc/google_auth-2.35.0-py2.py3-none-any.whl", hash = "sha256:25df55f327ef021de8be50bad0dfd4a916ad0de96da86cd05661c9297723ad3f", size = 208968 },
264 | ]
265 |
266 | [[package]]
267 | name = "google-auth-httplib2"
268 | version = "0.2.0"
269 | source = { registry = "https://pypi.org/simple" }
270 | dependencies = [
271 | { name = "google-auth" },
272 | { name = "httplib2" },
273 | ]
274 | sdist = { url = "https://files.pythonhosted.org/packages/56/be/217a598a818567b28e859ff087f347475c807a5649296fb5a817c58dacef/google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05", size = 10842 }
275 | wheels = [
276 | { url = "https://files.pythonhosted.org/packages/be/8a/fe34d2f3f9470a27b01c9e76226965863f153d5fbe276f83608562e49c04/google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d", size = 9253 },
277 | ]
278 |
279 | [[package]]
280 | name = "google-generativeai"
281 | version = "0.8.1"
282 | source = { registry = "https://pypi.org/simple" }
283 | dependencies = [
284 | { name = "google-ai-generativelanguage" },
285 | { name = "google-api-core" },
286 | { name = "google-api-python-client" },
287 | { name = "google-auth" },
288 | { name = "protobuf" },
289 | { name = "pydantic" },
290 | { name = "tqdm" },
291 | { name = "typing-extensions" },
292 | ]
293 | wheels = [
294 | { url = "https://files.pythonhosted.org/packages/9c/ea/07d6432c1eb6307d51c148ca70cb7cf4dab08da273e0349a32d3f22a2d8e/google_generativeai-0.8.1-py3-none-any.whl", hash = "sha256:b031877f24d51af0945207657c085896a0a886eceec7a1cb7029327b0aa6e2f6", size = 165045 },
295 | ]
296 |
297 | [[package]]
298 | name = "googleapis-common-protos"
299 | version = "1.65.0"
300 | source = { registry = "https://pypi.org/simple" }
301 | dependencies = [
302 | { name = "protobuf" },
303 | ]
304 | sdist = { url = "https://files.pythonhosted.org/packages/53/3b/1599ceafa875ffb951480c8c74f4b77646a6b80e80970698f2aa93c216ce/googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0", size = 113657 }
305 | wheels = [
306 | { url = "https://files.pythonhosted.org/packages/ec/08/49bfe7cf737952cc1a9c43e80cc258ed45dad7f183c5b8276fc94cb3862d/googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63", size = 220890 },
307 | ]
308 |
309 | [[package]]
310 | name = "grpcio"
311 | version = "1.66.1"
312 | source = { registry = "https://pypi.org/simple" }
313 | sdist = { url = "https://files.pythonhosted.org/packages/e7/42/94293200e40480d79fc876b2330e7dffb20f959b390afa77c0dbaa0c8372/grpcio-1.66.1.tar.gz", hash = "sha256:35334f9c9745add3e357e3372756fd32d925bd52c41da97f4dfdafbde0bf0ee2", size = 12326405 }
314 | wheels = [
315 | { url = "https://files.pythonhosted.org/packages/25/31/fa15c10757a8703332d9f9eff2ab676e8f8807e8636c01b965a37f806ded/grpcio-1.66.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:a92c4f58c01c77205df6ff999faa008540475c39b835277fb8883b11cada127a", size = 4912090 },
316 | { url = "https://files.pythonhosted.org/packages/31/3f/09f796724b44b625e4d294f6df8ab0bb63b4709664bd574ea97a8c0d6159/grpcio-1.66.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fdb14bad0835914f325349ed34a51940bc2ad965142eb3090081593c6e347be9", size = 10579733 },
317 | { url = "https://files.pythonhosted.org/packages/bc/d5/15c5934ac3550f682b04753e5481eca18a3710b220e16d3345a7e6f7c9f6/grpcio-1.66.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f03a5884c56256e08fd9e262e11b5cfacf1af96e2ce78dc095d2c41ccae2c80d", size = 5421092 },
318 | { url = "https://files.pythonhosted.org/packages/fa/77/f8ab8d436373ad09e1f8f50bf759b4afc8ad1bc121e5cf7dedd8507a4b63/grpcio-1.66.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ca2559692d8e7e245d456877a85ee41525f3ed425aa97eb7a70fc9a79df91a0", size = 6028550 },
319 | { url = "https://files.pythonhosted.org/packages/1d/6c/a813a5b6d716cbc5cc3e496b186b6878816bf5f32aa7f7ae5f9d8dc5e669/grpcio-1.66.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ca1be089fb4446490dd1135828bd42a7c7f8421e74fa581611f7afdf7ab761", size = 5672550 },
320 | { url = "https://files.pythonhosted.org/packages/a0/72/06962e2891fe3846a9dc61547d8ef35151b8976a083187e6647e65306c45/grpcio-1.66.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d639c939ad7c440c7b2819a28d559179a4508783f7e5b991166f8d7a34b52815", size = 6354719 },
321 | { url = "https://files.pythonhosted.org/packages/43/10/4db87a953a3f3c73a8284e176556b6eca33496b8ffaa93107f37f772148e/grpcio-1.66.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b9feb4e5ec8dc2d15709f4d5fc367794d69277f5d680baf1910fc9915c633524", size = 5933351 },
322 | { url = "https://files.pythonhosted.org/packages/47/c7/f1fdd77bbe1c6459777a2d604228cc80124373e75d775c2a019755c29182/grpcio-1.66.1-cp312-cp312-win32.whl", hash = "sha256:7101db1bd4cd9b880294dec41a93fcdce465bdbb602cd8dc5bd2d6362b618759", size = 3538005 },
323 | { url = "https://files.pythonhosted.org/packages/66/2b/a6e68d7ea6f4fbc31cce20e354d6cef484da0a9891ee6a3eaf3aa9659d01/grpcio-1.66.1-cp312-cp312-win_amd64.whl", hash = "sha256:b0aa03d240b5539648d996cc60438f128c7f46050989e35b25f5c18286c86734", size = 4275565 },
324 | ]
325 |
326 | [[package]]
327 | name = "grpcio-status"
328 | version = "1.66.1"
329 | source = { registry = "https://pypi.org/simple" }
330 | dependencies = [
331 | { name = "googleapis-common-protos" },
332 | { name = "grpcio" },
333 | { name = "protobuf" },
334 | ]
335 | sdist = { url = "https://files.pythonhosted.org/packages/c9/ff/3f916e8c3698134f633e973402c807df554e21b82df86e036be335741c52/grpcio_status-1.66.1.tar.gz", hash = "sha256:b3f7d34ccc46d83fea5261eea3786174459f763c31f6e34f1d24eba6d515d024", size = 13554 }
336 | wheels = [
337 | { url = "https://files.pythonhosted.org/packages/77/8f/c87481addb26cb431dc4d114a777dbd4c6a2e163d219e7e472892c75de0c/grpcio_status-1.66.1-py3-none-any.whl", hash = "sha256:cf9ed0b4a83adbe9297211c95cb5488b0cd065707e812145b842c85c4782ff02", size = 14444 },
338 | ]
339 |
340 | [[package]]
341 | name = "httplib2"
342 | version = "0.22.0"
343 | source = { registry = "https://pypi.org/simple" }
344 | dependencies = [
345 | { name = "pyparsing" },
346 | ]
347 | sdist = { url = "https://files.pythonhosted.org/packages/3d/ad/2371116b22d616c194aa25ec410c9c6c37f23599dcd590502b74db197584/httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81", size = 351116 }
348 | wheels = [
349 | { url = "https://files.pythonhosted.org/packages/a8/6c/d2fbdaaa5959339d53ba38e94c123e4e84b8fbc4b84beb0e70d7c1608486/httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc", size = 96854 },
350 | ]
351 |
352 | [[package]]
353 | name = "idna"
354 | version = "3.10"
355 | source = { registry = "https://pypi.org/simple" }
356 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
357 | wheels = [
358 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
359 | ]
360 |
361 | [[package]]
362 | name = "ipykernel"
363 | version = "6.29.5"
364 | source = { registry = "https://pypi.org/simple" }
365 | dependencies = [
366 | { name = "appnope", marker = "platform_system == 'Darwin'" },
367 | { name = "comm" },
368 | { name = "debugpy" },
369 | { name = "ipython" },
370 | { name = "jupyter-client" },
371 | { name = "jupyter-core" },
372 | { name = "matplotlib-inline" },
373 | { name = "nest-asyncio" },
374 | { name = "packaging" },
375 | { name = "psutil" },
376 | { name = "pyzmq" },
377 | { name = "tornado" },
378 | { name = "traitlets" },
379 | ]
380 | sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/67594cb0c7055dc50814b21731c22a601101ea3b1b50a9a1b090e11f5d0f/ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215", size = 163367 }
381 | wheels = [
382 | { url = "https://files.pythonhosted.org/packages/94/5c/368ae6c01c7628438358e6d337c19b05425727fbb221d2a3c4303c372f42/ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", size = 117173 },
383 | ]
384 |
385 | [[package]]
386 | name = "ipython"
387 | version = "8.27.0"
388 | source = { registry = "https://pypi.org/simple" }
389 | dependencies = [
390 | { name = "colorama", marker = "sys_platform == 'win32'" },
391 | { name = "decorator" },
392 | { name = "jedi" },
393 | { name = "matplotlib-inline" },
394 | { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
395 | { name = "prompt-toolkit" },
396 | { name = "pygments" },
397 | { name = "stack-data" },
398 | { name = "traitlets" },
399 | ]
400 | sdist = { url = "https://files.pythonhosted.org/packages/57/24/d4fabaca03c8804bf0b8d994c8ae3a20e57e9330d277fb43d83e558dec5e/ipython-8.27.0.tar.gz", hash = "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e", size = 5494984 }
401 | wheels = [
402 | { url = "https://files.pythonhosted.org/packages/a8/a2/6c725958e6f135d8e5de081e69841bb2c1d84b3fc259d02eb092b8fc203a/ipython-8.27.0-py3-none-any.whl", hash = "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c", size = 818986 },
403 | ]
404 |
405 | [[package]]
406 | name = "ipywidgets"
407 | version = "8.1.5"
408 | source = { registry = "https://pypi.org/simple" }
409 | dependencies = [
410 | { name = "comm" },
411 | { name = "ipython" },
412 | { name = "jupyterlab-widgets" },
413 | { name = "traitlets" },
414 | { name = "widgetsnbextension" },
415 | ]
416 | sdist = { url = "https://files.pythonhosted.org/packages/c7/4c/dab2a281b07596a5fc220d49827fe6c794c66f1493d7a74f1df0640f2cc5/ipywidgets-8.1.5.tar.gz", hash = "sha256:870e43b1a35656a80c18c9503bbf2d16802db1cb487eec6fab27d683381dde17", size = 116723 }
417 | wheels = [
418 | { url = "https://files.pythonhosted.org/packages/22/2d/9c0b76f2f9cc0ebede1b9371b6f317243028ed60b90705863d493bae622e/ipywidgets-8.1.5-py3-none-any.whl", hash = "sha256:3290f526f87ae6e77655555baba4f36681c555b8bdbbff430b70e52c34c86245", size = 139767 },
419 | ]
420 |
421 | [[package]]
422 | name = "jedi"
423 | version = "0.19.1"
424 | source = { registry = "https://pypi.org/simple" }
425 | dependencies = [
426 | { name = "parso" },
427 | ]
428 | sdist = { url = "https://files.pythonhosted.org/packages/d6/99/99b493cec4bf43176b678de30f81ed003fd6a647a301b9c927280c600f0a/jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd", size = 1227821 }
429 | wheels = [
430 | { url = "https://files.pythonhosted.org/packages/20/9f/bc63f0f0737ad7a60800bfd472a4836661adae21f9c2535f3957b1e54ceb/jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0", size = 1569361 },
431 | ]
432 |
433 | [[package]]
434 | name = "jupyter-client"
435 | version = "8.6.3"
436 | source = { registry = "https://pypi.org/simple" }
437 | dependencies = [
438 | { name = "jupyter-core" },
439 | { name = "python-dateutil" },
440 | { name = "pyzmq" },
441 | { name = "tornado" },
442 | { name = "traitlets" },
443 | ]
444 | sdist = { url = "https://files.pythonhosted.org/packages/71/22/bf9f12fdaeae18019a468b68952a60fe6dbab5d67cd2a103cac7659b41ca/jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419", size = 342019 }
445 | wheels = [
446 | { url = "https://files.pythonhosted.org/packages/11/85/b0394e0b6fcccd2c1eeefc230978a6f8cb0c5df1e4cd3e7625735a0d7d1e/jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f", size = 106105 },
447 | ]
448 |
449 | [[package]]
450 | name = "jupyter-core"
451 | version = "5.7.2"
452 | source = { registry = "https://pypi.org/simple" }
453 | dependencies = [
454 | { name = "platformdirs" },
455 | { name = "pywin32", marker = "platform_python_implementation != 'PyPy' and sys_platform == 'win32'" },
456 | { name = "traitlets" },
457 | ]
458 | sdist = { url = "https://files.pythonhosted.org/packages/00/11/b56381fa6c3f4cc5d2cf54a7dbf98ad9aa0b339ef7a601d6053538b079a7/jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9", size = 87629 }
459 | wheels = [
460 | { url = "https://files.pythonhosted.org/packages/c9/fb/108ecd1fe961941959ad0ee4e12ee7b8b1477247f30b1fdfd83ceaf017f0/jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409", size = 28965 },
461 | ]
462 |
463 | [[package]]
464 | name = "jupyterlab-widgets"
465 | version = "3.0.13"
466 | source = { registry = "https://pypi.org/simple" }
467 | sdist = { url = "https://files.pythonhosted.org/packages/59/73/fa26bbb747a9ea4fca6b01453aa22990d52ab62dd61384f1ac0dc9d4e7ba/jupyterlab_widgets-3.0.13.tar.gz", hash = "sha256:a2966d385328c1942b683a8cd96b89b8dd82c8b8f81dda902bb2bc06d46f5bed", size = 203556 }
468 | wheels = [
469 | { url = "https://files.pythonhosted.org/packages/a9/93/858e87edc634d628e5d752ba944c2833133a28fa87bb093e6832ced36a3e/jupyterlab_widgets-3.0.13-py3-none-any.whl", hash = "sha256:e3cda2c233ce144192f1e29914ad522b2f4c40e77214b0cc97377ca3d323db54", size = 214392 },
470 | ]
471 |
472 | [[package]]
473 | name = "matplotlib-inline"
474 | version = "0.1.7"
475 | source = { registry = "https://pypi.org/simple" }
476 | dependencies = [
477 | { name = "traitlets" },
478 | ]
479 | sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159 }
480 | wheels = [
481 | { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 },
482 | ]
483 |
484 | [[package]]
485 | name = "nest-asyncio"
486 | version = "1.6.0"
487 | source = { registry = "https://pypi.org/simple" }
488 | sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418 }
489 | wheels = [
490 | { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195 },
491 | ]
492 |
493 | [[package]]
494 | name = "numpy"
495 | version = "2.1.1"
496 | source = { registry = "https://pypi.org/simple" }
497 | sdist = { url = "https://files.pythonhosted.org/packages/59/5f/9003bb3e632f2b58f5e3a3378902dcc73c5518070736c6740fe52454e8e1/numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd", size = 18874860 }
498 | wheels = [
499 | { url = "https://files.pythonhosted.org/packages/36/11/c573ef66c004f991989c2c6218229d9003164525549409aec5ec9afc0285/numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e", size = 20884403 },
500 | { url = "https://files.pythonhosted.org/packages/6b/6c/a9fbef5fd2f9685212af2a9e47485cde9357c3e303e079ccf85127516f2d/numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe", size = 13493375 },
501 | { url = "https://files.pythonhosted.org/packages/34/f2/1316a6b08ad4c161d793abe81ff7181e9ae2e357a5b06352a383b9f8e800/numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f", size = 5088823 },
502 | { url = "https://files.pythonhosted.org/packages/be/15/fabf78a6d4a10c250e87daf1cd901af05e71501380532ac508879cc46a7e/numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521", size = 6619825 },
503 | { url = "https://files.pythonhosted.org/packages/9f/8a/76ddef3e621541ddd6984bc24d256a4e3422d036790cbbe449e6cad439ee/numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b", size = 13696705 },
504 | { url = "https://files.pythonhosted.org/packages/cb/22/2b840d297183916a95847c11f82ae11e248fa98113490b2357f774651e1d/numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201", size = 16041649 },
505 | { url = "https://files.pythonhosted.org/packages/c7/e8/6f4825d8f576cfd5e4d6515b9eec22bd618868bdafc8a8c08b446dcb65f0/numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a", size = 16409358 },
506 | { url = "https://files.pythonhosted.org/packages/bf/f8/5edf1105b0dc24fd66fc3e9e7f3bca3d920cde571caaa4375ec1566073c3/numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313", size = 14172488 },
507 | { url = "https://files.pythonhosted.org/packages/f4/c2/dddca3e69a024d2f249a5b68698328163cbdafb7e65fbf6d36373bbabf12/numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed", size = 6237195 },
508 | { url = "https://files.pythonhosted.org/packages/b7/98/5640a09daa3abf0caeaefa6e7bf0d10c0aa28a77c84e507d6a716e0e23df/numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270", size = 12568082 },
509 | { url = "https://files.pythonhosted.org/packages/6b/9e/8bc6f133bc6d359ccc9ec051853aded45504d217685191f31f46d36b7065/numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5", size = 20834810 },
510 | { url = "https://files.pythonhosted.org/packages/32/1b/429519a2fa28681814c511574017d35f3aab7136d554cc65f4c1526dfbf5/numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5", size = 13507739 },
511 | { url = "https://files.pythonhosted.org/packages/25/18/c732d7dd9896d11e4afcd487ac65e62f9fa0495563b7614eb850765361fa/numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136", size = 5074465 },
512 | { url = "https://files.pythonhosted.org/packages/3e/37/838b7ae9262c370ab25312bab365492016f11810ffc03ebebbd54670b669/numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0", size = 6606418 },
513 | { url = "https://files.pythonhosted.org/packages/8b/b9/7ff3bfb71e316a5b43a124c4b7a5881ab12f3c32636014bef1f757f19dbd/numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb", size = 13692464 },
514 | { url = "https://files.pythonhosted.org/packages/42/78/75bcf16e6737cd196ff7ecf0e1fd3f953293a34dff4fd93fb488e8308536/numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df", size = 16037763 },
515 | { url = "https://files.pythonhosted.org/packages/23/99/36bf5ffe034d06df307bc783e25cf164775863166dcd878879559fe0379f/numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78", size = 16410374 },
516 | { url = "https://files.pythonhosted.org/packages/7f/16/04c5dab564887d4cd31a9ed30e51467fa70d52a4425f5a9bd1eed5b3d34c/numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556", size = 14169873 },
517 | { url = "https://files.pythonhosted.org/packages/09/e0/d1b5adbf1731886c4186c59a9fa208585df9452a43a2b60e79af7c649717/numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b", size = 6234118 },
518 | { url = "https://files.pythonhosted.org/packages/d0/9c/2391ee6e9ebe77232ddcab29d92662b545e99d78c3eb3b4e26d59b9ca1ca/numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0", size = 12561742 },
519 | { url = "https://files.pythonhosted.org/packages/38/0e/c4f754f9e73f9bb520e8bf418c646f2c4f70c5d5f2bc561e90f884593193/numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553", size = 20858403 },
520 | { url = "https://files.pythonhosted.org/packages/32/fc/d69092b9171efa0cb8079577e71ce0cac0e08f917d33f6e99c916ed51d44/numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480", size = 13519851 },
521 | { url = "https://files.pythonhosted.org/packages/14/2a/d7cf2cd9f15b23f623075546ea64a2c367cab703338ca22aaaecf7e704df/numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f", size = 5115444 },
522 | { url = "https://files.pythonhosted.org/packages/8e/00/e87b2cb4afcecca3b678deefb8fa53005d7054f3b5c39596e5554e5d98f8/numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468", size = 6628903 },
523 | { url = "https://files.pythonhosted.org/packages/ab/9d/337ae8721b3beec48c3413d71f2d44b2defbf3c6f7a85184fc18b7b61f4a/numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef", size = 13665945 },
524 | { url = "https://files.pythonhosted.org/packages/c0/90/ee8668e84c5d5cc080ef3beb622c016adf19ca3aa51afe9dbdcc6a9baf59/numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f", size = 16023473 },
525 | { url = "https://files.pythonhosted.org/packages/38/a0/57c24b2131879183051dc698fbb53fd43b77c3fa85b6e6311014f2bc2973/numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c", size = 16400624 },
526 | { url = "https://files.pythonhosted.org/packages/bb/4c/14a41eb5c9548c6cee6af0936eabfd985c69230ffa2f2598321431a9aa0a/numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec", size = 14155072 },
527 | ]
528 |
529 | [[package]]
530 | name = "openpyxl"
531 | version = "3.1.5"
532 | source = { registry = "https://pypi.org/simple" }
533 | dependencies = [
534 | { name = "et-xmlfile" },
535 | ]
536 | sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464 }
537 | wheels = [
538 | { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910 },
539 | ]
540 |
541 | [[package]]
542 | name = "packaging"
543 | version = "24.1"
544 | source = { registry = "https://pypi.org/simple" }
545 | sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 }
546 | wheels = [
547 | { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 },
548 | ]
549 |
550 | [[package]]
551 | name = "pandas"
552 | version = "2.2.3"
553 | source = { registry = "https://pypi.org/simple" }
554 | dependencies = [
555 | { name = "numpy" },
556 | { name = "python-dateutil" },
557 | { name = "pytz" },
558 | { name = "tzdata" },
559 | ]
560 | sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 }
561 | wheels = [
562 | { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 },
563 | { url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 },
564 | { url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 },
565 | { url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 },
566 | { url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235 },
567 | { url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 },
568 | { url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 },
569 | { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 },
570 | { url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 },
571 | { url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 },
572 | { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 },
573 | { url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 },
574 | { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 },
575 | { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 },
576 | { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 },
577 | { url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 },
578 | { url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 },
579 | { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 },
580 | { url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 },
581 | { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 },
582 | ]
583 |
584 | [[package]]
585 | name = "parso"
586 | version = "0.8.4"
587 | source = { registry = "https://pypi.org/simple" }
588 | sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609 }
589 | wheels = [
590 | { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 },
591 | ]
592 |
593 | [[package]]
594 | name = "pexpect"
595 | version = "4.9.0"
596 | source = { registry = "https://pypi.org/simple" }
597 | dependencies = [
598 | { name = "ptyprocess" },
599 | ]
600 | sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 }
601 | wheels = [
602 | { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 },
603 | ]
604 |
605 | [[package]]
606 | name = "platformdirs"
607 | version = "4.3.6"
608 | source = { registry = "https://pypi.org/simple" }
609 | sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
610 | wheels = [
611 | { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
612 | ]
613 |
614 | [[package]]
615 | name = "prompt-toolkit"
616 | version = "3.0.47"
617 | source = { registry = "https://pypi.org/simple" }
618 | dependencies = [
619 | { name = "wcwidth" },
620 | ]
621 | sdist = { url = "https://files.pythonhosted.org/packages/47/6d/0279b119dafc74c1220420028d490c4399b790fc1256998666e3a341879f/prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360", size = 425859 }
622 | wheels = [
623 | { url = "https://files.pythonhosted.org/packages/e8/23/22750c4b768f09386d1c3cc4337953e8936f48a888fa6dddfb669b2c9088/prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", size = 386411 },
624 | ]
625 |
626 | [[package]]
627 | name = "proto-plus"
628 | version = "1.24.0"
629 | source = { registry = "https://pypi.org/simple" }
630 | dependencies = [
631 | { name = "protobuf" },
632 | ]
633 | sdist = { url = "https://files.pythonhosted.org/packages/3e/fc/e9a65cd52c1330d8d23af6013651a0bc50b6d76bcbdf91fae7cd19c68f29/proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445", size = 55942 }
634 | wheels = [
635 | { url = "https://files.pythonhosted.org/packages/7c/6f/db31f0711c0402aa477257205ce7d29e86a75cb52cd19f7afb585f75cda0/proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12", size = 50080 },
636 | ]
637 |
638 | [[package]]
639 | name = "protobuf"
640 | version = "5.28.2"
641 | source = { registry = "https://pypi.org/simple" }
642 | sdist = { url = "https://files.pythonhosted.org/packages/b1/a4/4579a61de526e19005ceeb93e478b61d77aa38c8a85ad958ff16a9906549/protobuf-5.28.2.tar.gz", hash = "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0", size = 422494 }
643 | wheels = [
644 | { url = "https://files.pythonhosted.org/packages/e9/30/231764750e0987755b7b8d66771f161e5f002e165d27b72154c776dbabf7/protobuf-5.28.2-cp310-abi3-win32.whl", hash = "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d", size = 419662 },
645 | { url = "https://files.pythonhosted.org/packages/7d/46/3fdf7462160135aee6a530f1ec66665b5b4132fa2e1002ab971bc6ec2589/protobuf-5.28.2-cp310-abi3-win_amd64.whl", hash = "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132", size = 431479 },
646 | { url = "https://files.pythonhosted.org/packages/37/45/d2a760580f8f2ed2825ba44cb370e0a4011ddef85e728f46ea3dd565a8a5/protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7", size = 414736 },
647 | { url = "https://files.pythonhosted.org/packages/e6/23/ed718dc18e6a561445ece1e7a17d2dda0c634ad9cf663102b47f10005d8f/protobuf-5.28.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f", size = 316518 },
648 | { url = "https://files.pythonhosted.org/packages/23/08/a1ce0415a115c2b703bfa798f06f0e43ca91dbe29d6180bf86a9287b15e2/protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f", size = 316605 },
649 | { url = "https://files.pythonhosted.org/packages/9b/55/f24e3b801d2e108c48aa2b1b59bb791b5cffba89465cbbf66fc98de89270/protobuf-5.28.2-py3-none-any.whl", hash = "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece", size = 169566 },
650 | ]
651 |
652 | [[package]]
653 | name = "psutil"
654 | version = "6.0.0"
655 | source = { registry = "https://pypi.org/simple" }
656 | sdist = { url = "https://files.pythonhosted.org/packages/18/c7/8c6872f7372eb6a6b2e4708b88419fb46b857f7a2e1892966b851cc79fc9/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", size = 508067 }
657 | wheels = [
658 | { url = "https://files.pythonhosted.org/packages/c5/66/78c9c3020f573c58101dc43a44f6855d01bbbd747e24da2f0c4491200ea3/psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35", size = 249766 },
659 | { url = "https://files.pythonhosted.org/packages/e1/3f/2403aa9558bea4d3854b0e5e567bc3dd8e9fbc1fc4453c0aa9aafeb75467/psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1", size = 253024 },
660 | { url = "https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", size = 250961 },
661 | { url = "https://files.pythonhosted.org/packages/35/56/72f86175e81c656a01c4401cd3b1c923f891b31fbcebe98985894176d7c9/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", size = 287478 },
662 | { url = "https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", size = 290455 },
663 | { url = "https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132", size = 292046 },
664 | { url = "https://files.pythonhosted.org/packages/8b/20/2ff69ad9c35c3df1858ac4e094f20bd2374d33c8643cf41da8fd7cdcb78b/psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d", size = 253560 },
665 | { url = "https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3", size = 257399 },
666 | { url = "https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0", size = 251988 },
667 | ]
668 |
669 | [[package]]
670 | name = "ptyprocess"
671 | version = "0.7.0"
672 | source = { registry = "https://pypi.org/simple" }
673 | sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 }
674 | wheels = [
675 | { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 },
676 | ]
677 |
678 | [[package]]
679 | name = "pure-eval"
680 | version = "0.2.3"
681 | source = { registry = "https://pypi.org/simple" }
682 | sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752 }
683 | wheels = [
684 | { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 },
685 | ]
686 |
687 | [[package]]
688 | name = "pyasn1"
689 | version = "0.6.1"
690 | source = { registry = "https://pypi.org/simple" }
691 | sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322 }
692 | wheels = [
693 | { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135 },
694 | ]
695 |
696 | [[package]]
697 | name = "pyasn1-modules"
698 | version = "0.4.1"
699 | source = { registry = "https://pypi.org/simple" }
700 | dependencies = [
701 | { name = "pyasn1" },
702 | ]
703 | sdist = { url = "https://files.pythonhosted.org/packages/1d/67/6afbf0d507f73c32d21084a79946bfcfca5fbc62a72057e9c23797a737c9/pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c", size = 310028 }
704 | wheels = [
705 | { url = "https://files.pythonhosted.org/packages/77/89/bc88a6711935ba795a679ea6ebee07e128050d6382eaa35a0a47c8032bdc/pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd", size = 181537 },
706 | ]
707 |
708 | [[package]]
709 | name = "pycparser"
710 | version = "2.22"
711 | source = { registry = "https://pypi.org/simple" }
712 | sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 }
713 | wheels = [
714 | { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 },
715 | ]
716 |
717 | [[package]]
718 | name = "pydantic"
719 | version = "2.9.2"
720 | source = { registry = "https://pypi.org/simple" }
721 | dependencies = [
722 | { name = "annotated-types" },
723 | { name = "pydantic-core" },
724 | { name = "typing-extensions" },
725 | ]
726 | sdist = { url = "https://files.pythonhosted.org/packages/a9/b7/d9e3f12af310e1120c21603644a1cd86f59060e040ec5c3a80b8f05fae30/pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f", size = 769917 }
727 | wheels = [
728 | { url = "https://files.pythonhosted.org/packages/df/e4/ba44652d562cbf0bf320e0f3810206149c8a4e99cdbf66da82e97ab53a15/pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12", size = 434928 },
729 | ]
730 |
731 | [[package]]
732 | name = "pydantic-core"
733 | version = "2.23.4"
734 | source = { registry = "https://pypi.org/simple" }
735 | dependencies = [
736 | { name = "typing-extensions" },
737 | ]
738 | sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156 }
739 | wheels = [
740 | { url = "https://files.pythonhosted.org/packages/74/7b/8e315f80666194b354966ec84b7d567da77ad927ed6323db4006cf915f3f/pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231", size = 1856459 },
741 | { url = "https://files.pythonhosted.org/packages/14/de/866bdce10ed808323d437612aca1ec9971b981e1c52e5e42ad9b8e17a6f6/pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee", size = 1770007 },
742 | { url = "https://files.pythonhosted.org/packages/dc/69/8edd5c3cd48bb833a3f7ef9b81d7666ccddd3c9a635225214e044b6e8281/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87", size = 1790245 },
743 | { url = "https://files.pythonhosted.org/packages/80/33/9c24334e3af796ce80d2274940aae38dd4e5676298b4398eff103a79e02d/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8", size = 1801260 },
744 | { url = "https://files.pythonhosted.org/packages/a5/6f/e9567fd90104b79b101ca9d120219644d3314962caa7948dd8b965e9f83e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327", size = 1996872 },
745 | { url = "https://files.pythonhosted.org/packages/2d/ad/b5f0fe9e6cfee915dd144edbd10b6e9c9c9c9d7a56b69256d124b8ac682e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2", size = 2661617 },
746 | { url = "https://files.pythonhosted.org/packages/06/c8/7d4b708f8d05a5cbfda3243aad468052c6e99de7d0937c9146c24d9f12e9/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36", size = 2071831 },
747 | { url = "https://files.pythonhosted.org/packages/89/4d/3079d00c47f22c9a9a8220db088b309ad6e600a73d7a69473e3a8e5e3ea3/pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126", size = 1917453 },
748 | { url = "https://files.pythonhosted.org/packages/e9/88/9df5b7ce880a4703fcc2d76c8c2d8eb9f861f79d0c56f4b8f5f2607ccec8/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e", size = 1968793 },
749 | { url = "https://files.pythonhosted.org/packages/e3/b9/41f7efe80f6ce2ed3ee3c2dcfe10ab7adc1172f778cc9659509a79518c43/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24", size = 2116872 },
750 | { url = "https://files.pythonhosted.org/packages/63/08/b59b7a92e03dd25554b0436554bf23e7c29abae7cce4b1c459cd92746811/pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84", size = 1738535 },
751 | { url = "https://files.pythonhosted.org/packages/88/8d/479293e4d39ab409747926eec4329de5b7129beaedc3786eca070605d07f/pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9", size = 1917992 },
752 | { url = "https://files.pythonhosted.org/packages/ad/ef/16ee2df472bf0e419b6bc68c05bf0145c49247a1095e85cee1463c6a44a1/pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc", size = 1856143 },
753 | { url = "https://files.pythonhosted.org/packages/da/fa/bc3dbb83605669a34a93308e297ab22be82dfb9dcf88c6cf4b4f264e0a42/pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd", size = 1770063 },
754 | { url = "https://files.pythonhosted.org/packages/4e/48/e813f3bbd257a712303ebdf55c8dc46f9589ec74b384c9f652597df3288d/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05", size = 1790013 },
755 | { url = "https://files.pythonhosted.org/packages/b4/e0/56eda3a37929a1d297fcab1966db8c339023bcca0b64c5a84896db3fcc5c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d", size = 1801077 },
756 | { url = "https://files.pythonhosted.org/packages/04/be/5e49376769bfbf82486da6c5c1683b891809365c20d7c7e52792ce4c71f3/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510", size = 1996782 },
757 | { url = "https://files.pythonhosted.org/packages/bc/24/e3ee6c04f1d58cc15f37bcc62f32c7478ff55142b7b3e6d42ea374ea427c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6", size = 2661375 },
758 | { url = "https://files.pythonhosted.org/packages/c1/f8/11a9006de4e89d016b8de74ebb1db727dc100608bb1e6bbe9d56a3cbbcce/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b", size = 2071635 },
759 | { url = "https://files.pythonhosted.org/packages/7c/45/bdce5779b59f468bdf262a5bc9eecbae87f271c51aef628d8c073b4b4b4c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327", size = 1916994 },
760 | { url = "https://files.pythonhosted.org/packages/d8/fa/c648308fe711ee1f88192cad6026ab4f925396d1293e8356de7e55be89b5/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6", size = 1968877 },
761 | { url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814 },
762 | { url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360 },
763 | { url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411 },
764 | ]
765 |
766 | [[package]]
767 | name = "pygments"
768 | version = "2.18.0"
769 | source = { registry = "https://pypi.org/simple" }
770 | sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 }
771 | wheels = [
772 | { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 },
773 | ]
774 |
775 | [[package]]
776 | name = "pyparsing"
777 | version = "3.1.4"
778 | source = { registry = "https://pypi.org/simple" }
779 | sdist = { url = "https://files.pythonhosted.org/packages/83/08/13f3bce01b2061f2bbd582c9df82723de943784cf719a35ac886c652043a/pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032", size = 900231 }
780 | wheels = [
781 | { url = "https://files.pythonhosted.org/packages/e5/0c/0e3c05b1c87bb6a1c76d281b0f35e78d2d80ac91b5f8f524cebf77f51049/pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", size = 104100 },
782 | ]
783 |
784 | [[package]]
785 | name = "python-dateutil"
786 | version = "2.9.0.post0"
787 | source = { registry = "https://pypi.org/simple" }
788 | dependencies = [
789 | { name = "six" },
790 | ]
791 | sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
792 | wheels = [
793 | { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
794 | ]
795 |
796 | [[package]]
797 | name = "python-dotenv"
798 | version = "1.0.1"
799 | source = { registry = "https://pypi.org/simple" }
800 | sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
801 | wheels = [
802 | { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
803 | ]
804 |
805 | [[package]]
806 | name = "pytz"
807 | version = "2024.2"
808 | source = { registry = "https://pypi.org/simple" }
809 | sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 }
810 | wheels = [
811 | { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 },
812 | ]
813 |
814 | [[package]]
815 | name = "pywin32"
816 | version = "306"
817 | source = { registry = "https://pypi.org/simple" }
818 | wheels = [
819 | { url = "https://files.pythonhosted.org/packages/14/91/17e016d5923e178346aabda3dfec6629d1a26efe587d19667542105cf0a6/pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", size = 8507705 },
820 | { url = "https://files.pythonhosted.org/packages/83/1c/25b79fc3ec99b19b0a0730cc47356f7e2959863bf9f3cd314332bddb4f68/pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", size = 9227429 },
821 | { url = "https://files.pythonhosted.org/packages/1c/43/e3444dc9a12f8365d9603c2145d16bf0a2f8180f343cf87be47f5579e547/pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", size = 10388145 },
822 | ]
823 |
824 | [[package]]
825 | name = "pyzmq"
826 | version = "26.2.0"
827 | source = { registry = "https://pypi.org/simple" }
828 | dependencies = [
829 | { name = "cffi", marker = "implementation_name == 'pypy'" },
830 | ]
831 | sdist = { url = "https://files.pythonhosted.org/packages/fd/05/bed626b9f7bb2322cdbbf7b4bd8f54b1b617b0d2ab2d3547d6e39428a48e/pyzmq-26.2.0.tar.gz", hash = "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f", size = 271975 }
832 | wheels = [
833 | { url = "https://files.pythonhosted.org/packages/28/2f/78a766c8913ad62b28581777ac4ede50c6d9f249d39c2963e279524a1bbe/pyzmq-26.2.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9", size = 1343105 },
834 | { url = "https://files.pythonhosted.org/packages/b7/9c/4b1e2d3d4065be715e007fe063ec7885978fad285f87eae1436e6c3201f4/pyzmq-26.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52", size = 1008365 },
835 | { url = "https://files.pythonhosted.org/packages/4f/ef/5a23ec689ff36d7625b38d121ef15abfc3631a9aecb417baf7a4245e4124/pyzmq-26.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08", size = 665923 },
836 | { url = "https://files.pythonhosted.org/packages/ae/61/d436461a47437d63c6302c90724cf0981883ec57ceb6073873f32172d676/pyzmq-26.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5", size = 903400 },
837 | { url = "https://files.pythonhosted.org/packages/47/42/fc6d35ecefe1739a819afaf6f8e686f7f02a4dd241c78972d316f403474c/pyzmq-26.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae", size = 860034 },
838 | { url = "https://files.pythonhosted.org/packages/07/3b/44ea6266a6761e9eefaa37d98fabefa112328808ac41aa87b4bbb668af30/pyzmq-26.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711", size = 860579 },
839 | { url = "https://files.pythonhosted.org/packages/38/6f/4df2014ab553a6052b0e551b37da55166991510f9e1002c89cab7ce3b3f2/pyzmq-26.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6", size = 1196246 },
840 | { url = "https://files.pythonhosted.org/packages/38/9d/ee240fc0c9fe9817f0c9127a43238a3e28048795483c403cc10720ddef22/pyzmq-26.2.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3", size = 1507441 },
841 | { url = "https://files.pythonhosted.org/packages/85/4f/01711edaa58d535eac4a26c294c617c9a01f09857c0ce191fd574d06f359/pyzmq-26.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b", size = 1406498 },
842 | { url = "https://files.pythonhosted.org/packages/07/18/907134c85c7152f679ed744e73e645b365f3ad571f38bdb62e36f347699a/pyzmq-26.2.0-cp312-cp312-win32.whl", hash = "sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7", size = 575533 },
843 | { url = "https://files.pythonhosted.org/packages/ce/2c/a6f4a20202a4d3c582ad93f95ee78d79bbdc26803495aec2912b17dbbb6c/pyzmq-26.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a", size = 637768 },
844 | { url = "https://files.pythonhosted.org/packages/5f/0e/eb16ff731632d30554bf5af4dbba3ffcd04518219d82028aea4ae1b02ca5/pyzmq-26.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b", size = 540675 },
845 | { url = "https://files.pythonhosted.org/packages/04/a7/0f7e2f6c126fe6e62dbae0bc93b1bd3f1099cf7fea47a5468defebe3f39d/pyzmq-26.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726", size = 1006564 },
846 | { url = "https://files.pythonhosted.org/packages/31/b6/a187165c852c5d49f826a690857684333a6a4a065af0a6015572d2284f6a/pyzmq-26.2.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3", size = 1340447 },
847 | { url = "https://files.pythonhosted.org/packages/68/ba/f4280c58ff71f321602a6e24fd19879b7e79793fb8ab14027027c0fb58ef/pyzmq-26.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50", size = 665485 },
848 | { url = "https://files.pythonhosted.org/packages/77/b5/c987a5c53c7d8704216f29fc3d810b32f156bcea488a940e330e1bcbb88d/pyzmq-26.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb", size = 903484 },
849 | { url = "https://files.pythonhosted.org/packages/29/c9/07da157d2db18c72a7eccef8e684cefc155b712a88e3d479d930aa9eceba/pyzmq-26.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187", size = 859981 },
850 | { url = "https://files.pythonhosted.org/packages/43/09/e12501bd0b8394b7d02c41efd35c537a1988da67fc9c745cae9c6c776d31/pyzmq-26.2.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b", size = 860334 },
851 | { url = "https://files.pythonhosted.org/packages/eb/ff/f5ec1d455f8f7385cc0a8b2acd8c807d7fade875c14c44b85c1bddabae21/pyzmq-26.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18", size = 1196179 },
852 | { url = "https://files.pythonhosted.org/packages/ec/8a/bb2ac43295b1950fe436a81fc5b298be0b96ac76fb029b514d3ed58f7b27/pyzmq-26.2.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115", size = 1507668 },
853 | { url = "https://files.pythonhosted.org/packages/a9/49/dbc284ebcfd2dca23f6349227ff1616a7ee2c4a35fe0a5d6c3deff2b4fed/pyzmq-26.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e", size = 1406539 },
854 | { url = "https://files.pythonhosted.org/packages/00/68/093cdce3fe31e30a341d8e52a1ad86392e13c57970d722c1f62a1d1a54b6/pyzmq-26.2.0-cp313-cp313-win32.whl", hash = "sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5", size = 575567 },
855 | { url = "https://files.pythonhosted.org/packages/92/ae/6cc4657148143412b5819b05e362ae7dd09fb9fe76e2a539dcff3d0386bc/pyzmq-26.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad", size = 637551 },
856 | { url = "https://files.pythonhosted.org/packages/6c/67/fbff102e201688f97c8092e4c3445d1c1068c2f27bbd45a578df97ed5f94/pyzmq-26.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797", size = 540378 },
857 | { url = "https://files.pythonhosted.org/packages/3f/fe/2d998380b6e0122c6c4bdf9b6caf490831e5f5e2d08a203b5adff060c226/pyzmq-26.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a", size = 1007378 },
858 | { url = "https://files.pythonhosted.org/packages/4a/f4/30d6e7157f12b3a0390bde94d6a8567cdb88846ed068a6e17238a4ccf600/pyzmq-26.2.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc", size = 1329532 },
859 | { url = "https://files.pythonhosted.org/packages/82/86/3fe917870e15ee1c3ad48229a2a64458e36036e64b4afa9659045d82bfa8/pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5", size = 653242 },
860 | { url = "https://files.pythonhosted.org/packages/50/2d/242e7e6ef6c8c19e6cb52d095834508cd581ffb925699fd3c640cdc758f1/pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672", size = 888404 },
861 | { url = "https://files.pythonhosted.org/packages/ac/11/7270566e1f31e4ea73c81ec821a4b1688fd551009a3d2bab11ec66cb1e8f/pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797", size = 845858 },
862 | { url = "https://files.pythonhosted.org/packages/91/d5/72b38fbc69867795c8711bdd735312f9fef1e3d9204e2f63ab57085434b9/pyzmq-26.2.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386", size = 847375 },
863 | { url = "https://files.pythonhosted.org/packages/dd/9a/10ed3c7f72b4c24e719c59359fbadd1a27556a28b36cdf1cd9e4fb7845d5/pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306", size = 1183489 },
864 | { url = "https://files.pythonhosted.org/packages/72/2d/8660892543fabf1fe41861efa222455811adac9f3c0818d6c3170a1153e3/pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6", size = 1492932 },
865 | { url = "https://files.pythonhosted.org/packages/7b/d6/32fd69744afb53995619bc5effa2a405ae0d343cd3e747d0fbc43fe894ee/pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0", size = 1392485 },
866 | ]
867 |
868 | [[package]]
869 | name = "requests"
870 | version = "2.32.3"
871 | source = { registry = "https://pypi.org/simple" }
872 | dependencies = [
873 | { name = "certifi" },
874 | { name = "charset-normalizer" },
875 | { name = "idna" },
876 | { name = "urllib3" },
877 | ]
878 | sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
879 | wheels = [
880 | { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
881 | ]
882 |
883 | [[package]]
884 | name = "rsa"
885 | version = "4.9"
886 | source = { registry = "https://pypi.org/simple" }
887 | dependencies = [
888 | { name = "pyasn1" },
889 | ]
890 | sdist = { url = "https://files.pythonhosted.org/packages/aa/65/7d973b89c4d2351d7fb232c2e452547ddfa243e93131e7cfa766da627b52/rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21", size = 29711 }
891 | wheels = [
892 | { url = "https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", size = 34315 },
893 | ]
894 |
895 | [[package]]
896 | name = "six"
897 | version = "1.16.0"
898 | source = { registry = "https://pypi.org/simple" }
899 | sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 }
900 | wheels = [
901 | { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 },
902 | ]
903 |
904 | [[package]]
905 | name = "stack-data"
906 | version = "0.6.3"
907 | source = { registry = "https://pypi.org/simple" }
908 | dependencies = [
909 | { name = "asttokens" },
910 | { name = "executing" },
911 | { name = "pure-eval" },
912 | ]
913 | sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707 }
914 | wheels = [
915 | { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 },
916 | ]
917 |
918 | [[package]]
919 | name = "tornado"
920 | version = "6.4.1"
921 | source = { registry = "https://pypi.org/simple" }
922 | sdist = { url = "https://files.pythonhosted.org/packages/ee/66/398ac7167f1c7835406888a386f6d0d26ee5dbf197d8a571300be57662d3/tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9", size = 500623 }
923 | wheels = [
924 | { url = "https://files.pythonhosted.org/packages/00/d9/c33be3c1a7564f7d42d87a8d186371a75fd142097076767a5c27da941fef/tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8", size = 435924 },
925 | { url = "https://files.pythonhosted.org/packages/2e/0f/721e113a2fac2f1d7d124b3279a1da4c77622e104084f56119875019ffab/tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14", size = 433883 },
926 | { url = "https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4", size = 437224 },
927 | { url = "https://files.pythonhosted.org/packages/e4/8e/a6ce4b8d5935558828b0f30f3afcb2d980566718837b3365d98e34f6067e/tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842", size = 436597 },
928 | { url = "https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3", size = 436797 },
929 | { url = "https://files.pythonhosted.org/packages/cf/3f/2c792e7afa7dd8b24fad7a2ed3c2f24a5ec5110c7b43a64cb6095cc106b8/tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f", size = 437516 },
930 | { url = "https://files.pythonhosted.org/packages/71/63/c8fc62745e669ac9009044b889fc531b6f88ac0f5f183cac79eaa950bb23/tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4", size = 436958 },
931 | { url = "https://files.pythonhosted.org/packages/94/d4/f8ac1f5bd22c15fad3b527e025ce219bd526acdbd903f52053df2baecc8b/tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698", size = 436882 },
932 | { url = "https://files.pythonhosted.org/packages/4b/3e/a8124c21cc0bbf144d7903d2a0cadab15cadaf683fa39a0f92bc567f0d4d/tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d", size = 438092 },
933 | { url = "https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7", size = 438532 },
934 | ]
935 |
936 | [[package]]
937 | name = "tqdm"
938 | version = "4.66.5"
939 | source = { registry = "https://pypi.org/simple" }
940 | dependencies = [
941 | { name = "colorama", marker = "platform_system == 'Windows'" },
942 | ]
943 | sdist = { url = "https://files.pythonhosted.org/packages/58/83/6ba9844a41128c62e810fddddd72473201f3eacde02046066142a2d96cc5/tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad", size = 169504 }
944 | wheels = [
945 | { url = "https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd", size = 78351 },
946 | ]
947 |
948 | [[package]]
949 | name = "traitlets"
950 | version = "5.14.3"
951 | source = { registry = "https://pypi.org/simple" }
952 | sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621 }
953 | wheels = [
954 | { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359 },
955 | ]
956 |
957 | [[package]]
958 | name = "typing-extensions"
959 | version = "4.12.2"
960 | source = { registry = "https://pypi.org/simple" }
961 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
962 | wheels = [
963 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
964 | ]
965 |
966 | [[package]]
967 | name = "tzdata"
968 | version = "2024.1"
969 | source = { registry = "https://pypi.org/simple" }
970 | sdist = { url = "https://files.pythonhosted.org/packages/74/5b/e025d02cb3b66b7b76093404392d4b44343c69101cc85f4d180dd5784717/tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd", size = 190559 }
971 | wheels = [
972 | { url = "https://files.pythonhosted.org/packages/65/58/f9c9e6be752e9fcb8b6a0ee9fb87e6e7a1f6bcab2cdc73f02bb7ba91ada0/tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252", size = 345370 },
973 | ]
974 |
975 | [[package]]
976 | name = "uritemplate"
977 | version = "4.1.1"
978 | source = { registry = "https://pypi.org/simple" }
979 | sdist = { url = "https://files.pythonhosted.org/packages/d2/5a/4742fdba39cd02a56226815abfa72fe0aa81c33bed16ed045647d6000eba/uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", size = 273898 }
980 | wheels = [
981 | { url = "https://files.pythonhosted.org/packages/81/c0/7461b49cd25aeece13766f02ee576d1db528f1c37ce69aee300e075b485b/uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e", size = 10356 },
982 | ]
983 |
984 | [[package]]
985 | name = "urllib3"
986 | version = "2.2.3"
987 | source = { registry = "https://pypi.org/simple" }
988 | sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 }
989 | wheels = [
990 | { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 },
991 | ]
992 |
993 | [[package]]
994 | name = "wcwidth"
995 | version = "0.2.13"
996 | source = { registry = "https://pypi.org/simple" }
997 | sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 }
998 | wheels = [
999 | { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 },
1000 | ]
1001 |
1002 | [[package]]
1003 | name = "widgetsnbextension"
1004 | version = "4.0.13"
1005 | source = { registry = "https://pypi.org/simple" }
1006 | sdist = { url = "https://files.pythonhosted.org/packages/56/fc/238c424fd7f4ebb25f8b1da9a934a3ad7c848286732ae04263661eb0fc03/widgetsnbextension-4.0.13.tar.gz", hash = "sha256:ffcb67bc9febd10234a362795f643927f4e0c05d9342c727b65d2384f8feacb6", size = 1164730 }
1007 | wheels = [
1008 | { url = "https://files.pythonhosted.org/packages/21/02/88b65cc394961a60c43c70517066b6b679738caf78506a5da7b88ffcb643/widgetsnbextension-4.0.13-py3-none-any.whl", hash = "sha256:74b2692e8500525cc38c2b877236ba51d34541e6385eeed5aec15a70f88a6c71", size = 2335872 },
1009 | ]
1010 |
1011 | [[package]]
1012 | name = "xlrd"
1013 | version = "2.0.1"
1014 | source = { registry = "https://pypi.org/simple" }
1015 | sdist = { url = "https://files.pythonhosted.org/packages/a6/b3/19a2540d21dea5f908304375bd43f5ed7a4c28a370dc9122c565423e6b44/xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88", size = 100259 }
1016 | wheels = [
1017 | { url = "https://files.pythonhosted.org/packages/a6/0c/c2a72d51fe56e08a08acc85d13013558a2d793028ae7385448a6ccdfae64/xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd", size = 96531 },
1018 | ]
1019 |
--------------------------------------------------------------------------------