Skip to content

Commit

Permalink
feat: Console client, file created
Browse files Browse the repository at this point in the history
  • Loading branch information
JCruiz15 authored and jfaldanam committed Jun 25, 2024
1 parent 6fa7c25 commit 27d7472
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 16 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,4 @@ cython_debug/

# Others
*inspo*
wip-file*
__main__.py
wip-file*
207 changes: 207 additions & 0 deletions sigpac_tools/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import argparse
import structlog

logger = structlog.get_logger()


def get_parser():
parser = argparse.ArgumentParser(description="SIGPAC Tools")

subparsers = parser.add_subparsers(dest="command", help="Available commands")
subparsers.required = True

# Search command

search_parser = subparsers.add_parser(
"search", help="Search for a reference in the SIGPAC database"
)
search_parser.add_argument(
"--community",
type=int,
help="Community of the location",
required=False,
metavar="INT",
)
search_parser.add_argument(
"--province",
type=int,
help="Province of the location",
required=False,
metavar="INT",
)
search_parser.add_argument(
"--municipality",
type=int,
help="Municipality of the location",
required=False,
metavar="INT",
)
search_parser.add_argument(
"--polygon",
type=int,
help="Polygon of the location",
required=False,
metavar="INT",
)
search_parser.add_argument(
"--parcel",
type=int,
help="Parcel of the location",
required=False,
metavar="INT",
)

# Locate command

geom_parser = subparsers.add_parser(
"geometry",
help="Locate a geometry given the coordinates in the SIGPAC database",
)
geom_parser.add_argument(
"--layer",
choices=["parcela", "recinto"],
help="Layer to search from",
metavar="STRING",
required=True,
)
geom_parser.add_argument(
"--lat",
type=float,
help="Latitude of the location",
metavar="FLOAT",
required=True,
)
geom_parser.add_argument(
"--lon",
type=float,
help="Longitude of the location",
metavar="FLOAT",
required=True,
)
geom_parser.add_argument(
"--reference",
type=int,
help="Reference to search for",
required=False,
metavar="INT",
)

# Get metadata command

annotate_parser = subparsers.add_parser(
"get-metadata", help="Get metadata of a location in the SIGPAC database"
)
annotate_parser.add_argument(
"--layer",
choices=["parcela", "recinto"],
help="Layer to search from",
metavar="STRING",
required=True,
)
annotate_parser.add_argument(
"--province",
type=int,
help="Province of the location",
metavar="INT",
required=True,
)
annotate_parser.add_argument(
"--aggregate",
type=int,
default=0,
help="Aggregate of the location",
metavar="INT",
)
annotate_parser.add_argument(
"--zone", type=int, default=0, help="Zone of the location", metavar="INT"
)
annotate_parser.add_argument(
"--municipality",
type=int,
help="Municipality of the location",
metavar="INT",
required=True,
)
annotate_parser.add_argument(
"--polygon",
type=int,
help="Polygon of the location",
metavar="INT",
required=True,
)
annotate_parser.add_argument(
"--parcel",
type=int,
help="Parcel of the location",
metavar="INT",
required=True,
)
annotate_parser.add_argument(
"--enclosure",
type=int,
help="Enclosure of the location",
required=False,
metavar="INT",
)

return parser


def main():
args, _ = get_parser().parse_known_args()

match args.command:
case "search":
from sigpac_tools.search import search
import json

data = {
"community": args.community,
"province": args.province,
"municipality": args.municipality,
"polygon": args.polygon,
"parcel": args.parcel,
}
search_res = search(data)
logger.info(f"Search results:\n{json.dumps(search_res, indent=2)}")
return search_res

case "geometry":
from sigpac_tools.locate import geometry_from_coords
import json

print(args)

layer = args.layer
lat = args.lat
lon = args.lon
reference = args.reference
geom = geometry_from_coords(layer, lat, lon, reference)
logger.info(
f"Geometry for coords ({lat}, {lon}):\n{json.dumps(geom, indent=2)}"
)
return geom

case "get-metadata":
from sigpac_tools.anotate import get_metadata
import json

layer = args.layer
data = {
"province": args.province,
"aggregate": args.aggregate,
"zone": args.zone,
"municipality": args.municipality,
"polygon": args.polygon,
"parcel": args.parcel,
"enclosure": args.enclosure,
}
metadata = get_metadata(layer, data)
logger.info(f"Metadata:\n{json.dumps(metadata, indent=2)}")
return metadata
case _:
raise ValueError("Invalid command")


if __name__ == "__main__":
main()
4 changes: 3 additions & 1 deletion sigpac_tools/anotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ def get_metadata(layer: str, data: dict):
if not encl and layer == "recinto":
raise ValueError("Enclosure not specified")

