Example #1
0
 def test_restrictions(self):
     parsed = matcher.parse_ast('a = 1\na = 2', '<string>')
     stmt_match, stmt_nomatch = parsed.tree.body
     m = syntax_matchers.StmtPattern(
         'a = $name', {'name': syntax_matchers.ExprPattern('1')})
     self.assertIsNotNone(m.match(matcher.MatchContext(parsed), stmt_match))
     self.assertIsNone(m.match(matcher.MatchContext(parsed), stmt_nomatch))
Example #2
0
 def test_restrictions(self):
     parsed = matcher.parse_ast('1\n2', '<string>')
     expr_match = parsed.tree.body[0].value
     expr_nomatch = parsed.tree.body[1].value
     m = syntax_matchers.ExprPattern(
         '$name', {'name': syntax_matchers.ExprPattern('1')})
     self.assertIsNotNone(m.match(matcher.MatchContext(parsed), expr_match))
     self.assertIsNone(m.match(matcher.MatchContext(parsed), expr_nomatch))
Example #3
0
 def test_type_only(self):
   parsed, e = expression('~a')
   self.assertEqual(
       ast_matchers.UnaryOp().match(matcher.MatchContext(parsed), e),
       matcher.MatchInfo(
           matcher.LexicalASTMatch(e, parsed.text, e.first_token,
                                   e.last_token)))
Example #4
0
 def test_ancestor(self):
   """The matcher won't traverse into child nodes."""
   parsed = matcher.parse_ast('~a', '<string>')
   self.assertIsNone(
       ast_matchers.UnaryOp(
           op=base_matchers.Unless(base_matchers.Anything())).match(
               matcher.MatchContext(parsed), parsed.tree.body[0]))
Example #5
0
 def test_num(self, num_matcher):
   for s in '0', '0.0', '0j':
     with self.subTest(s=s):
       parsed = matcher.parse_ast(s, '<string>')
       self.assertIsNotNone(
           num_matcher.match(
               matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #6
0
 def test_non_lexical_node(self):
   """The matcher doesn't return lexical data for non-lexical AST nodes."""
   parsed, binop = expression('a + b')
   add = binop.op
   self.assertEqual(
       ast_matchers.Add().match(matcher.MatchContext(parsed), add),
       matcher.MatchInfo(match.ObjectMatch(add)))
Example #7
0
 def test_named_constant(self, constant):
   parsed = matcher.parse_ast(str(constant), '<string>')
   for m in ast_matchers.NameConstant(), ast_matchers.NameConstant(
       value=constant):
     with self.subTest(matcher=m):
       self.assertIsNotNone(
           m.match(matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #8
0
 def test_nonvariable_name_fails(self):
     """Names are only treated as variables, or anything weird, on request."""
     parsed = matcher.parse_ast('3', '<string>')
     stmt = parsed.tree.body[0]
     self.assertIsNone(
         syntax_matchers.StmtPattern('name').match(
             matcher.MatchContext(parsed), stmt))
Example #9
0
 def test_renamed_import(self):
     any_m = base_matchers.Anything()
     m_success = syntax_matchers.WithTopLevelImport(any_m, 'os', 'renamed')
     m_fail = syntax_matchers.WithTopLevelImport(any_m, 'os')
     context = matcher.MatchContext(
         matcher.parse_ast('import os as renamed'))
     self.assertIsNotNone(m_success.match(context, 1))
     self.assertIsNone(m_fail.match(context, 1))
Example #10
0
 def test_renamed_fromimport(self, import_stmt):
     any_m = base_matchers.Anything()
     m_success = syntax_matchers.WithTopLevelImport(any_m, 'os.path',
                                                    'renamed')
     m_fail = syntax_matchers.WithTopLevelImport(any_m, 'os.path')
     context = matcher.MatchContext(matcher.parse_ast(import_stmt))
     self.assertIsNotNone(m_success.match(context, 1))
     self.assertIsNone(m_fail.match(context, 1))
Example #11
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)}))
Example #12
0
def empty_context():
    """Returns a new match context for some empty file.

  The return value is suitable for use with matchers, e.g.:

    >>> from refex.python.matchers import base_matchers
    >>> base_matchers.Anything().match(empty_context(), object())
    MatchInfo(...)
  """
    return matcher.MatchContext(matcher.parse_ast(''))
Example #13
0
 def test_explicit_anything(self):
   parsed, e = expression('~a')
   self.assertEqual(
       ast_matchers.UnaryOp(
           op=base_matchers.Anything(),
           operand=base_matchers.Anything()).match(
               matcher.MatchContext(parsed), e),
       matcher.MatchInfo(
           matcher.LexicalASTMatch(e, parsed.text, e.first_token,
                                   e.last_token)))
Example #14
0
 def test_complex_variable(self):
     parsed = matcher.parse_ast('foo + bar', '<string>')
     expr = parsed.tree.body[0].value
     self.assertEqual(
         syntax_matchers.ExprPattern('foo + $name').match(
             matcher.MatchContext(parsed), expr),
         matcher.MatchInfo(matcher.LexicalASTMatch(expr, parsed.text,
                                                   expr.first_token,
                                                   expr.last_token),
                           bindings=mock.ANY))
Example #15
0
 def test_lvalue_variable(self):
     parsed = matcher.parse_ast('a = b', '<string>')
     stmt = parsed.tree.body[0]
     self.assertEqual(
         syntax_matchers.StmtPattern('$x = $y').match(
             matcher.MatchContext(parsed), stmt),
         matcher.MatchInfo(matcher.LexicalASTMatch(stmt, parsed.text,
                                                   stmt.first_token,
                                                   stmt.last_token),
                           bindings=mock.ANY))
