Example #1
0
    def test_exit_context(self):
        """The __exit__() method should re-raise exceptions that are
        not allowed and it should return True when there are no errors
        or if all differences have been allowed (see PEP 343 for
        context manager protocol).
        """
        try:
            raise ValidationError([Missing('A'), Extra('B')], 'error description')
        except ValidationError:
            type, value, traceback = sys.exc_info()  # Get exception info.

        with self.assertRaises(ValidationError) as cm:
            allowance = MinimalAllowance('allowance message')
            allowance.__exit__(type, value, traceback)

        description = cm.exception.description
        self.assertEqual(description, 'allowance message: error description')

        # Test with no error description.
        try:
            raise ValidationError([Missing('A'), Extra('B')])  # <- No description.
        except ValidationError:
            type, value, traceback = sys.exc_info()  # Get exception info.

        with self.assertRaises(ValidationError) as cm:
            allowance = MinimalAllowance('allowance message')
            allowance.__exit__(type, value, traceback)

        description = cm.exception.description
        self.assertEqual(description, 'allowance message')
Example #2
0
    def test_get_deviation_expected_extra_or_single_arg_invalid(self):
        """Extra and single-argument Invalid differences should be
        treated the same.
        """
        func = AcceptedTolerance._get_deviation_expected

        self.assertEqual(func(Extra(2)), (2, 0))
        self.assertEqual(func(Invalid(2)), (2, 0))

        self.assertEqual(func(Extra(-2)), (-2, 0))
        self.assertEqual(func(Invalid(-2)), (-2, 0))

        self.assertEqual(func(Extra(0)), (0, 0))
        self.assertEqual(func(Invalid(0)), (0, 0))

        with self.assertRaises(TypeError):
            func(Extra((1, 2)))

        with self.assertRaises(TypeError):
            func(Invalid((1, 2)))

        with self.assertRaises(TypeError):
            func(Extra('abc'))

        with self.assertRaises(TypeError):
            func(Invalid('abc'))
Example #3
0
    def test_accepted_extra(self):
        differences = [Extra('X'), Extra('Y'), Missing('X')]

        with self.assertRaises(ValidationError) as cm:
            with AcceptedDifferences(Extra):  # <- Apply acceptance!
                raise ValidationError(differences)
        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Missing('X')])
Example #4
0
    def test_allowed_invalid(self):
        differences =  [Invalid('X'), Invalid('Y'), Extra('Z')]

        with self.assertRaises(ValidationError) as cm:
            with allowed_invalid():  # <- Apply allowance!
                raise ValidationError(differences)
        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Extra('Z')])
Example #5
0
 def test_extra(self):
     data = ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff']
     requirement = ['aaa', 'ccc', 'fff']
     error = _require_sequence(data, requirement)
     self.assertEqual(error, {
         (1, 2): [Extra('bbb')],
         (3, 5): [Extra('ddd'), Extra('eee')]
     })
Example #6
0
    def test_extra(self):
        diff = Extra('foo')

        with self.assertRaises(AttributeError):
            diff.attr = ('bar', )

        with self.assertRaises(AttributeError):
            diff.new_attribute = 'baz'
Example #7
0
 def test_mapping_vs_type(self):
     differences = {
         'a': [Missing('X')],
         'b': [Missing('Y'), Extra('X')],
         'c': Missing('X'),
     }
     acceptance = AcceptedDifferences(Missing)
     expected = {'b': Extra('X')}
     self.assertAcceptance(differences, acceptance, expected)
Example #8
0
 def test_extra_deviation_percent(self):
     with self.assertRaises(ValidationError) as cm:
         with AcceptedPercent(2.0):  # <- Accepts +/- 200%.
             raise ValidationError([
                 Extra(-1),  # <- Rejected: Can not be accepted by percent.
                 Extra(0),  # <- ACCEPTED!
                 Extra(2),  # <- Rejected: Can not be accepted by percent.
             ])
     remaining = cm.exception.differences
     self.assertEqual(remaining, [Extra(-1), Extra(2)])
