Skip to content

fix vecteur: extraction GPKG BD TOPO fiona >=1.9 (Geometry/date non s… #80

fix vecteur: extraction GPKG BD TOPO fiona >=1.9 (Geometry/date non s…

fix vecteur: extraction GPKG BD TOPO fiona >=1.9 (Geometry/date non s… #80

Workflow file for this run

name: CI cross-platform
on:
push:
paths:
- 'lidar2map.py'
- 'deploy.py'
- 'tests/**'
- 'providers/**'
- 'pyproject.toml'
- '.github/workflows/ci.yml'
pull_request:
paths:
- 'lidar2map.py'
- 'deploy.py'
- 'tests/**'
- 'providers/**'
- 'pyproject.toml'
- '.github/workflows/ci.yml'
workflow_dispatch:
jobs:
# Lint rapide (quelques secondes) : échoue avant de payer la matrice 3 OS.
# Règles F (pyflakes) seulement, config dans pyproject.toml : imports
# inutilisés, variables mortes, noms non définis. Dès son premier run
# local, a attrapé un F821 réel (variable supprimée encore référencée
# dans une branche que ni py_compile ni les tests n'exercent).
lint:
name: ruff (pyflakes)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Installer ruff
run: pip install ruff
- name: Ruff check
run: ruff check .
test:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
env:
# Pas d'auto-install/venv dans le runner : les deps sont posées par pip
# ci-dessous, et un manque doit échouer net (message clair) plutôt que
# déclencher le bootstrap.
LIDAR2MAP_BOOTSTRAP: none
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Installer les dependances Python
# Liste alignée sur les deps OBLIGATOIRES de lidar2map (cf.
# _installer_deps) : depuis le refactor rasterio, ijson/rasterio/
# fiona/certifi sont requis à l'import — l'ancienne ligne (pyproj
# Pillow numpy scipy) est la raison des échecs CI d'avril 2026.
run: pip install pyproj Pillow numpy scipy ijson rasterio fiona certifi
- name: Syntaxe Python
run: python -c "import ast; ast.parse(open('lidar2map.py', encoding='utf-8').read()); print('OK')"
- name: Syntaxe _loader.py
run: python -c "import ast; ast.parse(open('_loader.py', encoding='utf-8').read()); print('OK')"
- name: Import complet sans erreur
run: |
python -c "
import sys, types
sys.argv = ['lidar2map.py', '--help']
try:
import lidar2map
except SystemExit:
pass
print('Import OK')
"
- name: help ignlidar
run: python lidar2map.py --ignlidar --help
- name: help ignraster
run: python lidar2map.py --ignraster --help
- name: help ignvecteur
run: python lidar2map.py --ignvecteur --help
- name: help fusionner
run: python lidar2map.py --fusionner --source dummy.geojson --help
- name: help osm
run: python lidar2map.py --osm --help
- name: _parser_departements
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
assert lidar2map._parser_departements('83') == ['83']
assert lidar2map._parser_departements('1-3') == ['01','02','03']
assert lidar2map._parser_departements('30,35,75') == ['30','35','75']
assert lidar2map._parser_departements('1-3,75,83') == ['01','02','03','75','83']
assert lidar2map._parser_departements('2A') == ['2A']
assert lidar2map._parser_departements('971') == ['971']
print('_parser_departements OK')
"
- name: _epsilon_depuis_surface_km2
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
eps = lidar2map._epsilon_depuis_surface_km2
assert eps(100) == 3 / 111000
assert eps(500) == 8 / 111000
assert eps(9000) == 15 / 111000
assert eps(50000) == 25 / 111000
assert eps(200000)== 40 / 111000
print('_epsilon_depuis_surface_km2 OK')
"
- name: _hms
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
assert lidar2map._hms(5) == '5s'
assert lidar2map._hms(90) == '1m30s'
assert lidar2map._hms(3661) == '1h01m01s'
print('_hms OK')
"
- name: normaliser_nom
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
assert lidar2map.normaliser_nom('Gareoult') == 'gareoult'
assert lidar2map.normaliser_nom('Ile-de-France') == 'ile-de-france'
assert lidar2map.normaliser_nom('Saint Jean') == 'saint_jean'
print('normaliser_nom OK')
"
- name: _GEOFABRIK completude
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
codes = [f'{n:02d}' for n in range(1,20)] + [f'{n:02d}' for n in range(21,96)]
codes += ['2A','2B','971','972','973','974','976']
print(f'Codes a couvrir : {len(codes)}')
print('_GEOFABRIK structure OK')
"
- name: wgs84_to_lamb93_approx
# Référence pyproj plutôt que bornes en dur : les anciennes bornes
# (950000 < x) étaient fausses (X exact = 946880.8) et n'avaient
# jamais été exercées, la CI tombant avant sur l'import.
# Tolérance 50 m = précision documentée de l'approximation.
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
from pyproj import Transformer
t = Transformer.from_crs('EPSG:4326', 'EPSG:2154', always_xy=True)
xe, ye = t.transform(6.0423, 43.3156)
x, y = lidar2map.wgs84_to_lamb93_approx(6.0423, 43.3156)
assert abs(x - xe) < 50 and abs(y - ye) < 50, f'dx={x-xe:.1f}m dy={y-ye:.1f}m'
print(f'wgs84_to_lamb93_approx OK : X={x:.1f} Y={y:.1f} (pyproj a {abs(x-xe)*100:.0f}/{abs(y-ye)*100:.0f} cm)')
"
- name: lamb93_to_wgs84_approx
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
from pyproj import Transformer
t = Transformer.from_crs('EPSG:2154', 'EPSG:4326', always_xy=True)
lon_e, lat_e = t.transform(960000, 6258000)
lon, lat = lidar2map.lamb93_to_wgs84_approx(960000, 6258000)
assert abs(lon - lon_e) < 0.0007 and abs(lat - lat_e) < 0.0005, f'dlon={lon-lon_e} dlat={lat-lat_e}'
print(f'lamb93_to_wgs84_approx OK : lon={lon:.5f} lat={lat:.5f}')
"
- name: Historique lecture ecriture
run: |
python -c "
import sys, tempfile, os
from pathlib import Path
sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
tmp = Path(tempfile.mkdtemp())
lidar2map._HISTORIQUE_PATH = tmp / 'historique.json'
lidar2map._sauver_historique({'type':'osm','nom':'test','mode':'dep','dep':'83'}, 120, '/tmp/out')
hist = lidar2map._lire_historique()
assert len(hist) == 1
assert hist[0]['nom'] == 'test'
assert hist[0]['dep'] == '83'
assert hist[0]['duree'] == '2m00s'
print('Historique OK')
"
- name: Platform flags
run: |
python -c "
import sys; sys.argv=['lidar2map.py','--ignlidar','--help']
try: import lidar2map
except SystemExit: pass
import platform
expected_win = platform.system() == 'Windows'
expected_linux = platform.system() == 'Linux'
expected_mac = platform.system() == 'Darwin'
assert lidar2map.WINDOWS == expected_win, f'WINDOWS={lidar2map.WINDOWS}'
assert lidar2map.LINUX == expected_linux, f'LINUX={lidar2map.LINUX}'
assert lidar2map.MACOS == expected_mac, f'MACOS={lidar2map.MACOS}'
print(f'Platform flags OK : WINDOWS={lidar2map.WINDOWS} LINUX={lidar2map.LINUX} MACOS={lidar2map.MACOS}')
"
# Tests de régression des calculs scientifiques (kernels Horn/SVF/openness,
# LRM, RRIM, tuilage MBTiles/RMAP/SQLiteDB). Ubuntu uniquement : les calculs
# sont identiques sur les 3 OS (numpy/numba), inutile de payer 3× la
# compilation numba — le job 'test' ci-dessus couvre déjà la matrice OS
# pour la syntaxe et les imports.
tests-scientifiques:
name: tests scientifiques (ubuntu)
runs-on: ubuntu-latest
env:
LIDAR2MAP_BOOTSTRAP: none
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Installer les dependances calcul
# numba pour les kernels + la liste obligatoire de lidar2map
# (l'import sous bootstrap=none vérifie ijson/fiona/certifi aussi).
run: pip install numpy scipy rasterio numba Pillow pyproj ijson fiona certifi
- name: Tests calculs scientifiques
run: python tests/_test_corrections.py
- name: Tests tuilage MBTiles/RMAP/SQLiteDB
run: python tests/_test_tiling.py