Exemple #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))
Exemple #2
0
 def parse(self, data: Text, filename: str):
     """Returns a :class:`refex.python.matcher.PythonParsedFile`."""
     try:
         return _matcher.parse_ast(data, filename)
     except _matcher.ParseError as e:
         # Probably Python 2. TODO: figure out how to handle this.
         raise SkipFileError(str(e))
Exemple #3
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]))
 def test_nonexpr_in_expr_context(self, template):
     parsed = matcher.parse_ast('[x]')
     m = base_matchers.Bind('bound', ast_matchers.Name())
     [matchinfo] = matcher.find_iter(m, parsed)
     with self.assertRaises(formatting.RewriteError):
         template.substitute_match(parsed, matchinfo.match,
                                   {'bound': matchinfo.match})
Exemple #5
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))
Exemple #6
0
 def test_simple_node_is_expr(self):
     """In a non-simple statement, subexpressions are their own simple node."""
     parsed = matcher.parse_ast('for x in y: pass')
     for_stmt = parsed.tree.body[0]
     self.assertIs(parsed.nav.get_simple_node(for_stmt.target),
                   for_stmt.target)
     self.assertIs(parsed.nav.get_simple_node(for_stmt.iter), for_stmt.iter)
Exemple #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))
Exemple #8
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))
Exemple #9
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))
Exemple #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))
Exemple #11
0
 def test_invalid_syntax(self):
     parsed = matcher.parse_ast('x')
     m = base_matchers.Bind('x', ast_matchers.Name())
     [matchinfo] = matcher.find_iter(m, parsed)
     template = syntactic_template.PythonTemplate('$x')
     with self.assertRaises(formatting.RewriteError):
         template.substitute_match(parsed, matchinfo.match,
                                   {'x': match.StringMatch('x  y')}),
Exemple #12
0
 def test_nonpython_dollars_source(self, src):
     parsed = matcher.parse_ast(src)
     m = base_matchers.Bind('bound', ast_matchers.Call())
     [matchinfo] = matcher.find_iter(m, parsed)
     self.assertEqual(
         src,
         syntactic_template.PythonExprTemplate('$bound').substitute_match(
             parsed, matchinfo.match, {'bound': matchinfo.match}))
Exemple #13
0
    def test_doesnt_match(self):
        parsed = matcher.parse_ast('hi = 42', '<string>')
        m = base_matchers.AllOf(base_matchers.FileMatchesRegex('hello'),
                                ast_matchers.Num())

        matches = list(matcher.find_iter(m, parsed))

        self.assertEqual(matches, [])
Exemple #14
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))
Exemple #15
0
    def test_matches(self):
        parsed = matcher.parse_ast('var_hello = 42', '<string>')
        m = base_matchers.AllOf(base_matchers.FileMatchesRegex('hello'),
                                ast_matchers.Num())

        matches = list(matcher.find_iter(m, parsed))

        self.assertLen(matches, 1)
Exemple #16
0
 def test_inner_nomatches(self):
     parsed = matcher.parse_ast('xy = 2', '<string>')
     matches = list(
         matcher.find_iter(
             base_matchers.MatchesRegex(
                 r'', base_matchers.Unless(base_matchers.Anything())),
             parsed))
     self.assertEqual(matches, [])
Exemple #17
0
 def test_fullmatch_semantics(self):
     """The regexp only matches the full expression."""
     for var in ['x_', '_x']:
         with self.subTest(var=var):
             parsed = matcher.parse_ast(var, '<string>')
             self.assertEqual(
                 list(
                     matcher.find_iter(base_matchers.MatchesRegex(r'x'),
                                       parsed)), [])
Exemple #18
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)}))
Exemple #19
0
 def test_bindings(self):
     parsed = matcher.parse_ast('2', '<string>')
     matches = list(
         matcher.find_iter(
             base_matchers.MatchesRegex(r'(?P<var>.)', ast_matchers.Num()),
             parsed))
     self.assertLen(matches, 1)
     [m] = matches
     self.assertIn('var', m.bindings)
     self.assertEqual(m.bindings['var'].value.span, (0, 1))
