Esempio n. 1
0
 def test_from_diff_multiple(self):
     self.assertEqual(
         matcher.MatchInfo.from_diff('metavar', 'a\nb\nc\n', '1\nb\n3\n'),
         matcher.MatchInfo(
             match.Match(),
             bindings={
                 'metavar.0':
                 matcher.BoundValue(
                     match.SpanMatch(
                         string='a\n',
                         span=(0, 2),
                     )),
                 'metavar.1':
                 matcher.BoundValue(
                     match.SpanMatch(
                         string='c\n',
                         span=(4, 6),
                     )),
             },
             replacements={
                 'metavar.0': formatting.LiteralTemplate('1\n'),
                 'metavar.1': formatting.LiteralTemplate('3\n'),
             },
         ),
     )
Esempio n. 2
0
 def test_multi_bind(self):
     self.assertEqual(
         base_matchers.AllOf(base_matchers.Bind('foo'),
                             base_matchers.Bind('bar')).match(
                                 _FAKE_CONTEXT, 1),
         matcher.MatchInfo(
             match.ObjectMatch(1), {
                 'foo': matcher.BoundValue(match.ObjectMatch(1)),
                 'bar': matcher.BoundValue(match.ObjectMatch(1)),
             }))
Esempio n. 3
0
 def test_on_merge_differs(self):
     with self.assertRaises(matcher.MatchError):
         matcher.merge_bindings(
             {
                 'a':
                 matcher.BoundValue(0,
                                    on_merge=matcher.BindMerge.KEEP_FIRST)
             },
             {
                 'a':
                 matcher.BoundValue(0, on_merge=matcher.BindMerge.KEEP_LAST)
             },
         )
Esempio n. 4
0
 def test_on_conflict_differs(self):
     with self.assertRaises(matcher.MatchError):
         matcher.merge_bindings(
             {
                 'a':
                 matcher.BoundValue(0,
                                    on_conflict=matcher.BindConflict.SKIP)
             },
             {
                 'a':
                 matcher.BoundValue(0,
                                    on_conflict=matcher.BindConflict.ERROR)
             },
         )
Esempio n. 5
0
 def test_bind_2arg(self):
     self.assertEqual(
         base_matchers.Bind('foo', base_matchers.Anything()).match(
             _FAKE_CONTEXT, 1),
         matcher.MatchInfo(
             match.ObjectMatch(1),
             {'foo': matcher.BoundValue(match.ObjectMatch(1))}))
Esempio n. 6
0
 def test_match(self):
     container = [1]
     self.assertEqual(
         base_matchers.ItemsAre([base_matchers.Bind('a')
                                 ]).match(_FAKE_CONTEXT, container),
         matcher.MatchInfo(match.ObjectMatch(container),
                           {'a': matcher.BoundValue(match.ObjectMatch(1))}))
Esempio n. 7
0
 def test_string(self):
     self.assertEqual(
         base_matchers.HasItem(1, base_matchers.Bind('a')).match(
             _FAKE_CONTEXT, 'xy'),
         matcher.MatchInfo(
             match.StringMatch('xy'),
             {'a': matcher.BoundValue(match.StringMatch('y'))}))
Esempio n. 8
0
    def _match(self, context, candidate):
        """Returns the submatcher's match, with a binding introduced by this Bind.

    Args:
      context: The match context.
      candidate: The candidate node to be matched.

    Returns:
      An extended :class:`~refex.python.matcher.MatchInfo` with the new binding
      specified in the constructor. Conflicts are merged according to
      ``on_conflict``. If there was no match, or on_conflict result in a skip,
      then this returns ``None``.

      See matcher.merge_bindings for more details.
    """
        result = self._submatcher.match(context, candidate)
        if result is None:
            return None

        bindings = matcher.merge_bindings(
            result.bindings, {
                self.name:
                matcher.BoundValue(result.match,
                                   on_conflict=self._on_conflict,
                                   on_merge=self._on_merge)
            })
        if bindings is None:
            return None
        return attr.evolve(result, bindings=bindings)
Esempio n. 9
0
 def test_contains_binds(self):
     items = [1, 2, 3]
     m = base_matchers.Contains(base_matchers.Bind('foo', 1))
     expected = matcher.MatchInfo(
         match.ObjectMatch(items),
         {'foo': matcher.BoundValue(match.ObjectMatch(1))})
     self.assertEqual(m.match(_FAKE_CONTEXT, items), expected)
Esempio n. 10
0
 def test_bindings(self):
     m = base_matchers.Once(base_matchers.Bind('foo'))
     self.assertEqual(
         m.match(_FAKE_CONTEXT.new(), 1),
         matcher.MatchInfo(
             match.ObjectMatch(1),
             {'foo': matcher.BoundValue(match.ObjectMatch(1))}))
     self.assertEqual(m.bind_variables, {'foo'})
Esempio n. 11
0
 def test_multi_bind_first(self):
     self.assertEqual(
         base_matchers.AnyOf(base_matchers.Bind('foo'),
                             base_matchers.Bind('bar'),
                             _NOTHING).match(_FAKE_CONTEXT, 1),
         matcher.MatchInfo(
             match.ObjectMatch(1),
             {'foo': matcher.BoundValue(match.ObjectMatch(1))}))
Esempio n. 12
0
 def test_negative_index(self):
     container = ['xyz']
     self.assertEqual(
         base_matchers.HasItem(-1, base_matchers.Bind('a')).match(
             _FAKE_CONTEXT, container),
         matcher.MatchInfo(
             match.ObjectMatch(container),
             {'a': matcher.BoundValue(match.StringMatch('xyz'))}))
