def from_config(
        cls,
        config: BlocksConfigDict,
        fns: list[Callable],
        proxy_url: str,
    ) -> Blocks:
        """
        Factory method that creates a Blocks from a config and list of functions. Used
        internally by the gradio.external.load() method.

        Parameters:
        config: a dictionary containing the configuration of the Blocks.
        fns: a list of functions that are used in the Blocks. Must be in the same order as the dependencies in the config.
        proxy_url: an external url to use as a root URL when serving files for components in the Blocks.
        """
        config = copy.deepcopy(config)
        components_config = config["components"]
        theme = config.get("theme", "default")
        original_mapping: dict[int, Block] = {}
        proxy_urls = {proxy_url}

        def get_block_instance(id: int) -> Block:
            for block_config in components_config:
                if block_config["id"] == id:
                    break
            else:
                raise ValueError(f"Cannot find block with id {id}")
            cls = component_or_layout_class(block_config["props"]["name"])

            # If a Gradio app B is loaded into a Gradio app A, and B itself loads a
            # Gradio app C, then the proxy_urls of the components in A need to be the
            # URL of C, not B. The else clause below handles this case.
            if block_config["props"].get("proxy_url") is None:
                block_config["props"]["proxy_url"] = f"{proxy_url}/"
            postprocessed_value = block_config["props"].pop("value", None)

            constructor_args = cls.recover_kwargs(block_config["props"])
            block = cls(**constructor_args)
            if postprocessed_value is not None:
                block.value = postprocessed_value  # type: ignore

            block_proxy_url = block_config["props"]["proxy_url"]
            block.proxy_url = block_proxy_url
            proxy_urls.add(block_proxy_url)
            if (
                _selectable := block_config["props"].pop("_selectable", None)
            ) is not None:
                block._selectable = _selectable  # type: ignore

            return block

        def iterate_over_children(children_list):
            for child_config in children_list:
                id = child_config["id"]
                block = get_block_instance(id)

                original_mapping[id] = block

                children = child_config.get("children")
                if children is not None:
                    if not isinstance(block, BlockContext):
                        raise ValueError(
                            f"Invalid config, Block with id {id} has children but is not a BlockContext."
                        )
                    with block:
                        iterate_over_children(children)

        derived_fields = ["types"]

        with Blocks(theme=theme) as blocks:
            # ID 0 should be the root Blocks component
            original_mapping[0] = root_block = Context.root_block or blocks

            if "layout" in config:
                iterate_over_children(config["layout"].get("children", []))

            first_dependency = None

            # add the event triggers
            if "dependencies" not in config:
                raise ValueError(
                    "This config is missing the 'dependencies' field and cannot be loaded."
                )
            for dependency, fn in zip(config["dependencies"], fns, strict=False):
                # We used to add a "fake_event" to the config to cache examples
                # without removing it. This was causing bugs in calling gr.load
                # We fixed the issue by removing "fake_event" from the config in examples.py
                # but we still need to skip these events when loading the config to support
                # older demos
                if "trigger" in dependency and dependency["trigger"] == "fake_event":
                    continue
                for field in derived_fields:
                    dependency.pop(field, None)

                # older versions had a separate trigger field, but now it is part of the
                # targets field
                _targets = dependency.pop("targets")
                trigger = dependency.pop("trigger", None)
                is_then_event = False

                # This assumes that you cannot combine multiple .then() events in a single
                # gr.on() event, which is true for now. If this changes, we will need to
                # update this code.
                if not isinstance(_targets[0], int) and _targets[0][1] in [
                    "then",
                    "success",
                ]:
                    if len(_targets) != 1:
                        raise ValueError(
                            "This logic assumes that .then() events are not combined with other events in a single gr.on() event"
                        )
                    is_then_event = True

                dependency.pop("backend_fn")
                dependency.pop("documentation", None)
                dependency["inputs"] = [
                    original_mapping[i] for i in dependency["inputs"]
                ]
                dependency["outputs"] = [
                    original_mapping[o] for o in dependency["outputs"]
                ]
                dependency.pop("status_tracker", None)
                dependency.pop("zerogpu", None)
                dependency.pop("id", None)
                dependency.pop("rendered_in", None)
                dependency.pop("render_id", None)
                dependency.pop("every", None)
                dependency["preprocess"] = False
                dependency["postprocess"] = False
                if is_then_event:
                    targets = [EventListenerMethod(None, "then")]
                    dependency["trigger_after"] = dependency.pop("trigger_after")
                    dependency["trigger_only_on_success"] = dependency.pop(
                        "trigger_only_on_success"
                    )
                    dependency["no_target"] = True
                else:
                    targets = [
                        EventListenerMethod(
                            t.__self__ if t.has_trigger else None,
                            t.event_name,  # type: ignore
                        )
                        for t in Blocks.get_event_targets(
                            original_mapping, _targets, trigger
                        )
                    ]
                dependency = root_block.default_config.set_event_trigger(
                    targets=targets, fn=fn, **dependency
                )[0]
                if first_dependency is None:
                    first_dependency = dependency

            # Allows some use of Interface-specific methods with loaded Spaces
            if first_dependency and get_blocks_context():
                blocks.predict = [fns[0]]
                blocks.input_components = first_dependency.inputs
                blocks.output_components = first_dependency.outputs
                blocks.__name__ = "Interface"
                blocks.api_mode = True
        blocks.proxy_urls = proxy_urls
        return blocks

        Factory method that creates a Blocks from a config and list of functions. Used
        internally by the gradio.external.load() method.

        Parameters:
        config: a dictionary containing the configuration of the Blocks.
        fns: a list of functions that are used in the Blocks. Must be in the same order as the dependencies in the config.
        proxy_url: an external url to use as a root URL when serving files for components in the Blocks.
        
gradio/blocks.py