Skip to content

Commit d5817b0

Browse files
committed
Refactor for removing the need for saving last match group
1 parent e6ad4d0 commit d5817b0

File tree

1 file changed

+52
-29
lines changed

1 file changed

+52
-29
lines changed

adafruit_httpserver/route.py

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"""
99

1010
try:
11-
from typing import Callable, List, Union
11+
from typing import Callable, List, Union, Tuple
1212
except ImportError:
1313
pass
1414

@@ -22,41 +22,56 @@ class _HTTPRoute:
2222

2323
def __init__(self, path: str = "", method: HTTPMethod = HTTPMethod.GET) -> None:
2424

25-
contains_regex = re.search(r"<\w*>", path) is not None
25+
contains_parameters = re.search(r"<\w*>", path) is not None
2626

27-
self.path = path if not contains_regex else re.sub(r"<\w*>", r"([^/]*)", path)
27+
self.path = (
28+
path if not contains_parameters else re.sub(r"<\w*>", r"([^/]*)", path)
29+
)
2830
self.method = method
29-
self._contains_regex = contains_regex
30-
self._last_match_groups: Union[List[str], None] = None
31+
self._contains_parameters = contains_parameters
3132

32-
def matches(self, other: "_HTTPRoute") -> bool:
33+
def match(self, other: "_HTTPRoute") -> Tuple[bool, List[str]]:
3334
"""
3435
Checks if the route matches the other route.
3536
3637
If the route contains parameters, it will check if the ``other`` route contains values for
3738
them.
39+
40+
Returns tuple of a boolean and a list of strings. The boolean indicates if the routes match,
41+
and the list contains the values of the url parameters from the ``other`` route.
42+
43+
Examples::
44+
45+
route = _HTTPRoute("/example", HTTPMethod.GET)
46+
47+
other1 = _HTTPRoute("/example", HTTPMethod.GET)
48+
route.matches(other1) # True, []
49+
50+
other2 = _HTTPRoute("/other-example", HTTPMethod.GET)
51+
route.matches(other2) # False, []
52+
53+
...
54+
55+
route = _HTTPRoute("/example/<parameter>", HTTPMethod.GET)
56+
57+
other1 = _HTTPRoute("/example/123", HTTPMethod.GET)
58+
route.matches(other1) # True, ["123"]
59+
60+
other2 = _HTTPRoute("/other-example", HTTPMethod.GET)
61+
route.matches(other2) # False, []
3862
"""
63+
3964
if self.method != other.method:
40-
return False
65+
return False, []
4166

42-
if not self._contains_regex:
43-
return self.path == other.path
67+
if not self._contains_parameters:
68+
return self.path == other.path, []
4469

4570
regex_match = re.match(self.path, other.path)
4671
if regex_match is None:
47-
return False
48-
49-
self._last_match_groups = regex_match.groups()
50-
return True
51-
52-
def last_match_groups(self) -> Union[List[str], None]:
53-
"""
54-
Returns the last match groups from the last call to `matches`.
72+
return False, []
5573

56-
Useful for getting the values of the parameters from the route, without the need to call
57-
`re.match` again.
58-
"""
59-
return self._last_match_groups
74+
return True, regex_match.groups()
6075

6176
def __repr__(self) -> str:
6277
return f"_HTTPRoute(path={repr(self.path)}, method={repr(self.method)})"
@@ -90,19 +105,27 @@ def route_func(request, my_parameter):
90105
request.path == "/example/123" # True
91106
my_parameter == "123" # True
92107
"""
108+
if not self._routes:
109+
raise ValueError("No routes added")
110+
111+
found_route, _route = False, None
112+
113+
for _route in self._routes:
114+
matches, url_parameters_values = _route.match(route)
115+
116+
if matches:
117+
found_route = True
118+
break
93119

94-
try:
95-
matched_route = next(filter(lambda r: r.matches(route), self._routes))
96-
except StopIteration:
120+
if not found_route:
97121
return None
98122

99-
handler = self._handlers[self._routes.index(matched_route)]
100-
args = matched_route.last_match_groups() or []
123+
handler = self._handlers[self._routes.index(_route)]
101124

102-
def wrapper(request):
103-
return handler(request, *args)
125+
def wrapped_handler(request):
126+
return handler(request, *url_parameters_values)
104127

105-
return wrapper
128+
return wrapped_handler
106129

107130
def __repr__(self) -> str:
108131
return f"_HTTPRoutes({repr(self._routes)})"

0 commit comments

Comments
 (0)