# Path: augur/util_support/node_data.py
# class DuplicatedNonDictAttributeError(Exception):
#     def __init__(self, key):
#         self.key = key
# 
# Path: augur/util_support/node_data.py
# class NodeData:
#     """Data structure representing a set of Augur nodes"""
# 
#     def __init__(self):
#         self.attrs = {}
# 
#     def update(self, new_attrs):
#         for k, v in new_attrs.items():
#             self.deep_add_or_update(self.attrs, k, v)
# 
#     def deep_add_or_update(self, d, key, value):
#         """
#         Recursively merge in new attributes using the following rules:
# 
#             if key is new:
#                 add it
#             if key is old, but the old value is not a dict:
#                 if new value is also not a dict:
#                     overwrite it
#                 if trying to overwrite a non-dict with a dict:
#                     raise exception
#             if key old and the old value is a dict:
#                 if new value is also a dict:
#                     recursively merge
#                 if trying to overwrite a dict with a non-dict:
#                     raise exception
#         """
# 
#         # TODO Python 3.9: Use the new dictionary union operator (https://www.python.org/dev/peps/pep-0584/)
# 
#         if key not in d or (
#             not isinstance(d[key], dict) and not isinstance(value, dict)
#         ):
#             d[key] = value
#             return
# 
#         if not isinstance(d[key], dict) or not isinstance(value, dict):
#             raise DuplicatedNonDictAttributeError(key)
# 
#         for sub_k, sub_v in value.items():
#             self.deep_add_or_update(d[key], sub_k, sub_v)


from augur.util_support.node_data import DuplicatedNonDictAttributeError
from augur.util_support.node_data import NodeData
import pytest



class TestNodeData:
    def test_update(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})
        assert node_data.attrs == {"a": 5, "b": {"c": 6}}

        node_data.update({"a": 7})
        assert node_data.attrs == {"a": 7, "b": {"c": 6}}

        node_data.update({"b": {"d": 8}})
        assert node_data.attrs == {"a": 7, "b": {"c": 6, "d": 8}}

        node_data.update({"b": {"d": 9}})
        assert node_data.attrs == {"a": 7, "b": {"c": 6, "d": 9}}

    def test_update_merge_nondict_into_dict(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})

        with pytest.raises(DuplicatedNonDictAttributeError):
            node_data.update({"b": "a string!"})

    def test_update_merge_dict_into_nondict(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})


# Path: augur/util_support/node_data.py
# class DuplicatedNonDictAttributeError(Exception):
#     def __init__(self, key):
#         self.key = key
# 
# Path: augur/util_support/node_data.py
# class NodeData:
#     """Data structure representing a set of Augur nodes"""
# 
#     def __init__(self):
#         self.attrs = {}
# 
#     def update(self, new_attrs):
#         for k, v in new_attrs.items():
#             self.deep_add_or_update(self.attrs, k, v)
# 
#     def deep_add_or_update(self, d, key, value):
#         """
#         Recursively merge in new attributes using the following rules:
# 
#             if key is new:
#                 add it
#             if key is old, but the old value is not a dict:
#                 if new value is also not a dict:
#                     overwrite it
#                 if trying to overwrite a non-dict with a dict:
#                     raise exception
#             if key old and the old value is a dict:
#                 if new value is also a dict:
#                     recursively merge
#                 if trying to overwrite a dict with a non-dict:
#                     raise exception
#         """
# 
#         # TODO Python 3.9: Use the new dictionary union operator (https://www.python.org/dev/peps/pep-0584/)
# 
#         if key not in d or (
#             not isinstance(d[key], dict) and not isinstance(value, dict)
#         ):
#             d[key] = value
#             return
# 
#         if not isinstance(d[key], dict) or not isinstance(value, dict):
#             raise DuplicatedNonDictAttributeError(key)
# 
#         for sub_k, sub_v in value.items():
#             self.deep_add_or_update(d[key], sub_k, sub_v)


# Path: tests/util_support/test_node_data.py
from augur.util_support.node_data import DuplicatedNonDictAttributeError
from augur.util_support.node_data import NodeData
import pytest




class TestNodeData:
    def test_update(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})
        assert node_data.attrs == {"a": 5, "b": {"c": 6}}

        node_data.update({"a": 7})
        assert node_data.attrs == {"a": 7, "b": {"c": 6}}

        node_data.update({"b": {"d": 8}})
        assert node_data.attrs == {"a": 7, "b": {"c": 6, "d": 8}}

        node_data.update({"b": {"d": 9}})
        assert node_data.attrs == {"a": 7, "b": {"c": 6, "d": 9}}

    def test_update_merge_nondict_into_dict(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})

        with pytest.raises(DuplicatedNonDictAttributeError):
            node_data.update({"b": "a string!"})

    def test_update_merge_dict_into_nondict(self):
        node_data = NodeData()
        node_data.update({"a": 5, "b": {"c": 6}})


        with pytest.raises(DuplicatedNonDictAttributeError):