Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
Fix routing sort
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaoyingz committed Mar 28, 2024
1 parent 19359fc commit 124a5a4
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 39 deletions.
29 changes: 20 additions & 9 deletions src/python-flect/src/flect/routing/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ def parse_route_info_from_folder(
RouteInfo
The parsed route information.
"""
segment = ""
if not is_root_folder and not folder.stem.startswith(GROUP_ROUTE_PREFIX):
if folder.stem.startswith(DYNAMIC_ROUTE_PREFIX):
segment = "{" + folder.stem[len(DYNAMIC_ROUTE_PREFIX) :] + "}"
else:
segment = folder.stem
if not is_root_folder and folder.stem.startswith(DYNAMIC_ROUTE_PREFIX):
segment = "{" + folder.stem[len(DYNAMIC_ROUTE_PREFIX) :] + "}"
elif not is_root_folder and not folder.stem.startswith(GROUP_ROUTE_PREFIX):
segment = folder.stem
else:
segment = ""

path = f"{parent_path.rstrip('/')}/{segment}/" if segment else parent_path

Expand All @@ -120,7 +120,7 @@ def parse_route_info_from_folder(
return RouteInfo(segment=segment, path=path, absolute_path=absolute_path, loader_path=loader_path)


def get_client_routes(
def parse_client_routes(
folder: pathlib.Path,
is_root_folder: bool = True,
parent_path: str = "/",
Expand Down Expand Up @@ -153,7 +153,7 @@ def get_client_routes(

for child_folder in folder.iterdir():
if child_folder.is_dir() and child_folder.name not in EXCLUDED_FOLDER_NAMES:
routes.extend(get_client_routes(child_folder, False, route_info.path, route_info.absolute_path))
routes.extend(parse_client_routes(child_folder, False, route_info.path, route_info.absolute_path))

if page_file.is_file():
page_module = load_module(page_file)
Expand Down Expand Up @@ -184,4 +184,15 @@ def get_client_routes(
)
]

return sorted(routes, key=lambda route: path_priority(route.loader_path))
return routes


def sort_client_routes(routes: list[ClientRoute]) -> list[ClientRoute]:
for route in routes:
if route.children:
route.children = sort_client_routes(route.children)
return sorted(routes, key=lambda r: path_priority(r.loader_path))


def get_client_routes(folder: pathlib.Path) -> list[ClientRoute]:
return sort_client_routes(parse_client_routes(folder))
36 changes: 29 additions & 7 deletions src/python-flect/src/flect/routing/sort.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
import re

from flect.constants import DYNAMIC_ROUTE_PREFIX
from flect.constants import GROUP_ROUTE_PREFIX, LAYOUT_ROUTE_SUFFIX


def path_priority(path: str) -> tuple:
path = re.sub(rf"{DYNAMIC_ROUTE_PREFIX}[^/]+/", "", path)
parts = path.split("/")
"""
Calculate the priority of a route path based on several weighted factors.
catch_all_weight = float("inf") if "{path:path}" in path else 0
Parameters:
- path (str): The route path for which to calculate the priority.
Returns:
- tuple: A tuple representing the path's priority. Lower values indicate higher priority. The factors are:
1. catch_all_weight: Infinity if the path includes a catch-all pattern, indicating it should be matched last. Otherwise, 0.
2. depth_weight: The depth of the path, with deeper paths considered more specific and thus lower priority.
3. segment_weight: The last valid segment of the path, used for sorting when depths are equal.
4. layout_weight: 1 if the path is for a layout route, 0 otherwise. Layout routes typically have lower priority.
5. dynamic_weight: 1 if the path is for a dynamic route, 0 otherwise. Dynamic routes typically have lower priority.
"""

# Normalize path for processing
normalized_path = re.sub(rf"{GROUP_ROUTE_PREFIX}[^/]+/", "", path)
if normalized_path.endswith(LAYOUT_ROUTE_SUFFIX):
normalized_path = normalized_path[: -len(LAYOUT_ROUTE_SUFFIX)]

parts = normalized_path.strip("/").split("/")

# Calculate weights
catch_all_weight = float("inf") if "{path:path}" in normalized_path else 0
depth_weight = len(parts)
dynamic_weight = int(path.count("{"))
segment_weight = parts[-2] if len(parts) >= 2 else ""
return catch_all_weight, depth_weight, segment_weight, dynamic_weight
segment_weight = parts[-1] if parts else ""
layout_weight = 1 if path.endswith(LAYOUT_ROUTE_SUFFIX) else 0
dynamic_weight = 1 if path.endswith("}/") else 0

return catch_all_weight, depth_weight, segment_weight, layout_weight, dynamic_weight
43 changes: 22 additions & 21 deletions src/python-flect/tests/test_routing/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,29 @@ def test_get_client_routes(app_folder):
"loader_path": "/flect/_layout/",
"index": False,
"children": [
{
"segment": "",
"path": "/",
"absolute_path": "/flect/",
"loader_path": "/flect/",
"index": True,
"children": [],
},
{
"segment": "segment1",
"path": "/segment1/",
"absolute_path": "/flect/segment1/",
"loader_path": "/flect/segment1/_layout/",
"index": False,
"children": [
{
"segment": "segment1",
"path": "/segment1/",
"absolute_path": "/flect/segment1/",
"loader_path": "/flect/segment1/",
"index": True,
"children": [],
},
{
"segment": "",
"path": "/segment1/",
Expand All @@ -97,14 +113,6 @@ def test_get_client_routes(app_folder):
}
],
},
{
"segment": "{segment_id}",
"path": "/segment1/{segment_id}/",
"absolute_path": "/flect/segment1/dynamic__segment_id/",
"loader_path": "/flect/segment1/{segment_id}/",
"index": False,
"children": [],
},
{
"segment": "segment2",
"path": "/segment1/segment2/",
Expand All @@ -114,24 +122,17 @@ def test_get_client_routes(app_folder):
"children": [],
},
{
"segment": "segment1",
"path": "/segment1/",
"absolute_path": "/flect/segment1/",
"loader_path": "/flect/segment1/",
"index": True,
"segment": "{segment_id}",
"path": "/segment1/{segment_id}/",
"absolute_path": "/flect/segment1/dynamic__segment_id/",
"loader_path": "/flect/segment1/{segment_id}/",
"index": False,
"children": [],
},
],
},
{
"segment": "",
"path": "/",
"absolute_path": "/flect/",
"loader_path": "/flect/",
"index": True,
"children": [],
},
],
}
]

assert [route.model_dump() for route in routes] == expected_routes
4 changes: 2 additions & 2 deletions src/python-flect/tests/test_routing/test_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ def test_sort_path():
"/flect/segment1/",
"/flect/",
"{path:path}",
"/flect/segment1/dynamic__segment_id/",
"/flect/segment1/group__segment_id/",
]

assert sorted(paths, key=path_priority) == [
"/flect/",
"/flect/_layout/",
"/flect/segment1/",
"/flect/segment1/dynamic__segment_id/",
"/flect/segment1/group__segment_id/",
"/flect/segment1/_layout/",
"/flect/segment1/segment2/",
"/flect/segment1/segment3/",
Expand Down

0 comments on commit 124a5a4

Please sign in to comment.