| import tempfile |
| import zipfile |
| from io import BytesIO |
| from pathlib import Path |
|
|
| import pyogrio |
| import pytest |
|
|
| from utils.kml_to_tab import KmlToTabError, convert_kml_to_tab_zip |
|
|
|
|
| MIXED_KML = b"""<?xml version="1.0" encoding="UTF-8"?> |
| <kml xmlns="http://www.opengis.net/kml/2.2"> |
| <Document> |
| <Placemark> |
| <name>Site A</name> |
| <description>Point feature</description> |
| <Point> |
| <coordinates>50.606051,26.261322,0</coordinates> |
| </Point> |
| </Placemark> |
| <Placemark> |
| <name>Sector A</name> |
| <description>Polygon feature</description> |
| <Polygon> |
| <outerBoundaryIs> |
| <LinearRing> |
| <coordinates> |
| 50.606051,26.261322,0 |
| 50.607051,26.261322,0 |
| 50.607051,26.262322,0 |
| 50.606051,26.261322,0 |
| </coordinates> |
| </LinearRing> |
| </outerBoundaryIs> |
| </Polygon> |
| </Placemark> |
| </Document> |
| </kml> |
| """ |
|
|
| RSRP_KML = b"""<?xml version="1.0" encoding="UTF-8"?> |
| <kml xmlns="http://www.opengis.net/kml/2.2"> |
| <Document xmlns=""> |
| <Style id="normalPlacemark"> |
| <IconStyle> |
| <color>ff00ffff</color> |
| <scale>0.5</scale> |
| <Icon> |
| <href>http://kml-icons.actix.com/Dot.png</href> |
| </Icon> |
| </IconStyle> |
| </Style> |
| <Placemark> |
| <description>DriveTest-LTE_UE_RSRP |
| -105.599998474121</description> |
| <styleUrl>normalPlacemark</styleUrl> |
| <Point> |
| <coordinates>-5.687045,11.305296</coordinates> |
| </Point> |
| </Placemark> |
| <Style id="normalPlacemark"> |
| <IconStyle> |
| <color>ff0000ff</color> |
| <scale>0.5</scale> |
| <Icon> |
| <href>http://kml-icons.actix.com/Dot.png</href> |
| </Icon> |
| </IconStyle> |
| </Style> |
| <Placemark> |
| <description>DriveTest-LTE_UE_RSRP |
| -116.099998474121</description> |
| <styleUrl>normalPlacemark</styleUrl> |
| <Point> |
| <coordinates>-5.687901,11.305419</coordinates> |
| </Point> |
| </Placemark> |
| </Document> |
| </kml> |
| """ |
|
|
| STRUCTURED_DESCRIPTION_KML = b"""<?xml version="1.0" encoding="UTF-8"?> |
| <kml xmlns="http://www.opengis.net/kml/2.2"> |
| <Document> |
| <Placemark> |
| <name>Busaiteen_1</name> |
| <description><b>Sector Details:</b><br><b>code:</b> 1004<br><b>name:</b> Busaiteen_1<br><b>Azimut:</b> 30<br><b>Longitude:</b> 50.606051<br><b>Latitude:</b> 26.261322<br><b>size:</b> 1000<br><b>color:</b> 7fff0000<br></description> |
| <Polygon> |
| <outerBoundaryIs> |
| <LinearRing> |
| <coordinates> |
| 50.606051,26.261322,0 |
| 50.607051,26.261322,0 |
| 50.607051,26.262322,0 |
| 50.606051,26.261322,0 |
| </coordinates> |
| </LinearRing> |
| </outerBoundaryIs> |
| </Polygon> |
| </Placemark> |
| </Document> |
| </kml> |
| """ |
|
|
|
|
| def test_convert_kml_to_tab_zip_splits_mixed_geometries(): |
| result = convert_kml_to_tab_zip(MIXED_KML, "mixed sample.kml") |
|
|
| with zipfile.ZipFile(BytesIO(result.zip_bytes)) as zf: |
| names = sorted(zf.namelist()) |
|
|
| assert "mixed_sample_point.tab" in names |
| assert "mixed_sample_point.dat" in names |
| assert "mixed_sample_point.map" in names |
| assert "mixed_sample_point.id" in names |
| assert "mixed_sample_polygon.tab" in names |
| assert "mixed_sample_polygon.dat" in names |
| assert "mixed_sample_polygon.map" in names |
| assert "mixed_sample_polygon.id" in names |
| assert [(layer.geometry_type, layer.feature_count) for layer in result.layers] == [ |
| ("Point", 1), |
| ("Polygon", 1), |
| ] |
|
|
|
|
| def test_convert_kml_to_tab_zip_preserves_measurement_values(): |
| result = convert_kml_to_tab_zip(RSRP_KML, "rsrp.kml") |
|
|
| with tempfile.TemporaryDirectory() as tmp_dir_name: |
| tmp_dir = Path(tmp_dir_name) |
| with zipfile.ZipFile(BytesIO(result.zip_bytes)) as zf: |
| zf.extractall(tmp_dir) |
|
|
| metadata, _fids, _geometry, field_data = pyogrio.raw.read(tmp_dir / "rsrp.tab") |
|
|
| fields = metadata["fields"].tolist() |
| data = dict(zip(fields, field_data)) |
|
|
| assert "value" in fields |
| assert "metric" not in fields |
| assert "parameter" not in fields |
| assert "legend" not in fields |
| assert "kml_color" not in fields |
| assert "style_rgb" not in fields |
| assert data["value"].tolist() == [-105.599998474121, -116.099998474121] |
|
|
|
|
| def test_convert_kml_to_tab_zip_expands_structured_description_fields(): |
| result = convert_kml_to_tab_zip(STRUCTURED_DESCRIPTION_KML, "sectors.kml") |
|
|
| with tempfile.TemporaryDirectory() as tmp_dir_name: |
| tmp_dir = Path(tmp_dir_name) |
| with zipfile.ZipFile(BytesIO(result.zip_bytes)) as zf: |
| zf.extractall(tmp_dir) |
|
|
| metadata, _fids, _geometry, field_data = pyogrio.raw.read( |
| tmp_dir / "sectors.tab" |
| ) |
|
|
| fields = metadata["fields"].tolist() |
| data = dict(zip(fields, field_data)) |
|
|
| assert "value" not in fields |
| for field in [ |
| "code", |
| "description_name", |
| "Azimut", |
| "Longitude", |
| "Latitude", |
| "size", |
| "color", |
| ]: |
| assert field in fields |
| assert data["code"].tolist() == ["1004"] |
| assert data["description_name"].tolist() == ["Busaiteen_1"] |
| assert data["Azimut"].tolist() == ["30"] |
| assert data["Longitude"].tolist() == ["50.606051"] |
| assert data["Latitude"].tolist() == ["26.261322"] |
| assert data["size"].tolist() == ["1000"] |
| assert data["color"].tolist() == ["7fff0000"] |
|
|
|
|
| def test_convert_kml_to_tab_zip_rejects_empty_input(): |
| with pytest.raises(KmlToTabError, match="vide"): |
| convert_kml_to_tab_zip(b"", "empty.kml") |
|
|