Пример #1
0
    def test_mapping_vs_mapping_failing(self):
        with self.assertRaises(ValidationError) as cm:
            data = {
                'a': ('abc', 1.0),
                'b': ('xyz', 2.0)
            }  # Mapping of base-elements.
            requirement = {
                'a': ('abc', int),
                'b': ('abc', float)
            }  # Mapping of requirements.
            validate(data, requirement)
        actual = cm.exception.differences
        expected = {
            'a': Invalid(('abc', 1.0), ('abc', int)),
            'b': Invalid(('xyz', 2.0), ('abc', float)),
        }
        self.assertEqual(actual, expected)

        with self.assertRaises(ValidationError) as cm:
            data = {
                'a': [('abc', 1.0), ('abc', 2)],
                'b': [('abc', 1.0), ('xyz', 2.0)]
            }  # Mapping of containers.
            requirement = {
                'a': ('abc', int),
                'b': ('abc', float)
            }  # Mapping of requirements.
            validate(data, requirement)
        actual = cm.exception.differences
        expected = {
            'a': [Invalid(('abc', 1.0))],
            'b': [Invalid(('xyz', 2.0))],
        }
        self.assertEqual(actual, expected)
Пример #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'))
Пример #3
0
 def test_custom_difference(self):
     """When a predicate function returns a difference object,
     it should be used in place of an auto-generated one.
     """
     pred = lambda x: Invalid('custom')
     result = _require_predicate('A', pred, False)
     self.assertEqual(result, Invalid('custom'))
Пример #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')])
Пример #5
0
    def test_invalid(self):
        diff = Invalid('foo')

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

        with self.assertRaises(AttributeError):
            diff.new_attribute = 'baz'
Пример #6
0
 def test_duplicate_false(self):
     """Should return an error for every non-match (incl. duplicates)."""
     data = iter(['a1', 'b2', 'XX', 'XX', 'XX'])  # <- Multiple XX's.
     result = _require_predicate_from_iterable(data, self.regex)
     self.assertEqual(
         list(result),
         [Invalid('XX'), Invalid('XX'),
          Invalid('XX')])
Пример #7
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))
Пример #8
0
 def test_duplicate_false(self):
     """Should return an error for every false result (incl. duplicates)."""
     data = ['10', '20', 'XX', 'XX', 'XX']  # <- Multiple XX's.
     result = _require_predicate_from_iterable(data, self.isdigit)
     self.assertEqual(
         list(result),
         [Invalid('XX'), Invalid('XX'),
          Invalid('XX')])
Пример #9
0
    def test_repr(self):
        diff = Invalid('foo')
        self.assertEqual(repr(diff), "Invalid('foo')")

        diff = Invalid('foo', 'bar')
        self.assertEqual(repr(diff), "Invalid('foo', expected='bar')")

        diff = Invalid('foo', None)
        self.assertEqual(repr(diff), "Invalid('foo', expected=None)")
Пример #10
0
    def test_same(self):
        """The _make_difference() function returns differences for
        objects that are KNOWN TO BE DIFFERENT--it does not test
        for differences itself.
        """
        diff = _make_difference('a', 'a')
        self.assertEqual(diff, Invalid('a', 'a'))

        diff = _make_difference(None, None)
        self.assertEqual(diff, Invalid(None, None))
Пример #11
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)
Пример #12
0
    def test_show_expected(self):
        """If requirement is common it should be omitted from Invalid
        difference (but not from Deviation differences).
        """
        diff = _make_difference('a', 6, show_expected=True)
        self.assertEqual(diff, Invalid('a', expected=6))

        diff = _make_difference('a', 6, show_expected=False)
        self.assertEqual(diff, Invalid('a'))

        diff = _make_difference(NOVALUE, 6, show_expected=False)
        self.assertEqual(diff, Deviation(-6, 6))
Пример #13
0
 def test_invalid_deviation_single_arg_percent(self):
     # Check error percent.
     with self.assertRaises(ValidationError) as cm:
         with AcceptedPercent(2.0):  # <- Accepts +/- 200%.
             raise ValidationError([
                 Invalid(
                     -1),  # <- Rejected: Can not be accepted by percent.
                 Invalid(0),  # <- ACCEPTED!
                 Invalid(2),  # <- Rejected: Can not be accepted by percent.
             ])
     remaining = cm.exception.differences
     self.assertEqual(remaining, [Invalid(-1), Invalid(2)])
