Renzo
commited on
Commit
·
c2e4a2f
1
Parent(s):
16aef61
Optimize route data JSON for context window efficiency
Browse filesRefactor route data pipeline to reduce JSON size from ~5000 to ~200 characters:
- Move image generation to get_route_data() using full geometry for quality
- Extract route image utilities to separate route_utils.py module
- Update generate_route_image() to load pre-generated images with optional custom titles
- Remove coordinate arrays from JSON, replaced with temporary image file paths
- Update app.py interface descriptions to reflect new workflow
This optimization significantly reduces MCP server context window usage while maintaining full route visualization capabilities.
- .gitignore +2 -1
- app.py +56 -9
- pyproject.toml +4 -0
- requirements.txt +44 -4
- route_utils.py +77 -0
- tools.py +107 -26
- uv.lock +324 -55
.gitignore
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
.env
|
2 |
.idea
|
3 |
-
__pycache__
|
|
|
|
1 |
.env
|
2 |
.idea
|
3 |
+
__pycache__
|
4 |
+
.claude/*
|
app.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
-
from tools import get_coords_from_address,
|
|
|
3 |
|
4 |
# --- Tools ---
|
5 |
geocoding_interface = gr.Interface(
|
@@ -15,7 +16,7 @@ geocoding_interface = gr.Interface(
|
|
15 |
)
|
16 |
|
17 |
distance_interface = gr.Interface(
|
18 |
-
fn=
|
19 |
inputs=[
|
20 |
gr.Number(label="Latitude Point A"),
|
21 |
gr.Number(label="Longitude Point A"),
|
@@ -31,7 +32,7 @@ distance_interface = gr.Interface(
|
|
31 |
)
|
32 |
|
33 |
route_planner_interface = gr.Interface(
|
34 |
-
fn=
|
35 |
inputs=[
|
36 |
gr.Number(label="Start Latitude"),
|
37 |
gr.Number(label="Start Longitude"),
|
@@ -43,7 +44,34 @@ route_planner_interface = gr.Interface(
|
|
43 |
gr.Textbox(label="Route Details")
|
44 |
],
|
45 |
title="Route Planner",
|
46 |
-
description="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
)
|
48 |
|
49 |
# --- About Tab ---
|
@@ -57,9 +85,26 @@ with gr.Blocks() as about_tab:
|
|
57 |
|
58 |
## Available Tools
|
59 |
|
60 |
-
|
61 |
-
- **
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
## If you have any questions or feedback, please don't hesitate to reach me.
|
65 |
|
@@ -72,8 +117,10 @@ with gr.Blocks() as about_tab:
|
|
72 |
|
73 |
# --- Assemble the Tabbed Interface ---
|
74 |
demo = gr.TabbedInterface(
|
75 |
-
[about_tab, geocoding_interface, distance_interface, route_planner_interface
|
76 |
-
|
|
|
|
|
77 |
title="🌍 Geocalc MCP Server"
|
78 |
)
|
79 |
|
|
|
1 |
import gradio as gr
|
2 |
+
from tools import get_coords_from_address, calculate_direct_distance, get_route_data, extract_route_time, \
|
3 |
+
extract_route_distance, generate_route_image
|
4 |
|
5 |
# --- Tools ---
|
6 |
geocoding_interface = gr.Interface(
|
|
|
16 |
)
|
17 |
|
18 |
distance_interface = gr.Interface(
|
19 |
+
fn=calculate_direct_distance,
|
20 |
inputs=[
|
21 |
gr.Number(label="Latitude Point A"),
|
22 |
gr.Number(label="Longitude Point A"),
|
|
|
32 |
)
|
33 |
|
34 |
route_planner_interface = gr.Interface(
|
35 |
+
fn=get_route_data,
|
36 |
inputs=[
|
37 |
gr.Number(label="Start Latitude"),
|
38 |
gr.Number(label="Start Longitude"),
|
|
|
44 |
gr.Textbox(label="Route Details")
|
45 |
],
|
46 |
title="Route Planner",
|
47 |
+
description="Get optimized route data with pre-generated map image for visualization."
|
48 |
+
)
|
49 |
+
|
50 |
+
extract_time_interface = gr.Interface(
|
51 |
+
fn=extract_route_time,
|
52 |
+
inputs=gr.Textbox(label="Route Data (JSON)", lines=3),
|
53 |
+
outputs=gr.Textbox(label="Travel Time"),
|
54 |
+
title="Extract Route Time",
|
55 |
+
description="Extract human-readable travel time from route data"
|
56 |
+
)
|
57 |
+
|
58 |
+
extract_distance_interface = gr.Interface(
|
59 |
+
fn=extract_route_distance,
|
60 |
+
inputs=gr.Textbox(label="Route Data (JSON)", lines=3),
|
61 |
+
outputs=gr.Textbox(label="Distance"),
|
62 |
+
title="Extract Route Distance",
|
63 |
+
description="Extract distance in km from route data"
|
64 |
+
)
|
65 |
+
|
66 |
+
route_map_interface = gr.Interface(
|
67 |
+
fn=generate_route_image,
|
68 |
+
inputs=[
|
69 |
+
gr.Textbox(label="Route Data (JSON)", lines=3),
|
70 |
+
gr.Textbox(label="Custom Title (Optional)", placeholder="e.g., My Route to Work")
|
71 |
+
],
|
72 |
+
outputs="image",
|
73 |
+
title="Generate Route Map",
|
74 |
+
description="Extract route image and optionally add custom title overlay."
|
75 |
)
|
76 |
|
77 |
# --- About Tab ---
|
|
|
85 |
|
86 |
## Available Tools
|
87 |
|
88 |
+
### 📍 Location Tools
|
89 |
+
- **Address Geocoding**: Converts a physical address into latitude and longitude coordinates
|
90 |
+
|
91 |
+
### 📏 Distance Tools
|
92 |
+
- **Distance Calculator**: Calculates straight-line distance between two coordinates
|
93 |
+
- **Extract Route Distance**: Extracts the actual travel distance from route data
|
94 |
+
|
95 |
+
### 🚗 Route Planning
|
96 |
+
- **Route Planner**: Gets complete route data including geometry, distance and duration for car/walk/bike
|
97 |
+
- **Extract Route Time**: Extracts human-readable travel time from route data (e.g., "15 min", "1 h 23 min")
|
98 |
+
|
99 |
+
### 🗺️ Visualization
|
100 |
+
- **Generate Route Map**: Extracts pre-generated route image with optional custom title overlay
|
101 |
+
|
102 |
+
## Usage
|
103 |
+
These tools are designed to work together. For example:
|
104 |
+
1. Use Address Geocoding to get coordinates
|
105 |
+
2. Use Route Planner to get route data
|
106 |
+
3. Use Extract tools to get specific metrics
|
107 |
+
4. Use Generate Route Map to visualize the route
|
108 |
|
109 |
## If you have any questions or feedback, please don't hesitate to reach me.
|
110 |
|
|
|
117 |
|
118 |
# --- Assemble the Tabbed Interface ---
|
119 |
demo = gr.TabbedInterface(
|
120 |
+
[about_tab, geocoding_interface, distance_interface, route_planner_interface,
|
121 |
+
extract_time_interface, extract_distance_interface, route_map_interface],
|
122 |
+
["About", "Address Geocoding", "Distance Calculator", "Route Planner",
|
123 |
+
"Extract Time", "Extract Distance", "Route Map"],
|
124 |
title="🌍 Geocalc MCP Server"
|
125 |
)
|
126 |
|
pyproject.toml
CHANGED
@@ -8,7 +8,11 @@ dependencies = [
|
|
8 |
"aiohttp>=3.12.9",
|
9 |
"geopy>=2.4.1",
|
10 |
"gradio>=5.33.0",
|
|
|
11 |
"mcp>=1.9.3",
|
12 |
"openrouteservice>=2.3.3",
|
|
|
|
|
|
|
13 |
"python-dotenv>=1.1.0",
|
14 |
]
|
|
|
8 |
"aiohttp>=3.12.9",
|
9 |
"geopy>=2.4.1",
|
10 |
"gradio>=5.33.0",
|
11 |
+
"matplotlib>=3.10.3",
|
12 |
"mcp>=1.9.3",
|
13 |
"openrouteservice>=2.3.3",
|
14 |
+
"pillow<10.0.0",
|
15 |
+
"polyline>=2.0.2",
|
16 |
+
"py-staticmaps>=0.4.0",
|
17 |
"python-dotenv>=1.1.0",
|
18 |
]
|
requirements.txt
CHANGED
@@ -17,6 +17,8 @@ anyio==4.9.0
|
|
17 |
# mcp
|
18 |
# sse-starlette
|
19 |
# starlette
|
|
|
|
|
20 |
attrs==25.3.0
|
21 |
# via aiohttp
|
22 |
certifi==2025.4.26
|
@@ -30,12 +32,18 @@ click==8.2.1
|
|
30 |
# via
|
31 |
# typer
|
32 |
# uvicorn
|
|
|
|
|
|
|
|
|
33 |
fastapi==0.115.12
|
34 |
# via gradio
|
35 |
ffmpy==0.6.0
|
36 |
# via gradio
|
37 |
filelock==3.18.0
|
38 |
# via huggingface-hub
|
|
|
|
|
39 |
frozenlist==1.6.2
|
40 |
# via
|
41 |
# aiohttp
|
@@ -44,8 +52,12 @@ fsspec==2025.5.1
|
|
44 |
# via
|
45 |
# gradio-client
|
46 |
# huggingface-hub
|
|
|
|
|
47 |
geographiclib==2.0
|
48 |
-
# via
|
|
|
|
|
49 |
geopy==2.4.1
|
50 |
# via geocalc-mcp (pyproject.toml)
|
51 |
gradio==5.33.0
|
@@ -82,12 +94,16 @@ idna==3.10
|
|
82 |
# yarl
|
83 |
jinja2==3.1.6
|
84 |
# via gradio
|
|
|
|
|
85 |
markdown-it-py==3.0.0
|
86 |
# via rich
|
87 |
markupsafe==3.0.2
|
88 |
# via
|
89 |
# gradio
|
90 |
# jinja2
|
|
|
|
|
91 |
mcp==1.9.3
|
92 |
# via geocalc-mcp (pyproject.toml)
|
93 |
mdurl==0.1.2
|
@@ -98,7 +114,9 @@ multidict==6.4.4
|
|
98 |
# yarl
|
99 |
numpy==2.2.6
|
100 |
# via
|
|
|
101 |
# gradio
|
|
|
102 |
# pandas
|
103 |
openrouteservice==2.3.3
|
104 |
# via geocalc-mcp (pyproject.toml)
|
@@ -109,14 +127,23 @@ packaging==25.0
|
|
109 |
# gradio
|
110 |
# gradio-client
|
111 |
# huggingface-hub
|
|
|
112 |
pandas==2.3.0
|
113 |
# via gradio
|
114 |
-
pillow==
|
115 |
-
# via
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
propcache==0.3.1
|
117 |
# via
|
118 |
# aiohttp
|
119 |
# yarl
|
|
|
|
|
120 |
pydantic==2.11.5
|
121 |
# via
|
122 |
# fastapi
|
@@ -131,8 +158,12 @@ pydub==0.25.1
|
|
131 |
# via gradio
|
132 |
pygments==2.19.1
|
133 |
# via rich
|
|
|
|
|
134 |
python-dateutil==2.9.0.post0
|
135 |
-
# via
|
|
|
|
|
136 |
python-dotenv==1.1.0
|
137 |
# via
|
138 |
# geocalc-mcp (pyproject.toml)
|
@@ -141,6 +172,8 @@ python-multipart==0.0.20
|
|
141 |
# via
|
142 |
# gradio
|
143 |
# mcp
|
|
|
|
|
144 |
pytz==2025.2
|
145 |
# via pandas
|
146 |
pyyaml==6.0.2
|
@@ -151,10 +184,13 @@ requests==2.32.3
|
|
151 |
# via
|
152 |
# huggingface-hub
|
153 |
# openrouteservice
|
|
|
154 |
rich==14.0.0
|
155 |
# via typer
|
156 |
ruff==0.11.13
|
157 |
# via gradio
|
|
|
|
|
158 |
safehttpx==0.1.6
|
159 |
# via gradio
|
160 |
semantic-version==2.10.0
|
@@ -172,6 +208,10 @@ starlette==0.46.2
|
|
172 |
# fastapi
|
173 |
# gradio
|
174 |
# mcp
|
|
|
|
|
|
|
|
|
175 |
tomlkit==0.13.3
|
176 |
# via gradio
|
177 |
tqdm==4.67.1
|
|
|
17 |
# mcp
|
18 |
# sse-starlette
|
19 |
# starlette
|
20 |
+
appdirs==1.4.4
|
21 |
+
# via py-staticmaps
|
22 |
attrs==25.3.0
|
23 |
# via aiohttp
|
24 |
certifi==2025.4.26
|
|
|
32 |
# via
|
33 |
# typer
|
34 |
# uvicorn
|
35 |
+
contourpy==1.3.2
|
36 |
+
# via matplotlib
|
37 |
+
cycler==0.12.1
|
38 |
+
# via matplotlib
|
39 |
fastapi==0.115.12
|
40 |
# via gradio
|
41 |
ffmpy==0.6.0
|
42 |
# via gradio
|
43 |
filelock==3.18.0
|
44 |
# via huggingface-hub
|
45 |
+
fonttools==4.58.2
|
46 |
+
# via matplotlib
|
47 |
frozenlist==1.6.2
|
48 |
# via
|
49 |
# aiohttp
|
|
|
52 |
# via
|
53 |
# gradio-client
|
54 |
# huggingface-hub
|
55 |
+
future==1.0.0
|
56 |
+
# via s2sphere
|
57 |
geographiclib==2.0
|
58 |
+
# via
|
59 |
+
# geopy
|
60 |
+
# py-staticmaps
|
61 |
geopy==2.4.1
|
62 |
# via geocalc-mcp (pyproject.toml)
|
63 |
gradio==5.33.0
|
|
|
94 |
# yarl
|
95 |
jinja2==3.1.6
|
96 |
# via gradio
|
97 |
+
kiwisolver==1.4.8
|
98 |
+
# via matplotlib
|
99 |
markdown-it-py==3.0.0
|
100 |
# via rich
|
101 |
markupsafe==3.0.2
|
102 |
# via
|
103 |
# gradio
|
104 |
# jinja2
|
105 |
+
matplotlib==3.10.3
|
106 |
+
# via geocalc-mcp (pyproject.toml)
|
107 |
mcp==1.9.3
|
108 |
# via geocalc-mcp (pyproject.toml)
|
109 |
mdurl==0.1.2
|
|
|
114 |
# yarl
|
115 |
numpy==2.2.6
|
116 |
# via
|
117 |
+
# contourpy
|
118 |
# gradio
|
119 |
+
# matplotlib
|
120 |
# pandas
|
121 |
openrouteservice==2.3.3
|
122 |
# via geocalc-mcp (pyproject.toml)
|
|
|
127 |
# gradio
|
128 |
# gradio-client
|
129 |
# huggingface-hub
|
130 |
+
# matplotlib
|
131 |
pandas==2.3.0
|
132 |
# via gradio
|
133 |
+
pillow==9.5.0
|
134 |
+
# via
|
135 |
+
# geocalc-mcp (pyproject.toml)
|
136 |
+
# gradio
|
137 |
+
# matplotlib
|
138 |
+
# py-staticmaps
|
139 |
+
polyline==2.0.2
|
140 |
+
# via geocalc-mcp (pyproject.toml)
|
141 |
propcache==0.3.1
|
142 |
# via
|
143 |
# aiohttp
|
144 |
# yarl
|
145 |
+
py-staticmaps==0.4.0
|
146 |
+
# via geocalc-mcp (pyproject.toml)
|
147 |
pydantic==2.11.5
|
148 |
# via
|
149 |
# fastapi
|
|
|
158 |
# via gradio
|
159 |
pygments==2.19.1
|
160 |
# via rich
|
161 |
+
pyparsing==3.2.3
|
162 |
+
# via matplotlib
|
163 |
python-dateutil==2.9.0.post0
|
164 |
+
# via
|
165 |
+
# matplotlib
|
166 |
+
# pandas
|
167 |
python-dotenv==1.1.0
|
168 |
# via
|
169 |
# geocalc-mcp (pyproject.toml)
|
|
|
172 |
# via
|
173 |
# gradio
|
174 |
# mcp
|
175 |
+
python-slugify==8.0.4
|
176 |
+
# via py-staticmaps
|
177 |
pytz==2025.2
|
178 |
# via pandas
|
179 |
pyyaml==6.0.2
|
|
|
184 |
# via
|
185 |
# huggingface-hub
|
186 |
# openrouteservice
|
187 |
+
# py-staticmaps
|
188 |
rich==14.0.0
|
189 |
# via typer
|
190 |
ruff==0.11.13
|
191 |
# via gradio
|
192 |
+
s2sphere==0.2.5
|
193 |
+
# via py-staticmaps
|
194 |
safehttpx==0.1.6
|
195 |
# via gradio
|
196 |
semantic-version==2.10.0
|
|
|
208 |
# fastapi
|
209 |
# gradio
|
210 |
# mcp
|
211 |
+
svgwrite==1.4.3
|
212 |
+
# via py-staticmaps
|
213 |
+
text-unidecode==1.3
|
214 |
+
# via python-slugify
|
215 |
tomlkit==0.13.3
|
216 |
# via gradio
|
217 |
tqdm==4.67.1
|
route_utils.py
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import uuid
|
3 |
+
import tempfile
|
4 |
+
import staticmaps
|
5 |
+
from PIL import Image
|
6 |
+
|
7 |
+
|
8 |
+
TEMP_DIR = tempfile.mkdtemp(prefix="geocalc_")
|
9 |
+
|
10 |
+
|
11 |
+
def generate_route_image_file(coords, start_lat, start_lon, end_lat, end_lon):
|
12 |
+
"""Generate route image and save to temp file."""
|
13 |
+
context = staticmaps.Context()
|
14 |
+
context.set_tile_provider(staticmaps.tile_provider_OSM)
|
15 |
+
|
16 |
+
# Create route line
|
17 |
+
line = staticmaps.Line(
|
18 |
+
[staticmaps.create_latlng(lat, lng) for lat, lng in coords],
|
19 |
+
color=staticmaps.BLUE,
|
20 |
+
width=4
|
21 |
+
)
|
22 |
+
context.add_object(line)
|
23 |
+
|
24 |
+
# Add start marker (green)
|
25 |
+
start_marker = staticmaps.Marker(
|
26 |
+
staticmaps.create_latlng(start_lat, start_lon),
|
27 |
+
color=staticmaps.GREEN,
|
28 |
+
size=12
|
29 |
+
)
|
30 |
+
context.add_object(start_marker)
|
31 |
+
|
32 |
+
# Add end marker (red)
|
33 |
+
end_marker = staticmaps.Marker(
|
34 |
+
staticmaps.create_latlng(end_lat, end_lon),
|
35 |
+
color=staticmaps.RED,
|
36 |
+
size=12
|
37 |
+
)
|
38 |
+
context.add_object(end_marker)
|
39 |
+
|
40 |
+
# Generate image and save to temp file
|
41 |
+
image = context.render_pillow(800, 600)
|
42 |
+
|
43 |
+
# Create unique temp file path
|
44 |
+
filename = f"route_{uuid.uuid4().hex[:8]}.png"
|
45 |
+
filepath = os.path.join(TEMP_DIR, filename)
|
46 |
+
|
47 |
+
image.save(filepath)
|
48 |
+
return filepath
|
49 |
+
|
50 |
+
|
51 |
+
def load_image_with_title(image_path, custom_title=None):
|
52 |
+
"""Load image from path and optionally add custom title."""
|
53 |
+
image = Image.open(image_path)
|
54 |
+
|
55 |
+
if custom_title:
|
56 |
+
from PIL import ImageDraw, ImageFont
|
57 |
+
draw = ImageDraw.Draw(image)
|
58 |
+
|
59 |
+
# Try to use a nice font, fallback to default
|
60 |
+
try:
|
61 |
+
font = ImageFont.truetype("Arial.ttf", 24)
|
62 |
+
except:
|
63 |
+
font = ImageFont.load_default()
|
64 |
+
|
65 |
+
# Add title at top center
|
66 |
+
text_bbox = draw.textbbox((0, 0), custom_title, font=font)
|
67 |
+
text_width = text_bbox[2] - text_bbox[0]
|
68 |
+
x = (image.width - text_width) // 2
|
69 |
+
y = 10
|
70 |
+
|
71 |
+
# Add background rectangle for better readability
|
72 |
+
padding = 5
|
73 |
+
draw.rectangle([x-padding, y-padding, x+text_width+padding, y+text_bbox[3]+padding],
|
74 |
+
fill="white", outline="black")
|
75 |
+
draw.text((x, y), custom_title, fill="black", font=font)
|
76 |
+
|
77 |
+
return image
|
tools.py
CHANGED
@@ -1,11 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from geopy.geocoders import Nominatim
|
2 |
from geopy import distance
|
3 |
import openrouteservice
|
4 |
from openrouteservice.exceptions import ApiError
|
5 |
import os
|
6 |
from dotenv import load_dotenv
|
|
|
7 |
|
8 |
load_dotenv()
|
|
|
9 |
|
10 |
|
11 |
def get_coords_from_address(address: str) -> str:
|
@@ -37,7 +44,7 @@ def get_coords_from_address(address: str) -> str:
|
|
37 |
return "An error occurred while trying to contact the geocoding service."
|
38 |
|
39 |
|
40 |
-
def
|
41 |
"""
|
42 |
Calculates the distance between two points on the Earth's surface using the Haversine formula.
|
43 |
|
@@ -49,20 +56,21 @@ def calculate_distance(lat1: float, lon1: float, lat2: float, lon2: float, unit:
|
|
49 |
unit (str, optional): Unit of measurement for the distance. Default is "km".
|
50 |
|
51 |
Returns:
|
52 |
-
|
53 |
"""
|
54 |
|
55 |
print("calculate_distance", lat1, lon1, lat2, lon2, unit)
|
56 |
if unit == "km":
|
57 |
-
return distance.distance((lat1, lon1), (lat2, lon2)).km
|
58 |
else:
|
59 |
-
return distance.distance((lat1, lon1), (lat2, lon2)).miles
|
60 |
|
61 |
|
62 |
# This is now a standard, synchronous function
|
63 |
-
def
|
64 |
"""
|
65 |
-
|
|
|
66 |
|
67 |
Args:
|
68 |
start_lat (float): Latitude of the starting point.
|
@@ -72,7 +80,7 @@ def get_route_details(start_lat: float, start_lon: float, end_lat: float, end_lo
|
|
72 |
mode (str): The mode of transportation (e.g., "car", "walk", "bike").
|
73 |
|
74 |
Returns:
|
75 |
-
|
76 |
"""
|
77 |
profile_map = {
|
78 |
"car": "driving-car",
|
@@ -81,33 +89,106 @@ def get_route_details(start_lat: float, start_lon: float, end_lat: float, end_lo
|
|
81 |
}
|
82 |
|
83 |
if mode not in profile_map:
|
84 |
-
return "Invalid mode. Please use 'car', 'walk', or 'bike'."
|
85 |
|
86 |
-
ORS_API_KEY = os.getenv("ORS_API_KEY")
|
87 |
client_ors = openrouteservice.Client(key=ORS_API_KEY)
|
88 |
-
|
89 |
coords = ((start_lon, start_lat), (end_lon, end_lat))
|
90 |
|
91 |
try:
|
92 |
-
|
93 |
-
|
94 |
-
coordinates=coords,
|
95 |
-
profile=profile_map[mode],
|
96 |
-
)
|
97 |
|
98 |
-
#
|
99 |
-
|
100 |
-
print("get_route_details summary:", summary)
|
101 |
-
distance_km = round(summary['distance'] / 1000, 1) # Distance in meters
|
102 |
-
duration_sec = summary['duration'] # Duration in seconds
|
103 |
|
104 |
-
#
|
105 |
-
|
106 |
-
minutes = int((duration_sec % 3600) // 60)
|
107 |
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
|
|
110 |
except ApiError as e:
|
111 |
-
return f"Could not find a route. API Error: {e}"
|
112 |
except Exception as e:
|
113 |
-
return f"An unexpected error occurred: {e}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import matplotlib.pyplot as plt
|
3 |
+
import polyline
|
4 |
+
from PIL import Image
|
5 |
+
from io import BytesIO
|
6 |
from geopy.geocoders import Nominatim
|
7 |
from geopy import distance
|
8 |
import openrouteservice
|
9 |
from openrouteservice.exceptions import ApiError
|
10 |
import os
|
11 |
from dotenv import load_dotenv
|
12 |
+
from route_utils import generate_route_image_file, load_image_with_title
|
13 |
|
14 |
load_dotenv()
|
15 |
+
ORS_API_KEY = os.getenv("ORS_API_KEY")
|
16 |
|
17 |
|
18 |
def get_coords_from_address(address: str) -> str:
|
|
|
44 |
return "An error occurred while trying to contact the geocoding service."
|
45 |
|
46 |
|
47 |
+
def calculate_direct_distance(lat1: float, lon1: float, lat2: float, lon2: float, unit: str = "km") -> str:
|
48 |
"""
|
49 |
Calculates the distance between two points on the Earth's surface using the Haversine formula.
|
50 |
|
|
|
56 |
unit (str, optional): Unit of measurement for the distance. Default is "km".
|
57 |
|
58 |
Returns:
|
59 |
+
str: The distance between the two points in kilometers.
|
60 |
"""
|
61 |
|
62 |
print("calculate_distance", lat1, lon1, lat2, lon2, unit)
|
63 |
if unit == "km":
|
64 |
+
return str(round(distance.distance((lat1, lon1), (lat2, lon2)).km, 2))
|
65 |
else:
|
66 |
+
return str(round(distance.distance((lat1, lon1), (lat2, lon2)).miles, 2))
|
67 |
|
68 |
|
69 |
# This is now a standard, synchronous function
|
70 |
+
def get_route_data(start_lat: float, start_lon: float, end_lat: float, end_lon: float, mode: str) -> str:
|
71 |
"""
|
72 |
+
Fetches optimized route data from the OpenRouteService API for a given start/end point and travel mode.
|
73 |
+
This is the primary data-gathering tool. Its output is a compact JSON string meant to be used by other tools.
|
74 |
|
75 |
Args:
|
76 |
start_lat (float): Latitude of the starting point.
|
|
|
80 |
mode (str): The mode of transportation (e.g., "car", "walk", "bike").
|
81 |
|
82 |
Returns:
|
83 |
+
A compact JSON string containing optimized route details with decoded coordinates.
|
84 |
"""
|
85 |
profile_map = {
|
86 |
"car": "driving-car",
|
|
|
89 |
}
|
90 |
|
91 |
if mode not in profile_map:
|
92 |
+
return json.dumps({"error": "Invalid mode. Please use 'car', 'walk', or 'bike'."})
|
93 |
|
|
|
94 |
client_ors = openrouteservice.Client(key=ORS_API_KEY)
|
|
|
95 |
coords = ((start_lon, start_lat), (end_lon, end_lat))
|
96 |
|
97 |
try:
|
98 |
+
routes = client_ors.directions(coordinates=coords, profile=profile_map[mode], geometry='true')
|
99 |
+
route_data = routes['routes'][0]
|
|
|
|
|
|
|
100 |
|
101 |
+
# Decode full polyline geometry for image generation
|
102 |
+
decoded_coords = polyline.decode(route_data['geometry'])
|
|
|
|
|
|
|
103 |
|
104 |
+
# Generate route image with full detail
|
105 |
+
image_path = generate_route_image_file(decoded_coords, start_lat, start_lon, end_lat, end_lon)
|
|
|
106 |
|
107 |
+
# Return optimized JSON with image path
|
108 |
+
optimized_data = {
|
109 |
+
"summary": route_data['summary'],
|
110 |
+
"map_image_path": image_path,
|
111 |
+
"start_point": [start_lat, start_lon],
|
112 |
+
"end_point": [end_lat, end_lon]
|
113 |
+
}
|
114 |
|
115 |
+
return json.dumps(optimized_data)
|
116 |
except ApiError as e:
|
117 |
+
return json.dumps({"error": f"Could not find a route. API Error: {e}"})
|
118 |
except Exception as e:
|
119 |
+
return json.dumps({"error": f"An unexpected error occurred: {e}"})
|
120 |
+
|
121 |
+
|
122 |
+
def extract_route_time(route_json: str) -> str:
|
123 |
+
"""
|
124 |
+
Extract travel time from route data.
|
125 |
+
|
126 |
+
Args:
|
127 |
+
route_json (str): JSON string containing route data
|
128 |
+
|
129 |
+
Returns:
|
130 |
+
Time in human format like '15 min' or '1 h 23 min'
|
131 |
+
"""
|
132 |
+
data = json.loads(route_json)
|
133 |
+
if "error" in data:
|
134 |
+
return data["error"]
|
135 |
+
|
136 |
+
seconds = data['summary']['duration']
|
137 |
+
minutes = int(seconds / 60)
|
138 |
+
|
139 |
+
if minutes < 60:
|
140 |
+
return f"{minutes} min"
|
141 |
+
else:
|
142 |
+
hours = minutes // 60
|
143 |
+
mins = minutes % 60
|
144 |
+
return f"{hours} h {mins} min"
|
145 |
+
|
146 |
+
|
147 |
+
def extract_route_distance(route_json: str) -> str:
|
148 |
+
"""
|
149 |
+
Extract distance from route data.
|
150 |
+
|
151 |
+
Args:
|
152 |
+
route_json (str): JSON string containing route data
|
153 |
+
Returns:
|
154 |
+
Distance like '5.2 km'
|
155 |
+
"""
|
156 |
+
data = json.loads(route_json)
|
157 |
+
print("extract_route_distance", data)
|
158 |
+
if "error" in data:
|
159 |
+
return data["error"]
|
160 |
+
|
161 |
+
meters = data['summary']['distance']
|
162 |
+
km = round(meters / 1000, 1)
|
163 |
+
return f"{km} km"
|
164 |
+
|
165 |
+
|
166 |
+
def generate_route_image(route_json: str, custom_title: str = None) -> Image.Image:
|
167 |
+
"""
|
168 |
+
Extract route image from JSON data and optionally add custom title.
|
169 |
+
|
170 |
+
Args:
|
171 |
+
route_json (str): JSON string containing route data
|
172 |
+
custom_title (str): Optional title to add to the image
|
173 |
+
|
174 |
+
Returns:
|
175 |
+
PIL.Image.Image: The generated route image
|
176 |
+
"""
|
177 |
+
data = json.loads(route_json)
|
178 |
+
|
179 |
+
if "error" in data:
|
180 |
+
# Create error image
|
181 |
+
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
|
182 |
+
ax.text(0.5, 0.5, f"Error: {data['error']}",
|
183 |
+
ha='center', va='center', fontsize=12, color='red')
|
184 |
+
ax.axis('off')
|
185 |
+
buf = BytesIO()
|
186 |
+
fig.savefig(buf, format='png', dpi=150, bbox_inches='tight')
|
187 |
+
buf.seek(0)
|
188 |
+
img = Image.open(buf)
|
189 |
+
plt.close(fig)
|
190 |
+
return img
|
191 |
+
|
192 |
+
# Load image from path and add title if provided
|
193 |
+
image_path = data['map_image_path']
|
194 |
+
return load_image_with_title(image_path, custom_title)
|
uv.lock
CHANGED
@@ -127,6 +127,15 @@ wheels = [
|
|
127 |
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
|
128 |
]
|
129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
[[package]]
|
131 |
name = "attrs"
|
132 |
version = "25.3.0"
|
@@ -254,6 +263,69 @@ wheels = [
|
|
254 |
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
255 |
]
|
256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
[[package]]
|
258 |
name = "fastapi"
|
259 |
version = "0.115.12"
|
@@ -286,6 +358,39 @@ wheels = [
|
|
286 |
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 },
|
287 |
]
|
288 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
[[package]]
|
290 |
name = "frozenlist"
|
291 |
version = "1.6.2"
|
@@ -372,6 +477,15 @@ wheels = [
|
|
372 |
{ url = "https://files.pythonhosted.org/packages/bb/61/78c7b3851add1481b048b5fdc29067397a1784e2910592bc81bb3f608635/fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462", size = 199052 },
|
373 |
]
|
374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
[[package]]
|
376 |
name = "geocalc-mcp"
|
377 |
version = "0.1.0"
|
@@ -380,8 +494,12 @@ dependencies = [
|
|
380 |
{ name = "aiohttp" },
|
381 |
{ name = "geopy" },
|
382 |
{ name = "gradio" },
|
|
|
383 |
{ name = "mcp" },
|
384 |
{ name = "openrouteservice" },
|
|
|
|
|
|
|
385 |
{ name = "python-dotenv" },
|
386 |
]
|
387 |
|
@@ -390,8 +508,12 @@ requires-dist = [
|
|
390 |
{ name = "aiohttp", specifier = ">=3.12.9" },
|
391 |
{ name = "geopy", specifier = ">=2.4.1" },
|
392 |
{ name = "gradio", specifier = ">=5.33.0" },
|
|
|
393 |
{ name = "mcp", specifier = ">=1.9.3" },
|
394 |
{ name = "openrouteservice", specifier = ">=2.3.3" },
|
|
|
|
|
|
|
395 |
{ name = "python-dotenv", specifier = ">=1.1.0" },
|
396 |
]
|
397 |
|
@@ -583,6 +705,72 @@ wheels = [
|
|
583 |
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
|
584 |
]
|
585 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
[[package]]
|
587 |
name = "markdown-it-py"
|
588 |
version = "3.0.0"
|
@@ -643,6 +831,49 @@ wheels = [
|
|
643 |
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
|
644 |
]
|
645 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
646 |
[[package]]
|
647 |
name = "mcp"
|
648 |
version = "1.9.3"
|
@@ -914,61 +1145,33 @@ wheels = [
|
|
914 |
|
915 |
[[package]]
|
916 |
name = "pillow"
|
917 |
-
version = "
|
918 |
-
source = { registry = "https://pypi.org/simple" }
|
919 |
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
920 |
-
wheels = [
|
921 |
-
{ url = "https://files.pythonhosted.org/packages/
|
922 |
-
{ url = "https://files.pythonhosted.org/packages/
|
923 |
-
{ url = "https://files.pythonhosted.org/packages/
|
924 |
-
{ url = "https://files.pythonhosted.org/packages/
|
925 |
-
{ url = "https://files.pythonhosted.org/packages/
|
926 |
-
{ url = "https://files.pythonhosted.org/packages/
|
927 |
-
{ url = "https://files.pythonhosted.org/packages/
|
928 |
-
{ url = "https://files.pythonhosted.org/packages/
|
929 |
-
{ url = "https://files.pythonhosted.org/packages/
|
930 |
-
{ url = "https://files.pythonhosted.org/packages/
|
931 |
-
{ url = "https://files.pythonhosted.org/packages/
|
932 |
-
{ url = "https://files.pythonhosted.org/packages/
|
933 |
-
{ url = "https://files.pythonhosted.org/packages/
|
934 |
-
{ url = "https://files.pythonhosted.org/packages/
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
{ url = "https://files.pythonhosted.org/packages/
|
944 |
-
{ url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166 },
|
945 |
-
{ url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674 },
|
946 |
-
{ url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005 },
|
947 |
-
{ url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707 },
|
948 |
-
{ url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008 },
|
949 |
-
{ url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420 },
|
950 |
-
{ url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655 },
|
951 |
-
{ url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329 },
|
952 |
-
{ url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388 },
|
953 |
-
{ url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950 },
|
954 |
-
{ url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759 },
|
955 |
-
{ url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284 },
|
956 |
-
{ url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826 },
|
957 |
-
{ url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329 },
|
958 |
-
{ url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049 },
|
959 |
-
{ url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408 },
|
960 |
-
{ url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863 },
|
961 |
-
{ url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938 },
|
962 |
-
{ url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774 },
|
963 |
-
{ url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895 },
|
964 |
-
{ url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234 },
|
965 |
-
{ url = "https://files.pythonhosted.org/packages/a4/ad/2613c04633c7257d9481ab21d6b5364b59fc5d75faafd7cb8693523945a3/pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed", size = 3181734 },
|
966 |
-
{ url = "https://files.pythonhosted.org/packages/a4/fd/dcdda4471ed667de57bb5405bb42d751e6cfdd4011a12c248b455c778e03/pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c", size = 2999841 },
|
967 |
-
{ url = "https://files.pythonhosted.org/packages/ac/89/8a2536e95e77432833f0db6fd72a8d310c8e4272a04461fb833eb021bf94/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd", size = 3437470 },
|
968 |
-
{ url = "https://files.pythonhosted.org/packages/9d/8f/abd47b73c60712f88e9eda32baced7bfc3e9bd6a7619bb64b93acff28c3e/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076", size = 3460013 },
|
969 |
-
{ url = "https://files.pythonhosted.org/packages/f6/20/5c0a0aa83b213b7a07ec01e71a3d6ea2cf4ad1d2c686cc0168173b6089e7/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b", size = 3527165 },
|
970 |
-
{ url = "https://files.pythonhosted.org/packages/58/0e/2abab98a72202d91146abc839e10c14f7cf36166f12838ea0c4db3ca6ecb/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f", size = 3571586 },
|
971 |
-
{ url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751 },
|
972 |
]
|
973 |
|
974 |
[[package]]
|
@@ -1044,6 +1247,21 @@ wheels = [
|
|
1044 |
{ url = "https://files.pythonhosted.org/packages/b8/d3/c3cb8f1d6ae3b37f83e1de806713a9b3642c5895f0215a62e1a4bd6e5e34/propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", size = 12376 },
|
1045 |
]
|
1046 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1047 |
[[package]]
|
1048 |
name = "pydantic"
|
1049 |
version = "2.11.5"
|
@@ -1156,6 +1374,15 @@ wheels = [
|
|
1156 |
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
1157 |
]
|
1158 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1159 |
[[package]]
|
1160 |
name = "python-dateutil"
|
1161 |
version = "2.9.0.post0"
|
@@ -1186,6 +1413,18 @@ wheels = [
|
|
1186 |
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 },
|
1187 |
]
|
1188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1189 |
[[package]]
|
1190 |
name = "pytz"
|
1191 |
version = "2025.2"
|
@@ -1283,6 +1522,18 @@ wheels = [
|
|
1283 |
{ url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928 },
|
1284 |
]
|
1285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1286 |
[[package]]
|
1287 |
name = "safehttpx"
|
1288 |
version = "0.1.6"
|
@@ -1355,6 +1606,24 @@ wheels = [
|
|
1355 |
{ url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 },
|
1356 |
]
|
1357 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1358 |
[[package]]
|
1359 |
name = "tomlkit"
|
1360 |
version = "0.13.3"
|
|
|
127 |
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
|
128 |
]
|
129 |
|
130 |
+
[[package]]
|
131 |
+
name = "appdirs"
|
132 |
+
version = "1.4.4"
|
133 |
+
source = { registry = "https://pypi.org/simple" }
|
134 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470 }
|
135 |
+
wheels = [
|
136 |
+
{ url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566 },
|
137 |
+
]
|
138 |
+
|
139 |
[[package]]
|
140 |
name = "attrs"
|
141 |
version = "25.3.0"
|
|
|
263 |
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
264 |
]
|
265 |
|
266 |
+
[[package]]
|
267 |
+
name = "contourpy"
|
268 |
+
version = "1.3.2"
|
269 |
+
source = { registry = "https://pypi.org/simple" }
|
270 |
+
dependencies = [
|
271 |
+
{ name = "numpy" },
|
272 |
+
]
|
273 |
+
sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130 }
|
274 |
+
wheels = [
|
275 |
+
{ url = "https://files.pythonhosted.org/packages/b3/b9/ede788a0b56fc5b071639d06c33cb893f68b1178938f3425debebe2dab78/contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445", size = 269636 },
|
276 |
+
{ url = "https://files.pythonhosted.org/packages/e6/75/3469f011d64b8bbfa04f709bfc23e1dd71be54d05b1b083be9f5b22750d1/contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773", size = 254636 },
|
277 |
+
{ url = "https://files.pythonhosted.org/packages/8d/2f/95adb8dae08ce0ebca4fd8e7ad653159565d9739128b2d5977806656fcd2/contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1", size = 313053 },
|
278 |
+
{ url = "https://files.pythonhosted.org/packages/c3/a6/8ccf97a50f31adfa36917707fe39c9a0cbc24b3bbb58185577f119736cc9/contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43", size = 352985 },
|
279 |
+
{ url = "https://files.pythonhosted.org/packages/1d/b6/7925ab9b77386143f39d9c3243fdd101621b4532eb126743201160ffa7e6/contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab", size = 323750 },
|
280 |
+
{ url = "https://files.pythonhosted.org/packages/c2/f3/20c5d1ef4f4748e52d60771b8560cf00b69d5c6368b5c2e9311bcfa2a08b/contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7", size = 326246 },
|
281 |
+
{ url = "https://files.pythonhosted.org/packages/8c/e5/9dae809e7e0b2d9d70c52b3d24cba134dd3dad979eb3e5e71f5df22ed1f5/contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83", size = 1308728 },
|
282 |
+
{ url = "https://files.pythonhosted.org/packages/e2/4a/0058ba34aeea35c0b442ae61a4f4d4ca84d6df8f91309bc2d43bb8dd248f/contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd", size = 1375762 },
|
283 |
+
{ url = "https://files.pythonhosted.org/packages/09/33/7174bdfc8b7767ef2c08ed81244762d93d5c579336fc0b51ca57b33d1b80/contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f", size = 178196 },
|
284 |
+
{ url = "https://files.pythonhosted.org/packages/5e/fe/4029038b4e1c4485cef18e480b0e2cd2d755448bb071eb9977caac80b77b/contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878", size = 222017 },
|
285 |
+
{ url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580 },
|
286 |
+
{ url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530 },
|
287 |
+
{ url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688 },
|
288 |
+
{ url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331 },
|
289 |
+
{ url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963 },
|
290 |
+
{ url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681 },
|
291 |
+
{ url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674 },
|
292 |
+
{ url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480 },
|
293 |
+
{ url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489 },
|
294 |
+
{ url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042 },
|
295 |
+
{ url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630 },
|
296 |
+
{ url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670 },
|
297 |
+
{ url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694 },
|
298 |
+
{ url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986 },
|
299 |
+
{ url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060 },
|
300 |
+
{ url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747 },
|
301 |
+
{ url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895 },
|
302 |
+
{ url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098 },
|
303 |
+
{ url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535 },
|
304 |
+
{ url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096 },
|
305 |
+
{ url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090 },
|
306 |
+
{ url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643 },
|
307 |
+
{ url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443 },
|
308 |
+
{ url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865 },
|
309 |
+
{ url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162 },
|
310 |
+
{ url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355 },
|
311 |
+
{ url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935 },
|
312 |
+
{ url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168 },
|
313 |
+
{ url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550 },
|
314 |
+
{ url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214 },
|
315 |
+
{ url = "https://files.pythonhosted.org/packages/ff/c0/91f1215d0d9f9f343e4773ba6c9b89e8c0cc7a64a6263f21139da639d848/contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0", size = 266807 },
|
316 |
+
{ url = "https://files.pythonhosted.org/packages/d4/79/6be7e90c955c0487e7712660d6cead01fa17bff98e0ea275737cc2bc8e71/contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5", size = 318729 },
|
317 |
+
{ url = "https://files.pythonhosted.org/packages/87/68/7f46fb537958e87427d98a4074bcde4b67a70b04900cfc5ce29bc2f556c1/contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5", size = 221791 },
|
318 |
+
]
|
319 |
+
|
320 |
+
[[package]]
|
321 |
+
name = "cycler"
|
322 |
+
version = "0.12.1"
|
323 |
+
source = { registry = "https://pypi.org/simple" }
|
324 |
+
sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 }
|
325 |
+
wheels = [
|
326 |
+
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 },
|
327 |
+
]
|
328 |
+
|
329 |
[[package]]
|
330 |
name = "fastapi"
|
331 |
version = "0.115.12"
|
|
|
358 |
{ url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 },
|
359 |
]
|
360 |
|
361 |
+
[[package]]
|
362 |
+
name = "fonttools"
|
363 |
+
version = "4.58.2"
|
364 |
+
source = { registry = "https://pypi.org/simple" }
|
365 |
+
sdist = { url = "https://files.pythonhosted.org/packages/b6/a9/3319c6ae07fd9dde51064ddc6d82a2b707efad8ed407d700a01091121bbc/fonttools-4.58.2.tar.gz", hash = "sha256:4b491ddbfd50b856e84b0648b5f7941af918f6d32f938f18e62b58426a8d50e2", size = 3524285 }
|
366 |
+
wheels = [
|
367 |
+
{ url = "https://files.pythonhosted.org/packages/63/d0/335d12ee943b8d67847864bba98478fedf3503d8b168eeeefadd8660256a/fonttools-4.58.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:024faaf20811296fd2f83ebdac7682276362e726ed5fea4062480dd36aff2fd9", size = 2755885 },
|
368 |
+
{ url = "https://files.pythonhosted.org/packages/66/c2/d8ceb8b91e3847786a19d4b93749b1d804833482b5f79bee35b68327609e/fonttools-4.58.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2faec6e7f2abd80cd9f2392dfa28c02cfd5b1125be966ea6eddd6ca684deaa40", size = 2317804 },
|
369 |
+
{ url = "https://files.pythonhosted.org/packages/7c/93/865c8d50b3a1f50ebdc02227f28bb81817df88cee75bc6f2652469e754b1/fonttools-4.58.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:520792629a938c14dd7fe185794b156cfc159c609d07b31bbb5f51af8dc7918a", size = 4916900 },
|
370 |
+
{ url = "https://files.pythonhosted.org/packages/60/d1/301aec4f02995958b7af6728f838b2e5cc9296bec7eae350722dec31f685/fonttools-4.58.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12fbc6e0bf0c75ce475ef170f2c065be6abc9e06ad19a13b56b02ec2acf02427", size = 4937358 },
|
371 |
+
{ url = "https://files.pythonhosted.org/packages/15/22/75dc23a4c7200b8feb90baa82c518684a601a3a03be25f7cc3dde1525e37/fonttools-4.58.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:44a39cf856d52109127d55576c7ec010206a8ba510161a7705021f70d1649831", size = 4980151 },
|
372 |
+
{ url = "https://files.pythonhosted.org/packages/14/51/5d402f65c4b0c89ce0cdbffe86646f3996da209f7bc93f1f4a13a7211ee0/fonttools-4.58.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5390a67c55a835ad5a420da15b3d88b75412cbbd74450cb78c4916b0bd7f0a34", size = 5091255 },
|
373 |
+
{ url = "https://files.pythonhosted.org/packages/c7/5e/dee28700276129db1a0ee8ab0d5574d255a1d72df7f6df58a9d26ddef687/fonttools-4.58.2-cp311-cp311-win32.whl", hash = "sha256:f7e10f4e7160bcf6a240d7560e9e299e8cb585baed96f6a616cef51180bf56cb", size = 2190095 },
|
374 |
+
{ url = "https://files.pythonhosted.org/packages/bd/60/b90fda549942808b68c1c5bada4b369f4f55d4c28a7012f7537670438f82/fonttools-4.58.2-cp311-cp311-win_amd64.whl", hash = "sha256:29bdf52bfafdae362570d3f0d3119a3b10982e1ef8cb3a9d3ebb72da81cb8d5e", size = 2238013 },
|
375 |
+
{ url = "https://files.pythonhosted.org/packages/eb/68/7ec64584dc592faf944d540307c3562cd893256c48bb028c90de489e4750/fonttools-4.58.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c6eeaed9c54c1d33c1db928eb92b4e180c7cb93b50b1ee3e79b2395cb01f25e9", size = 2741645 },
|
376 |
+
{ url = "https://files.pythonhosted.org/packages/8f/0c/b327838f63baa7ebdd6db3ffdf5aff638e883f9236d928be4f32c692e1bd/fonttools-4.58.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbe1d9c72b7f981bed5c2a61443d5e3127c1b3aca28ca76386d1ad93268a803f", size = 2311100 },
|
377 |
+
{ url = "https://files.pythonhosted.org/packages/ae/c7/dec024a1c873c79a4db98fe0104755fa62ec2b4518e09d6fda28246c3c9b/fonttools-4.58.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85babe5b3ce2cbe57fc0d09c0ee92bbd4d594fd7ea46a65eb43510a74a4ce773", size = 4815841 },
|
378 |
+
{ url = "https://files.pythonhosted.org/packages/94/33/57c81abad641d6ec9c8b06c99cd28d687cb4849efb6168625b5c6b8f9fa4/fonttools-4.58.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:918a2854537fcdc662938057ad58b633bc9e0698f04a2f4894258213283a7932", size = 4882659 },
|
379 |
+
{ url = "https://files.pythonhosted.org/packages/a5/37/2f8faa2bf8bd1ba016ea86a94c72a5e8ef8ea1c52ec64dada617191f0515/fonttools-4.58.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b379cf05bf776c336a0205632596b1c7d7ab5f7135e3935f2ca2a0596d2d092", size = 4876128 },
|
380 |
+
{ url = "https://files.pythonhosted.org/packages/a0/ca/f1caac24ae7028a33f2a95e66c640571ff0ce5cb06c4c9ca1f632e98e22c/fonttools-4.58.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99ab3547a15a5d168c265e139e21756bbae1de04782ac9445c9ef61b8c0a32ce", size = 5027843 },
|
381 |
+
{ url = "https://files.pythonhosted.org/packages/52/6e/3200fa2bafeed748a3017e4e6594751fd50cce544270919265451b21b75c/fonttools-4.58.2-cp312-cp312-win32.whl", hash = "sha256:6764e7a3188ce36eea37b477cdeca602ae62e63ae9fc768ebc176518072deb04", size = 2177374 },
|
382 |
+
{ url = "https://files.pythonhosted.org/packages/55/ab/8f3e726f3f3ef3062ce9bbb615727c55beb11eea96d1f443f79cafca93ee/fonttools-4.58.2-cp312-cp312-win_amd64.whl", hash = "sha256:41f02182a1d41b79bae93c1551855146868b04ec3e7f9c57d6fef41a124e6b29", size = 2226685 },
|
383 |
+
{ url = "https://files.pythonhosted.org/packages/ac/01/29f81970a508408af20b434ff5136cd1c7ef92198957eb8ddadfbb9ef177/fonttools-4.58.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:829048ef29dbefec35d95cc6811014720371c95bdc6ceb0afd2f8e407c41697c", size = 2732398 },
|
384 |
+
{ url = "https://files.pythonhosted.org/packages/0c/f1/095f2338359333adb2f1c51b8b2ad94bf9a2fa17e5fcbdf8a7b8e3672d2d/fonttools-4.58.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:64998c5993431e45b474ed5f579f18555f45309dd1cf8008b594d2fe0a94be59", size = 2306390 },
|
385 |
+
{ url = "https://files.pythonhosted.org/packages/bf/d4/9eba134c7666a26668c28945355cd86e5d57828b6b8d952a5489fe45d7e2/fonttools-4.58.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b887a1cf9fbcb920980460ee4a489c8aba7e81341f6cdaeefa08c0ab6529591c", size = 4795100 },
|
386 |
+
{ url = "https://files.pythonhosted.org/packages/2a/34/345f153a24c1340daa62340c3be2d1e5ee6c1ee57e13f6d15613209e688b/fonttools-4.58.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27d74b9f6970cefbcda33609a3bee1618e5e57176c8b972134c4e22461b9c791", size = 4864585 },
|
387 |
+
{ url = "https://files.pythonhosted.org/packages/01/5f/091979a25c9a6c4ba064716cfdfe9431f78ed6ffba4bd05ae01eee3532e9/fonttools-4.58.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec26784610056a770e15a60f9920cee26ae10d44d1e43271ea652dadf4e7a236", size = 4866191 },
|
388 |
+
{ url = "https://files.pythonhosted.org/packages/9d/09/3944d0ece4a39560918cba37c2e0453a5f826b665a6db0b43abbd9dbe7e1/fonttools-4.58.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ed0a71d57dd427c0fb89febd08cac9b925284d2a8888e982a6c04714b82698d7", size = 5003867 },
|
389 |
+
{ url = "https://files.pythonhosted.org/packages/68/97/190b8f9ba22f8b7d07df2faa9fd7087b453776d0705d3cb5b0cbd89b8ef0/fonttools-4.58.2-cp313-cp313-win32.whl", hash = "sha256:994e362b01460aa863ef0cb41a29880bc1a498c546952df465deff7abf75587a", size = 2175688 },
|
390 |
+
{ url = "https://files.pythonhosted.org/packages/94/ea/0e6d4a39528dbb6e0f908c2ad219975be0a506ed440fddf5453b90f76981/fonttools-4.58.2-cp313-cp313-win_amd64.whl", hash = "sha256:f95dec862d7c395f2d4efe0535d9bdaf1e3811e51b86432fa2a77e73f8195756", size = 2226464 },
|
391 |
+
{ url = "https://files.pythonhosted.org/packages/e8/e5/c1cb8ebabb80be76d4d28995da9416816653f8f572920ab5e3d2e3ac8285/fonttools-4.58.2-py3-none-any.whl", hash = "sha256:84f4b0bcfa046254a65ee7117094b4907e22dc98097a220ef108030eb3c15596", size = 1114597 },
|
392 |
+
]
|
393 |
+
|
394 |
[[package]]
|
395 |
name = "frozenlist"
|
396 |
version = "1.6.2"
|
|
|
477 |
{ url = "https://files.pythonhosted.org/packages/bb/61/78c7b3851add1481b048b5fdc29067397a1784e2910592bc81bb3f608635/fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462", size = 199052 },
|
478 |
]
|
479 |
|
480 |
+
[[package]]
|
481 |
+
name = "future"
|
482 |
+
version = "1.0.0"
|
483 |
+
source = { registry = "https://pypi.org/simple" }
|
484 |
+
sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490 }
|
485 |
+
wheels = [
|
486 |
+
{ url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326 },
|
487 |
+
]
|
488 |
+
|
489 |
[[package]]
|
490 |
name = "geocalc-mcp"
|
491 |
version = "0.1.0"
|
|
|
494 |
{ name = "aiohttp" },
|
495 |
{ name = "geopy" },
|
496 |
{ name = "gradio" },
|
497 |
+
{ name = "matplotlib" },
|
498 |
{ name = "mcp" },
|
499 |
{ name = "openrouteservice" },
|
500 |
+
{ name = "pillow" },
|
501 |
+
{ name = "polyline" },
|
502 |
+
{ name = "py-staticmaps" },
|
503 |
{ name = "python-dotenv" },
|
504 |
]
|
505 |
|
|
|
508 |
{ name = "aiohttp", specifier = ">=3.12.9" },
|
509 |
{ name = "geopy", specifier = ">=2.4.1" },
|
510 |
{ name = "gradio", specifier = ">=5.33.0" },
|
511 |
+
{ name = "matplotlib", specifier = ">=3.10.3" },
|
512 |
{ name = "mcp", specifier = ">=1.9.3" },
|
513 |
{ name = "openrouteservice", specifier = ">=2.3.3" },
|
514 |
+
{ name = "pillow", specifier = "<10.0.0" },
|
515 |
+
{ name = "polyline", specifier = ">=2.0.2" },
|
516 |
+
{ name = "py-staticmaps", specifier = ">=0.4.0" },
|
517 |
{ name = "python-dotenv", specifier = ">=1.1.0" },
|
518 |
]
|
519 |
|
|
|
705 |
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
|
706 |
]
|
707 |
|
708 |
+
[[package]]
|
709 |
+
name = "kiwisolver"
|
710 |
+
version = "1.4.8"
|
711 |
+
source = { registry = "https://pypi.org/simple" }
|
712 |
+
sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538 }
|
713 |
+
wheels = [
|
714 |
+
{ url = "https://files.pythonhosted.org/packages/da/ed/c913ee28936c371418cb167b128066ffb20bbf37771eecc2c97edf8a6e4c/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84", size = 124635 },
|
715 |
+
{ url = "https://files.pythonhosted.org/packages/4c/45/4a7f896f7467aaf5f56ef093d1f329346f3b594e77c6a3c327b2d415f521/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561", size = 66717 },
|
716 |
+
{ url = "https://files.pythonhosted.org/packages/5f/b4/c12b3ac0852a3a68f94598d4c8d569f55361beef6159dce4e7b624160da2/kiwisolver-1.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7", size = 65413 },
|
717 |
+
{ url = "https://files.pythonhosted.org/packages/a9/98/1df4089b1ed23d83d410adfdc5947245c753bddfbe06541c4aae330e9e70/kiwisolver-1.4.8-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03", size = 1343994 },
|
718 |
+
{ url = "https://files.pythonhosted.org/packages/8d/bf/b4b169b050c8421a7c53ea1ea74e4ef9c335ee9013216c558a047f162d20/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954", size = 1434804 },
|
719 |
+
{ url = "https://files.pythonhosted.org/packages/66/5a/e13bd341fbcf73325ea60fdc8af752addf75c5079867af2e04cc41f34434/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79", size = 1450690 },
|
720 |
+
{ url = "https://files.pythonhosted.org/packages/9b/4f/5955dcb376ba4a830384cc6fab7d7547bd6759fe75a09564910e9e3bb8ea/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6", size = 1376839 },
|
721 |
+
{ url = "https://files.pythonhosted.org/packages/3a/97/5edbed69a9d0caa2e4aa616ae7df8127e10f6586940aa683a496c2c280b9/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0", size = 1435109 },
|
722 |
+
{ url = "https://files.pythonhosted.org/packages/13/fc/e756382cb64e556af6c1809a1bbb22c141bbc2445049f2da06b420fe52bf/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab", size = 2245269 },
|
723 |
+
{ url = "https://files.pythonhosted.org/packages/76/15/e59e45829d7f41c776d138245cabae6515cb4eb44b418f6d4109c478b481/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc", size = 2393468 },
|
724 |
+
{ url = "https://files.pythonhosted.org/packages/e9/39/483558c2a913ab8384d6e4b66a932406f87c95a6080112433da5ed668559/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25", size = 2355394 },
|
725 |
+
{ url = "https://files.pythonhosted.org/packages/01/aa/efad1fbca6570a161d29224f14b082960c7e08268a133fe5dc0f6906820e/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc", size = 2490901 },
|
726 |
+
{ url = "https://files.pythonhosted.org/packages/c9/4f/15988966ba46bcd5ab9d0c8296914436720dd67fca689ae1a75b4ec1c72f/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67", size = 2312306 },
|
727 |
+
{ url = "https://files.pythonhosted.org/packages/2d/27/bdf1c769c83f74d98cbc34483a972f221440703054894a37d174fba8aa68/kiwisolver-1.4.8-cp311-cp311-win_amd64.whl", hash = "sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34", size = 71966 },
|
728 |
+
{ url = "https://files.pythonhosted.org/packages/4a/c9/9642ea855604aeb2968a8e145fc662edf61db7632ad2e4fb92424be6b6c0/kiwisolver-1.4.8-cp311-cp311-win_arm64.whl", hash = "sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2", size = 65311 },
|
729 |
+
{ url = "https://files.pythonhosted.org/packages/fc/aa/cea685c4ab647f349c3bc92d2daf7ae34c8e8cf405a6dcd3a497f58a2ac3/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502", size = 124152 },
|
730 |
+
{ url = "https://files.pythonhosted.org/packages/c5/0b/8db6d2e2452d60d5ebc4ce4b204feeb16176a851fd42462f66ade6808084/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31", size = 66555 },
|
731 |
+
{ url = "https://files.pythonhosted.org/packages/60/26/d6a0db6785dd35d3ba5bf2b2df0aedc5af089962c6eb2cbf67a15b81369e/kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb", size = 65067 },
|
732 |
+
{ url = "https://files.pythonhosted.org/packages/c9/ed/1d97f7e3561e09757a196231edccc1bcf59d55ddccefa2afc9c615abd8e0/kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f", size = 1378443 },
|
733 |
+
{ url = "https://files.pythonhosted.org/packages/29/61/39d30b99954e6b46f760e6289c12fede2ab96a254c443639052d1b573fbc/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc", size = 1472728 },
|
734 |
+
{ url = "https://files.pythonhosted.org/packages/0c/3e/804163b932f7603ef256e4a715e5843a9600802bb23a68b4e08c8c0ff61d/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a", size = 1478388 },
|
735 |
+
{ url = "https://files.pythonhosted.org/packages/8a/9e/60eaa75169a154700be74f875a4d9961b11ba048bef315fbe89cb6999056/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a", size = 1413849 },
|
736 |
+
{ url = "https://files.pythonhosted.org/packages/bc/b3/9458adb9472e61a998c8c4d95cfdfec91c73c53a375b30b1428310f923e4/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a", size = 1475533 },
|
737 |
+
{ url = "https://files.pythonhosted.org/packages/e4/7a/0a42d9571e35798de80aef4bb43a9b672aa7f8e58643d7bd1950398ffb0a/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3", size = 2268898 },
|
738 |
+
{ url = "https://files.pythonhosted.org/packages/d9/07/1255dc8d80271400126ed8db35a1795b1a2c098ac3a72645075d06fe5c5d/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b", size = 2425605 },
|
739 |
+
{ url = "https://files.pythonhosted.org/packages/84/df/5a3b4cf13780ef6f6942df67b138b03b7e79e9f1f08f57c49957d5867f6e/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4", size = 2375801 },
|
740 |
+
{ url = "https://files.pythonhosted.org/packages/8f/10/2348d068e8b0f635c8c86892788dac7a6b5c0cb12356620ab575775aad89/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d", size = 2520077 },
|
741 |
+
{ url = "https://files.pythonhosted.org/packages/32/d8/014b89fee5d4dce157d814303b0fce4d31385a2af4c41fed194b173b81ac/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8", size = 2338410 },
|
742 |
+
{ url = "https://files.pythonhosted.org/packages/bd/72/dfff0cc97f2a0776e1c9eb5bef1ddfd45f46246c6533b0191887a427bca5/kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50", size = 71853 },
|
743 |
+
{ url = "https://files.pythonhosted.org/packages/dc/85/220d13d914485c0948a00f0b9eb419efaf6da81b7d72e88ce2391f7aed8d/kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476", size = 65424 },
|
744 |
+
{ url = "https://files.pythonhosted.org/packages/79/b3/e62464a652f4f8cd9006e13d07abad844a47df1e6537f73ddfbf1bc997ec/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1c8ceb754339793c24aee1c9fb2485b5b1f5bb1c2c214ff13368431e51fc9a09", size = 124156 },
|
745 |
+
{ url = "https://files.pythonhosted.org/packages/8d/2d/f13d06998b546a2ad4f48607a146e045bbe48030774de29f90bdc573df15/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a62808ac74b5e55a04a408cda6156f986cefbcf0ada13572696b507cc92fa1", size = 66555 },
|
746 |
+
{ url = "https://files.pythonhosted.org/packages/59/e3/b8bd14b0a54998a9fd1e8da591c60998dc003618cb19a3f94cb233ec1511/kiwisolver-1.4.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68269e60ee4929893aad82666821aaacbd455284124817af45c11e50a4b42e3c", size = 65071 },
|
747 |
+
{ url = "https://files.pythonhosted.org/packages/f0/1c/6c86f6d85ffe4d0ce04228d976f00674f1df5dc893bf2dd4f1928748f187/kiwisolver-1.4.8-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34d142fba9c464bc3bbfeff15c96eab0e7310343d6aefb62a79d51421fcc5f1b", size = 1378053 },
|
748 |
+
{ url = "https://files.pythonhosted.org/packages/4e/b9/1c6e9f6dcb103ac5cf87cb695845f5fa71379021500153566d8a8a9fc291/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc373e0eef45b59197de815b1b28ef89ae3955e7722cc9710fb91cd77b7f47", size = 1472278 },
|
749 |
+
{ url = "https://files.pythonhosted.org/packages/ee/81/aca1eb176de671f8bda479b11acdc42c132b61a2ac861c883907dde6debb/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77e6f57a20b9bd4e1e2cedda4d0b986ebd0216236f0106e55c28aea3d3d69b16", size = 1478139 },
|
750 |
+
{ url = "https://files.pythonhosted.org/packages/49/f4/e081522473671c97b2687d380e9e4c26f748a86363ce5af48b4a28e48d06/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08e77738ed7538f036cd1170cbed942ef749137b1311fa2bbe2a7fda2f6bf3cc", size = 1413517 },
|
751 |
+
{ url = "https://files.pythonhosted.org/packages/8f/e9/6a7d025d8da8c4931522922cd706105aa32b3291d1add8c5427cdcd66e63/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5ce1e481a74b44dd5e92ff03ea0cb371ae7a0268318e202be06c8f04f4f1246", size = 1474952 },
|
752 |
+
{ url = "https://files.pythonhosted.org/packages/82/13/13fa685ae167bee5d94b415991c4fc7bb0a1b6ebea6e753a87044b209678/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fc2ace710ba7c1dfd1a3b42530b62b9ceed115f19a1656adefce7b1782a37794", size = 2269132 },
|
753 |
+
{ url = "https://files.pythonhosted.org/packages/ef/92/bb7c9395489b99a6cb41d502d3686bac692586db2045adc19e45ee64ed23/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3452046c37c7692bd52b0e752b87954ef86ee2224e624ef7ce6cb21e8c41cc1b", size = 2425997 },
|
754 |
+
{ url = "https://files.pythonhosted.org/packages/ed/12/87f0e9271e2b63d35d0d8524954145837dd1a6c15b62a2d8c1ebe0f182b4/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e9a60b50fe8b2ec6f448fe8d81b07e40141bfced7f896309df271a0b92f80f3", size = 2376060 },
|
755 |
+
{ url = "https://files.pythonhosted.org/packages/02/6e/c8af39288edbce8bf0fa35dee427b082758a4b71e9c91ef18fa667782138/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:918139571133f366e8362fa4a297aeba86c7816b7ecf0bc79168080e2bd79957", size = 2520471 },
|
756 |
+
{ url = "https://files.pythonhosted.org/packages/13/78/df381bc7b26e535c91469f77f16adcd073beb3e2dd25042efd064af82323/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e063ef9f89885a1d68dd8b2e18f5ead48653176d10a0e324e3b0030e3a69adeb", size = 2338793 },
|
757 |
+
{ url = "https://files.pythonhosted.org/packages/d0/dc/c1abe38c37c071d0fc71c9a474fd0b9ede05d42f5a458d584619cfd2371a/kiwisolver-1.4.8-cp313-cp313-win_amd64.whl", hash = "sha256:a17b7c4f5b2c51bb68ed379defd608a03954a1845dfed7cc0117f1cc8a9b7fd2", size = 71855 },
|
758 |
+
{ url = "https://files.pythonhosted.org/packages/a0/b6/21529d595b126ac298fdd90b705d87d4c5693de60023e0efcb4f387ed99e/kiwisolver-1.4.8-cp313-cp313-win_arm64.whl", hash = "sha256:3cd3bc628b25f74aedc6d374d5babf0166a92ff1317f46267f12d2ed54bc1d30", size = 65430 },
|
759 |
+
{ url = "https://files.pythonhosted.org/packages/34/bd/b89380b7298e3af9b39f49334e3e2a4af0e04819789f04b43d560516c0c8/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:370fd2df41660ed4e26b8c9d6bbcad668fbe2560462cba151a721d49e5b6628c", size = 126294 },
|
760 |
+
{ url = "https://files.pythonhosted.org/packages/83/41/5857dc72e5e4148eaac5aa76e0703e594e4465f8ab7ec0fc60e3a9bb8fea/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:84a2f830d42707de1d191b9490ac186bf7997a9495d4e9072210a1296345f7dc", size = 67736 },
|
761 |
+
{ url = "https://files.pythonhosted.org/packages/e1/d1/be059b8db56ac270489fb0b3297fd1e53d195ba76e9bbb30e5401fa6b759/kiwisolver-1.4.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7a3ad337add5148cf51ce0b55642dc551c0b9d6248458a757f98796ca7348712", size = 66194 },
|
762 |
+
{ url = "https://files.pythonhosted.org/packages/e1/83/4b73975f149819eb7dcf9299ed467eba068ecb16439a98990dcb12e63fdd/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7506488470f41169b86d8c9aeff587293f530a23a23a49d6bc64dab66bedc71e", size = 1465942 },
|
763 |
+
{ url = "https://files.pythonhosted.org/packages/c7/2c/30a5cdde5102958e602c07466bce058b9d7cb48734aa7a4327261ac8e002/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f0121b07b356a22fb0414cec4666bbe36fd6d0d759db3d37228f496ed67c880", size = 1595341 },
|
764 |
+
{ url = "https://files.pythonhosted.org/packages/ff/9b/1e71db1c000385aa069704f5990574b8244cce854ecd83119c19e83c9586/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6d6bd87df62c27d4185de7c511c6248040afae67028a8a22012b010bc7ad062", size = 1598455 },
|
765 |
+
{ url = "https://files.pythonhosted.org/packages/85/92/c8fec52ddf06231b31cbb779af77e99b8253cd96bd135250b9498144c78b/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:291331973c64bb9cce50bbe871fb2e675c4331dab4f31abe89f175ad7679a4d7", size = 1522138 },
|
766 |
+
{ url = "https://files.pythonhosted.org/packages/0b/51/9eb7e2cd07a15d8bdd976f6190c0164f92ce1904e5c0c79198c4972926b7/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:893f5525bb92d3d735878ec00f781b2de998333659507d29ea4466208df37bed", size = 1582857 },
|
767 |
+
{ url = "https://files.pythonhosted.org/packages/0f/95/c5a00387a5405e68ba32cc64af65ce881a39b98d73cc394b24143bebc5b8/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b47a465040146981dc9db8647981b8cb96366fbc8d452b031e4f8fdffec3f26d", size = 2293129 },
|
768 |
+
{ url = "https://files.pythonhosted.org/packages/44/83/eeb7af7d706b8347548313fa3a3a15931f404533cc54fe01f39e830dd231/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:99cea8b9dd34ff80c521aef46a1dddb0dcc0283cf18bde6d756f1e6f31772165", size = 2421538 },
|
769 |
+
{ url = "https://files.pythonhosted.org/packages/05/f9/27e94c1b3eb29e6933b6986ffc5fa1177d2cd1f0c8efc5f02c91c9ac61de/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:151dffc4865e5fe6dafce5480fab84f950d14566c480c08a53c663a0020504b6", size = 2390661 },
|
770 |
+
{ url = "https://files.pythonhosted.org/packages/d9/d4/3c9735faa36ac591a4afcc2980d2691000506050b7a7e80bcfe44048daa7/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:577facaa411c10421314598b50413aa1ebcf5126f704f1e5d72d7e4e9f020d90", size = 2546710 },
|
771 |
+
{ url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213 },
|
772 |
+
]
|
773 |
+
|
774 |
[[package]]
|
775 |
name = "markdown-it-py"
|
776 |
version = "3.0.0"
|
|
|
831 |
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
|
832 |
]
|
833 |
|
834 |
+
[[package]]
|
835 |
+
name = "matplotlib"
|
836 |
+
version = "3.10.3"
|
837 |
+
source = { registry = "https://pypi.org/simple" }
|
838 |
+
dependencies = [
|
839 |
+
{ name = "contourpy" },
|
840 |
+
{ name = "cycler" },
|
841 |
+
{ name = "fonttools" },
|
842 |
+
{ name = "kiwisolver" },
|
843 |
+
{ name = "numpy" },
|
844 |
+
{ name = "packaging" },
|
845 |
+
{ name = "pillow" },
|
846 |
+
{ name = "pyparsing" },
|
847 |
+
{ name = "python-dateutil" },
|
848 |
+
]
|
849 |
+
sdist = { url = "https://files.pythonhosted.org/packages/26/91/d49359a21893183ed2a5b6c76bec40e0b1dcbf8ca148f864d134897cfc75/matplotlib-3.10.3.tar.gz", hash = "sha256:2f82d2c5bb7ae93aaaa4cd42aca65d76ce6376f83304fa3a630b569aca274df0", size = 34799811 }
|
850 |
+
wheels = [
|
851 |
+
{ url = "https://files.pythonhosted.org/packages/f5/bd/af9f655456f60fe1d575f54fb14704ee299b16e999704817a7645dfce6b0/matplotlib-3.10.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0ef061f74cd488586f552d0c336b2f078d43bc00dc473d2c3e7bfee2272f3fa8", size = 8178873 },
|
852 |
+
{ url = "https://files.pythonhosted.org/packages/c2/86/e1c86690610661cd716eda5f9d0b35eaf606ae6c9b6736687cfc8f2d0cd8/matplotlib-3.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96985d14dc5f4a736bbea4b9de9afaa735f8a0fc2ca75be2fa9e96b2097369d", size = 8052205 },
|
853 |
+
{ url = "https://files.pythonhosted.org/packages/54/51/a9f8e49af3883dacddb2da1af5fca1f7468677f1188936452dd9aaaeb9ed/matplotlib-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5f0283da91e9522bdba4d6583ed9d5521566f63729ffb68334f86d0bb98049", size = 8465823 },
|
854 |
+
{ url = "https://files.pythonhosted.org/packages/e7/e3/c82963a3b86d6e6d5874cbeaa390166458a7f1961bab9feb14d3d1a10f02/matplotlib-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdfa07c0ec58035242bc8b2c8aae37037c9a886370eef6850703d7583e19964b", size = 8606464 },
|
855 |
+
{ url = "https://files.pythonhosted.org/packages/0e/34/24da1027e7fcdd9e82da3194c470143c551852757a4b473a09a012f5b945/matplotlib-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c0b9849a17bce080a16ebcb80a7b714b5677d0ec32161a2cc0a8e5a6030ae220", size = 9413103 },
|
856 |
+
{ url = "https://files.pythonhosted.org/packages/a6/da/948a017c3ea13fd4a97afad5fdebe2f5bbc4d28c0654510ce6fd6b06b7bd/matplotlib-3.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:eef6ed6c03717083bc6d69c2d7ee8624205c29a8e6ea5a31cd3492ecdbaee1e1", size = 8065492 },
|
857 |
+
{ url = "https://files.pythonhosted.org/packages/eb/43/6b80eb47d1071f234ef0c96ca370c2ca621f91c12045f1401b5c9b28a639/matplotlib-3.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ab1affc11d1f495ab9e6362b8174a25afc19c081ba5b0775ef00533a4236eea", size = 8179689 },
|
858 |
+
{ url = "https://files.pythonhosted.org/packages/0f/70/d61a591958325c357204870b5e7b164f93f2a8cca1dc6ce940f563909a13/matplotlib-3.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a818d8bdcafa7ed2eed74487fdb071c09c1ae24152d403952adad11fa3c65b4", size = 8050466 },
|
859 |
+
{ url = "https://files.pythonhosted.org/packages/e7/75/70c9d2306203148cc7902a961240c5927dd8728afedf35e6a77e105a2985/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748ebc3470c253e770b17d8b0557f0aa85cf8c63fd52f1a61af5b27ec0b7ffee", size = 8456252 },
|
860 |
+
{ url = "https://files.pythonhosted.org/packages/c4/91/ba0ae1ff4b3f30972ad01cd4a8029e70a0ec3b8ea5be04764b128b66f763/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed70453fd99733293ace1aec568255bc51c6361cb0da94fa5ebf0649fdb2150a", size = 8601321 },
|
861 |
+
{ url = "https://files.pythonhosted.org/packages/d2/88/d636041eb54a84b889e11872d91f7cbf036b3b0e194a70fa064eb8b04f7a/matplotlib-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbed9917b44070e55640bd13419de83b4c918e52d97561544814ba463811cbc7", size = 9406972 },
|
862 |
+
{ url = "https://files.pythonhosted.org/packages/b1/79/0d1c165eac44405a86478082e225fce87874f7198300bbebc55faaf6d28d/matplotlib-3.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:cf37d8c6ef1a48829443e8ba5227b44236d7fcaf7647caa3178a4ff9f7a5be05", size = 8067954 },
|
863 |
+
{ url = "https://files.pythonhosted.org/packages/3b/c1/23cfb566a74c696a3b338d8955c549900d18fe2b898b6e94d682ca21e7c2/matplotlib-3.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9f2efccc8dcf2b86fc4ee849eea5dcaecedd0773b30f47980dc0cbeabf26ec84", size = 8180318 },
|
864 |
+
{ url = "https://files.pythonhosted.org/packages/6c/0c/02f1c3b66b30da9ee343c343acbb6251bef5b01d34fad732446eaadcd108/matplotlib-3.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ddbba06a6c126e3301c3d272a99dcbe7f6c24c14024e80307ff03791a5f294e", size = 8051132 },
|
865 |
+
{ url = "https://files.pythonhosted.org/packages/b4/ab/8db1a5ac9b3a7352fb914133001dae889f9fcecb3146541be46bed41339c/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748302b33ae9326995b238f606e9ed840bf5886ebafcb233775d946aa8107a15", size = 8457633 },
|
866 |
+
{ url = "https://files.pythonhosted.org/packages/f5/64/41c4367bcaecbc03ef0d2a3ecee58a7065d0a36ae1aa817fe573a2da66d4/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a80fcccbef63302c0efd78042ea3c2436104c5b1a4d3ae20f864593696364ac7", size = 8601031 },
|
867 |
+
{ url = "https://files.pythonhosted.org/packages/12/6f/6cc79e9e5ab89d13ed64da28898e40fe5b105a9ab9c98f83abd24e46d7d7/matplotlib-3.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55e46cbfe1f8586adb34f7587c3e4f7dedc59d5226719faf6cb54fc24f2fd52d", size = 9406988 },
|
868 |
+
{ url = "https://files.pythonhosted.org/packages/b1/0f/eed564407bd4d935ffabf561ed31099ed609e19287409a27b6d336848653/matplotlib-3.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:151d89cb8d33cb23345cd12490c76fd5d18a56581a16d950b48c6ff19bb2ab93", size = 8068034 },
|
869 |
+
{ url = "https://files.pythonhosted.org/packages/3e/e5/2f14791ff69b12b09e9975e1d116d9578ac684460860ce542c2588cb7a1c/matplotlib-3.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c26dd9834e74d164d06433dc7be5d75a1e9890b926b3e57e74fa446e1a62c3e2", size = 8218223 },
|
870 |
+
{ url = "https://files.pythonhosted.org/packages/5c/08/30a94afd828b6e02d0a52cae4a29d6e9ccfcf4c8b56cc28b021d3588873e/matplotlib-3.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:24853dad5b8c84c8c2390fc31ce4858b6df504156893292ce8092d190ef8151d", size = 8094985 },
|
871 |
+
{ url = "https://files.pythonhosted.org/packages/89/44/f3bc6b53066c889d7a1a3ea8094c13af6a667c5ca6220ec60ecceec2dabe/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f7878214d369d7d4215e2a9075fef743be38fa401d32e6020bab2dfabaa566", size = 8483109 },
|
872 |
+
{ url = "https://files.pythonhosted.org/packages/ba/c7/473bc559beec08ebee9f86ca77a844b65747e1a6c2691e8c92e40b9f42a8/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6929fc618cb6db9cb75086f73b3219bbb25920cb24cee2ea7a12b04971a4158", size = 8618082 },
|
873 |
+
{ url = "https://files.pythonhosted.org/packages/d8/e9/6ce8edd264c8819e37bbed8172e0ccdc7107fe86999b76ab5752276357a4/matplotlib-3.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c7818292a5cc372a2dc4c795e5c356942eb8350b98ef913f7fda51fe175ac5d", size = 9413699 },
|
874 |
+
{ url = "https://files.pythonhosted.org/packages/1b/92/9a45c91089c3cf690b5badd4be81e392ff086ccca8a1d4e3a08463d8a966/matplotlib-3.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4f23ffe95c5667ef8a2b56eea9b53db7f43910fa4a2d5472ae0f72b64deab4d5", size = 8139044 },
|
875 |
+
]
|
876 |
+
|
877 |
[[package]]
|
878 |
name = "mcp"
|
879 |
version = "1.9.3"
|
|
|
1145 |
|
1146 |
[[package]]
|
1147 |
name = "pillow"
|
1148 |
+
version = "9.5.0"
|
1149 |
+
source = { registry = "https://pypi.org/simple" }
|
1150 |
+
sdist = { url = "https://files.pythonhosted.org/packages/00/d5/4903f310765e0ff2b8e91ffe55031ac6af77d982f0156061e20a4d1a8b2d/Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1", size = 50488147 }
|
1151 |
+
wheels = [
|
1152 |
+
{ url = "https://files.pythonhosted.org/packages/78/a8/3c2d737d856eb9cd8c18e78f6fe0ed08a2805bded74cbb0455584859023b/Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32", size = 3395792 },
|
1153 |
+
{ url = "https://files.pythonhosted.org/packages/a9/15/310cde63cb15a091de889ded26281924cf9cfa5c000b36b06bd0c7f50261/Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c", size = 3077092 },
|
1154 |
+
{ url = "https://files.pythonhosted.org/packages/17/66/20db69c0361902a2f6ee2086d3e83c70133e3fb4cb31470e59a8ed37184e/Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3", size = 3112543 },
|
1155 |
+
{ url = "https://files.pythonhosted.org/packages/5c/a8/ff526cdec6b56eb20c992e7083f02c8065049ed1e62fbc159390d7a3dd5e/Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a", size = 3386654 },
|
1156 |
+
{ url = "https://files.pythonhosted.org/packages/3b/70/e9a45a2e9c58c23e023fcda5af9686f5b42c718cc9bc86194e0025cf0ec5/Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1", size = 3308566 },
|
1157 |
+
{ url = "https://files.pythonhosted.org/packages/61/a5/ee306d6cc53c9a30c23ba2313b43b67fdf76c611ca5afd0cdd62922cbd3e/Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99", size = 3164027 },
|
1158 |
+
{ url = "https://files.pythonhosted.org/packages/3d/59/e6bd2c3715ace343d9739276ceed79657fe116923238d102cf731ab463dd/Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625", size = 3415610 },
|
1159 |
+
{ url = "https://files.pythonhosted.org/packages/9a/6d/9beb596ba5a5e61081c843187bcdbb42a5c9a9ef552751b554894247da7a/Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579", size = 3350704 },
|
1160 |
+
{ url = "https://files.pythonhosted.org/packages/1e/e4/de633d85be3b3c770c554a37a89e8273069bd19c34b15a419c2795600310/Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296", size = 3414604 },
|
1161 |
+
{ url = "https://files.pythonhosted.org/packages/46/a0/e410f655300932308e70e883dd60c0c51e6f74bed138641ea9193e64fd7c/Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec", size = 2211929 },
|
1162 |
+
{ url = "https://files.pythonhosted.org/packages/0c/02/7729c8aecbc525b560c7eb283ffa34c6f5a6d0ed6d1339570c65a3e63088/Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4", size = 2511551 },
|
1163 |
+
{ url = "https://files.pythonhosted.org/packages/b9/8b/d38cc68796be4ac238db327682a1acfbc5deccf64a150aa44ee1efbaafae/Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089", size = 2489206 },
|
1164 |
+
{ url = "https://files.pythonhosted.org/packages/5d/38/b7bcbab3bfe1946ba9cf71c1fa03e541b498069457be49eadcdc229412ef/Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb", size = 2211914 },
|
1165 |
+
{ url = "https://files.pythonhosted.org/packages/29/8a/f4cf3f32bc554f9260b645ea1151449ac13525796d3d1a42076d75945d8d/Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b", size = 2511483 },
|
1166 |
+
]
|
1167 |
+
|
1168 |
+
[[package]]
|
1169 |
+
name = "polyline"
|
1170 |
+
version = "2.0.2"
|
1171 |
+
source = { registry = "https://pypi.org/simple" }
|
1172 |
+
sdist = { url = "https://files.pythonhosted.org/packages/1d/2f/e6a437b785d951867882b9fba52a70b81fe8af778bbb4d96b6fb69630f72/polyline-2.0.2.tar.gz", hash = "sha256:10541e759c5fd51f746ee304e9af94744089a4055b6257b293b3afd1df64e369", size = 6400 }
|
1173 |
+
wheels = [
|
1174 |
+
{ url = "https://files.pythonhosted.org/packages/d7/4f/fbf07370cbf98af0098de83a26625d29aaa0bf73ef7123b561459729f3e6/polyline-2.0.2-py3-none-any.whl", hash = "sha256:389655c893bdabf2863c6aaa49490cf83dcdcec86ae715f67044ee98be57bef5", size = 5970 },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1175 |
]
|
1176 |
|
1177 |
[[package]]
|
|
|
1247 |
{ url = "https://files.pythonhosted.org/packages/b8/d3/c3cb8f1d6ae3b37f83e1de806713a9b3642c5895f0215a62e1a4bd6e5e34/propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40", size = 12376 },
|
1248 |
]
|
1249 |
|
1250 |
+
[[package]]
|
1251 |
+
name = "py-staticmaps"
|
1252 |
+
version = "0.4.0"
|
1253 |
+
source = { registry = "https://pypi.org/simple" }
|
1254 |
+
dependencies = [
|
1255 |
+
{ name = "appdirs" },
|
1256 |
+
{ name = "geographiclib" },
|
1257 |
+
{ name = "pillow" },
|
1258 |
+
{ name = "python-slugify" },
|
1259 |
+
{ name = "requests" },
|
1260 |
+
{ name = "s2sphere" },
|
1261 |
+
{ name = "svgwrite" },
|
1262 |
+
]
|
1263 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/22/efa565521b37c3cf8b64c6a2c7a3631efae15724231e23c9fd37623df7ef/py-staticmaps-0.4.0.tar.gz", hash = "sha256:5aba5ad59f30a63f860e76ed99407a6efb24eaad5c8997aa8617363989f17389", size = 21972 }
|
1264 |
+
|
1265 |
[[package]]
|
1266 |
name = "pydantic"
|
1267 |
version = "2.11.5"
|
|
|
1374 |
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
1375 |
]
|
1376 |
|
1377 |
+
[[package]]
|
1378 |
+
name = "pyparsing"
|
1379 |
+
version = "3.2.3"
|
1380 |
+
source = { registry = "https://pypi.org/simple" }
|
1381 |
+
sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608 }
|
1382 |
+
wheels = [
|
1383 |
+
{ url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120 },
|
1384 |
+
]
|
1385 |
+
|
1386 |
[[package]]
|
1387 |
name = "python-dateutil"
|
1388 |
version = "2.9.0.post0"
|
|
|
1413 |
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 },
|
1414 |
]
|
1415 |
|
1416 |
+
[[package]]
|
1417 |
+
name = "python-slugify"
|
1418 |
+
version = "8.0.4"
|
1419 |
+
source = { registry = "https://pypi.org/simple" }
|
1420 |
+
dependencies = [
|
1421 |
+
{ name = "text-unidecode" },
|
1422 |
+
]
|
1423 |
+
sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921 }
|
1424 |
+
wheels = [
|
1425 |
+
{ url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051 },
|
1426 |
+
]
|
1427 |
+
|
1428 |
[[package]]
|
1429 |
name = "pytz"
|
1430 |
version = "2025.2"
|
|
|
1522 |
{ url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928 },
|
1523 |
]
|
1524 |
|
1525 |
+
[[package]]
|
1526 |
+
name = "s2sphere"
|
1527 |
+
version = "0.2.5"
|
1528 |
+
source = { registry = "https://pypi.org/simple" }
|
1529 |
+
dependencies = [
|
1530 |
+
{ name = "future" },
|
1531 |
+
]
|
1532 |
+
sdist = { url = "https://files.pythonhosted.org/packages/01/8e/08260a5f03c642d3f6f040756425dc3f466842c4d5e978f6c2be960dde2f/s2sphere-0.2.5.tar.gz", hash = "sha256:c2478c1ff7c601a59a7151a57b605435897514578fa6bdb8730721c182adbbaf", size = 51789 }
|
1533 |
+
wheels = [
|
1534 |
+
{ url = "https://files.pythonhosted.org/packages/49/fc/be2251ac7ee75e725027b107ab14d161d829aaac22362f75eaabc859bfba/s2sphere-0.2.5-py2.py3-none-any.whl", hash = "sha256:d2340c9cf458ddc9a89afd1d8048a4195ce6fa6b0095ab900d4be5271e537401", size = 23540 },
|
1535 |
+
]
|
1536 |
+
|
1537 |
[[package]]
|
1538 |
name = "safehttpx"
|
1539 |
version = "0.1.6"
|
|
|
1606 |
{ url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 },
|
1607 |
]
|
1608 |
|
1609 |
+
[[package]]
|
1610 |
+
name = "svgwrite"
|
1611 |
+
version = "1.4.3"
|
1612 |
+
source = { registry = "https://pypi.org/simple" }
|
1613 |
+
sdist = { url = "https://files.pythonhosted.org/packages/16/c1/263d4e93b543390d86d8eb4fc23d9ce8a8d6efd146f9427364109004fa9b/svgwrite-1.4.3.zip", hash = "sha256:a8fbdfd4443302a6619a7f76bc937fc683daf2628d9b737c891ec08b8ce524c3", size = 189516 }
|
1614 |
+
wheels = [
|
1615 |
+
{ url = "https://files.pythonhosted.org/packages/84/15/640e399579024a6875918839454025bb1d5f850bb70d96a11eabb644d11c/svgwrite-1.4.3-py3-none-any.whl", hash = "sha256:bb6b2b5450f1edbfa597d924f9ac2dd099e625562e492021d7dd614f65f8a22d", size = 67122 },
|
1616 |
+
]
|
1617 |
+
|
1618 |
+
[[package]]
|
1619 |
+
name = "text-unidecode"
|
1620 |
+
version = "1.3"
|
1621 |
+
source = { registry = "https://pypi.org/simple" }
|
1622 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885 }
|
1623 |
+
wheels = [
|
1624 |
+
{ url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154 },
|
1625 |
+
]
|
1626 |
+
|
1627 |
[[package]]
|
1628 |
name = "tomlkit"
|
1629 |
version = "0.13.3"
|