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', )
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', )
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, )
def assert_equivalent_under_mock(self, lhs, rhs, m): """Checks that lhs and rhs perform the same operations in a mock namespace. The mock object has its _attributes_ used as members of the namespace. So, for example, if you want to ensure a global FOO is set to 3 during evaluation, you must set m.FOO = 3. The mock is reset between calls, so things like return_value will not work. Args: lhs: An object that can be passed to eval() rhs: An object that can be passed to eval() m: A Mock object. """ m.reset_mock() # to be safe. objs_map = fixer.ImmutableDefaultDict(lambda k: getattr(m, k)) lhs_result = None lhs_e = None try: lhs_result = eval(lhs, {}, objs_map) # It's for the greater good: pylint: disable=eval-used except Exception as e: # pylint: disable=broad-except lhs_e = e lhs_calls = m.mock_calls # Rest the mock so we can reuse it. This keeps sub-mock ids the same, # so that e.g. a(b) is the "same call". # If we used two mocks, then b would be a different object each time, # and the calls would not compare equal. m.reset_mock() rhs_result = None rhs_e = None try: rhs_result = eval(rhs, {}, objs_map) # It's for the greater good: pylint: disable=eval-used except Exception as e: # pylint: disable=broad-except rhs_e = e self.assertEqual(lhs_calls, m.mock_calls) # Try to check that the return values are at least remotely similar. # Either the return values are equal (e.g. 1L == 1), or the types are the # same (eg. object() != object(), but we'd still like that case to pass.) self.assertTrue( lhs_result == rhs_result or type(lhs_result) == type(rhs_result), # pylint: disable=unidiomatic-typecheck '{!r} != {!r}'.format(lhs_result, rhs_result)) self.assertEqual(type(lhs_e), type(rhs_e))
def test_len(self): self.assertEmpty(fixer.ImmutableDefaultDict(lambda _: 'a'))
def test_replacement(self): self.assertEqual( string.Template('$a == $b').substitute( fixer.ImmutableDefaultDict(lambda k: k)), 'a == b')