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

Code before:
            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)
                props = {
                    p: getattr(c, p)
                    for p in c._prop_names  # pylint: disable=protected-access
                    if hasattr(c, p)
                    and (
                        p == "id" or not sig or sig.parameters[p].default == c.REQUIRED
                    )
                }
                if props.get("children", children):
                    props["children"] = children or []
                return cls(**props)

            layout_value = self._layout_value()

            if isinstance(layout_value, (list, tuple)):
                layout_value = html.Div(children=layout_value)

            _validate.validate_layout(value, layout_value)
            self.validation_layout = simple_clone(
                # pylint: disable=protected-access
                layout_value,
                [simple_clone(c) for c in layout_value._traverse_ids()],
            )

    @property
    def index_string(self):
        return self._index_string

    @index_string.setter
    def index_string(self, value):
        checks = (_re_index_entry, _re_index_config, _re_index_scripts)
        _validate.validate_index("index string", checks, value)
        self._index_string = value

    def serve_layout(self):
        layout = self._layout_value()

        # TODO - Set browser cache limit - pass hash into frontend
        return flask.Response(
            to_json(layout),
            mimetype="application/json",

Review comment (suggestion):
We can  delete the function [`simple_clone`](https://github.com/plotly/dash/blob/bbd013cd9d97d8c41700b240dd95c32e6b875998/dash/dash.py#L711-L727) and assign the `self.validation_layout = layout_value`  instead.

Code after:
        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
        ):

            layout_value = self._layout_value()
            _validate.validate_layout(value, layout_value)
            self.validation_layout = layout_value

    @property
    def index_string(self):
        return self._index_string

    @index_string.setter
    def index_string(self, value):
        checks = (_re_index_entry, _re_index_config, _re_index_scripts)
        _validate.validate_index("index string", checks, value)
        self._index_string = value

    def serve_layout(self):
        layout = self._layout_value()

        # TODO - Set browser cache limit - pass hash into frontend
        return flask.Response(
            to_json(layout),
            mimetype="application/json",
        )

    def _config(self):
        # pieces of config needed by the front end
        config = {
            "url_base_pathname": self.config.url_base_pathname,
            "requests_pathname_prefix": self.config.requests_pathname_prefix,
            "ui": self._dev_tools.ui,
            "props_check": self._dev_tools.props_check,
            "show_undo_redo": self.config.show_undo_redo,
            "suppress_callback_exceptions": self.config.suppress_callback_exceptions,
            "update_title": self.config.update_title,
            "children_props": ComponentRegistry.children_props,
            "serve_locally": self.config.serve_locally,
        }
        if not self.config.serve_locally:
            config["plotlyjs_url"] = self._plotlyjs_url
        if self._dev_tools.hot_reload:
            config["hot_reload"] = {
                # convert from seconds to msec as used by js `setInterval`