Example #9
0
    def test_nonmapping_vs_mapping(self):
        """A mapping accpetance will not accept any non-mapping differences."""

        differences = [Missing('Y'), Extra('X')]
        acceptance = AcceptedDifferences({'a': Extra('X')})
        self.assertAcceptance(differences, acceptance, differences)

        differences = Extra('X')
        acceptance = AcceptedDifferences({'a': Extra('X')})
        self.assertAcceptance(differences, acceptance, [differences])
Example #10
0
    def test_filterfalse(self):
        class allowed_missing(MinimalAllowance):
            def call_predicate(_self, item):
                return isinstance(item[1], Missing)

        allowed = allowed_missing()
        result = allowed._filterfalse([
            (None, Missing('A')),
            (None, Extra('B')),
        ])
        self.assertEqual(list(result), [(None, Extra('B'))])
Example #11
0
    def test_list_and_list(self):
        differences = [Extra('xxx'), Missing('yyy')]
        allowed = [Extra('xxx')]
        expected = [Missing('yyy')]

        with self.assertRaises(ValidationError) as cm:
            with allowed_specific(allowed):
                raise ValidationError(differences)

        actual = list(cm.exception.differences)
        self.assertEqual(actual, expected)
Example #12
0
    def test_list_and_diff(self):
        differences = [Extra('xxx'), Missing('yyy')]
        allowed = Extra('xxx')  # <- Single diff, not in a container.

        with self.assertRaises(ValidationError) as cm:
            with allowed_specific(allowed):
                raise ValidationError(differences)

        actual = list(cm.exception.differences)
        expected = [Missing('yyy')]
        self.assertEqual(actual, expected)
Example #13
0
    def test_dict_and_dict(self):
        differences = {'foo': Extra('xxx'), 'bar': [Extra('xxx'), Missing('yyy')]}
        allowed = {'bar': Extra('xxx')}

        with self.assertRaises(ValidationError) as cm:
            with allowed_specific(allowed):
                raise ValidationError(differences)

        actual = cm.exception.differences
        expected = {'foo': Extra('xxx'), 'bar': Missing('yyy')}
        self.assertEqual(actual, expected)
Example #14
0
    def test_dict_and_list(self):
        """List of allowed differences applied to each group separately."""
        differences = {'foo': Extra('xxx'), 'bar': [Extra('xxx'), Missing('yyy')]}
        allowed = [Extra('xxx')]

        with self.assertRaises(ValidationError) as cm:
            with allowed_specific(allowed):
                raise ValidationError(differences)

        actual = cm.exception.differences
        expected = {'bar': Missing('yyy')}
        self.assertEqual(actual, expected)
Example #15
0
    def test_nonmapping_container(self):
        """When differences container is not a mapping, the keys that
        allowed_key() sees are all None.
        """
        with self.assertRaises(ValidationError) as cm:

            with allowed_keys('foo'):  # <- Allow keys that equal 'foo'.
                differences = [Missing(1), Extra(2)]  # <- List has no keys!
                raise ValidationError(differences)

        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Missing(1), Extra(2)])
Example #16
0
    def test_scope(self):
        with self.assertRaises(ValidationError) as cm:
            with AcceptedCount(2, scope='group'):  # <- Accepts 2 per group.
                raise ValidationError({
                    'foo': [Extra('xxx'), Extra('yyy')],
                    'bar': [Missing('xxx'), Missing('yyy')],
                    'baz': [Invalid('xxx'),
                            Invalid('yyy'),
                            Invalid('zzz')],
                })

        remaining = cm.exception.differences
        self.assertEqual(remaining, {'baz': Invalid('zzz')})
Example #17
0
    def test_UnionedAllowance(self):
        original_diffs = [Missing('a'), Extra('a'), Missing('b'), Extra('b')]

        with self.assertRaises(ValidationError) as cm:
            with UnionedAllowance(self.allowed_missing, self.allowed_letter_a):
                raise ValidationError(original_diffs)
        differences = cm.exception.differences
        self.assertEqual(list(differences), [Extra('b')])

        # Test with allowances in reverse-order (should give same result).
        with self.assertRaises(ValidationError) as cm:
            with UnionedAllowance(self.allowed_letter_a, self.allowed_missing):
                raise ValidationError(original_diffs)
        differences = cm.exception.differences
        self.assertEqual(list(differences), [Extra('b')])