Exemple #20
0
 def test_autoparen_outer(self):
     parsed = matcher.parse_ast('x * 2')
     m = base_matchers.Bind('x', ast_matchers.Name())
     [matchinfo] = matcher.find_iter(m, parsed)
     template = syntactic_template.PythonTemplate('$x')
     self.assertEqual(
         template.substitute_match(parsed, matchinfo.match,
                                   {'x': match.StringMatch('x + y')}),
         '(x + y)',
     )
Exemple #21
0
 def test_nonpython_dollars_dest(self):
     src = 'f'
     parsed = matcher.parse_ast(src)
     m = base_matchers.Bind('bound', ast_matchers.Name())
     [matchinfo] = matcher.find_iter(m, parsed)
     self.assertEqual(
         'f("$x")',
         syntactic_template.PythonExprTemplate(
             '$bound("$x")').substitute_match(parsed, matchinfo.match,
                                              {'bound': matchinfo.match}))
Exemple #22
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))
Exemple #23
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))
Exemple #24
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(''))
Exemple #25
0
 def test_line_pragma(self):
     prefix = 'not_annotated()\n'
     suffix = 'a() # foo: bar=baz.quux'
     source = ''.join([prefix, suffix, '\nalso_not_annotated()'])
     self.assertEqual(
         matcher.parse_ast(source).pragmas,
         (parsed_file.Pragma(tag='foo',
                             data={'bar': 'baz.quux'},
                             start=len(prefix),
                             end=len(prefix) + len(suffix)), ))
Exemple #26
0
    def test_memoized_nodes(self):
        """Some nodes like the BinOp.op attribute are memoized, which we must undo.

    Otherwise, the parent would just be the last binop to be read, etc.
    """
        parsed = matcher.parse_ast('[1+2, 3+4, 5+6]')
        binop1, binop2, binop3 = parsed.tree.body[0].value.elts
        self.assertIs(parsed.nav.get_parent(binop1.op), binop1)
        self.assertIs(parsed.nav.get_parent(binop2.op), binop2)
        self.assertIs(parsed.nav.get_parent(binop3.op), binop3)
Exemple #27
0
 def test_locally_scoped_pragma(self, first_line):
     prefix = 'def foo():\n' + first_line
     suffix = '  # foo: bar=baz.quux\n  hello_world()\n\n'
     source = ''.join(
         [prefix, suffix, 'def bar():\n  also_not_annotated()'])
     self.assertEqual(
         matcher.parse_ast(source).pragmas,
         (parsed_file.Pragma(tag='foo',
                             data={'bar': 'baz.quux'},
                             start=len(prefix),
                             end=len(prefix) + len(suffix)), ))
Exemple #28
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))
Exemple #29
0
 def test_assignment(self, template):
     template = syntactic_template.PythonStmtTemplate(template)
     # Test with different values of `ctx` for the variable being substituted.
     for variable_source in 'a = 1', 'a':
         with self.subTest(variable_souce=variable_source):
             [matchinfo] = matcher.find_iter(
                 base_matchers.Bind('x', ast_matchers.Name()),
                 matcher.parse_ast(variable_source))
             substituted = template.substitute_match(
                 None, None, {'x': matchinfo.match})
             self.assertEqual(substituted,
                              template.template.replace('$x', 'a'))
Exemple #30
0
    def test_multi_regex(self):
        """Tests that the lazy dictionary doesn't walk over itself or something."""
        parsed = matcher.parse_ast('var_hello = 42', '<string>')
        m = base_matchers.AllOf(
            base_matchers.FileMatchesRegex('var'),
            base_matchers.FileMatchesRegex('hello'),
            base_matchers.FileMatchesRegex('42'),
            base_matchers.FileMatchesRegex(r'\Avar_hello = 42\Z'),
            ast_matchers.Num())

        matches = list(matcher.find_iter(m, parsed))

        self.assertLen(matches, 1)