Пример #14
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')})
Пример #15
0
 def test_numeric_matching(self):
     """When checking sequence order, numeric differences should not
     be converted into Deviation objects.
     """
     data = [1, 100, 4, 200, 300]
     requirement = [1, 2, 3, 4, 5]
     actual = _require_sequence(data, requirement)
     expected = {
         (1, 2): [Invalid(100, expected=2),
                  Missing(3)],
         (3, 5): [Invalid(200, expected=5),
                  Extra(300)],
     }
     self.assertEqual(actual, expected)
Пример #16
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)
Пример #17
0
    def test_unhashable_contents(self):
        """The hash behavior of differences should act like tuples do.
        When a difference's contents are unhashable, the difference
        itself becomes unhashable too.
        """
        with self.assertRaises(TypeError):
            hash(Missing(['foo']))

        with self.assertRaises(TypeError):
            hash(Extra(['bar']))

        with self.assertRaises(TypeError):
            hash(Invalid(['baz']))

        with self.assertRaises(TypeError):
            hash(Invalid('baz', ['qux']))
Пример #18
0
 def test_nonnumeric_but_compatible(self):
     with self.assertRaises(ValidationError) as cm:
         with AcceptedTolerance(
                 datetime.timedelta(hours=2)):  # <- Accepts +/- 2 hours.
             raise ValidationError([
                 Invalid(datetime.datetime(1989, 2, 24, hour=10, minute=30),
                         datetime.datetime(1989, 2, 24, hour=11,
                                           minute=30)),
                 Invalid(datetime.datetime(1989, 2, 24, hour=15, minute=10),
                         datetime.datetime(1989, 2, 24, hour=11, minute=30))
             ])
     remaining = cm.exception.differences
     self.assertEqual(remaining, [
         Invalid(datetime.datetime(1989, 2, 24, 15, 10),
                 expected=datetime.datetime(1989, 2, 24, 11, 30))
     ])
Пример #19
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 = {
            (2, 4): [Invalid('x', expected='c'),
                     Invalid(3, expected=4)],
        }
        self.assertEqual(error.differences, expected)
        self.assertEqual(error.args[1], 'does not match sequence order')
Пример #20
0
    def test_unhashable(self):
        """Uses "deep hashing" to attempt to sort unhashable types."""
        first = [{'a': 1}, {'b': 2}, {'c': 3}]
        second = [{'a': 1}, {'b': 2}, {'c': 3}]
        error = _require_sequence(first, second)
        self.assertIsNone(error)  # No difference, returns None.

        data = [{'a': 1}, {'x': 0}, {'d': 4}, {'y': 5}, {'g': 7}]
        requirement = [{'a': 1}, {'b': 2}, {'c': 3}, {'d': 4}, {'f': 6}]
        actual = _require_sequence(data, requirement)
        expected = {
            (1, 2): [Invalid({'x': 0}, expected={'b': 2}),
                     Missing({'c': 3})],
            (3, 5): [Invalid({'y': 5}, expected={'f': 6}),
                     Extra({'g': 7})],
        }
        self.assertEqual(actual, expected)
Пример #21
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)
Пример #22
0
    def test_required_mapping(self):
        with self.assertRaises(ValidationError) as cm:
            data = {'AAA': 'a', 'BBB': 'x'}
            required = {'AAA': 'a', 'BBB': 'b', 'CCC': 'c'}
            self.assertValid(data, required)

        differences = cm.exception.differences
        self.assertEqual(differences, {'BBB': Invalid('x', 'b'), 'CCC': Missing('c')})
Пример #23
0
 def test_invalid(self):
     data = ['aaa', 'xxx', 'ccc']
     requirement = ['aaa', 'bbb', 'ccc']
     actual = _require_sequence(data, requirement)
     expected = {
         (1, 2): [Invalid('xxx', 'bbb')],
     }
     self.assertEqual(actual, expected)