Example #16
0
 def test_fully_specified_matcher(self):
   parsed, e = expression('~a')
   self.assertEqual(
       ast_matchers.UnaryOp(
           op=ast_matchers.Invert(),
           operand=ast_matchers.Name(ctx=ast_matchers.Load())).match(
               matcher.MatchContext(parsed), e),
       matcher.MatchInfo(
           matcher.LexicalASTMatch(e, parsed.text, e.first_token,
                                   e.last_token)))
Example #17
0
    def test_has_nested_import(self, import_stmt):
        any_m = base_matchers.Anything()
        matchers = [
            syntax_matchers.WithTopLevelImport(any_m, 'os.path'),
            syntax_matchers.WithTopLevelImport(any_m, 'os.path', 'path'),
        ]

        context = matcher.MatchContext(matcher.parse_ast(import_stmt))
        for m in matchers:
            with self.subTest(m=m):
                self.assertIsNotNone(m.match(context, 1))
Example #18
0
    def test_identical_patterns(self):
        """Tests that patterns match themselves when not parameterized.

    Many cases (e.g. None) are interesting for 2/3 compatibility, because the
    AST changes in Python 3. syntax_matchers gives an easy way to get
    cross-version compatibility.
    """
        for code in ['None', '{}', '[]', '{1:2, 3:4}', 'lambda a: a', '""']:
            parsed = matcher.parse_ast(code, '<string>')
            expr = parsed.tree.body[0].value
            for extra_comment in ['', "# comment doesn't matter"]:
                with self.subTest(code=code, extra_comment=extra_comment):
                    self.assertEqual(
                        syntax_matchers.ExprPattern(
                            code + extra_comment).match(
                                matcher.MatchContext(parsed), expr),
                        matcher.MatchInfo(
                            matcher.LexicalASTMatch(expr, parsed.text,
                                                    expr.first_token,
                                                    expr.last_token)))
Example #19
0
 def test_num_non_number(self, non_number):
   parsed = matcher.parse_ast(non_number, '<string>')
   self.assertIsNone(ast_matchers.Num().match(
       matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #20
0
 def test_type_mismatch(self):
   parsed, e = expression('a + b')
   self.assertIsNone(ast_matchers.UnaryOp().match(
       matcher.MatchContext(parsed), e))
Example #21
0
 def test_submatcher_fail(self):
   parsed, e = expression('~a')
   self.assertIsNone(
       ast_matchers.UnaryOp(
           op=base_matchers.Unless(base_matchers.Anything())).match(
               matcher.MatchContext(parsed), e))
Example #22
0
 def test_missing_import(self, import_stmt):
     any_m = base_matchers.Anything()
     m = syntax_matchers.WithTopLevelImport(any_m, 'os.path')
     context = matcher.MatchContext(matcher.parse_ast(import_stmt))
     self.assertIsNone(m.match(context, 1))
Example #23
0
 def test_dict_wrong_order(self):
     parsed = matcher.parse_ast('{1:2, 3:4}', '<string>')
     stmt = parsed.tree.body[0]
     self.assertIsNone(
         syntax_matchers.StmtPattern('{3:4, 1:2}').match(
             matcher.MatchContext(parsed), stmt))
Example #24
0
 def test_bytes_non_bytes(self):
   parsed = matcher.parse_ast('"string"', '<string>')
   self.assertIsNone(ast_matchers.Bytes().match(
       matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #25
0
 def test_named_constant_non_named_constant(self):
   parsed = matcher.parse_ast('1', '<string>')
   self.assertIsNone(ast_matchers.NameConstant().match(
       matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #26
0
 def test_string(self, str_matcher):
   parsed = matcher.parse_ast('""', '<string>')
   self.assertIsNotNone(
       str_matcher.match(
           matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #27
0
 def test_ellipsis_non_ellipsis(self):
   parsed = matcher.parse_ast('1', '<string>')
   self.assertIsNone(ast_matchers.Ellipsis().match(
       matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #28
0
 def test_string_non_string(self):
   parsed = matcher.parse_ast('2', '<string>')
   self.assertIsNone(ast_matchers.Str().match(
       matcher.MatchContext(parsed), parsed.tree.body[0].value))
Example #29
0
import ast
import collections
import textwrap

from absl.testing import absltest
from absl.testing import parameterized
import attr

from refex import formatting
from refex import match
from refex import parsed_file
from refex.python import matcher
from refex.python.matchers import ast_matchers
from refex.python.matchers import base_matchers

_FAKE_CONTEXT = matcher.MatchContext(matcher.parse_ast('', 'foo.py'))


@attr.s(frozen=True)
class _SubmatcherAttribsClass(object):
    submatcher = matcher.submatcher_attrib(default=base_matchers.Anything())
    submatcher_list = matcher.submatcher_list_attrib(
        default=(base_matchers.Anything(), ))


class SubmatcherAttribTest(parameterized.TestCase):
    @parameterized.parameters(42, matcher.ImplicitEquals(42))
    def test_coerce(self, value):
        self.assertEqual(matcher.coerce(value), matcher.ImplicitEquals(42))

    def test_coerce_nounwrap(self):
Example #30
0
 def test_bytes(self, kwargs):
   bytes_matcher = ast_matchers.Bytes(**kwargs)  # hack for py2
   parsed = matcher.parse_ast('b""', '<string>')
   self.assertIsNotNone(
       bytes_matcher.match(
           matcher.MatchContext(parsed), parsed.tree.body[0].value))