Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions LOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# LOG

## 2026-06-09 — v0.2.2 — validazione upfront target in `batch`

- `batch`: check immediato che `--to` sia un target valido per `--from`; fallisce prima di leggere il CSV con messaggio chiaro (`Run 'openverto targets <from>'`).
- 2 nuovi test offline (`test_batch_rejects_invalid_target`, `test_batch_accepts_valid_target_combination`).

## 2026-06-09 — docs: disclaimer non-affiliazione + nota Z/M planimetrica

- Spunti da `sag1687/geobridge` (plugin QGIS per lo stesso servizio IGM): aggiunti due punti che mancavano.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "openverto"
version = "0.2.1"
version = "0.2.2"
description = "Python CLI and library for the official IGM Verto Online coordinate transforms between Italian reference systems"
readme = "README.md"
authors = [
Expand Down
10 changes: 10 additions & 0 deletions src/openverto/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,16 @@ def batch(
"""
in_e = _parse_epsg(from_epsg)
out_e = _parse_epsg(to_epsg)
try:
valid_targets = lib_targets(in_e, with_live=False)
except KeyError:
_die(f"EPSG {in_e} is not IGM-supported; run 'openverto systems'", EXIT_NOT_FOUND)
if out_e not in {r["epsg"] for r in valid_targets}:
Comment on lines +399 to +403

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Potentially-unbound variable visible to static analysis

valid_targets is only assigned inside the try block. If KeyError is raised and _die is called, execution never reaches the if statement below — but _die is typed -> None, not -> NoReturn. Static type checkers (mypy/pyright) will therefore report valid_targets as possibly unbound on the next line, and any future change to _die that makes it return normally (e.g. for testing) would produce a NameError. Annotating _die as -> NoReturn (or restructuring with an else block) is the minimal fix.

Fix in Claude Code

_die(
f"EPSG {out_e} is not a valid target for EPSG {in_e}. "
f"Run 'openverto targets {in_e}' to see valid options.",
EXIT_USAGE,
)
if fmt not in ("csv", "geojson"):
_die(f"--format must be 'csv' or 'geojson', got {fmt!r}", EXIT_USAGE)
try:
Expand Down
42 changes: 42 additions & 0 deletions tests/test_offline.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,45 @@ def test_resolve_column_by_alias_and_missing():
assert resolve_column(header, "nord", ["n"]) == 2 # explicit name
with pytest.raises(ValueError):
resolve_column(header, "manca", E_ALIASES)


def test_batch_rejects_invalid_target(tmp_path):
"""batch must fail upfront when --to is not a valid target for --from."""
from typer.testing import CliRunner

from openverto.cli import app

p = tmp_path / "coords.csv"
p.write_text("lon,lat\n12.0,41.0\n", encoding="utf-8")

runner = CliRunner()
result = runner.invoke(app, ["batch", str(p), "--from", "23033", "--to", "32633"])
normalized = " ".join(result.output.split())
assert result.exit_code != 0
assert "32633" in normalized
assert "23033" in normalized
assert "targets 23033" in normalized


def test_batch_accepts_valid_target_combination(tmp_path, monkeypatch):
"""batch must pass the target check for a known-valid from/to pair."""
import openverto.transform as convmod

def fake_post(body):
return {
"stato": "successo",
"coordinate": [{"e": c["e"] + 0.001, "n": c["n"] + 0.002} for c in body["coordinate"]],
}

monkeypatch.setattr(convmod, "post", fake_post)

from typer.testing import CliRunner

from openverto.cli import app

p = tmp_path / "coords.csv"
p.write_text("lon,lat\n290000.0,4640000.0\n", encoding="utf-8")

runner = CliRunner()
result = runner.invoke(app, ["batch", str(p), "--from", "23033", "--to", "6706"])
assert result.exit_code == 0
Loading