Source code for tests.test_utils

# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

from __future__ import annotations

import pytest

from extra_platforms._utils import _recursive_update, _remove_blanks


[docs] def test_recursive_update_basic(): """Test basic recursive update.""" a = {"key1": "value1", "key2": {"nested": "old"}} b = {"key2": {"nested": "new"}} result = _recursive_update(a, b) assert result["key1"] == "value1" assert result["key2"]["nested"] == "new"
[docs] def test_recursive_update_adds_new_keys(): """Test that recursive update ignores keys not in first dict.""" a = {"existing": "value"} b = {"existing": "updated", "new_key": "new_value"} result = _recursive_update(a, b) assert result["existing"] == "updated" assert "new_key" not in result
[docs] def test_recursive_update_strict_mode(): """Test strict mode raises ValueError for unregistered keys.""" a = {"existing": "value"} b = {"existing": "updated", "unregistered": "value"} with pytest.raises( ValueError, match="Parameter 'unregistered' found in second dict" ): _recursive_update(a, b, strict=True)
[docs] def test_recursive_update_deep_nesting(): """Test recursive update with deep nesting (3+ levels).""" a = { "level1": { "level2": { "level3": { "level4": "old_value", "keep": "this", }, }, }, } b = { "level1": { "level2": { "level3": { "level4": "new_value", }, }, }, } result = _recursive_update(a, b) assert result["level1"]["level2"]["level3"]["level4"] == "new_value" assert result["level1"]["level2"]["level3"]["keep"] == "this"
[docs] def test_recursive_update_overwrites_non_dict(): """Test that non-dict values are overwritten, not merged.""" a = {"key": "old_value"} b = {"key": "new_value"} result = _recursive_update(a, b) assert result["key"] == "new_value"
[docs] def test_recursive_update_preserves_original(): """Test that original dict is modified in place.""" a = {"key": "value"} b = {"key": "updated"} result = _recursive_update(a, b) # The function returns a, so result is the same object. assert result is a assert a["key"] == "updated"
[docs] @pytest.mark.parametrize( "blank_type,tree,remove_kwargs,should_remove", [ # Test removing None values ( "none", { "key1": "value", "key2": None, "key3": {"nested": None, "other": "keep"}, }, {"remove_none": True}, True, ), # Test keeping None values ( "none", {"key1": "value", "key2": None}, {"remove_none": False}, False, ), # Test removing empty strings ( "empty_string", { "key1": "value", "key2": "", "key3": {"nested": "", "other": "keep"}, }, {"remove_str": True}, True, ), # Test keeping empty strings ( "empty_string", {"key1": "value", "key2": ""}, {"remove_str": False}, False, ), # Test removing empty dicts ( "empty_dict", { "key1": "value", "key2": {}, "key3": {"nested": {}, "other": "keep"}, }, {"remove_dicts": True}, True, ), # Test keeping empty dicts ( "empty_dict", {"key1": "value", "key2": {}}, {"remove_dicts": False}, False, ), ], ) def test_remove_blanks_options(blank_type, tree, remove_kwargs, should_remove): """Test removing or keeping different types of blank values.""" result = _remove_blanks(tree, **remove_kwargs) assert "key1" in result if should_remove: # When removing, blank values should be gone assert "key2" not in result if "key3" in tree: assert "nested" not in result["key3"] assert result["key3"]["other"] == "keep" else: # When keeping, blank values should remain assert "key2" in result if blank_type == "none": assert result["key2"] is None elif blank_type == "empty_string": assert result["key2"] == "" elif blank_type == "empty_dict": assert result["key2"] == {}
[docs] def test_remove_blanks_mixed_scenario(): """Test removing all blank types in a mixed scenario.""" tree = { "keep_value": "value", "remove_none": None, "remove_empty_str": "", "remove_empty_dict": {}, "nested": { "keep": "this", "remove_none": None, "remove_empty": "", "deeply_nested": { "remove_all": None, }, }, } result = _remove_blanks(tree, remove_none=True, remove_str=True, remove_dicts=True) assert result == { "keep_value": "value", "nested": { "keep": "this", }, }
[docs] def test_remove_blanks_all_options_disabled(): """Test that nothing is removed when all options are disabled.""" tree = { "key1": "value", "key2": None, "key3": "", "key4": {}, } result = _remove_blanks( tree, remove_none=False, remove_str=False, remove_dicts=False ) assert result == tree
[docs] def test_remove_blanks_recursive_cleanup(): """Test that nested dicts are cleaned recursively.""" tree = { "level1": { "level2": { "level3": { "remove": None, }, }, }, } result = _remove_blanks(tree, remove_none=True, remove_dicts=True) # All nested empty dicts should be removed. assert result == {}
[docs] def test_remove_blanks_preserves_non_blank_values(): """Test that non-blank values of all types are preserved.""" tree = { "string": "text", "number": 42, "zero": 0, "false": False, "list": [1, 2, 3], "dict": {"key": "value"}, } result = _remove_blanks(tree) assert result == tree