From 0667739aa23464cbfbb7565cb7d63f7e0994f074 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 11 Jun 2023 13:01:47 +0000 Subject: [PATCH 1/2] Closes #1087. This PR addresses an edge-case where `AssertionError` is raised during a call to `OmegaConf.unsafe_merge`. This PR is marked as a draft: - I haven't written tests yet - I'm not sure if this is the best approach to solving the issue. --- omegaconf/basecontainer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/omegaconf/basecontainer.py b/omegaconf/basecontainer.py index 575df3c72..8f3279a26 100644 --- a/omegaconf/basecontainer.py +++ b/omegaconf/basecontainer.py @@ -531,8 +531,12 @@ def _set_item_impl(self, key: Any, value: Any) -> None: if isinstance(value, Node): do_deepcopy = not self._get_flag("no_deepcopy_set_nodes") if not do_deepcopy and isinstance(value, Box): + # Detect the special case where value has no root: + value_has_root = ( + isinstance(value, Container) or value._get_parent() is not None + ) # if value is from the same config, perform a deepcopy no matter what. - if self._get_root() is value._get_root(): + if value_has_root and self._get_root() is value._get_root(): do_deepcopy = True if do_deepcopy: From 3cc1ba6205954f9fab4dfdf0dfd5c7862cef0f4c Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:23:50 +0000 Subject: [PATCH 2/2] add test --- tests/test_merge.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_merge.py b/tests/test_merge.py index e5310eca5..07a0e8f53 100644 --- a/tests/test_merge.py +++ b/tests/test_merge.py @@ -1,6 +1,7 @@ import copy import re import sys +from dataclasses import dataclass from textwrap import dedent from typing import ( Any, @@ -1412,6 +1413,26 @@ def test_merge_with_other_as_interpolation( assert OmegaConf.is_interpolation(res, node) +@mark.parametrize("merge", [OmegaConf.merge, OmegaConf.unsafe_merge]) +def test_merge_with_nested_structured_config_and_union_type( + merge: Any, +) -> None: + @dataclass + class Inner: + x: Union[int, str] + + @dataclass + class Outer: + inner: Inner + + dst = OmegaConf.structured(Outer) + src = OmegaConf.create({"inner": {"x": 10}}) + res = merge(dst, src) + + expected = {"inner": {"x": 10}} + assert res == expected + + @mark.parametrize( ("c1", "c2"), [