Esempio n. 13
0
def _re_match_to_bindings(compiled_regex, text, m):
    """Converts an ``re.Match`` to a bindings dict."""
    return {
        bind_name:
        matcher.BoundValue(match.SpanMatch.from_text(text,
                                                     m.regs[match_index]))
        for bind_name, match_index in compiled_regex.groupindex.items()
    }
Esempio n. 14
0
    def test_error_after_skip(self):
        """ERROR should still raise even if it is processed after a skip."""
        # This is a gnarly thing to test, because dicts aren't ordered.
        # Even if we used OrderedDict, ordered dict key views don't (and can't)
        # preserve order when they're intersected and so on.

        @attr.s()
        class OrderedKeyView(object):
            """Ordered fake key view for deterministic key iteration order."""
            keys = attr.ib()

            def __sub__(self, other_ordered_key_view):
                if self.keys != other_ordered_key_view.keys:
                    raise NotImplementedError(
                        "Test ordered key view doesn't support this.")
                return frozenset()

            def __and__(self, other_ordered_key_view):
                # can't preserve order otherwise...
                if self.keys != other_ordered_key_view.keys:
                    raise NotImplementedError("Can't preserve order.")
                return list(self.keys)

        @attr.s()
        class OrderedBindings(object):
            """OrderedDict wrapper that returns OrderedKeyView."""
            _dict = attr.ib(converter=collections.OrderedDict)

            def __getitem__(self, v):
                return self._dict[v]

            def keys(self):
                return OrderedKeyView(self._dict)

            viewkeys = keys

        bad_bindings = [
            ('a', matcher.BoundValue(0, matcher.BindConflict.SKIP)),
            ('b', matcher.BoundValue(0, matcher.BindConflict.ERROR)),
        ]

        for bindings in [bad_bindings, bad_bindings[::-1]]:
            with self.subTest(bindings=bindings):
                bindings = OrderedBindings(bindings)
                with self.assertRaises(matcher.MatchError):
                    matcher.merge_bindings(bindings, bindings)
Esempio n. 15
0
 def test_multi_overlap(self):
     # TODO: it'd be nice to give a good error at some point, instead.
     self.assertEqual(
         base_matchers.AllOf(base_matchers.Bind('foo'),
                             base_matchers.Bind('foo')).match(
                                 _FAKE_CONTEXT, 1),
         matcher.MatchInfo(
             match.ObjectMatch(1),
             {'foo': matcher.BoundValue(match.ObjectMatch(1))}))
Esempio n. 16
0
 def test_simple(self):
     for nonempty_container in (('x', 'y'), ['x', 'y'], {1: 'y'}):
         with self.subTest(nonempty_container=nonempty_container):
             self.assertEqual(
                 base_matchers.HasItem(1, base_matchers.Bind('a')).match(
                     _FAKE_CONTEXT, nonempty_container),
                 matcher.MatchInfo(
                     match.ObjectMatch(nonempty_container),
                     {'a': matcher.BoundValue(match.StringMatch('y'))}))
Esempio n. 17
0
 def test_variable_name(self):
     parsed = matcher.parse_ast('3', '<string>')
     expr = parsed.tree.body[0].value
     expr_match = matcher.LexicalASTMatch(expr, parsed.text,
                                          expr.first_token, expr.last_token)
     self.assertEqual(
         syntax_matchers.ExprPattern('$name').match(
             matcher.MatchContext(parsed), expr),
         matcher.MatchInfo(expr_match,
                           {'name': matcher.BoundValue(expr_match)}))
Esempio n. 18
0
 def test_from_diff_change(self):
     self.assertEqual(
         matcher.MatchInfo.from_diff('metavar', 'a\nb\n', 'a\nc\n'),
         matcher.MatchInfo(
             match.Match(),
             bindings={
                 'metavar.0':
                 matcher.BoundValue(
                     match.SpanMatch(
                         string='b\n',
                         span=(2, 4),
                     ))
             },
             replacements={'metavar.0': formatting.LiteralTemplate('c\n')},
         ),
     )
Esempio n. 19
0
 def test_matches(self):
     parsed = matcher.parse_ast('xy = 2', '<string>')
     matches = list(
         matcher.find_iter(
             base_matchers.MatchesRegex(r'^(?P<name>.)(.)$',
                                        base_matchers.Bind('inner')),
             parsed))
     # There is only one AST node of length >= 2 (which the regex requires): xy.
     self.assertEqual(matches, [
         matcher.MatchInfo(
             mock.ANY, {
                 'inner': mock.ANY,
                 'name': matcher.BoundValue(match.SpanMatch('x', (0, 1))),
             })
     ])
     [matchinfo] = matches
     self.assertEqual(matchinfo.match.span, (0, 2))
     self.assertEqual(matchinfo.match, matchinfo.bindings['inner'].value)
Esempio n. 20
0
 def test_eq(self, m):
     self.assertEqual(
         base_matchers.Bind('a', m).match(_FAKE_CONTEXT, 3),
         matcher.MatchInfo(match.ObjectMatch(3),
                           {'a': matcher.BoundValue(match.ObjectMatch(3))}))
Esempio n. 21
0
 def test_noconflict(self):
     bindings = {'a': matcher.BoundValue(0)}
     self.assertEqual(matcher.merge_bindings({}, bindings), bindings)
Esempio n. 22
0
 def test_skip(self):
     skip_bindings = {'a': matcher.BoundValue(0, matcher.BindConflict.SKIP)}
     self.assertIsNone(matcher.merge_bindings(skip_bindings, skip_bindings))
Esempio n. 23
0
 def test_error(self):
     error_bindings = {
         'a': matcher.BoundValue(0, matcher.BindConflict.ERROR)
     }
     with self.assertRaises(matcher.MatchError):
         matcher.merge_bindings(error_bindings, error_bindings)