diff --git a/.gitignore b/.gitignore index 4a1c268..dd2695a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ __pycache__ stderr.log sensitive.py *.egg-info +/ctabus_venv/* diff --git a/ctabus/fetch.py b/ctabus/fetch.py index 123a51e..789b02d 100644 --- a/ctabus/fetch.py +++ b/ctabus/fetch.py @@ -2,6 +2,7 @@ import json from urllib.parse import urlencode from urllib.request import urlopen +from ctabus.internal.exceptions import CTABusError, NoArrivalTimesError from ctabus.internal.config import API_KEY as api from ctabus.internal.disk_cache import disk_cache @@ -18,13 +19,18 @@ def get_data(type, api_key=api, timeout=None, **args): data = json.load(response)["bustime-response"] try: data["error"] - raise Exception(str(data["error"])) + raise CTABusError(data) except KeyError: return data def get_times(stop_id, api_key=api, timeout=None): - return get_data("getpredictions", api_key, stpid=stop_id, timeout=timeout) + try: + result = get_data("getpredictions", api_key, stpid=stop_id, timeout=timeout) + return result + except CTABusError as e: + if e.data["error"]["msg"] == "No arrival times": + raise NoArrivalTimesError(e.data) @disk_cache diff --git a/ctabus/internal/exceptions.py b/ctabus/internal/exceptions.py new file mode 100644 index 0000000..4246a4b --- /dev/null +++ b/ctabus/internal/exceptions.py @@ -0,0 +1,14 @@ +class CTABusError(Exception): + """Base error for ctabus module""" + + def __init__(self, data): + self.data = data + + +class NoArrivalTimesError(CTABusError): + """Error raised for when there are no bus times available""" + + def __init__(self, data): + self.message = "No arrival times available for stop id {}".format[ + data["error"]["stpid"] + ] diff --git a/ctabus/internal/search.py b/ctabus/internal/search.py index 3644797..ecc467c 100644 --- a/ctabus/internal/search.py +++ b/ctabus/internal/search.py @@ -3,6 +3,8 @@ import re import edlib +words_re = re.compile(r"[a-zA-Z0-9]+") + def editdistance(a, b): return edlib.align(a, b)["editDistance"] @@ -26,21 +28,27 @@ class Search: class StopSearch(Search): def __init__(self, query): super().__init__(query) - query = query.lower() - parts = re.split(r" ?(?:(?[^\)]+)\)", stop) - ret = [editdistance(self.query, stop), editdistance(self.query_reversed, stop)] - if paren: - paren = paren.group("data") - ret.append(editdistance(self.query, paren)) - if self.raw_lower in stop: - ret = (item - 100 for item in ret) - return min(ret) + raw_lower = stop.lower() + no_ampersand = raw_lower.replace("&", "and") + parts = words_re.findall(no_ampersand) + replaceable_parts = self.parts.copy() + total_distance = 0 + while len(parts) > 0 and len(replaceable_parts) > 0: + part = parts.pop() + lowest = max(map(len, replaceable_parts)) + index = 0 + for i in range(len(replaceable_parts)): + distance = editdistance(replaceable_parts[i], part) + if distance < lowest: + index = i + lowest = distance + total_distance += lowest + del replaceable_parts[index] + return total_distance def __str__(self): return "{}|{}".format(self.query, self.query_reversed) diff --git a/setup.py b/setup.py index 4fd1755..97f7754 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("requirements.txt") as file: setup( name="ctabus", - version="2.1.3", + version="2.2", description="Python package for tracking cta bus times", install_requires=INSTALL_REQUIRES, author="rlbr",