|
11 | 11 | from cfgv import check_any |
12 | 12 | from cfgv import check_array |
13 | 13 | from cfgv import check_bool |
| 14 | +from cfgv import check_int |
14 | 15 | from cfgv import check_one_of |
15 | 16 | from cfgv import check_regex |
| 17 | +from cfgv import check_string |
16 | 18 | from cfgv import check_type |
17 | 19 | from cfgv import Conditional |
18 | 20 | from cfgv import ConditionalOptional |
19 | 21 | from cfgv import ConditionalRecurse |
20 | 22 | from cfgv import In |
| 23 | +from cfgv import KeyValueMap |
21 | 24 | from cfgv import load_from_filename |
22 | 25 | from cfgv import Map |
23 | 26 | from cfgv import MISSING |
@@ -728,3 +731,79 @@ def test_warn_additional_keys_when_has_extra_keys(warn_additional_keys): |
728 | 731 | def test_warn_additional_keys_when_no_extra_keys(warn_additional_keys): |
729 | 732 | validate({True: True}, warn_additional_keys.schema) |
730 | 733 | assert not warn_additional_keys.record.called |
| 734 | + |
| 735 | + |
| 736 | +key_value_map_schema = KeyValueMap( |
| 737 | + 'Container', |
| 738 | + check_string, |
| 739 | + Map( |
| 740 | + 'Object', 'name', |
| 741 | + Required('name', check_string), |
| 742 | + Optional('setting', check_bool, False), |
| 743 | + ), |
| 744 | +) |
| 745 | +key_value_map_ints_schema = KeyValueMap( |
| 746 | + 'Container', |
| 747 | + check_int, |
| 748 | + Array(Map('Object', 'nane', Required('name', check_string))), |
| 749 | +) |
| 750 | + |
| 751 | + |
| 752 | +def test_key_value_map_schema_ok(): |
| 753 | + validate( |
| 754 | + {'hello': {'name': 'hello'}, 'world': {'name': 'world'}}, |
| 755 | + key_value_map_schema, |
| 756 | + ) |
| 757 | + validate( |
| 758 | + {1: [{'name': 'hello'}], 2: [{'name': 'world'}]}, |
| 759 | + key_value_map_ints_schema, |
| 760 | + ) |
| 761 | + |
| 762 | + |
| 763 | +def test_key_value_map_apply_defaults(): |
| 764 | + orig = {'hello': {'name': 'hello'}} |
| 765 | + ret = apply_defaults(orig, key_value_map_schema) |
| 766 | + assert orig == {'hello': {'name': 'hello'}} |
| 767 | + assert ret == {'hello': {'name': 'hello', 'setting': False}} |
| 768 | + |
| 769 | + |
| 770 | +def test_key_value_map_remove_defaults(): |
| 771 | + orig = {'hello': {'name': 'hello', 'setting': False}} |
| 772 | + ret = remove_defaults(orig, key_value_map_schema) |
| 773 | + assert orig == {'hello': {'name': 'hello', 'setting': False}} |
| 774 | + assert ret == {'hello': {'name': 'hello'}} |
| 775 | + |
| 776 | + |
| 777 | +def test_key_value_map_not_a_map(): |
| 778 | + with pytest.raises(ValidationError) as excinfo: |
| 779 | + validate([], key_value_map_schema) |
| 780 | + expected = ( |
| 781 | + 'Expected a Container map but got a list', |
| 782 | + ) |
| 783 | + _assert_exception_trace(excinfo.value, expected) |
| 784 | + |
| 785 | + |
| 786 | +def test_key_value_map_wrong_key_type(): |
| 787 | + with pytest.raises(ValidationError) as excinfo: |
| 788 | + val = {1: {'name': 'hello'}} |
| 789 | + validate(val, key_value_map_schema) |
| 790 | + expected = ( |
| 791 | + 'At Container()', |
| 792 | + 'For key: 1', |
| 793 | + 'Expected string got int', |
| 794 | + ) |
| 795 | + _assert_exception_trace(excinfo.value, expected) |
| 796 | + |
| 797 | + |
| 798 | +def test_key_value_map_error_in_child_schema(): |
| 799 | + with pytest.raises(ValidationError) as excinfo: |
| 800 | + val = {'hello': {'name': 1}} |
| 801 | + validate(val, key_value_map_schema) |
| 802 | + expected = ( |
| 803 | + 'At Container()', |
| 804 | + 'At key: hello', |
| 805 | + 'At Object(name=1)', |
| 806 | + 'At key: name', |
| 807 | + 'Expected string got int', |
| 808 | + ) |
| 809 | + _assert_exception_trace(excinfo.value, expected) |
0 commit comments