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

Code before:
        self._add_url("", self.index)

        # catch-all for front-end routes, used by dcc.Location
        self._add_url("<path:path>", self.index)

    def _add_url(self, name, view_func, methods=("GET",)):
        full_name = self.config.routes_pathname_prefix + name

        self.server.add_url_rule(
            full_name, view_func=view_func, endpoint=full_name, methods=list(methods)
        )

        # record the url in Dash.routes so that it can be accessed later
        # e.g. for adding authentication with flask_login
        self.routes.append(full_name)

    @property
    def layout(self):
        return self._layout

    def _layout_value(self):
        layout = self._layout() if self._layout_is_function else self._layout

        # Add extra hidden components
        if self._extra_components:
            if not hasattr(layout, "children"):
                setattr(layout, "children", [])
            for c in self._extra_components:
                if c not in layout.children:
                    layout.children.append(c)

        return layout

    @layout.setter
    def layout(self, value):
        _validate.validate_layout_type(value)
        self._layout_is_function = isinstance(value, patch_collections_abc("Callable"))
        self._layout = value

        # for using flask.has_request_context() to deliver a full layout for
        # validation inside a layout function - track if a user might be doing this.
        if (
            self._layout_is_function
            and not self.validation_layout
            and not self.config.suppress_callback_exceptions
        ):

            def simple_clone(c, children=None):
                cls = type(c)
                # in Py3 we can use the __init__ signature to reduce to just
                # required args and id; in Py2 this doesn't work so we just

Review comment (suggestion):
Some simple apps just use `app.layout = DataTable(...)` or a graph or something, that don't support children. Mostly this is just for testing purposes but maybe not always. In that case what do we do, throw an error? Wrap in `html.Div`? Actually there's something nice about wrapping in a div, then we don't need to keep testing if we've already added these components into the layout, and don't need to mutate it. I can't really think of how mutating the layout would cause a problem but it makes me uneasy.

Code after:
        self._add_url("", self.index)

        # catch-all for front-end routes, used by dcc.Location
        self._add_url("<path:path>", self.index)

    def _add_url(self, name, view_func, methods=("GET",)):
        full_name = self.config.routes_pathname_prefix + name

        self.server.add_url_rule(
            full_name, view_func=view_func, endpoint=full_name, methods=list(methods)
        )

        # record the url in Dash.routes so that it can be accessed later
        # e.g. for adding authentication with flask_login
        self.routes.append(full_name)

    @property
    def layout(self):
        return self._layout

    def _layout_value(self):
        from dash_html_components import Div  # pylint: disable=import-outside-toplevel

        layout = self._layout() if self._layout_is_function else self._layout

        # Add any extra components
        if self._extra_components:
            layout = Div(children=[layout] + self._extra_components)

        return layout

    @layout.setter
    def layout(self, value):
        _validate.validate_layout_type(value)
        self._layout_is_function = isinstance(value, patch_collections_abc("Callable"))
        self._layout = value

        # for using flask.has_request_context() to deliver a full layout for
        # validation inside a layout function - track if a user might be doing this.
        if (
            self._layout_is_function
            and not self.validation_layout
            and not self.config.suppress_callback_exceptions
        ):

            def simple_clone(c, children=None):
                cls = type(c)
                # in Py3 we can use the __init__ signature to reduce to just
                # required args and id; in Py2 this doesn't work so we just
                # empty out children.
                sig = getattr(cls.__init__, "__signature__", None)