Skip to content

Instantly share code, notes, and snippets.

@nitori
Last active July 10, 2024 17:35
Show Gist options
  • Save nitori/fdd56e700496f5f49d7eb32b60a32004 to your computer and use it in GitHub Desktop.
Save nitori/fdd56e700496f5f49d7eb32b60a32004 to your computer and use it in GitHub Desktop.
Sample App with routes and route parameters
import re
def extract_variables(endpoint: str):
"""
Very simple route "parsing" using regex:
The route:
"/item/{item_id}"
becomes:
[
('string', '/item/'),
('variable', 'item_id'),
]
"""
parts = re.split(r'\{(\w+)\}', endpoint) # -> ["/item/", "item_id", ""]
route_pieces = []
for i, part in enumerate(parts):
if i % 2 == 0:
route_pieces.append(('string', part))
else:
route_pieces.append(('variable', part))
# if the last part was a variable, it still ends with one
# empty ('string', '') part, that we just remove.
if route_pieces[-1][1] == '':
route_pieces.pop()
return route_pieces
class Route:
"""A simple route class"""
def __init__(self, pattern: str, func):
self.pattern = pattern
self.func = func
self._regex_pattern = re.compile(self._compile_as_regexp(pattern))
def _compile_as_regexp(self, pattern: str):
"""
A pattern like: "/item/{item_id}"
becomes a regex like: "/item/(?P<item_id>[^/]+)"
"""
parts = extract_variables(pattern)
regex_parts = []
for kind, part in parts:
if kind == 'string':
regex_parts.append(re.escape(part))
else:
regex_parts.append(rf'(?P<{part}>[^/]+)')
return '^' + ''.join(regex_parts) + '$'
def matches(self, request_path: str):
return self._regex_pattern.match(request_path)
class App:
"""A simple App"""
def __init__(self):
self.routes = []
def get(self, pattern: str):
def decorator(func):
print('This is called immediately on function definition (not when the function is called).')
self.routes.append(Route(pattern, func))
return func
return decorator
def match(self, request: str):
"""find a route that matches the request"""
for route in self.routes:
if m := route.matches(request):
return route, m.groupdict()
app = App()
@app.get("/item/{item_id}")
def get_item(item_id):
print('hello. The item id is:', item_id)
print('Routes have been registered:')
print(app.routes)
result = app.match('/item/123')
if result:
route, view_args = result
route.func(**view_args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment