From 9f7e9dd17325fd8f96ed22594b05c9edffa92718 Mon Sep 17 00:00:00 2001 From: hacklab Date: Tue, 11 Aug 2026 18:44:41 +0200 Subject: [PATCH] =?UTF-8?q?Quitar=20el=20reparto=20por=20paquetes,=20que?= =?UTF-8?q?=20sobra=20al=20ir=20los=20pa=C3=ADses=20en=20el=20repositorio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Los zips por país y el descargador se hicieron para no meter 40 MB de visores en git. Como al final entran, esa vía no aporta nada y sí puede estorbar: descargar.py descomprimía encima de out// y habría pisado en silencio un visor versionado con la copia de una release vieja. Fuera src/empaquetar.py, src/descargar.py y sus objetivos del Makefile. Se queda 'make selector', que sí hace falta: cada visor congela la lista de países al construirse y al calcular uno nuevo hay que rehacer el de los demás. --- .gitignore | 3 -- Makefile | 15 +++------ README.md | 16 +++------ docs/Publicar.md | 38 +++++----------------- src/descargar.py | 82 ----------------------------------------------- src/empaquetar.py | 51 ----------------------------- 6 files changed, 16 insertions(+), 189 deletions(-) delete mode 100644 src/descargar.py delete mode 100644 src/empaquetar.py diff --git a/.gitignore b/.gitignore index 6423b0f..098b1e9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,9 +31,6 @@ out/*/* !out/*/candidatos_estrellas.csv !out/*/stats.json -# Paquetes por país listos para subir a una release -dist/ - # Restos de trabajo *.log .DS_Store diff --git a/Makefile b/Makefile index b246929..d908a13 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # así que se puede reejecutar solo la parte que interese. PY := ./.venv/bin/python -.PHONY: all datos rasters modelo salidas cobertura revisar empaquetar descargar selector limpio +.PHONY: all datos rasters modelo salidas cobertura revisar selector limpio all: datos rasters modelo salidas revisar @@ -52,16 +52,9 @@ cobertura: revisar: $(PY) src/revisar.py -## --- países: paquetes para publicar y descarga de los publicados --- -# El repositorio lleva España. Los demás se calculan (REGION=xx make all) o se -# bajan ya hechos, que son unos pocos MB en vez de un par de horas. -empaquetar: - $(PY) src/empaquetar.py - -descargar: - $(PY) src/descargar.py $(or $(PAIS),todos) - -# Vuelve a poner al día el desplegable de país de todos los visores en disco. +## --- desplegable de país --- +# Cada visor congela la lista de países al construirse, así que al calcular uno +# nuevo hay que rehacer el selector de los demás. selector: $(PY) src/paises.py diff --git a/README.md b/README.md index 7e53e8b..ded7185 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ No hace falta servidor ni conexión. Ojo: `visor.html` necesita la carpeta | `out/ortho/` | Ortofoto PNOA de cada localización, 640 m de lado | | `out/stats.json` | Cifras del modelo, que leen el informe y el visor | | `src/` | El pipeline entero, reproducible | -| `out//` | Lo mismo para cada país calculado. No van al repositorio: se publican como paquetes (`make empaquetar`) y se bajan con `make descargar` | +| `out//` | El visor y los datos de cada uno de los otros 22 países | ## Cómo se calcula @@ -133,18 +133,10 @@ clima, así que ese 8 % del modelo deja de distinguir y les baja la banda de estrellas a todos por igual. Finlandia no sale con cero cinco-estrellas porque sus sitios sean peores. -## Bajarse un país, o calcular otro +## Calcular un país -El repositorio lleva España. Los demás se bajan ya hechos, que son unos pocos MB -y un momento, en vez de un par de horas y 25 GB: - -```bash -make descargar PAIS=is # solo Islandia -make descargar # todos los publicados -``` - -Aparecen en el desplegable de país del visor automáticamente. Y para calcular -uno que no esté: +Los 27 del catálogo ya están calculados y vienen en el repositorio. Para añadir +uno nuevo: ```bash ./.venv/bin/python src/regions.py # ver el catálogo diff --git a/docs/Publicar.md b/docs/Publicar.md index 0828080..aaa914e 100644 --- a/docs/Publicar.md +++ b/docs/Publicar.md @@ -1,38 +1,16 @@ # Publicar -## Los países, fuera del repositorio +## Los países van dentro del repositorio -En el repositorio va **España y nada más**. Cada visor lleva el relieve y un -recorte de terreno por candidato incrustados en base64, así que pesa entre 1 y -4 MB y cualquier recálculo reescribe el fichero entero: doce países en el -historial de git son cientos de MB en unos pocos recálculos, y el clon deja de -ser algo que la gente pueda bajarse sin pensárselo. +De cada país entra el visor —que es autónomo, lleva el relieve y el terreno +incrustados— y los datos en CSV: unos 40 MB los 23. Fuera se quedan los WebP, +que van ya dentro del visor, los PNG de los mapas, que solo usa el informe, y +el GeoTIFF del score. -Los demás se publican como adjuntos de una release: +Al clonar están todos, y se salta de uno a otro desde el desplegable del visor. -```bash -make empaquetar # deja dist/rave-scout-.zip, 13 MB los once -``` - -Se suben a una release con la etiqueta `paises`. A partir de ahí, cualquiera: - -```bash -make descargar PAIS=is -make descargar # todos los publicados -``` - -El paquete lleva el visor y los CSV, que es lo que hace falta para mirar el -país. Fuera se quedan los PNG de los mapas (solo los usa el informe, que -únicamente existe para España), los WebP (ya van dentro del visor) y el GeoTIFF -del score. Al descomprimir se actualiza solo el desplegable de país de todos los -visores que haya en disco, que si no el recién bajado no aparecería en los otros. - -Si lo publicas en otro sitio, `RAVE_SCOUT_PAISES` manda sobre la dirección por -defecto: - -```bash -RAVE_SCOUT_PAISES=https://mi-servidor/rave-scout make descargar PAIS=no -``` +Ojo al regenerar: el visor es binario a efectos de git, así que cada recálculo +mete una copia entera en el historial y esa ya no sale. ## Este repositorio está en Gitea diff --git a/src/descargar.py b/src/descargar.py deleted file mode 100644 index fc0cd1c..0000000 --- a/src/descargar.py +++ /dev/null @@ -1,82 +0,0 @@ -"""Baja el visor de un país ya calculado, sin recalcular nada. - -Calcular un país son un par de horas, varios GB de descarga y unos 25 GB de -disco. Quien solo quiera mirarlo no tiene por qué pagar eso: el visor es un -HTML autónomo de unos pocos MB. - - python src/descargar.py is ie hr # países sueltos - python src/descargar.py todos # los que haya publicados - -La dirección sale de RAVE_SCOUT_PAISES si está puesta, y si no de las releases -del repositorio. Si el paquete no está publicado todavía, lo dice y sigue con -el siguiente en vez de dejarlo a medias. -""" -import io -import os -import sys -import urllib.error -import urllib.request -import zipfile -from pathlib import Path - -sys.path.insert(0, str(Path(__file__).resolve().parent)) -import paises -import regions as R - -BASE = os.environ.get( - "RAVE_SCOUT_PAISES", - "https://gitea.laenre.net/hacklab/EXPLORER/releases/download/paises") - - -def bajar(code): - if code not in R.REGIONS: - print(f" {code}: no está en el catálogo (src/regions.py)") - return False - if code == R.DEFAULT: - print(f" {code}: es el país por defecto, ya viene en el repositorio") - return False - - url = f"{BASE}/rave-scout-{code}.zip" - print(f" {R.REGIONS[code]['name']:14s} {url}") - try: - with urllib.request.urlopen(url, timeout=120) as r: - datos = r.read() - except urllib.error.HTTPError as e: - print(f" no está publicado todavía (HTTP {e.code})") - return False - except Exception as e: - print(f" no se ha podido bajar: {type(e).__name__}") - return False - - with zipfile.ZipFile(io.BytesIO(datos)) as zf: - # Las rutas del zip son out//…, relativas a la raíz. Se comprueba - # que ninguna se salga de ahí antes de escribir nada: un zip es un - # fichero de fuera y '../' dentro de un nombre escribe donde quiera. - for nombre in zf.namelist(): - destino = (paises.ROOT / nombre).resolve() - if not str(destino).startswith(str((paises.ROOT / "out").resolve())): - raise SystemExit(f" ruta sospechosa en el zip: {nombre}") - zf.extractall(paises.ROOT) - n = len(list(zf.namelist())) - print(f" {n} ficheros en out/{code}/") - return True - - -def main(args): - if not args: - raise SystemExit(__doc__) - if args == ["todos"]: - args = [c for c in R.REGIONS if c != R.DEFAULT] - - ok = sum(bajar(c) for c in args) - if ok: - # Los visores llevan la lista de países congelada de cuando se - # construyeron: sin esto, el país recién bajado no sale en el - # desplegable de los demás. - print("\nactualizando el selector de país de los visores…") - paises.refrescar() - print(f"\n{ok} países añadidos.") - - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/src/empaquetar.py b/src/empaquetar.py deleted file mode 100644 index 64f826e..0000000 --- a/src/empaquetar.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Empaqueta cada país calculado en un zip para subirlo a una release. - -El repositorio se queda con España. Los demás países pesan entre 1 y 4 MB de -visor cada uno, y como el visor lleva el relieve incrustado, cualquier recálculo -reescribe el fichero entero: en el historial de git eso son cientos de MB en -unos pocos recálculos, y el clon deja de ser portable. - -Al paquete va solo lo que hace falta para mirar el país, que es el visor —es -autónomo, sin servidor ni conexión— y los datos en CSV. Fuera se quedan los -PNG de los mapas (solo los usa el informe, que únicamente existe para España), -los WebP (van ya incrustados dentro del visor) y el GeoTIFF del score, que pesa -lo que pesa y se regenera. -""" -import sys -import zipfile -from pathlib import Path - -sys.path.insert(0, str(Path(__file__).resolve().parent)) -import paises -import regions as R - -DENTRO = ("visor.html", "candidatos_estrellas.csv", "stats.json") -DIST = paises.ROOT / "dist" - - -def main(): - DIST.mkdir(exist_ok=True) - hechos = [(c, d, n) for c, d, n in paises.calculados() if c != R.DEFAULT] - if not hechos: - raise SystemExit("no hay ningún país calculado aparte del de por defecto") - - total = 0 - for code, d, n in sorted(hechos): - z = DIST / f"rave-scout-{code}.zip" - with zipfile.ZipFile(z, "w", zipfile.ZIP_DEFLATED, compresslevel=9) as zf: - for nombre in DENTRO: - f = d / nombre - if f.exists(): - # Dentro del zip cuelgan de out//, para que se - # descomprima en su sitio desde la raíz del proyecto. - zf.write(f, f"out/{code}/{nombre}") - total += z.stat().st_size - print(f" {R.REGIONS[code]['name']:14s} {n:>4} localizaciones " - f"{z.stat().st_size/1e6:5.1f} MB {z.name}") - - print(f"\n{len(hechos)} paquetes, {total/1e6:.1f} MB en {DIST}") - print("Súbelos como adjuntos de una release con la etiqueta 'paises'.") - - -if __name__ == "__main__": - main()