Exemple #1
0
def assert_message_fixer(old_expr, new_expr, method, is_absl=False):
  """Fixer for assertTrue()/assertFalse()/etc.

  related error fixes.

  assertTrue(...) often produces less readable error information than
  alternative methods like assertEqual etc.

  Args:
    old_expr: a ExprPattern string for the expr to match
    new_expr: a template string for the replacement
    method: the method to link to in the docs.
    is_absl: Whether this is an absl method with absl docs.

  Returns:
    A fixer that replaces old_expr with new_expr.
  """
  if is_absl:
    # absl doesn't have docs per se.
    url = f'https://github.com/abseil/abseil-py/search?q=%22def+{method}%22'
  else:
    url = f'https://docs.python.org/3/library/unittest.html#unittest.TestCase.{method}'
  dotdotdot = fixer.ImmutableDefaultDict(lambda _: '...')
  return fixer.SimplePythonFixer(
      message=(
          '%s is a more specific assertion, and may give more detailed error information than %s.'
          % (string.Template(new_expr).substitute(dotdotdot),
             string.Template(old_expr).substitute(dotdotdot))),
      matcher=syntax_matchers.ExprPattern(old_expr),
      replacement=syntactic_template.PythonExprTemplate(new_expr),
      url=url,
      category='pylint.g-generic-assert',
  )
Exemple #2
0
def idiom_fixer(
    old_expr,
    new_expr,
    category,
    url='https://refex.readthedocs.io/en/latest/guide/fixers/idiom.html',
):
    """Fixer for making expressions "clearer" / less convoluted.

  This also helps normalize them for other fixers to apply.

  Args:
    old_expr: An ExprPattern string for the expr to match.
    new_expr: A string.Template string for the replacement.
    category: A category for the fix.
    url: An URL describing the fix.

  Returns:
    A fixer that replaces old_expr with new_expr.
  """
    dotdotdot = fixer.ImmutableDefaultDict(lambda _: '...')
    return fixer.SimplePythonFixer(
        message=('This could be more Pythonic: %s -> %s.' %
                 ((string.Template(old_expr).substitute(dotdotdot),
                   string.Template(new_expr).substitute(dotdotdot)))),
        matcher=syntax_matchers.ExprPattern(old_expr),
        replacement=syntactic_template.PythonExprTemplate(new_expr),
        url=url,
        significant=False,
        category=category,
    )
Exemple #3
0
def assert_alias_fixer(
    old_expr,
    new_expr,
    url='https://docs.python.org/3/library/unittest.html#deprecated-aliases'):
  """Fixer for deprecated unittest aliases.

  Args:
    old_expr: A string for an ExprPattern matching the target expr.
    new_expr: A string for a PythonExprTemplate to replace it with.
    url: The URL documenting the deprecation.

  Returns:
    A fixer that replaces old_expr with new_expr.
  """
  dotdotdot = fixer.ImmutableDefaultDict(lambda _: '...')
  return fixer.SimplePythonFixer(
      message=('{old} is a deprecated alias for {new} in the unittest module.'
               .format(
                   old=string.Template(old_expr).substitute(dotdotdot),
                   new=string.Template(new_expr).substitute(dotdotdot))),
      matcher=syntax_matchers.ExprPattern(old_expr),
      replacement=syntactic_template.PythonExprTemplate(new_expr),
      url=url,
      significant=False,
      category='pylint.g-deprecated-assert',
  )
Exemple #4
0
def main():
    cli.run(
        runner=cli.RefexRunner(
            searcher=search.PyExprRewritingSearcher.from_matcher(
                # --mode=py.expr is equivalent to PyExprRewritingSearcher paired
                # with an ExprPattern. However, you can pass any matcher, not just
                # an ExprPattern.
                syntax_matchers.ExprPattern('hello'),
                {
                    # Using ROOT_LABEL as a key is equivalent to --sub=world.
                    # To get the equivalent of --named-sub=x=world,
                    # it would 'x' as a key instead.
                    #
                    # The value type corresponds to the --sub-mode. While
                    # refex on the command line defaults to picking the paired
                    # --sub-mode that matches the --mode, here there are no
                    # defaults and you must be explicit.
                    # e.g. for unsafe textual substitutions, as with
                    # --sub-mode=sh, you would use formatting.ShTemplate.
                    search.ROOT_LABEL:
                    syntactic_template.PythonExprTemplate('world')
                },
            ),
            dry_run=False,
        ),
        files=sys.argv[1:],
        bug_report_url='<project bug report URL goes here>',
    )