Example #18
0
    def test_over_limit(self):
        with self.assertRaises(ValidationError) as cm:
            with allowed_limit(1):  # <- Allows 1 but there are 2.
                raise ValidationError([Extra('xxx'), Missing('yyy')])

        remaining = list(cm.exception.differences)
        self.assertEqual(remaining, [Missing('yyy')])

        with self.assertRaises(ValidationError) as cm:
            with allowed_limit(1):  # <- Allows 1 and there are 2.
                raise ValidationError({'foo': Extra('xxx'), 'bar': Missing('yyy')})

        remaining = cm.exception.differences
        self.assertIsInstance(remaining, collections.Mapping)
        self.assertEqual(len(remaining), 1)
Example #19
0
    def test_dict_global_wildcard_predicate(self):
        """Ellipsis wildcard key matches all, treats as a single group."""
        differences = {'foo': Extra('xxx'), 'bar': [Extra('xxx'), Missing('yyy')]}
        allowed = {Ellipsis: Extra('xxx')}

        with self.assertRaises(ValidationError) as cm:
            with allowed_specific(allowed):
                raise ValidationError(differences)

        actual = cm.exception.differences
        # Actual result can vary with unordered dictionaries.
        if len(actual) == 1:
            expected = {'bar': [Extra('xxx'), Missing('yyy')]}
        else:
            expected = {'foo': Extra('xxx'), 'bar': Missing('yyy')}
        self.assertEqual(actual, expected)
Example #20
0
    def test_some_differences(self):
        # Sequence order.
        data = {'a': ['x', 'y']}
        result = _apply_mapping_requirement(data, {'a': ['x', 'z']})
        result = dict(result)
        self.assertTrue(len(result) == 1)
        self.assertEqual(result, {'a': {(1, 2): [Invalid('y', 'z')]}})

        # Set membership.
        data = {'a': ['x', 'x'], 'b': ['x', 'y', 'z']}
        result = _apply_mapping_requirement(data, {
            'a': set(['x', 'y']),
            'b': set(['x', 'y'])
        })
        expected = {'a': [Missing('y')], 'b': [Extra('z')]}
        self.assertEqual(dict(result), expected)

        # Equality of single values.
        data = {'a': 'x', 'b': 10}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9})
        expected = {'a': Invalid('x', expected='j'), 'b': Deviation(+1, 9)}
        self.assertEqual(dict(result), expected)

        # Equality of multiple values.
        data = {'a': ['x', 'j'], 'b': [10, 9]}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9})
        expected = {'a': [Invalid('x')], 'b': [Deviation(+1, 9)]}
        self.assertEqual(dict(result), expected)

        # Equality of single tuples.
        data = {'a': (1, 'x'), 'b': (9, 10)}
        result = _apply_mapping_requirement(data, {'a': (1, 'j'), 'b': (9, 9)})
        expected = {
            'a': Invalid((1, 'x'), expected=(1, 'j')),
            'b': Invalid((9, 10), expected=(9, 9))
        }
        self.assertEqual(dict(result), expected)

        # Equality of multiple tuples.
        data = {'a': [(1, 'j'), (1, 'x')], 'b': [(9, 9), (9, 10)]}
        result = _apply_mapping_requirement(data, {'a': (1, 'j'), 'b': (9, 9)})
        expected = {'a': [Invalid((1, 'x'))], 'b': [Invalid((9, 10))]}
        self.assertEqual(dict(result), expected)

        # Equality of multiple values, missing key with single item.
        data = {'a': ['x', 'j'], 'b': [10, 9]}
        result = _apply_mapping_requirement(data, {'a': 'j', 'b': 9, 'c': 'z'})
        expected = {
            'a': [Invalid('x')],
            'b': [Deviation(+1, 9)],
            'c': Missing('z')
        }
        self.assertEqual(dict(result), expected)

        # Missing key, set membership.
        data = {'a': 'x'}
        result = _apply_mapping_requirement(data, {'a': 'x', 'b': set(['z'])})
        expected = {'b': [Missing('z')]}
        self.assertEqual(dict(result), expected)
