Skip to content

Commit 100fef5

Browse files
authored
Merge pull request #20 from ways/performance-and-refactoring-improvements
Improve code quality and error handling
2 parents d4aa839 + 0daacc8 commit 100fef5

File tree

2 files changed

+44
-45
lines changed

2 files changed

+44
-45
lines changed

fingr.py

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -146,60 +146,52 @@ def clean_input(data: str) -> str:
146146

147147
def resolve_location(
148148
redis_client: redis.client,
149+
geolocator: Nominatim,
149150
data="Oslo/Norway",
150151
) -> Tuple[Optional[float], Optional[float], str, bool]:
151-
"""Get coordinates from location name. Return lat, long, name."""
152-
cache = None
153-
152+
"""Get coordinates from location name. Return lat, long, name, cached."""
154153
# Check if coordinates
155154
if "," in data:
156-
lat, lon = data.split(",")
157155
try:
158-
lat = float(lat)
159-
lon = float(lon)
156+
lat_str, lon_str = data.split(",", 1)
157+
lat = float(lat_str)
158+
lon = float(lon_str)
160159
return lat, lon, f"coordinates {lat}, {lon}", False
161-
except ValueError:
160+
except (ValueError, IndexError):
162161
pass
163162

164-
lat = None
165-
lon = None
166-
address = None
167-
168163
# Check if in redis cache
169-
if redis_client is not None:
170-
cache = redis_client.get(data)
164+
cache = redis_client.get(data) if redis_client is not None else None
171165
if cache:
172-
lat, lon, address = cache.decode("utf-8").split("|")
173-
lat = float(lat)
174-
lon = float(lon)
166+
lat_str, lon_str, address = cache.decode("utf-8").split("|", 2)
167+
return float(lat_str), float(lon_str), address, True
175168

176-
else:
177-
coordinate = None
178-
try:
179-
coordinate = geolocator.geocode(data, language="en")
180-
except socket.timeout as err:
181-
# nominatim.openstreetmap.org down
182-
print(f"nominatim.openstreetmap.org down. {err}")
183-
return None, None, "No service", False
184-
if coordinate:
185-
lat = coordinate.latitude
186-
lon = coordinate.longitude
187-
try:
188-
address = coordinate.address.decode("utf-8")
189-
except AttributeError:
190-
address = coordinate.address
169+
# Geocode the location
170+
try:
171+
coordinate = geolocator.geocode(data, language="en")
172+
except socket.timeout as err:
173+
logger.warning("Geocoding service timeout: %s", err)
174+
return None, None, "No service", False
191175

192-
if lat:
193-
# Store to redis cache as <search>: "lat,lon,address"
194-
if not cache:
176+
if not coordinate:
177+
return None, None, "No location found", False
178+
179+
lat = coordinate.latitude
180+
lon = coordinate.longitude
181+
address = coordinate.address if isinstance(coordinate.address, str) else str(coordinate.address)
182+
183+
# Store to redis cache as <search>: "lat|lon|address"
184+
if redis_client is not None:
185+
try:
195186
redis_client.setex(
196187
data,
197188
datetime.timedelta(days=7),
198-
"|".join([str(lat), str(lon), str(address)]),
189+
"|".join([str(lat), str(lon), address]),
199190
)
200-
return lat, lon, address, cache
191+
except redis.exceptions.RedisError as err:
192+
logger.warning("Redis cache write failed: %s", err)
201193

202-
return None, None, "No location found", False
194+
return lat, lon, address, False
203195

204196

205197
def fetch_weather(lat: float, lon: float, address: str = ""):
@@ -504,6 +496,8 @@ def format_oneliner(forecast, timezone, imperial=False, beaufort=False, offset=0
504496

505497
async def handle_request(reader, writer):
506498
"""Receives connections and responds."""
499+
global r, geolocator
500+
507501
data = await reader.read(input_limit)
508502
response = ""
509503
updated = None
@@ -544,16 +538,20 @@ async def handle_request(reader, writer):
544538
user_input = user_input[1:]
545539
wind_chill = True
546540

541+
# Parse screen width
547542
if "~" in user_input:
548-
screenwidth = int(user_input.split("~")[1])
549-
user_input = user_input.split("~")[0]
543+
try:
544+
user_input, width_str = user_input.split("~", 1)
545+
screenwidth = max(80, min(int(width_str), 200))
546+
except ValueError:
547+
pass
550548

551549
if user_input == "help" or len(user_input) == 0:
552550
logger.info("%s help", addr[0])
553551
response = service_usage()
554552

555553
else:
556-
lat, lon, address, cached_location = resolve_location(r, user_input)
554+
lat, lon, address, cached_location = resolve_location(r, geolocator, user_input)
557555
if not lat:
558556
if address == "No service":
559557
response += "Error: address service down. You can still use coordinates."
@@ -605,9 +603,11 @@ async def handle_request(reader, writer):
605603
writer.close()
606604

607605
if last_reply_file:
608-
with open(last_reply_file, mode="w", encoding="utf-8") as f:
609-
f.write(addr[0] + " " + user_input + "\n\n")
610-
f.write(response)
606+
try:
607+
with open(last_reply_file, mode="w", encoding="utf-8") as f:
608+
f.write(f"{addr[0]} {user_input}\n\n{response}")
609+
except OSError as err:
610+
logger.warning("Failed to write last reply file: %s", err)
611611

612612

613613
async def main(args):

fingr_test.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313

1414
class TestServerMethods(unittest.TestCase):
15-
1615
def test_wind_direction(self):
1716
"""Test results from wind direction"""
1817
symbol = fingr.wind_direction(123)
@@ -44,7 +43,7 @@ def test_resolve_location(self):
4443
r = redis.Redis(host=server_address[0], port=server_address[1])
4544

4645
latitude, longitude, address, cached = fingr.resolve_location(
47-
r, data="Oslo/Norway"
46+
r, fingr.geolocator, data="Oslo/Norway"
4847
)
4948
self.assertEqual(latitude, 59.9133301)
5049
self.assertEqual(longitude, 10.7389701)

0 commit comments

Comments
 (0)