Skip to content

Commit b3fd4bc

Browse files
authored
chore: remove weather distance calc (#856)
1 parent b772f42 commit b3fd4bc

File tree

3 files changed

+3
-310
lines changed

3 files changed

+3
-310
lines changed

merino/providers/suggest/weather/backends/accuweather/backend.py

+2-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import logging
99
from enum import Enum
1010
from typing import Any, Callable, NamedTuple, cast
11-
from functools import partial
1211

1312
import aiodogstatsd
1413
from dateutil import parser
@@ -36,8 +35,7 @@
3635
process_location_completion_response,
3736
process_forecast_response,
3837
process_current_condition_response,
39-
process_location_response_with_country,
40-
process_location_response_with_country_and_region,
38+
process_location_response,
4139
get_language,
4240
)
4341

@@ -737,18 +735,15 @@ async def get_location_by_geolocation(
737735

738736
if region:
739737
url_path = self.url_cities_admin_path.format(country_code=country, admin_code=region)
740-
processor = process_location_response_with_country_and_region
741738
else:
742739
url_path = self.url_cities_path.format(country_code=country)
743-
partial_process_func = partial(process_location_response_with_country, weather_context)
744-
processor = partial_process_func
745740

746741
try:
747742
response: dict[str, Any] | None = await self.request_upstream(
748743
url_path,
749744
params=self.get_location_key_query_params(city),
750745
request_type=RequestType.LOCATIONS,
751-
process_api_response=processor,
746+
process_api_response=process_location_response,
752747
cache_ttl_sec=self.cached_location_key_ttl_sec,
753748
)
754749
except HTTPError as error:

merino/providers/suggest/weather/backends/accuweather/utils.py

+1-109
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
"""Utilities for the AccuWeather backend."""
22

33
import logging
4-
import math
54
from enum import StrEnum
65
from typing import Any, TypedDict
76

87
from httpx import URL, InvalidURL
98
from merino.configs import settings
10-
from merino.providers.suggest.weather.backends.protocol import WeatherContext
119

1210
PARTNER_PARAM_ID: str | None = settings.accuweather.get("url_param_partner_code")
1311
PARTNER_CODE: str | None = settings.accuweather.get("partner_code")
1412
VALID_LANGUAGES: frozenset = frozenset(settings.accuweather.default_languages)
1513

16-
# Max distance threshold used for distance calculation
17-
DISTANCE_THRESHOLD = (
18-
70 # 70 km based on logging data, either distances were ~60, or much greater than 60
19-
)
20-
2114
logger = logging.getLogger(__name__)
2215

2316

@@ -82,7 +75,7 @@ def process_location_completion_response(response: Any) -> list[dict[str, Any]]
8275
]
8376

8477

85-
def process_location_response_with_country_and_region(
78+
def process_location_response(
8679
response: Any,
8780
) -> ProcessedLocationResponse | None:
8881
"""Process the API response for location keys.
@@ -112,35 +105,6 @@ def process_location_response_with_country_and_region(
112105
return None
113106

114107

115-
def process_location_response_with_country(
116-
weather_context: WeatherContext | None, response: Any
117-
) -> ProcessedLocationResponse | None:
118-
"""Process the API response for a single location key from country code endpoint.
119-
120-
Note that if you change the return format, ensure you update `LUA_SCRIPT_CACHE_BULK_FETCH`
121-
to reflect the change(s) here.
122-
"""
123-
match response:
124-
case [
125-
{
126-
"Key": key,
127-
"LocalizedName": localized_name,
128-
"AdministrativeArea": {"ID": administrative_area_id},
129-
},
130-
]:
131-
# `type: ignore` is necessary because mypy gets confused when
132-
# matching structures of type `Any` and reports the following
133-
# line as unreachable. See
134-
# https://github.com/python/mypy/issues/12770
135-
return { # type: ignore
136-
"key": key,
137-
"localized_name": localized_name,
138-
"administrative_area_id": administrative_area_id,
139-
}
140-
case _:
141-
return get_closest_location_by_distance(response, weather_context) # type: ignore
142-
143-
144108
def process_current_condition_response(response: Any) -> dict[str, Any] | None:
145109
"""Process the API response for current conditions."""
146110
match response:
@@ -218,75 +182,3 @@ def get_language(requested_languages: list[str]) -> str:
218182
return next(
219183
(language for language in requested_languages if language in VALID_LANGUAGES), "en-US"
220184
)
221-
222-
223-
def get_closest_location_by_distance(
224-
locations: list[dict[str, Any]], weather_context: WeatherContext
225-
) -> ProcessedLocationResponse | None:
226-
"""Get the closest location by distance within the DISTANCE THRESHOLD."""
227-
weather_context.distance_calculation = False if locations else None
228-
coordinates = weather_context.geolocation.coordinates
229-
closest_location = None
230-
min_distance = math.inf
231-
temp_min_distance = math.inf
232-
233-
if coordinates:
234-
lat1 = coordinates.latitude
235-
long1 = coordinates.longitude
236-
237-
if not lat1 or not long1:
238-
return None
239-
240-
for location in locations:
241-
try:
242-
lat2 = location["GeoPosition"]["Latitude"]
243-
long2 = location["GeoPosition"]["Longitude"]
244-
245-
d = get_lat_long_distance(lat1, long1, lat2, long2)
246-
if d < min_distance and d <= DISTANCE_THRESHOLD:
247-
closest_location = location
248-
min_distance = d
249-
if d < temp_min_distance:
250-
temp_min_distance = d
251-
except KeyError:
252-
continue
253-
254-
if closest_location:
255-
try:
256-
weather_context.distance_calculation = True
257-
logging.info(
258-
f"Successful distance calculated for weather: {weather_context.geolocation.country}, {weather_context.geolocation.city}, dist:{min_distance} "
259-
)
260-
return {
261-
"key": closest_location["Key"],
262-
"localized_name": closest_location["LocalizedName"],
263-
"administrative_area_id": closest_location["AdministrativeArea"]["ID"],
264-
}
265-
except KeyError:
266-
weather_context.distance_calculation = False
267-
return None
268-
# temp for debugging
269-
if not math.isinf(temp_min_distance):
270-
logger.warning(
271-
f"Unable to calculate closest city: {weather_context.geolocation.country}, {weather_context.geolocation.city}, dist: {int(temp_min_distance)}"
272-
)
273-
return None
274-
275-
276-
def get_lat_long_distance(lat1: float, long1: float, lat2: float, long2: float) -> float:
277-
"""Calculate distance between two coordinates via the Haversine formula."""
278-
lat1 = math.radians(lat1)
279-
long1 = math.radians(long1)
280-
281-
lat2 = math.radians(lat2)
282-
long2 = math.radians(long2)
283-
284-
d_lat = lat2 - lat1
285-
d_long = long2 - long1
286-
287-
radicand = 1 - math.cos(d_lat) + (math.cos(lat1) * math.cos(lat2) * (1 - math.cos(d_long)))
288-
s9rt = math.sqrt(radicand / 2)
289-
# radius of the earth
290-
r = 6371
291-
292-
return 2 * r * math.asin(s9rt)

tests/unit/providers/suggest/weather/backends/test_utils.py

-194
This file was deleted.

0 commit comments

Comments
 (0)