Пример #1
0
def _create_root(config_name: Optional[str], with_hydra: bool) -> DefaultsTreeNode:
    primary: InputDefault
    if config_name is not None:
        primary = ConfigDefault(path=config_name, primary=True)
    else:
        primary = VirtualRoot()

    if with_hydra:
        root = DefaultsTreeNode(
            node=VirtualRoot(),
            children=[ConfigDefault(path="hydra/config"), primary],
        )
    else:
        root = DefaultsTreeNode(node=primary)
    return root
Пример #2
0
def _validate_self(
    containing_node: InputDefault,
    defaults: List[InputDefault],
    has_config_content: bool,
) -> bool:
    # check that self is present only once
    has_self = False
    has_non_override = False
    for d in defaults:
        if not d.is_override():
            has_non_override = True
        if d.is_self():
            if has_self:
                raise ConfigCompositionException(
                    f"Duplicate _self_ defined in {containing_node.get_config_path()}"
                )
            has_self = True

    if not has_self and has_non_override or len(defaults) == 0:
        # This check is here to make the migration from Hydra 1.0 to Hydra 1.1 smoother and should be removed in 1.2
        # The warning should be removed in 1.2
        if containing_node.primary and has_config_content and has_non_override:
            msg = (
                f"In '{containing_node.get_config_path()}': Defaults list is missing `_self_`. "
                f"See https://hydra.cc/docs/upgrades/1.0_to_1.1/default_composition_order for more information"
            )
            if os.environ.get("SELF_WARNING_AS_ERROR") == "1":
                raise ConfigCompositionException(msg)
            warnings.warn(msg, UserWarning)
        defaults.append(ConfigDefault(path="_self_"))

    return not has_self
Пример #3
0
def _validate_self(containing_node: InputDefault, defaults: List[InputDefault]) -> bool:
    # check that self is present only once
    has_self = False
    has_non_override = False
    for d in defaults:
        if not d.is_override():
            has_non_override = True
        if d.is_self():
            if has_self:
                raise ConfigCompositionException(
                    f"Duplicate _self_ defined in {containing_node.get_config_path()}"
                )
            has_self = True

    if not has_self and has_non_override or len(defaults) == 0:
        defaults.append(ConfigDefault(path="_self_"))

    return not has_self
Пример #4
0
def _create_defaults_tree_impl(
    repo: IConfigRepository,
    root: DefaultsTreeNode,
    is_root_config: bool,
    skip_missing: bool,
    interpolated_subtree: bool,
    overrides: Overrides,
) -> DefaultsTreeNode:
    parent = root.node
    children: List[Union[InputDefault, DefaultsTreeNode]] = []
    if parent.is_virtual():
        if is_root_config:
            return _expand_virtual_root(repo, root, overrides, skip_missing)
        else:
            return root

    if is_root_config:
        root.node.update_parent("", "")
        if not repo.config_exists(root.node.get_config_path()):
            config_not_found_error(repo=repo, tree=root)

    update_package_header(repo=repo, node=parent)

    if overrides.is_deleted(parent):
        overrides.delete(parent)
        return root

    overrides.set_known_choice(parent)

    if parent.get_name() is None:
        return root

    if _check_not_missing(repo=repo, default=parent,
                          skip_missing=skip_missing):
        return root

    path = parent.get_config_path()
    loaded = repo.load_config(config_path=path)

    if loaded is None:
        if parent.is_optional():
            assert isinstance(parent, (GroupDefault, ConfigDefault))
            parent.deleted = True
            return root
        config_not_found_error(repo=repo, tree=root)

    assert loaded is not None
    defaults_list = copy.deepcopy(loaded.defaults_list)
    if defaults_list is None:
        defaults_list = []

    self_added = False
    if (len(defaults_list) > 0
            or is_root_config and len(overrides.append_group_defaults) > 0):
        self_added = _validate_self(containing_node=parent,
                                    defaults=defaults_list)

    if is_root_config:
        # To ensure config overrides are last, insert the external overrides before the first config override.
        insert_idx = len(defaults_list)
        for idx, default in enumerate(defaults_list):
            if default.is_override():
                insert_idx = idx
                break

        defaults_list[insert_idx:insert_idx] = overrides.append_group_defaults

    _update_overrides(defaults_list, overrides, parent, interpolated_subtree)

    def add_child(
        child_list: List[Union[InputDefault, DefaultsTreeNode]],
        new_root_: DefaultsTreeNode,
    ) -> None:
        subtree_ = _create_defaults_tree_impl(
            repo=repo,
            root=new_root_,
            is_root_config=False,
            interpolated_subtree=interpolated_subtree,
            skip_missing=skip_missing,
            overrides=overrides,
        )
        if subtree_.children is None:
            child_list.append(new_root_.node)
        else:
            child_list.append(subtree_)

    for d in reversed(defaults_list):
        if d.is_self():
            d.update_parent(root.node.parent_base_dir, root.node.get_package())
            children.append(d)
        else:
            if d.is_override():
                continue

            d.update_parent(parent.get_group_path(),
                            parent.get_final_package())

            if overrides.is_overridden(d):
                assert isinstance(d, GroupDefault)
                overrides.override_default_option(d)

            if isinstance(d, GroupDefault) and d.is_options():
                # overriding may change from options to name
                if d.is_options():
                    for item in reversed(d.get_options()):
                        if "${" in item:
                            raise ConfigCompositionException(
                                f"In '{path}': Defaults List interpolation is not supported in options list items"
                            )

                        assert d.group is not None
                        node = ConfigDefault(
                            path=d.group + "/" + item,
                            package=d.package,
                            optional=d.is_optional(),
                        )
                        node.update_parent(parent.get_group_path(),
                                           parent.get_final_package())
                        new_root = DefaultsTreeNode(node=node, parent=root)
                        add_child(children, new_root)
                else:
                    new_root = DefaultsTreeNode(node=d, parent=root)
                    add_child(children, new_root)

            else:
                if d.is_interpolation():
                    children.append(d)
                    continue

                new_root = DefaultsTreeNode(node=d, parent=root)
                add_child(children, new_root)

    # processed deferred interpolations
    known_choices = _create_interpolation_map(overrides, defaults_list,
                                              self_added)

    for idx, dd in enumerate(children):
        if isinstance(dd, InputDefault) and dd.is_interpolation():
            dd.resolve_interpolation(known_choices)
            new_root = DefaultsTreeNode(node=dd, parent=root)
            dd.update_parent(parent.get_group_path(),
                             parent.get_final_package())
            subtree = _create_defaults_tree_impl(
                repo=repo,
                root=new_root,
                is_root_config=False,
                skip_missing=skip_missing,
                interpolated_subtree=True,
                overrides=overrides,
            )
            if subtree.children is not None:
                children[idx] = subtree

    if len(children) > 0:
        root.children = list(reversed(children))

    return root