diff --git a/README.md b/README.md
index 838e78e..7e2376e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# SWRData/Boundaries
-Ready-to-use, timestamped, tiled boundary data for Germany.
+Ready-to-use, timestamped boundary data for Germany.
[](https://github.com/SWRdata/boundaries/actions/workflows/deploy-demo.yaml) [](https://github.com/SWRdata/boundaries/actions/workflows/deploy-pipeline.yaml) [](https://github.com/SWRdata/boundaries/actions/workflows/ty.yaml)
@@ -14,15 +14,17 @@ See [demo](https://static.datenhub.net/apps/boundaries/main/index.html) for code
### Tilesets
-| Name | Description | Source | License |
-| ------------------ | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
-| `admin_boundaries` | Staat, Länder, Kreise, Gemeinden 1:250,000 | [BKG VG250](https://gdz.bkg.bund.de/index.php/default/digitale-geodaten/verwaltungsgebiete/verwaltungsgebiete-1-250-000-stand-01-01-vg250-01-01.html) | [DNN 2.0](https://sgx.geodatenzentrum.de/web_public/gdz/lizenz/deu/nutzungsbedingungen_vg250.pdf) |
-| `admin_labels` | Label points for all features in `admin_boundaries` | [BKG VG250](https://gdz.bkg.bund.de/index.php/default/digitale-geodaten/verwaltungsgebiete/verwaltungsgebiete-1-250-000-stand-01-01-vg250-01-01.html) | [DNN 2.0](https://sgx.geodatenzentrum.de/web_public/gdz/lizenz/deu/nutzungsbedingungen_vg250.pdf) |
+| Name | Description | Sources | License |
+| ------------------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `admin_boundaries` | Staat, Länder, Kreise, Gemeinden 1:250,000 | [BKG VG250](https://gdz.bkg.bund.de/index.php/default/digitale-geodaten/verwaltungsgebiete/verwaltungsgebiete-1-250-000-stand-01-01-vg250-01-01.html), [Natural Earth 10m Cultural Vectors](https://www.naturalearthdata.com/downloads/10m-cultural-vectors/) | [DNN 2.0](https://sgx.geodatenzentrum.de/web_public/gdz/lizenz/deu/nutzungsbedingungen_vg250.pdf), [Public Domain](https://www.naturalearthdata.com/about/terms-of-use/) |
+| `admin_labels` | Label points for all features in `admin_boundaries` | [BKG VG250](https://gdz.bkg.bund.de/index.php/default/digitale-geodaten/verwaltungsgebiete/verwaltungsgebiete-1-250-000-stand-01-01-vg250-01-01.html) | [DNN 2.0](https://sgx.geodatenzentrum.de/web_public/gdz/lizenz/deu/nutzungsbedingungen_vg250.pdf) |
### Timestamps
+
`2024-01-01`, `2025-01-01`
+
### Fields
diff --git a/demo/package.json b/demo/package.json
index bd4669d..b711358 100644
--- a/demo/package.json
+++ b/demo/package.json
@@ -9,9 +9,9 @@
"sync": "svelte-kit sync"
},
"devDependencies": {
- "@sveltejs/kit": "^2.61.1",
"@sveltejs/adapter-auto": "^7.0.1",
"@sveltejs/adapter-static": "^3.0.10",
+ "@sveltejs/kit": "^2.61.1",
"@sveltejs/vite-plugin-svelte": "^7.1.2",
"dotenv": "^17.4.2",
"prettier": "^3.8.3",
diff --git a/demo/src/lib/App.svelte b/demo/src/lib/App.svelte
index 3d3c122..4d6dd87 100644
--- a/demo/src/lib/App.svelte
+++ b/demo/src/lib/App.svelte
@@ -1,7 +1,16 @@
-
+
{:else}
-
+
{/if}
{/each}
@@ -125,7 +157,12 @@
type="line"
filter={["==", "admin_level", filter]}
paint={{
- "line-width": ["case", ["any", ["boolean", ["feature-state", "hovered"], false]], 1.75, 0],
+ "line-width": [
+ "case",
+ ["any", ["boolean", ["feature-state", "hovered"], false]],
+ 1.75,
+ 0,
+ ],
"line-color": "black",
"line-opacity": 1,
}}
@@ -155,7 +192,12 @@
{/if}
{#if hovered}
-
+
{#each Object.entries(hovered.properties) as [k, v]}
diff --git a/tasks/make_boundaries/Dockerfile b/tasks/make_boundaries/Dockerfile
index 6a2379d..178749b 100644
--- a/tasks/make_boundaries/Dockerfile
+++ b/tasks/make_boundaries/Dockerfile
@@ -41,4 +41,4 @@ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-dev --no-editable
-CMD [".venv/bin/python", "src/main.py"]
+CMD [".venv/bin/python", "src/main.py", "--mode=production", "--min_year=2024"]
diff --git a/tasks/make_boundaries/exploration/country_snapping.ipynb b/tasks/make_boundaries/exploration/country_snapping.ipynb
new file mode 100644
index 0000000..201aa6c
--- /dev/null
+++ b/tasks/make_boundaries/exploration/country_snapping.ipynb
@@ -0,0 +1,143 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "d83ab3d6",
+ "metadata": {},
+ "source": [
+ "# `boundaries`: Country snapping\n",
+ "\n",
+ "This notebook is for exploring how we're going to snap country boundaries from Natural Earth to our BKG data\n",
+ "\n",
+ "max.koehler@swr.de"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "e20f696c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import geopandas as gp\n",
+ "import shapely as shp\n",
+ "from matplotlib import pyplot as plt\n",
+ "from tqdm import tqdm\n",
+ "tqdm.pandas()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "612b0753",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = {}\n",
+ "data[\"ne\"] = gp.read_file(\"zip://../tmp/raw/ne_50m_admin_0_countries.zip/ne_50m_admin_0_countries.shp\")\n",
+ "for k in [\"STA\"]:\n",
+ " data[k] = gp.read_file(f\"zip://../tmp/raw/2025-01-01_vg250_01-01.utm32s.shape.ebenen.zip!vg250_01-01.utm32s.shape.ebenen/vg250_ebenen_0101/VG250_{k}.shp\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "489cbac7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "EPSG:25832\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 241/241 [00:00<00:00, 3224.12it/s]\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "EPSG:3857\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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QLdU1vm0cYu5KUgLNQf0kt/rUrjZpdoUWXdryYYynTQ+T3MOHKLmUFTLy+u0vqJRlx9mTss39riabl1d6yZDexv254iBgZs3b2bVQAAAuslcbM8cIOjoEGAuV1xaWqrs7OyEmBdqpi9zKWOzcvc06hLUGe+z+OJvkzrjfdbKPLSbrQGDBg2S2+12dneA+QPsKcnYxQwAhADqjPdZ4uFvkzrjfSZrav3epMYQSwAAsBtCAAAAKYoQ0APm5ka//OUv2eSIOutTvM+os3jgfZbadeaIgYEAACD2aAkAACBFEQIAAEhRhAAAAFIUIQAAgBRFCOjEnXfeqREjRigtLU0HHnigPvzwwz1WZHV1tebOnavi4mJrxOi4ceP04osvKpV0p86OOOIIa/XHr15OPPFEpZLuvs/mzZun8ePHKz093Vq18qqrrlJzc4ospN6DOguFQrrppps0evRo6/5TpkzRyy+/rFSycOFCnXTSSdbKcebf2NNPP73XxyxYsEDTp0+3PsvGjBmjBx98UKlkYTfrbMuWLTr77LOtz31zcbsf/ehHcgxzdgDae+yxxwy/32/87W9/M5YsWWJceOGFRl5enlFeXt5hVQWDQWPGjBnGCSecYLz99tvGunXrjAULFhifffZZylRtd+usoqLC2LJlS9tl8eLFhsfjMR544AEjVXS3zh5++GEjEAhYX8332CuvvGIUFxcbV111lZEqultn1157rTFo0CDjhRdeMNasWWPcddddRlpamvHJJ58YqeLFF180brjhBuOpp54yZ4IZ8+fP3+P9165da2RkZBg//vGPjaVLlxp/+tOfrL/Nl19+2UgVL3azzsy/xyuuuMJ46KGHjKlTpxpXXnml4RSEgA4ccMABxty5c9uuRyIR64Pk1ltv7bAS7777bmPUqFFGS0uLkaq6W2df9fvf/97Izs426uvrjVTR3Toz73vUUUe1u838oJ41a5aRKrpbZ2ZI+vOf/9zuttNOO80455xzjFTUlQOaGZz23XffdredeeaZxvHHH2+kInWhznZ1+OGHOyoE0B3wFS0tLfr44491zDHHtN1mNu+Y1997770OW1OeffZZHXzwwVZ3wIABAzRp0iTdcsstikQiSgU9qbOvuv/++3XWWWcpMzNTqaAndXbIIYdYj9nZ/L127Vqry+mEE05QKuhJnQWDQasbYFdmV8rbb7/d5+V1KrMud61j0/HHH9/lv2U4iyM2EIqn7du3Wwdv82C+K/P68uXLO3yM+WH8xhtv6JxzzrE+lFevXq3LLrvM6o80V5VKdj2ps12ZB7XFixdbQSBV9KTOzD5H83GHHnqotUNYOBzWJZdcouuvv16poCd1Zh687rjjDh122GHWuIDXX39dTz31VMoE9J4oKyvrsI7NHRqbmpqsEIXkQUtAjLY67t+/v+69917tv//+OvPMM3XDDTfonnvuicXTJz3z4D958mQdcMABdhcloZmDtcwWprvuukuffPKJdTB74YUX9Otf/9ruoiWsP/zhDxo7dqz22Wcf+f1+XX755fr+97+/x61VgVRCS8BX9OvXTx6PR+Xl5e1uN68PHDiww0o0ZwT4fD7rcTtNmDDBStRmE6b54ZPMelJnOzU0NOixxx6zRnCnkp7U2f/8z//ou9/9ri644ALruhmczPq76KKLrNCZ7Ae2ntRZUVGRNbLbnEFRUVFhjfb+2c9+plGjRsWp1M5j1mVHdWxuz0wrQPJJ7k+NHjAP2ObZvNlsuOuZvnnd7PfvyKxZs6wuAPN+O61cudIKB8keAHpaZzv961//svpt58yZo1TSkzprbGzc7UC/M3imwhYgvXmfmeMCBg8ebHWhPPnkkzrllFPiUGJnMuty1zo2vfbaa3utYziU3SMTE3UakjkV68EHH7SmyFx00UXWNKSysjLr+9/97neNn/3sZ23337hxozWy/fLLLzdWrFhhPP/880b//v2Nm2++2UgV3a2znQ499FBr5HEq6m6d/fKXv7TeZ48++qg1jevVV181Ro8ebcyePdtIFd2ts/fff9948sknremBCxcutGZXjBw50qiqqjJSRV1dnfHpp59aF/Mj/4477rD+vWHDBuv7Zn2Z9fbVKYLXXHONsWzZMuPOO+9MuSmCdd2sM9PO+++///7G2Wefbf3bnMaa6AgBnTDnxg4bNsyak2xOSzI/THadAnLeeee1u/+7775rHHjggdYHlDld8De/+Y0RDoeNVNLdOlu+fLn1B2YezFJVd+osFAoZv/rVr6wDvznXfejQocZll12WUge07taZuV7HhAkTrL/LwsJC64O7pKTESCX/+c9/rL+zr1521pP51ay3rz7GnO9u1rH5eZZK63f0tM46uv/w4cONRMdWwgAApCjGBAAAkKIIAQAApChCAAAAKYoQAABAiiIEAACQoggBAACkKEIAAAApihAAAECcLVy4UCeddJK1n4XL5bL2uOguc42i3/3udxo3bpwCgYC1NPZvfvObbj0HGwgBABBn5uZfU6ZM0fnnn6/TTjutR89x5ZVX6tVXX7WCgLmhWGVlpXXpDlYMBADARmZLwPz583Xqqae23WZurGbuDvroo4+qurpakyZN0m233aYjjjjC+v6yZcu03377afHixRo/fnyPX5vuAAAAEszll1+u9957z9pq/YsvvtAZZ5yhr3/961q1apX1/eeee87aEvv555/XyJEjNWLECGub8e62BBACAABIIBs3btQDDzxgbbX+ta99TaNHj9ZPfvITHXroodbtprVr12rDhg3Wff7+97/rwQcf1Mcff6zTTz+9W6/FmAAAABLIokWLFIlErAF/uzK7CAoLC61/R6NR67oZAHbe7/7779f++++vFStWdLmLgBAAAEACqa+vl8fjsc7sza+7ysrKsr4WFxfL6/W2CwoTJkxoa0kgBAAA4EDTpk2zWgK2bt1qdQd0ZNasWQqHw1qzZo3VXWBauXKl9XX48OFdfi1mBwAAYMPZ/urVq9sO+nfccYeOPPJIFRQUaNiwYZozZ47eeecd3X777db3t23bptdff92aEXDiiSda3QEzZ860WgbmzZtnXZ87d65ycnKsaYNdRQgAACDOFixYYB30v+q8886zBvmFQiHdfPPNVp9/SUmJ+vXrp4MOOkg33nijtSaAqbS0VD/84Q+tg35mZqa+8Y1vWKHBDBJdRQgAACBFMUUQAIAURQgAACBFEQIAAEhRhAAAAFIUIQAAgBRFCAAAIEURAgAASFGEAAAAUhQhAACAFEUIAAAgRRECAABIUYQAAACUmv4/Lc00nGnp/IwAAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "print(data[\"STA\"].crs)\n",
+ "germany = (\n",
+ " data[\"STA\"].loc[data[\"STA\"][\"OBJID\"] == \"DEBKGVG200000CKM\"].to_crs(\"EPSG:3857\")\n",
+ ")\n",
+ "ne_countries = data[\"ne\"].loc[data[\"ne\"][\"ADMIN\"] != \"Germany\"].to_crs(\"EPSG:3857\")\n",
+ "ne_countries[\"name\"] = ne_countries[\"NAME_DE\"]\n",
+ "ne_countries[\"admin_level\"] = 2\n",
+ "ne_countries[\"kind\"] = \"Staat\"\n",
+ "\n",
+ "neighbours = (\n",
+ " \"Austria\",\n",
+ " \"Belgium\",\n",
+ " \"Czech Republic\",\n",
+ " \"Denmark\",\n",
+ " \"France\",\n",
+ " \"Luxembourg\",\n",
+ " \"Netherlands\",\n",
+ " \"Poland\",\n",
+ " \"Switzerland\",\n",
+ ")\n",
+ "\n",
+ "ne_countries[\"geometry\"] = ne_countries.progress_apply(\n",
+ " lambda x: (\n",
+ " x[\"geometry\"].buffer(5_000).difference(germany[\"geometry\"][0])\n",
+ " if x[\"ADMIN\"] in neighbours\n",
+ " else x[\"geometry\"]\n",
+ " ),\n",
+ " axis=1,\n",
+ ")\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(8, 10))\n",
+ "bounds = germany.bounds.to_dict()\n",
+ "ax.set_xlim(bounds[\"minx\"][0] - 1e5, bounds[\"minx\"][0] + 5e5)\n",
+ "ax.set_ylim(bounds[\"miny\"][0], bounds[\"miny\"][0] + 1e6)\n",
+ "\n",
+ "germany.plot(ax=ax)\n",
+ "ne_countries.plot(ax=ax, cmap=\"Pastel1\")\n",
+ "print(ne_countries.crs)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "fetch-geometry",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tasks/make_boundaries/exploration/labels.ipynb b/tasks/make_boundaries/exploration/labels.ipynb
index 8bf9a70..5ea2775 100644
--- a/tasks/make_boundaries/exploration/labels.ipynb
+++ b/tasks/make_boundaries/exploration/labels.ipynb
@@ -5,16 +5,14 @@
"id": "d83ab3d6",
"metadata": {},
"source": [
- "# `boundaries`: Exploration\n",
- "\n",
- "This notebook is a place to work out processing steps before we move them into the production pipeline.\n",
+ "# `boundaries`: Label points exploration\n",
"\n",
"max.koehler@swr.de"
]
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"id": "e20f696c",
"metadata": {},
"outputs": [],
@@ -26,7 +24,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"id": "612b0753",
"metadata": {},
"outputs": [],
@@ -35,7 +33,7 @@
"for k in [\"STA\", \"LAN\", \"KRS\"]:\n",
" data[k] = gp.read_file(f\"zip://../tmp/raw/2025-01-01_vg250_01-01.utm32s.shape.ebenen.zip!vg250_01-01.utm32s.shape.ebenen/vg250_ebenen_0101/VG250_{k}.shp\")\n",
"\n",
- "data[\"subs\"] = gp.read_file(\"../label_substitutions.geojson\")\n"
+ "data[\"subs\"] = gp.read_file(\"../label_substitutions.geojson\")"
]
},
{
@@ -182,7 +180,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.10"
+ "version": "3.12.2"
}
},
"nbformat": 4,
diff --git a/tasks/make_boundaries/pyproject.toml b/tasks/make_boundaries/pyproject.toml
index 302df5e..ec66a9d 100644
--- a/tasks/make_boundaries/pyproject.toml
+++ b/tasks/make_boundaries/pyproject.toml
@@ -1,5 +1,5 @@
[project]
-name = "fetch-geometry"
+name = "make_boundaries"
version = "0.1.0"
description = ""
readme = "README.md"
@@ -9,8 +9,11 @@ dependencies = [
"dotenv>=0.9.9",
"geopandas>=1.1.2",
"google-cloud-storage>=3.9.0",
+ "ipykernel>=7.3.0",
"matplotlib>=3.10.9",
"pandas>=3.0.3",
"requests>=2.34.2",
"shapely>=2.1.2",
+ "tqdm>=4.68.2",
+ "typed-argument-parser>=1.12.0",
]
diff --git a/tasks/make_boundaries/src/globals.py b/tasks/make_boundaries/src/globals.py
index f7bd880..0dbe3c7 100644
--- a/tasks/make_boundaries/src/globals.py
+++ b/tasks/make_boundaries/src/globals.py
@@ -5,3 +5,15 @@
"Dillingen a.d.Donau": "Dillingen an der Donau",
"Mühldorf a.Inn": "Mühldorf am Inn",
}
+
+NEIGHBOURS = (
+ "Austria",
+ "Belgium",
+ "Czechia",
+ "Denmark",
+ "France",
+ "Luxembourg",
+ "Netherlands",
+ "Poland",
+ "Switzerland",
+)
diff --git a/tasks/make_boundaries/src/main.py b/tasks/make_boundaries/src/main.py
index 90c4b87..2e2c415 100644
--- a/tasks/make_boundaries/src/main.py
+++ b/tasks/make_boundaries/src/main.py
@@ -1,9 +1,10 @@
import datetime
import os
-from typing import Dict
+from typing import Dict, Literal
from dotenv import load_dotenv
from google.cloud import storage
+from tap import Tap
from entities.Tileset import Tileset
from usecases.fetch_bkg_years import fetch_bkg_years
@@ -12,35 +13,51 @@
from usecases.make_admin_labels import make_admin_labels
from usecases.upload_blob import upload_blob
-gcs_project = "swr-data-1"
-gcs_bucket = "datenhub-net-static"
-gcs_path = "data/boundaries/"
-min_year = 2024
-raw_dir = "./tmp/raw/"
-processed_dir = "./tmp/processed/"
-manifest_path = os.path.join(processed_dir, "manifest.csv")
+class ArgParser(Tap):
+ mode: Literal["production", "dev"] = "dev"
+ """dev mode disables reading/writing to GCS and some data fetches"""
+ min_year: int = 2024
+ gcs_project: str = "swr-data-1"
+ gcs_bucket: str = "datenhub-net-static"
+ gcs_path: str = "data/boundaries/"
+ raw_dir: str = "./tmp/raw/"
+ processed_dir: str = "./tmp/processed/"
-tilesets: Dict[str, Tileset] = {}
+def main(args: ArgParser):
+ tilesets: Dict[str, Tileset] = {}
-
-def run():
load_dotenv()
+ os.makedirs(os.path.dirname(args.raw_dir), exist_ok=True)
+ os.makedirs(os.path.dirname(args.processed_dir), exist_ok=True)
+ manifest_path = os.path.join(args.processed_dir, "manifest.csv")
+
+ print(f"running in {args.mode} mode")
- os.makedirs(os.path.dirname(raw_dir), exist_ok=True)
- os.makedirs(os.path.dirname(processed_dir), exist_ok=True)
+ if args.mode == "production":
+ print(f"{args.get_reproducibility_info()}")
- storage_client = storage.Client(project=gcs_project)
+ if args.mode == "production":
+ storage_client = storage.Client(project=args.gcs_project)
- print("Fetching BKG files... ", end="")
- available_years = fetch_bkg_years()
- # available_years = [2025]
+ # Fetch available years on the BKG wesite
+ if args.mode == "production":
+ print("fetching available bkg files... ", end="")
+ available_years = fetch_bkg_years()
+ else:
+ print("skipping fetching bkg files in dev mode... ", end="")
+ available_years = [2025]
print(f"found {len(available_years)}\n")
- print("Fetching existing files... ", end="")
- existing_files = fetch_existing(storage_client, gcs_bucket, gcs_path)
- # existing_files = []
+ # Fetch existing tilesets
+ if args.mode == "production":
+ print("fetching existing files... ", end="")
+ existing_files = fetch_existing(storage_client, args.gcs_bucket, args.gcs_path)
+ else:
+ print("skipping fetching existing files in dev mode... ", end="")
+ existing_files = []
+
if len(existing_files) > 0:
print(f"found {len(existing_files)}:\n- {'\n- '.join(existing_files)}")
else:
@@ -49,25 +66,25 @@ def run():
new_files: list[str] = []
failed_files: list[str] = []
- for y in [y for y in available_years if y >= min_year]:
+ for y in [y for y in available_years if y >= args.min_year]:
date = datetime.date(y, 1, 1)
tilesets[f"admin_boundaries_{date.strftime('%Y-%m-%d')}"] = Tileset(
name=f"Administrative Boundaries {y}",
make_fn=make_admin,
make_args={
- "cache_dir": raw_dir,
- "output_dir": processed_dir,
+ "cache_dir": args.raw_dir,
+ "output_dir": args.processed_dir,
"date": date,
},
)
-
+ continue
tilesets[f"admin_labels_{date.strftime('%Y-%m-%d')}"] = Tileset(
name=f"Administrative Labels {date}",
make_fn=make_admin_labels,
make_args={
- "cache_dir": raw_dir,
- "output_dir": processed_dir,
+ "cache_dir": args.raw_dir,
+ "output_dir": args.processed_dir,
"date": date,
},
)
@@ -96,12 +113,20 @@ def run():
f.write(f"name\n{'\n'.join([*existing_files, *new_files])}")
print(f"Wrote manifest to {manifest_path}")
- for f in [*new_files, manifest_path]:
- upload_blob(
- storage_client, f, gcs_bucket, os.path.join(gcs_path, os.path.basename(f))
+ if args.mode == "production":
+ for f in [*new_files, manifest_path]:
+ upload_blob(
+ storage_client,
+ f,
+ args.gcs_bucket,
+ os.path.join(args.gcs_path, os.path.basename(f)),
+ )
+ print(f"Uploaded {len(new_files)} new files ({len(failed_files)} failed)")
+ else:
+ print(
+ f"skipping updloading {len(new_files)} new files in dev mode ({len(failed_files)} failed)"
)
- print(f"Uploaded {len(new_files)} new files, {len(failed_files)} failed")
-
-run()
+args = ArgParser().parse_args()
+main(args)
diff --git a/tasks/make_boundaries/src/usecases/fetch_bkg_years.py b/tasks/make_boundaries/src/usecases/fetch_bkg_years.py
index b6f4821..08e7b8b 100644
--- a/tasks/make_boundaries/src/usecases/fetch_bkg_years.py
+++ b/tasks/make_boundaries/src/usecases/fetch_bkg_years.py
@@ -5,9 +5,8 @@
from globals import BKG_URL
-# Fetches a list of available years from the BKG website
-
+# Fetches a list of available years from the BKG website
def fetch_bkg_years() -> list[int]:
# verify=False if the government issued itself a broken SSL cert again
diff --git a/tasks/make_boundaries/src/usecases/make_admin.py b/tasks/make_boundaries/src/usecases/make_admin.py
index 6dbb777..a72d979 100644
--- a/tasks/make_boundaries/src/usecases/make_admin.py
+++ b/tasks/make_boundaries/src/usecases/make_admin.py
@@ -4,7 +4,7 @@
import geopandas as gp
import pandas as pd
-from globals import BKG_URL, NAME_SUBS
+from globals import BKG_URL, NAME_SUBS, NEIGHBOURS
from usecases.fetch_unless_cached import fetch_unless_cached
from usecases.make_versatiles import make_versatiles
@@ -14,7 +14,7 @@
# See: https://wiki.openstreetmap.org/wiki/File:Administrative_Gliederung_Deutschlands_admin_level.png
def make_admin(cache_dir: str, output_dir: str, date: date) -> list[str]:
- # 1. Fetch the BKG data we need
+ # 1. Fetch the BKG/Natural Earth data we need
ds = date.strftime("%Y-%m-%d")
json_path = os.path.join(cache_dir, f"admin_boundaries_{ds}.geojson")
versatiles_path = os.path.join(output_dir, f"admin_boundaries_{ds}.versatiles")
@@ -22,24 +22,54 @@ def make_admin(cache_dir: str, output_dir: str, date: date) -> list[str]:
fp = "vg250_01-01.utm32s.shape.ebenen/vg250_ebenen_0101"
- zip_name = "vg250_01-01.utm32s.shape.ebenen.zip"
- cache_path = f"{cache_dir}/{ds}_{zip_name}"
+ bkg_zip_name = "vg250_01-01.utm32s.shape.ebenen.zip"
+ bkg_cache_path = f"{cache_dir}/{ds}_{bkg_zip_name}"
+ ne_cache_path = f"{cache_dir}/ne_10m_admin_0_countries.zip"
- fetch_unless_cached(f"{BKG_URL}/{date.year}/{zip_name}", cache_path)
+ fetch_unless_cached(f"{BKG_URL}/{date.year}/{bkg_zip_name}", bkg_cache_path)
+ fetch_unless_cached(
+ "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_admin_0_countries.zip",
+ ne_cache_path,
+ )
# 2. Extract + wrangle shapes
# 2.1 Admin 2
print("Staat... ", end="")
- country = gp.read_file(f"zip://{cache_path}!{fp}/VG250_STA.shp")
- country["admin_level"] = 2
- country["kind"] = "Staat"
- country_processed = country.loc[country["OBJID"] == "DEBKGVG200000CKM"]
- assert country_processed.shape[0] == 1
- print(f"done ({country_processed.shape[0]} geom)")
+
+ germany = gp.read_file(f"zip://{bkg_cache_path}!{fp}/VG250_STA.shp")
+ germany["admin_level"] = 2
+ germany["kind"] = "Staat"
+ germany_processed = germany.loc[germany["OBJID"] == "DEBKGVG200000CKM"].to_crs(
+ "EPSG:3857"
+ )
+ assert germany_processed.shape[0] == 1
+
+ ne_countries_raw = gp.read_file(
+ f"zip://{ne_cache_path}!/ne_10m_admin_0_countries.shp"
+ )
+ ne_countries = ne_countries_raw.loc[ne_countries_raw["ADMIN"] != "Germany"].to_crs(
+ "EPSG:3857"
+ )
+
+ ne_countries["GEN"] = ne_countries["ADMIN"]
+ ne_countries["admin_level"] = 2
+ ne_countries["kind"] = "Staat"
+ ne_countries["geometry"] = ne_countries.apply(
+ lambda x: (
+ x["geometry"].buffer(10_000).difference(germany_processed["geometry"][0])
+ if x["ADMIN"] in NEIGHBOURS
+ else x["geometry"]
+ ),
+ axis=1,
+ )
+ countries = pd.concat(
+ [germany_processed.to_crs("EPSG:25832"), ne_countries.to_crs("EPSG:25832")]
+ )
+ print(f"done ({countries.shape[0]} geoms)")
# 2.2 Admin 4
print("Land... ", end="")
- laender = gp.read_file(f"zip://{cache_path}!{fp}/VG250_LAN.shp")
+ laender = gp.read_file(f"zip://{bkg_cache_path}!{fp}/VG250_LAN.shp")
laender["admin_level"] = 4
laender["kind"] = "Land"
laender["land"] = laender["SN_L"]
@@ -49,7 +79,7 @@ def make_admin(cache_dir: str, output_dir: str, date: date) -> list[str]:
# 2.3 Admin 6
print("Kreis... ", end="")
- kreise = gp.read_file(f"zip://{cache_path}!{fp}/VG250_KRS.shp")
+ kreise = gp.read_file(f"zip://{bkg_cache_path}!{fp}/VG250_KRS.shp")
kreise["admin_level"] = 6
kreise["kind"] = "Kreis"
kreise["land"] = kreise["SN_L"]
@@ -58,7 +88,7 @@ def make_admin(cache_dir: str, output_dir: str, date: date) -> list[str]:
# 2.4 Admin 8
print("Gemeinde... ", end="")
- gemeinden = gp.read_file(f"zip://{cache_path}!{fp}/VG250_GEM.shp")
+ gemeinden = gp.read_file(f"zip://{bkg_cache_path}!{fp}/VG250_GEM.shp")
gemeinden["admin_level"] = 8
gemeinden["kind"] = "Gemeinde"
gemeinden["land"] = gemeinden["SN_L"]
@@ -68,7 +98,7 @@ def make_admin(cache_dir: str, output_dir: str, date: date) -> list[str]:
res = gp.GeoDataFrame(
pd.concat(
[
- country_processed,
+ countries,
laender_processed,
kreise_processed,
gemeinden_processed,
diff --git a/tasks/make_boundaries/uv.lock b/tasks/make_boundaries/uv.lock
index cbbf7ed..22b6714 100644
--- a/tasks/make_boundaries/uv.lock
+++ b/tasks/make_boundaries/uv.lock
@@ -13,6 +13,24 @@ resolution-markers = [
"python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'",
]
+[[package]]
+name = "appnope"
+version = "0.1.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" },
+]
+
+[[package]]
+name = "asttokens"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" },
+]
+
[[package]]
name = "beautifulsoup4"
version = "4.14.3"
@@ -149,6 +167,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
]
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "comm"
+version = "0.2.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" },
+]
+
[[package]]
name = "contourpy"
version = "1.3.3"
@@ -277,6 +313,45 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
]
+[[package]]
+name = "debugpy"
+version = "1.8.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f2/aa/12037145b7a56eaa5b29b41872f7a21b538e807e13f32c4d3c46e59be084/debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6", size = 1697577, upload-time = "2026-06-01T19:30:35.156Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a2/df/bf625547431a9cadc9f4cbfeda38866e2b17f6aed147b625377e87834449/debugpy-1.8.21-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e", size = 2483609, upload-time = "2026-06-01T19:30:50.794Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/09/59324b903599031ff9faaec1758292409f6561a0ec2492fe4b703327705a/debugpy-1.8.21-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176", size = 3968900, upload-time = "2026-06-01T19:30:52.341Z" },
+ { url = "https://files.pythonhosted.org/packages/14/cd/27f65b805d7fe005c44e1a36b9183ecdfbcdbf9d3e721a5115d461ecc7ee/debugpy-1.8.21-cp312-cp312-win32.whl", hash = "sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9", size = 5336340, upload-time = "2026-06-01T19:30:54.047Z" },
+ { url = "https://files.pythonhosted.org/packages/77/1d/c84e30c0c674184948b66f076ab271c01d940618a2824c23cd035a27bc20/debugpy-1.8.21-cp312-cp312-win_amd64.whl", hash = "sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c", size = 5374751, upload-time = "2026-06-01T19:30:55.891Z" },
+ { url = "https://files.pythonhosted.org/packages/77/6b/d817e1f8cc77aa055d37fba092e0febfdff40fe652d8d53d4cd7a86ad98d/debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88", size = 2477398, upload-time = "2026-06-01T19:30:57.644Z" },
+ { url = "https://files.pythonhosted.org/packages/48/57/412421516afc3055fa577516f00beec3d663f9b0ab330639547ae6c57720/debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2", size = 3962096, upload-time = "2026-06-01T19:30:59.235Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/62/2c616337cf6ba7b07ebbc97f02c6c945a8e2f76b365e33ee809c32ee36d1/debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1", size = 5336288, upload-time = "2026-06-01T19:31:00.79Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/99/9175103392f84c4b1bf7622888cdc68da07f0ff7d9e581266428f6776033/debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0", size = 5376567, upload-time = "2026-06-01T19:31:02.56Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/3d/f4bbb323a548bfab2af3d6b4ffd9bf22636e55956a1285d317a1de643aad/debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782", size = 2477209, upload-time = "2026-06-01T19:31:04.157Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/2d/6e7ec524984a1702777868de49a4c53202bddac2a432a76a093469587750/debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e", size = 3927115, upload-time = "2026-06-01T19:31:05.863Z" },
+ { url = "https://files.pythonhosted.org/packages/97/47/d1aa6d64005a98a9144647d99306b419396f9ad7bf1d73c119e17a81fb4d/debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c", size = 5336724, upload-time = "2026-06-01T19:31:07.711Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/67/b905b90d163af11878c1af8abafa4a25206335e112e284e413454543a6da/debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8", size = 5373803, upload-time = "2026-06-01T19:31:09.469Z" },
+ { url = "https://files.pythonhosted.org/packages/95/51/67e7cf11a53e40694f720457d5b3a1cdaaa3d5a9a633e482f225456b93ff/debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92", size = 5352888, upload-time = "2026-06-01T19:31:25.186Z" },
+]
+
+[[package]]
+name = "decorator"
+version = "5.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" },
+]
+
+[[package]]
+name = "docstring-parser"
+version = "0.18.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" },
+]
+
[[package]]
name = "dotenv"
version = "0.9.9"
@@ -289,30 +364,12 @@ wheels = [
]
[[package]]
-name = "fetch-geometry"
-version = "0.1.0"
-source = { virtual = "." }
-dependencies = [
- { name = "beautifulsoup4" },
- { name = "dotenv" },
- { name = "geopandas" },
- { name = "google-cloud-storage" },
- { name = "matplotlib" },
- { name = "pandas" },
- { name = "requests" },
- { name = "shapely" },
-]
-
-[package.metadata]
-requires-dist = [
- { name = "beautifulsoup4", specifier = ">=4.14.3" },
- { name = "dotenv", specifier = ">=0.9.9" },
- { name = "geopandas", specifier = ">=1.1.2" },
- { name = "google-cloud-storage", specifier = ">=3.9.0" },
- { name = "matplotlib", specifier = ">=3.10.9" },
- { name = "pandas", specifier = ">=3.0.3" },
- { name = "requests", specifier = ">=2.34.2" },
- { name = "shapely", specifier = ">=2.1.2" },
+name = "executing"
+version = "2.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" },
]
[[package]]
@@ -489,6 +546,106 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" },
]
+[[package]]
+name = "ipykernel"
+version = "7.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "appnope", marker = "sys_platform == 'darwin'" },
+ { name = "comm" },
+ { name = "debugpy" },
+ { name = "ipython" },
+ { name = "jupyter-client" },
+ { name = "jupyter-core" },
+ { name = "matplotlib-inline" },
+ { name = "nest-asyncio2" },
+ { name = "packaging" },
+ { name = "psutil" },
+ { name = "pyzmq" },
+ { name = "tornado" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3d/c4/e4a38f579de4225a561305666f7541cdabb30075def2aa1ac17bd73c1fb5/ipykernel-7.3.0.tar.gz", hash = "sha256:9acaaaf97d16355166e4085afe9d225bfbdf2b7ef520f9df3be8f2b248275e09", size = 184899, upload-time = "2026-06-10T08:41:25.481Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3d/02/77b271f5dc58bfbc0b577c877b2365d1ffea2afe66a80c13f2312820348c/ipykernel-7.3.0-py3-none-any.whl", hash = "sha256:897eb64da762549ef610698fca5e9675195ec6ac8ec7f19d81ce1ca20c876057", size = 120583, upload-time = "2026-06-10T08:41:23.648Z" },
+]
+
+[[package]]
+name = "ipython"
+version = "9.14.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "decorator" },
+ { name = "ipython-pygments-lexers" },
+ { name = "jedi" },
+ { name = "matplotlib-inline" },
+ { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
+ { name = "prompt-toolkit" },
+ { name = "psutil", marker = "sys_platform != 'emscripten'" },
+ { name = "pygments" },
+ { name = "stack-data" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e2/23/3a27530575643c8bb7bfc757a28e2e7ef80092afbf59a2bc5716320b6602/ipython-9.14.1.tar.gz", hash = "sha256:f913bf74df06d458e46ced84ca506c23797590d594b236fe60b14df213291e7b", size = 4433457, upload-time = "2026-06-05T08:12:34.921Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/22/58818a63eaf8982b67632b1bc20585c811611b15a8da19d6012323dc76a5/ipython-9.14.1-py3-none-any.whl", hash = "sha256:5d4a9ecaa3b10e6e5f269dd0948bdb58ca9cb851899cd23e07c320d3eb11613c", size = 627770, upload-time = "2026-06-05T08:12:33.045Z" },
+]
+
+[[package]]
+name = "ipython-pygments-lexers"
+version = "1.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
+]
+
+[[package]]
+name = "jedi"
+version = "0.20.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "parso" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" },
+]
+
+[[package]]
+name = "jupyter-client"
+version = "8.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jupyter-core" },
+ { name = "python-dateutil" },
+ { name = "pyzmq" },
+ { name = "tornado" },
+ { name = "traitlets" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7d/dc/5512503b088997c2250b8bf18258fba9d9ce5ead641183700960d3c9d342/jupyter_client-8.9.1.tar.gz", hash = "sha256:a58f730dd9e728ba16ba1d62ebccf7ffe1ebbdbce4e95cfae941b7321ae1f4fa", size = 359256, upload-time = "2026-06-09T13:15:01.033Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3f/6f/56d39bf385c5c27988aebaf0c18a2a17e960575740100973511018bd904e/jupyter_client-8.9.1-py3-none-any.whl", hash = "sha256:0b7a295bc46e8751e9adae84781f726c851c1d911bd793edc4a3bde942e3da81", size = 109828, upload-time = "2026-06-09T13:14:58.835Z" },
+]
+
+[[package]]
+name = "jupyter-core"
+version = "5.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "platformdirs" },
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" },
+]
+
[[package]]
name = "kiwisolver"
version = "1.5.0"
@@ -575,6 +732,39 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/91/53255615acd2a1eaca307ede3c90eb550bae9c94581f8c00081b6b1c8f44/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57", size = 75987, upload-time = "2026-03-09T13:15:39.65Z" },
]
+[[package]]
+name = "make-boundaries"
+version = "0.1.0"
+source = { virtual = "." }
+dependencies = [
+ { name = "beautifulsoup4" },
+ { name = "dotenv" },
+ { name = "geopandas" },
+ { name = "google-cloud-storage" },
+ { name = "ipykernel" },
+ { name = "matplotlib" },
+ { name = "pandas" },
+ { name = "requests" },
+ { name = "shapely" },
+ { name = "tqdm" },
+ { name = "typed-argument-parser" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "beautifulsoup4", specifier = ">=4.14.3" },
+ { name = "dotenv", specifier = ">=0.9.9" },
+ { name = "geopandas", specifier = ">=1.1.2" },
+ { name = "google-cloud-storage", specifier = ">=3.9.0" },
+ { name = "ipykernel", specifier = ">=7.3.0" },
+ { name = "matplotlib", specifier = ">=3.10.9" },
+ { name = "pandas", specifier = ">=3.0.3" },
+ { name = "requests", specifier = ">=2.34.2" },
+ { name = "shapely", specifier = ">=2.1.2" },
+ { name = "tqdm", specifier = ">=4.68.2" },
+ { name = "typed-argument-parser", specifier = ">=1.12.0" },
+]
+
[[package]]
name = "matplotlib"
version = "3.10.9"
@@ -629,6 +819,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/78/23/92493c3e6e1b635ccfff146f7b99e674808787915420373ac399283764c2/matplotlib-3.10.9-cp314-cp314t-win_arm64.whl", hash = "sha256:a49f1eadc84ca85fd72fa4e89e70e61bf86452df6f971af04b12c60761a0772c", size = 8324785, upload-time = "2026-04-24T00:13:53.633Z" },
]
+[[package]]
+name = "matplotlib-inline"
+version = "0.2.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "traitlets" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" },
+]
+
+[[package]]
+name = "nest-asyncio2"
+version = "1.7.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b4/73/731debf26e27e0a0323d7bda270dc2f634b398e38f040a09da1f4351d0aa/nest_asyncio2-1.7.2.tar.gz", hash = "sha256:1921d70b92cc4612c374928d081552efb59b83d91b2b789d935c665fa01729a8", size = 14743, upload-time = "2026-02-13T00:34:04.386Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c5/3c/3179b85b0e1c3659f0369940200cd6d0fa900e6cefcc7ea0bc6dd0e29ffb/nest_asyncio2-1.7.2-py3-none-any.whl", hash = "sha256:f5dfa702f3f81f6a03857e9a19e2ba578c0946a4ad417b4c50a24d7ba641fe01", size = 7843, upload-time = "2026-02-13T00:34:02.691Z" },
+]
+
[[package]]
name = "numpy"
version = "2.4.2"
@@ -751,6 +962,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0f/54/68a0978d1ef8502b8492099beaa6e7a0c1b32e3b5d4f677f5810cb08711c/pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1", size = 9466464, upload-time = "2026-05-11T18:54:22.754Z" },
]
+[[package]]
+name = "parso"
+version = "0.8.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" },
+]
+
+[[package]]
+name = "pexpect"
+version = "4.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
+]
+
[[package]]
name = "pillow"
version = "12.2.0"
@@ -820,6 +1052,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" },
]
+[[package]]
+name = "platformdirs"
+version = "4.10.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" },
+]
+
+[[package]]
+name = "prompt-toolkit"
+version = "3.0.52"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "wcwidth" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
+]
+
[[package]]
name = "proto-plus"
version = "1.27.1"
@@ -847,6 +1100,52 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" },
]
+[[package]]
+name = "psutil"
+version = "7.2.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" },
+ { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" },
+ { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" },
+ { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" },
+ { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" },
+ { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" },
+ { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
+ { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
+]
+
+[[package]]
+name = "ptyprocess"
+version = "0.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" },
+]
+
+[[package]]
+name = "pure-eval"
+version = "0.2.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" },
+]
+
[[package]]
name = "pyasn1"
version = "0.6.3"
@@ -877,6 +1176,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
]
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
[[package]]
name = "pyogrio"
version = "0.12.1"
@@ -1006,6 +1314,49 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
]
+[[package]]
+name = "pyzmq"
+version = "27.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cffi", marker = "implementation_name == 'pypy'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" },
+ { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" },
+ { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" },
+ { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" },
+ { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" },
+ { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" },
+ { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" },
+ { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" },
+ { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" },
+ { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" },
+ { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" },
+]
+
[[package]]
name = "requests"
version = "2.34.2"
@@ -1102,6 +1453,70 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" },
]
+[[package]]
+name = "stack-data"
+version = "0.6.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "asttokens" },
+ { name = "executing" },
+ { name = "pure-eval" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" },
+]
+
+[[package]]
+name = "tornado"
+version = "6.5.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/64/24/95ec527ad67b76d59299e5465b3935d05e4294b7e0290a3924b7487df30b/tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2", size = 519252, upload-time = "2026-06-08T17:34:51.232Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/02/dc/c7043cab6fed8ae159fc1923ce829ada35c4dbd797d408a43858ffaf9639/tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163", size = 448543, upload-time = "2026-06-08T17:34:38.052Z" },
+ { url = "https://files.pythonhosted.org/packages/92/4f/090b1431e5a43df696feceffc268c5383cc079ecb5f08ce58f917109aafe/tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100", size = 446707, upload-time = "2026-06-08T17:34:39.594Z" },
+ { url = "https://files.pythonhosted.org/packages/37/d8/ef374952fd5da67d4463122c2b8e5a96536ec10b4b339254c6dcde81d01c/tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972", size = 449774, upload-time = "2026-06-08T17:34:41.204Z" },
+ { url = "https://files.pythonhosted.org/packages/35/37/d434c73f4c6e014b745b9b37085f34f40c022f007efff3d7fe65991899f3/tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b", size = 450745, upload-time = "2026-06-08T17:34:42.531Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/2b/56b9aff361d7f1ab728a805ec7d7ea835f8807afa9f5cc690ea0e630efb9/tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92", size = 450578, upload-time = "2026-06-08T17:34:43.787Z" },
+ { url = "https://files.pythonhosted.org/packages/02/30/a7444fb23aa76860a14198fab96ac79f1866b0a6e19e26c4381b0938e50f/tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5", size = 449985, upload-time = "2026-06-08T17:34:45.326Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/42/5f0e56c01e8d9d36f4e23f367b85ae6cae0c1ecddd5e6977d8388ad27488/tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4", size = 451047, upload-time = "2026-06-08T17:34:46.784Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/a4/b393076ffb21b469eec5b328a0534cf03a3b90bfc6b1f09507cdd075d938/tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4", size = 451485, upload-time = "2026-06-08T17:34:48.248Z" },
+ { url = "https://files.pythonhosted.org/packages/71/2e/7b1c769803121b809112cf9a00681c472eae1d80e32d7ec0e0bd61d0d0e1/tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796", size = 450506, upload-time = "2026-06-08T17:34:49.702Z" },
+]
+
+[[package]]
+name = "tqdm"
+version = "4.68.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/85/05/0d5260f1f1ca784f4a4a0def9cbe6affe587f5b4025328d446c3d67765f4/tqdm-4.68.2.tar.gz", hash = "sha256:89c230e8dbc67c7615c142487111222f878c77427ea09549960f62389e258add", size = 171923, upload-time = "2026-06-09T13:26:42.539Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/eb/75/1a0392bcc21c44dcdf87b3cf2d137e7829be2c083a1e38d44efca3d57a16/tqdm-4.68.2-py3-none-any.whl", hash = "sha256:d4240441fb5353290b87d6a85968c9decc131a99b8c7faa28269d829de669ede", size = 78578, upload-time = "2026-06-09T13:26:40.731Z" },
+]
+
+[[package]]
+name = "traitlets"
+version = "5.15.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/a9/a2584b8313b89f94869ddb3c4074617a691de1812a614d2d50e32ca5a7a6/traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722", size = 163344, upload-time = "2026-06-03T12:26:06.181Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/96/8d/1080ee4c231f361b6ce4470d556c8c435b67c7e0753aaa641497ee92f88b/traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92", size = 85858, upload-time = "2026-06-03T12:26:04.395Z" },
+]
+
+[[package]]
+name = "typed-argument-parser"
+version = "1.12.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "docstring-parser" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/20/d0/5240b74b8d76e20eadbd79fe7ce5daeb1bf86d70d923817563728ccf297a/typed_argument_parser-1.12.0.tar.gz", hash = "sha256:cf5f7cafac869fb9627c4c90394e321c895d58872d865ad2c62e65668d259fa0", size = 244627, upload-time = "2026-03-28T21:01:46.273Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/56/0c/0607f5ac258aa36621a18cec7e14b87b49c972348a6937ea19cfea81d7b7/typed_argument_parser-1.12.0-py3-none-any.whl", hash = "sha256:9cdf26c710b9cde2992ff0763288598628ac852d9a1accf5269837cd6e24a930", size = 32833, upload-time = "2026-03-28T21:01:44.999Z" },
+]
+
[[package]]
name = "typing-extensions"
version = "4.15.0"
@@ -1128,3 +1543,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
]
+
+[[package]]
+name = "wcwidth"
+version = "0.8.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/49/b4/51fe890511f0f242d07cb1ebe6a5b6db417262b9d2568b460347c57d95cc/wcwidth-0.8.1.tar.gz", hash = "sha256:faf5b4a5366a72dc49cad48cdf21f52bdf63bdda995178e483ba247ff79089b9", size = 1466072, upload-time = "2026-06-08T05:57:23.146Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bd/6e/95b0e537de1f4d4301f76f944642c6da50d1511cc7b3d64dc418a66c7509/wcwidth-0.8.1-py3-none-any.whl", hash = "sha256:f453740b1e4a4f3291faa37944c555d71056c4da08d59809b307ef4feba695c8", size = 323092, upload-time = "2026-06-08T05:57:21.413Z" },
+]
diff --git a/tasks/make_boundaries/versatiles.yaml b/tasks/make_boundaries/versatiles.yaml
index d52193f..ee9b852 100644
--- a/tasks/make_boundaries/versatiles.yaml
+++ b/tasks/make_boundaries/versatiles.yaml
@@ -1,19 +1,19 @@
server:
- ip: 127.0.0.1
- port: 8080
+ ip: 127.0.0.1
+ port: 8080
tiles:
- - name: admin_boundaries
- src: tmp/processed/admin_boundaries_2025-01-01.versatiles
- - name: admin_labels
- src: tmp/processed/admin_labels_2025-01-01.versatiles
+ - name: admin_boundaries
+ src: tmp/processed/admin_boundaries_2025-01-01.versatiles
+ - name: admin_labels
+ src: tmp/processed/admin_labels_2025-01-01.versatiles
cors:
- allowed_origins:
- - "*"
+ allowed_origins:
+ - "*"
extra_response_headers:
Cache-Control: "no-cache"
-static:
- - src: ./frontend-dev.tar.gz
+# static:
+# - src: ./frontend-dev.tar.gz