logger.info(f"Searching for the metadata of the location (province {prov}, municipality {muni}, polygon {polg}, parcel {parc}) in the SIGPAC database...")
logger.info(
f"Searching for the metadata of the location (province {prov}, municipality {muni}, polygon {polg}, parcel {parc}) in the SIGPAC database..."
)
return __query(
layer=layer,
province=prov,
Expand Down
10 changes: 8 additions & 2 deletions sigpac_tools/locate.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ def geometry_from_coords(layer: str, lat: float, lon: float, reference: int) ->
KeyError
If the layer is not supported
"""
if not layer or not lat or not lon or not reference:
raise ValueError("Layer, latitude, longitude or reference not specified")
if not layer or not lat or not lon:
raise ValueError("Layer, latitude or longitude not specified")

tile_x, tile_y = lng_lat_to_tile(lon, lat, 15)

Expand All @@ -69,6 +69,12 @@ def geometry_from_coords(layer: str, lat: float, lon: float, reference: int) ->

geojson_features = response.json()

if not reference:
logger.info(
f"No reference specified. Returning all features in the layer {layer} for coordinates ({lat}, {lon})"
)
return geojson_features

if layer in ["parcela", "recinto"]:
logger.info(f"Searching for reference {reference} in the layer {layer}...")
result = __locate_in_feature_collection(
Expand Down
2 changes: 1 addition & 1 deletion sigpac_tools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def lng_lat_to_tile(lng: float, lat: float, zoom: float) -> tuple[int, int]:
Latitude of the location
zoom : float
Zoom level to get the tile coordinates
Returns
-------
tuple[int, int]
Expand Down
43 changes: 33 additions & 10 deletions tests/test_locate.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
],
}


class TestGeometryFromCoords:
@patch("sigpac_tools.locate.requests.get")
@patch("sigpac_tools.locate.lng_lat_to_tile")
@patch("sigpac_tools.locate.transform_coords")
def test_geometry_from_coords_parcela(self, mock_transform_coords, mock_lng_lat_to_tile, mock_get):
def test_geometry_from_coords_parcela(
self, mock_transform_coords, mock_lng_lat_to_tile, mock_get
):
mock_lng_lat_to_tile.return_value = (1234, 5678)
mock_response = Mock()
mock_response.json.return_value = mock_geojson_response
Expand All @@ -39,14 +42,18 @@ def test_geometry_from_coords_parcela(self, mock_transform_coords, mock_lng_lat_
result = geometry_from_coords(layer, lat, lon, reference)

mock_lng_lat_to_tile.assert_called_once_with(lon, lat, 15)
mock_get.assert_called_once_with(f"{BASE_URL}/vectorsdg/vector/parcela@3857/15.1234.5678.geojson")
mock_get.assert_called_once_with(
f"{BASE_URL}/vectorsdg/vector/parcela@3857/15.1234.5678.geojson"
)
mock_transform_coords.assert_called_once()
assert result == mock_geojson_response["features"][0]["geometry"]

@patch("sigpac_tools.locate.requests.get")
@patch("sigpac_tools.locate.lng_lat_to_tile")
@patch("sigpac_tools.locate.transform_coords")
def test_geometry_from_coords_recinto(self, mock_transform_coords, mock_lng_lat_to_tile, mock_get):
def test_geometry_from_coords_recinto(
self, mock_transform_coords, mock_lng_lat_to_tile, mock_get
):
mock_lng_lat_to_tile.return_value = (1234, 5678)
mock_response = Mock()
mock_response.json.return_value = mock_geojson_response
Expand All @@ -60,7 +67,9 @@ def test_geometry_from_coords_recinto(self, mock_transform_coords, mock_lng_lat_
result = geometry_from_coords(layer, lat, lon, reference)

mock_lng_lat_to_tile.assert_called_once_with(lon, lat, 15)
mock_get.assert_called_once_with(f"{BASE_URL}/vectorsdg/vector/recinto@3857/15.1234.5678.geojson")
mock_get.assert_called_once_with(
f"{BASE_URL}/vectorsdg/vector/recinto@3857/15.1234.5678.geojson"
)
mock_transform_coords.assert_called_once()
assert result == mock_geojson_response["features"][0]["geometry"]

Expand All @@ -80,22 +89,36 @@ def test_geometry_not_found(self, mock_lng_lat_to_tile, mock_get):
result = geometry_from_coords(layer, lat, lon, reference)

mock_lng_lat_to_tile.assert_called_once_with(lon, lat, 15)
mock_get.assert_called_once_with(f"{BASE_URL}/vectorsdg/vector/parcela@3857/15.1234.5678.geojson")
mock_get.assert_called_once_with(
f"{BASE_URL}/vectorsdg/vector/parcela@3857/15.1234.5678.geojson"
)
assert result is None

def test_invalid_layer(self):
with pytest.raises(KeyError, match='Layer "invalid" not supported. Supported layers: "parcela", "recinto"'):
with pytest.raises(
KeyError,
match='Layer "invalid" not supported. Supported layers: "parcela", "recinto"',
):
geometry_from_coords("invalid", 40.0, -3.0, 123)

def test_missing_parameters(self):
with pytest.raises(ValueError, match="Layer, latitude, longitude or reference not specified"):
with pytest.raises(
ValueError, match="Layer, latitude, longitude or reference not specified"
):
geometry_from_coords("", 40.0, -3.0, 123)
with pytest.raises(ValueError, match="Layer, latitude, longitude or reference not specified"):
with pytest.raises(
ValueError, match="Layer, latitude, longitude or reference not specified"
):
geometry_from_coords("parcela", None, -3.0, 123)
with pytest.raises(ValueError, match="Layer, latitude, longitude or reference not specified"):
with pytest.raises(
ValueError, match="Layer, latitude, longitude or reference not specified"
):
geometry_from_coords("parcela", 40.0, None, 123)
with pytest.raises(ValueError, match="Layer, latitude, longitude or reference not specified"):
with pytest.raises(
ValueError, match="Layer, latitude, longitude or reference not specified"
):
geometry_from_coords("parcela", 40.0, -3.0, None)


if __name__ == "__main__":
pytest.main()

0 comments on commit 27d7472

Please sign in to comment.