Repository: plotly/dash
File: dash/_pages.py (Python)

Code before:
    page.update(redirect_from=_set_redirect(redirect_from, page["path"]))

    PAGE_REGISTRY[module] = page

    if page["path_template"]:
        _validate.validate_template(page["path_template"])

    if layout is not None:
        # Override the layout found in the file set during `plug`
        PAGE_REGISTRY[module]["layout"] = layout

    # set home page order
    order_supplied = any(
        p["supplied_order"] is not None for p in PAGE_REGISTRY.values()
    )

    for p in PAGE_REGISTRY.values():
        p["order"] = (
            0 if p["path"] == "/" and not order_supplied else p["supplied_order"]
        )
        p["relative_path"] = get_relative_path(p["path"])

    # Sort by order and module, then by module
    for page in sorted(
        PAGE_REGISTRY.values(),
        key=lambda i: (str(i.get("order", i["module"])).zfill(9), i["module"]),
    ):
        PAGE_REGISTRY.move_to_end(page["module"])


def _path_to_page(path_id):
    path_variables = None
    for page in PAGE_REGISTRY.values():
        if page["path_template"]:
            template_id = page["path_template"].strip("/")
            path_variables = _parse_path_variables(path_id, template_id)
            if path_variables:
                return page, path_variables
        if path_id == page["path"].strip("/"):
            return page, path_variables
    return {}, None


def _page_meta_tags(app):
    start_page, path_variables = _path_to_page(flask.request.path.strip("/"))

    # use the supplied image_url or create url based on image in the assets folder
    image = start_page.get("image", "")
    if image:
        image = app.get_asset_url(image)
    assets_image_url = (

Review comment (bug):
Thanks @gothicVI! This seems like it would fix a lot of common cases, feels a little arbitrary though, and IDK if anyone does this but it would also prevent using fractional orders, in case you want to squeeze a new page between two existing pages.

Also, I just had a chat with @AnnMarieW about this, if you provide a string for `order` it will interleave with `module` names - is that what we want? Or do we want everything that has a defined `order` to come before anything that doesn't? @AnnMarieW points out that if we change that it could be considered a breaking change, but I think we could argue this is also a bug and we should fix it.

My proposal then would be we order as:
- all defined numeric orders
- then all defined string orders
- with module as a secondary sort only when orders are equal.

which we could write as perhaps:
```suggestion
        key=lambda i: (
            "order" not in i,  # False (order given) sorts before True
            i["order"] if isinstance(i.get("order"), (int, float)) else float("inf"),
            str(i.get("order")),
            i["module"],
        ),
```
Whatever we end up with, let's extend [test_pages_order](https://github.com/plotly/dash/blob/dev/tests/integration/multi_page/test_pages_order.py) to lock in the fixed behavior.

Code after:
    page.update(redirect_from=_set_redirect(redirect_from, page["path"]))

    PAGE_REGISTRY[module] = page

    if page["path_template"]:
        _validate.validate_template(page["path_template"])

    if layout is not None:
        # Override the layout found in the file set during `plug`
        PAGE_REGISTRY[module]["layout"] = layout

    # set home page order
    order_supplied = any(
        p["supplied_order"] is not None for p in PAGE_REGISTRY.values()
    )

    for p in PAGE_REGISTRY.values():
        p["order"] = (
            0 if p["path"] == "/" and not order_supplied else p["supplied_order"]
        )
        p["relative_path"] = get_relative_path(p["path"])

    # Sort numeric orders first, then string orders, then no order,
    # finally by module name for matching orders
    for page in sorted(
        PAGE_REGISTRY.values(),
        key=lambda i: (
            i["order"] is None,  # False (order given) sorts before True
            i["order"] if isinstance(i["order"], (int, float)) else float("inf"),
            str(i["order"]),
            i["module"],
        ),
    ):
        PAGE_REGISTRY.move_to_end(page["module"])


def _path_to_page(path_id):
    path_variables = None
    for page in PAGE_REGISTRY.values():
        if page["path_template"]:
            template_id = page["path_template"].strip("/")
            path_variables = _parse_path_variables(path_id, template_id)
            if path_variables:
                return page, path_variables
        if path_id == page["path"].strip("/"):
            return page, path_variables
    return {}, None


def _page_meta_tags(app):
    start_page, path_variables = _path_to_page(flask.request.path.strip("/"))