diff --git a/solara/autorouting.py b/solara/autorouting.py index 542224b64..e81bfcd68 100644 --- a/solara/autorouting.py +++ b/solara/autorouting.py @@ -218,17 +218,25 @@ def get_args(f): title = route_current.label or "No title" title_element = solara.Title(title) module = None - if route_current.module is not None: + Page = route_current.component + # translate the default RenderPage as no value given (None) + if Page is RenderPage: + Page = None + if route_current.module is not None and (Page is None): + # if not a custom component is given, we try to find a Page component + # in the module assert route_current.module is not None module = route_current.module namespace = module.__dict__ - Page = nested_get(namespace, main_name, None) + Page = nested_get(namespace, main_name, Page) if Page is None: # app is for backwards compatibility - Page = namespace.get("page", namespace.get("app")) + Page = namespace.get("page", namespace.get("app", Page)) Page = nested_get(namespace, main_name, Page) - else: - Page = route_current.component + + if Page is None and route_current.children: + # we we did not get a component, but we recursively render + Page = RenderPage if isinstance(Page, ipywidgets.Widget): # If we have a widget, we need to execute this again for each # connection, since we cannot share widgets between connections/users. @@ -393,7 +401,7 @@ def generate_routes(module: ModuleType) -> List[solara.Route]: continue else: # skip empty modules - if get_renderable(submod) is None: + if get_renderable(submod) is None and not hasattr(submod, "routes"): continue children = getattr(submod, "routes", []) if subfile: diff --git a/tests/unit/autorouting_test.py b/tests/unit/autorouting_test.py index 17f12aafe..bf551d6ee 100644 --- a/tests/unit/autorouting_test.py +++ b/tests/unit/autorouting_test.py @@ -134,7 +134,7 @@ def test_routes_examples_docs(): def test_routes_directory(): routes = solara.autorouting.generate_routes_directory(HERE.parent / "solara_test_apps" / "multipage") - assert len(routes) == 7 + assert len(routes) == 8 assert routes[0].path == "/" assert routes[0].label == "Home" @@ -152,11 +152,18 @@ def test_routes_directory(): assert routes[4].path == "and-notebooks" assert routes[4].label == "And Notebooks" - assert routes[5].path == "single-file-directory" - assert routes[5].label == "Single File Directory" + assert routes[5].path == "custom-routes" + assert routes[5].label == "Custom Routes" + assert routes[5].children[0].path == "/" + assert routes[5].children[0].label == "Hi1" + assert routes[5].children[1].path == "page2" + assert routes[5].children[1].label == "Hi2" - assert routes[6].path == "some-other-python-script" - assert routes[6].label == "Some Other Python Script" + assert routes[6].path == "single-file-directory" + assert routes[6].label == "Single File Directory" + + assert routes[7].path == "some-other-python-script" + assert routes[7].label == "Some Other Python Script" main_object = solara.autorouting.RenderPage() solara_context = solara.RoutingProvider(children=[main_object], routes=routes, pathname="/") @@ -201,6 +208,16 @@ def test_routes_directory(): nav.location = "/a-directory/wrong-path" assert "Page not found" in rc._find(v.Alert).widget.children[0] + # custom routes in a single file + + nav.location = "/custom-routes" + button = rc._find(v.Btn, children=["hi1"]).widget + assert button.children[0] == "hi1" + + nav.location = "/custom-routes/page2" + button = rc._find(v.Btn, children=["hi2"]).widget + assert button.children[0] == "hi2" + def test_routes_regular_widgets(): # routes = solara.autorouting.generate_routes_directory(HERE.parent / "solara_test_apps" / "multipage")