Example #21
0
    def test_data_mapping(self):
        with self.assertRaises(ValidationError) as cm:
            data = {'a': set([1, 2]), 'b': set([1]), 'c': set([1, 2, 3])}
            required = set([1, 2])
            self.assertValid(data, required)

        differences = cm.exception.differences
        self.assertEqual(differences, {'b': [Missing(2)], 'c': [Extra(3)]})
Example #22
0
    def test_non_deviation_diffs(self):
        diffs = [Missing('foo'), Extra('bar'), Invalid('baz')]
        with self.assertRaises(ValidationError) as cm:
            with AcceptedPercent(0.05):
                raise ValidationError(diffs)

        uncaught_diffs = cm.exception.differences
        self.assertEqual(diffs, uncaught_diffs)
Example #23
0
 def test_hashable(self):
     """Differences with hashable *args should be hashable."""
     # Following should all pass without error.
     hash(Missing('foo'))
     hash(Extra('bar'))
     hash(Invalid('baz'))
     hash(Invalid('baz', 'qux'))
     hash(Deviation(-1, 10))
Example #24
0
    def test_unique_method(self):
        validate.unique([1, 2, 3, 4])

        with self.assertRaises(ValidationError) as cm:
            validate.unique([1, 2, 3, 3])
        actual = cm.exception.differences
        expected = [Extra(3)]
        self.assertEqual(actual, expected)
Example #25
0
    def test_missing_and_extra(self):
        data = iter(['a', 'c', 'x'])
        result = _require_set(data, self.requirement)

        result = list(result)
        self.assertEqual(len(result), 2)
        self.assertIn(Missing('b'), result)
        self.assertIn(Extra('x'), result)
Example #26
0
    def test_nonmapping(self):
        with self.assertRaises(ValidationError) as cm:
            data = set([1, 2, 3])
            required = set([1, 2, 4])
            self.assertValid(data, required)

        differences = cm.exception.differences
        self.assertEqual(differences, [Missing(4), Extra(3)])
Example #27
0
    def test_required_sequence(self):
        """When *required* is a sequence, _compare_sequence() should be
        called.
        """
        with self.assertRaises(ValidationError) as cm:
            data = ['a', 2, 'x', 3]
            required = ['a', 2, 'c', 4]
            self.assertValid(data, required)

        error = cm.exception
        expected = [
            Missing((2, 'c')),
            Extra((2, 'x')),
            Missing((3, 4)),
            Extra((3, 3)),
        ]
        self.assertEqual(error.differences, expected)
        self.assertEqual(error.args[1], 'does not match required sequence')
Example #28
0
    def test_set_method(self):
        data = [1, 2, 3, 4]
        requirement = Query.from_object([1, 2, 3, 4])
        validate.set(data, requirement)

        with self.assertRaises(ValidationError) as cm:
            data = [1, 2, 3, 5]
            requirement = set([1, 2, 3, 4])
            validate.set(data, requirement)
        actual = cm.exception.differences
        expected = [Missing(4), Extra(5)]
        self.assertEqual(actual, expected)

        with self.assertRaises(ValidationError) as cm:
            data = {'A': [1, 2, 3], 'B': [3]}
            requirement = {'A': iter([1, 2]), 'B': iter([3, 4])}
            validate.set(data, requirement)
        actual = cm.exception.differences
        expected = {'A': [Extra(3)], 'B': [Missing(4)]}
        self.assertEqual(actual, expected)
Example #29
0
 def test_mixed_differences(self):
     data = ['aaa', 'xxx', 'ddd', 'eee', 'ggg']
     requirement = ['aaa', 'bbb', 'ccc', 'ddd', 'fff']
     actual = _require_sequence(data, requirement)
     expected = {
         (1, 2): [Invalid('xxx', expected='bbb'),
                  Missing('ccc')],
         (3, 5): [Invalid('eee', expected='fff'),
                  Extra('ggg')],
     }
     self.assertEqual(actual, expected)
Example #30
0
    def test_string_predicate(self):
        with self.assertRaises(ValidationError) as cm:

            with allowed_args('bbb'):  # <- Allowance!
                raise ValidationError([
                    Missing('aaa'),
                    Missing('bbb'),
                    Extra('bbb'),
                ])

        remaining_diffs = cm.exception.differences
        self.assertEqual(list(remaining_diffs), [Missing('aaa')])