Skip to content

Commit

Permalink
Add map_maker client module with unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
NeonDaniel committed Dec 28, 2023
1 parent d0ba03f commit a5dbc15
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
72 changes: 72 additions & 0 deletions neon_api_proxy/client/map_maker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# NEON AI (TM) SOFTWARE, Software Development Kit & Application Framework
# All trademark and other rights reserved by their respective owners
# Copyright 2008-2022 Neongecko.com Inc.
# Contributors: Daniel McKnight, Guy Daniels, Elon Gasper, Richard Leeds,
# Regina Bloomstine, Casimiro Ferreira, Andrii Pernatii, Kirill Hrymailo
# BSD-3 License
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import json

from ovos_utils.log import LOG
from neon_api_proxy.client import NeonAPI, request_api


def get_coordinates(location: str) -> (float, float):
"""
Get coordinates for the requested location
@param location: Search term, i.e. City, Address, Landmark
@returns: coordinate latitude, longitude
"""
resp = _make_api_call({'address': location})
if resp['status_code'] != 200:
raise RuntimeError(f"API Request failed: {resp['content']}")
coords = resp['content'][0]['lat'], resp['content'][0]['lon']
LOG.info(f"Resolved: {coords}")
return float(coords[0]), float(coords[1])


def get_address(lat: float, lon: float) -> dict:
"""
Get a dict location for the specified coordinates
@param lat: latitude of point to look up
@param lon: longitude of point to look up
@returns: dict location (equivalent to Geopy Location.raw)
"""
resp = _make_api_call({'lat': lat, "lon": lon})
if resp['status_code'] != 200:
raise RuntimeError(f"API Request failed: {resp['content']}")
address = resp['content']['address']
if not address.get('city'):
LOG.debug(f"Response missing city, trying to find alternate tag in: "
f"{address.keys()}")
address['city'] = address.get('town') or address.get('village')
LOG.info(f"Resolved: {address}")
return address


def _make_api_call(request_data: dict) -> dict:
resp = request_api(NeonAPI.MAP_MAKER, request_data)
if resp['status_code'] == 200:
resp['content'] = json.loads(resp['content'])
return resp
26 changes: 26 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,29 @@ def test_get_forecast_no_api_key(self):
self.assertIsInstance(data["minutely"], list)
self.assertIsInstance(data["hourly"], list)
self.assertIsInstance(data["daily"], list)


class MapMakerTests(unittest.TestCase):
def test_get_coordinates(self):
from neon_api_proxy.client.map_maker import get_coordinates

# Valid request
lat, lon = get_coordinates("Kirkland")
self.assertIsInstance(lat, float)
self.assertIsInstance(lon, float)

# Invalid request
with self.assertRaises(RuntimeError):
get_coordinates("")

def test_get_address(self):
from neon_api_proxy.client.map_maker import get_address

# Valid Request
address = get_address(VALID_LAT, VALID_LNG)
self.assertEqual(address['state'], "Washington")
self.assertEqual(address['city'], "Renton", address)

# Invalid Request
with self.assertRaises(RuntimeError):
get_address('', '')

0 comments on commit a5dbc15

Please sign in to comment.