Exemple #5
0
 def test_labeled_replacements_example_fragment(self):
     fx = fixer.SimplePythonFixer(
         message='',
         matcher=syntax_matchers.ExprPattern('$y'),
         replacement={'y': syntactic_template.PythonExprTemplate('$y')},
     )
     with self.assertRaises(TypeError):
         fx.example_replacement()
 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}))
 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 #8
0
def _search_replace_fixer(search_expr,
                          replace,
                          message=None,
                          url='',
                          **kwargs):
    return fixer.SimplePythonFixer(
        message=message if message is not None else search_expr,
        matcher=syntax_matchers.ExprPattern(search_expr),
        replacement=syntactic_template.PythonExprTemplate(replace),
        url=url,
        category='TESTONLY',
        **kwargs)
class SumMatcherTest(absltest.TestCase):
    SEARCH_REPLACE = search.PyExprRewritingSearcher.from_matcher(
        example_custom_matcher.SumMatcher(),
        {search.ROOT_LABEL: syntactic_template.PythonExprTemplate('$sum')},
    )

    def test_sum_rewrite(self):
        self.assertEqual(
            search.rewrite_string(self.SEARCH_REPLACE, '1 + 2 + 3',
                                  'filename.py'), '6')

    def test_sum_no_rewrite(self):
        self.assertEqual(
            search.rewrite_string(self.SEARCH_REPLACE, '1 + var',
                                  'filename.py'), '1 + var')
Exemple #10
0
def _dict_iter_fixer(method_name):
    return fixer.SimplePythonFixer(
        message=('dict.{method} is deprecated and does not exist in Python 3. '
                 'Instead, import six and use six.{method}').format(
                     method=method_name),
        matcher=with_six(
            syntax_matchers.ExprPattern('$x.{}()'.format(method_name), {
                'x':
                base_matchers.Unless(syntax_matchers.ExprPattern('six'))
            }), ),
        replacement=syntactic_template.PythonExprTemplate(
            'six.{}($x)'.format(method_name)),
        url='https://www.python.org/doc/sunset-python-2/',
        category='pylint.dict-iter-method',
        # Must define manually due to the extra restrictions on the pattern.
        example_fragment='import six; x.{}()'.format(method_name),
        example_replacement='import six; six.{}(x)'.format(method_name),
    )
Exemple #11
0
from refex.python import syntactic_template
from refex.python.matchers import ast_matchers
from refex.python.matchers import base_matchers
from refex.python.matchers import syntax_matchers

SIMPLE_PYTHON_FIXERS = []  # Disabled except when running in Python 2.


def with_six(m):
    return syntax_matchers.WithTopLevelImport(m, 'six')


_HAS_KEY_FIXER = fixer.SimplePythonFixer(
    message='dict.has_key() was removed in Python 3.',
    matcher=syntax_matchers.ExprPattern('$a.has_key($b)'),
    replacement=syntactic_template.PythonExprTemplate('$b in $a'),
    url='https://docs.python.org/3.1/whatsnew/3.0.html#builtins',
    significant=True,
    category='refex.modernize.dict_has_key',
)


def _dict_iter_fixer(method_name):
    return fixer.SimplePythonFixer(
        message=('dict.{method} is deprecated and does not exist in Python 3. '
                 'Instead, import six and use six.{method}').format(
                     method=method_name),
        matcher=with_six(
            syntax_matchers.ExprPattern('$x.{}()'.format(method_name), {
                'x':
                base_matchers.Unless(syntax_matchers.ExprPattern('six'))
Exemple #12
0
 def test_empty_expr(self):
     with self.assertRaises(ValueError):
         syntactic_template.PythonExprTemplate('')
Exemple #13
0
 def test_variables(self, template, expected_variables):
     self.assertEqual(
         syntactic_template.PythonExprTemplate(template).variables,
         expected_variables)