Пример #24
0
    def test_some_false(self):
        data = ['x', 'x', 'y']
        result = _require_predicate_from_iterable(data, 'x')
        self.assertEqual(list(result), [Invalid('y')])

        data = [2, 2, 7]
        result = _require_predicate_from_iterable(data, 2)
        self.assertEqual(list(result), [Deviation(+5, 2)])
Пример #25
0
    def test_repr_with_callables(self):
        def myfunc(x):
            return True

        class MyClass(object):
            pass

        diff = Invalid('foo', myfunc)
        self.assertEqual(repr(diff), "Invalid('foo', expected=myfunc)")

        diff = Invalid('foo', MyClass)
        self.assertEqual(repr(diff), "Invalid('foo', expected=MyClass)")

        diff = Invalid(myfunc, 'bar')
        self.assertEqual(repr(diff), "Invalid(myfunc, expected='bar')")

        diff = Invalid(MyClass, 'bar')
        self.assertEqual(repr(diff), "Invalid(MyClass, expected='bar')")
Пример #26
0
    def test_invalid_different_lengths(self):
        data = ['aaa', 'xxx', 'ddd']
        requirement = ['aaa', 'bbb', 'ccc', 'ddd']
        actual = _require_sequence(data, requirement)
        expected = {
            (1, 2): [Invalid('xxx', 'bbb'),
                     Missing('ccc')],
        }
        self.assertEqual(actual, expected)

        data = ['aaa', 'xxx', 'yyy', 'ccc']
        requirement = ['aaa', 'bbb', 'ccc']
        actual = _require_sequence(data, requirement)
        expected = {
            (1, 3): [Invalid('xxx', 'bbb'),
                     Extra('yyy')],
        }
        self.assertEqual(actual, expected)
Пример #27
0
    def test_returned_error(self):
        """When a difference is returned, it is used in place of Invalid."""
        def func(x):
            if x == 'c':
                return Invalid("Letter 'c' is no good!")
            return True

        data = ['a', 'b', 'c']
        result = _require_predicate_from_iterable(data, func)
        self.assertEqual(list(result), [Invalid("Letter 'c' is no good!")])
Пример #28
0
    def test_required_vs_data_failing(self):
        """Apply single requirement to BaseElement or non-mapping
        container of data.
        """
        with self.assertRaises(ValidationError) as cm:
            data = ('abc', 1.0)  # A single base element.
            requirement = ('abc', int)
            validate(data, requirement)
        differences = cm.exception.differences
        self.assertEqual(differences, [Invalid(('abc', 1.0))])

        with self.assertRaises(ValidationError) as cm:
            data = [('abc', 1.0),
                    ('xyz', 2)]  # Non-mapping container of base elements.
            requirement = ('abc', int)
            validate(data, requirement)
        differences = cm.exception.differences
        self.assertEqual(
            differences, [Invalid(
                ('abc', 1.0)), Invalid(('xyz', 2))])
Пример #29
0
    def test_required_other(self):
        """When *required* is a string or other object, _compare_other()
        should be called.
        """
        with self.assertRaises(ValidationError) as cm:
            required = lambda x: x.isupper()
            data = ['AAA', 'BBB', 'ccc', 'DDD']
            self.assertValid(data, required)

        differences = cm.exception.differences
        self.assertEqual(differences, [Invalid('ccc')])
Пример #30
0
 def setUp(self):
     ntup = namedtuple('ntup', ('cls', 'args', 'priority'))
     self.acceptances = [
         ntup(cls=AcceptedFuzzy, args=tuple(), priority=4),
         ntup(cls=AcceptedPercent, args=(0.05, ), priority=4),
         ntup(cls=AcceptedKeys, args=(lambda args: True, ), priority=4),
         ntup(cls=AcceptedArgs, args=(lambda *args: True, ), priority=4),
         ntup(cls=AcceptedCount, args=(4, ), priority=256),
         ntup(cls=AcceptedDifferences, args=(Invalid('A'), ), priority=4),
         ntup(cls=AcceptedDifferences, args=([Invalid('A')], ),
              priority=32),
         ntup(cls=AcceptedDifferences,
              args=({
                  'X': [Invalid('A')]
              }, ),
              priority=32),
         ntup(cls=AcceptedDifferences,
              args=([Invalid('A')], None, 'whole'),
              priority=256),
     ]