def test_multi_name_detection_group(self): function_defs = astroid.extract_node( """ class First(object): def func(self): #@ pass def FUNC(): #@ pass """, module_name="test", ) message = Message( "invalid-name", node=function_defs[1], args=("Function", "FUNC", "'(?:(?P<UP>[A-Z]+)|(?P<down>[a-z]+))$' pattern"), ) with self.assertAddsMessages(message): func = None for func in function_defs: self.checker.visit_functiondef(func) if func: self.checker.leave_module(func.root)
def test_annotated_set_property(self): node = astroid.parse(""" class Bad(object): def __init__(self): self._temperature = 0 @temperature.setter def temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") self._temperature = value """) class_def = list(node.get_children())[0] fun_def = list(class_def.get_children())[2] with self.assertAddsMessages( Message( 'has-properties', node=fun_def, args=('temperature', ), )): self.walk(node.root())
def test_find_rethrown_numpy_multiple_raises(self): raise_node = astroid.extract_node(''' def my_func(self): """This is a docstring. Raises ------ NameError Sometimes """ try: fake_func() except (RuntimeError, ValueError): raise #@ raise NameError('hi') ''') node = raise_node.frame() with self.assertAddsMessages( Message(msg_id='missing-raises-doc', node=node, args=('RuntimeError, ValueError', ))): self.checker.visit_raise(raise_node)
def test_warns_missing_kwargs_numpy(self): node = test_utils.extract_node(''' def my_func(named_arg, **kwargs): """The docstring Args ---- named_arg : object Returned Returns ------- object or None Maybe named_arg """ if kwargs: return named_arg ''') with self.assertAddsMessages( Message(msg_id='missing-param-doc', node=node, args=('kwargs', ))): self.checker.visit_functiondef(node)
def test_exclude_protected(self): """Test that exclude-protected can be used to exclude names from protected-access warning. """ node = astroid.parse( """ class Protected: '''empty''' def __init__(self): self._meta = 42 self._manager = 24 self._teta = 29 OBJ = Protected() OBJ._meta OBJ._manager OBJ._teta """ ) with self.assertAddsMessages( Message("protected-access", node=node.body[-1].value, args="_teta") ): self.walk(node.root())
def test_property_names(self): # If a method is annotated with @property, it's name should # match the attr regex. Since by default the attribute regex is the same # as the method regex, we override it here. methods = astroid.extract_node(""" import abc def custom_prop(f): return property(f) class FooClass(object): @property def FOO(self): #@ pass @property def bar(self): #@ pass @abc.abstractproperty def BAZ(self): #@ pass @custom_prop def QUX(self): #@ pass """) with self.assertNoMessages(): self.checker.visit_functiondef(methods[0]) self.checker.visit_functiondef(methods[2]) self.checker.visit_functiondef(methods[3]) with self.assertAddsMessages( Message('invalid-name', node=methods[1], args=('attribute', 'bar', ''))): self.checker.visit_functiondef(methods[1])
def test_multi_line_double_quote_docstring_with_cfg_single_multiple_cls( self): test_str = ''' class TestClass1(object): """Class docstring on multiple lines. """ class TestClass2(object): #@ """Class level docstring on multiple lines. """ class TestClass3(object): """Another class level docstring on multiple lines. """ ''' msg = Message(msg_id='invalid-docstring-quote', line=8, args=(TRI_Q_DOUB, TRI_Q_SING)) self.check_class(test_str, msg)
def test_single_line_double_quote_docstring_with_cfg_single_cls_contents_02( self): test_str = ''' class TestClass(object): #@ """Class level docstring on a single line.""" # this is a class member member = {1:2, 3:4} def __init__(self, x): """Constructor """ self.x = x def get_x(): """Gets the x member""" return self.x ''' msg = Message(msg_id='invalid-docstring-quote', line=3, args=(TRI_Q_DOUB, TRI_Q_SING)) self.check_class(test_str, msg)
def test_unused_xcom(self): """Test invalid case: _pushtask() returns a value but it's never used.""" testcase = """ from airflow.operators.python_operator import PythonOperator def _pushtask(): print("do stuff") return "foobar" pushtask = PythonOperator(task_id="pushtask", python_callable=_pushtask) def _pulltask(): print("foobar") pulltask = PythonOperator(task_id="pulltask", python_callable=_pulltask) """ ast = astroid.parse(testcase) expected_msg_node = ast.body[2].value expected_args = "_pushtask" with self.assertAddsMessages( Message(msg_id="unused-xcom", node=expected_msg_node, args=expected_args)): self.checker.visit_module(ast)
def test_multi_name_detection_exempt(self): function_defs = astroid.extract_node(""" def FOO(): #@ pass def lower(): #@ pass def FOO(): #@ pass def UPPER(): #@ pass """) message = Message( "invalid-name", node=function_defs[3], args=( "Function", "UPPER", "'(?:(?P<ignore>FOO)|(?P<UP>[A-Z]+)|(?P<down>[a-z]+))$' pattern", ), ) with self.assertAddsMessages(message): for func in function_defs: self.checker.visit_functiondef(func) self.checker.leave_module(func.root)
def test_fixme(self): with create_file_backed_module("""a = 1 # FIXME """) as module: with self.assertAddsMessages( Message(msg_id='W0511', line=2, args=u'FIXME')): self.checker.process_module(module)
def testEmptyDocstringModule(self): module = test_utils.build_module("''''''") with self.assertAddsMessages( Message('empty-docstring', node=module, args=('module', ))): self.checker.visit_module(module)
def test_todo_without_message(self): code = """a = 1 # TODO """ with self.assertAddsMessages(Message(msg_id="fixme", line=2, args="TODO")): self.checker.process_tokens(_tokenize_str(code))
def test_raising_bad_type_python3(self): node = astroid.extract_node("raise (ZeroDivisionError, None) #@") message = Message("raising-bad-type", node=node, args="tuple") with self.assertAddsMessages(message): self.checker.visit_raise(node)
def testTrailingCommaBad(self): with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('No', 'allowed', 'before', 'bracket', '(a, )\n ^'))): self.checker.process_tokens(_tokenize_str('(a, )\n'))
def testKeywordSpacingBad(self): with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('No', 'allowed', 'before', 'keyword argument assignment', '(foo =bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo =bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('No', 'allowed', 'after', 'keyword argument assignment', '(foo= bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo= bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('No', 'allowed', 'around', 'keyword argument assignment', '(foo = bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo = bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('Exactly one', 'required', 'before', 'keyword argument assignment', '(foo: int= bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo: int= bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('Exactly one', 'required', 'after', 'keyword argument assignment', '(foo: int =bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo: int =bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('Exactly one', 'required', 'around', 'keyword argument assignment', '(foo: int=bar)\n ^'))): self.checker.process_tokens(_tokenize_str('(foo: int=bar)\n')) with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('Exactly one', 'required', 'around', 'keyword argument assignment', '(foo: List[int]=bar)\n ^'))): self.checker.process_tokens( _tokenize_str('(foo: List[int]=bar)\n')) # Regression test for #1831 with self.assertNoMessages(): self.checker.process_tokens( _tokenize_str("(arg: Tuple[\n int, str] = None):\n"))
def test_missing_docstring_module(self): module = test_utils.build_module("") with self.assertAddsMessages( Message('missing-docstring', node=module, args=('module', ))): self.checker.visit_module(module)
def testPositiveSuperfluousParensWalrusOperatorIf(self): """Test positive superfluous parens with the walrus operator""" code = "if ((odd := is_odd(i))):" msg = Message("superfluous-parens", line=1, args="if") with self.assertAddsMessages(msg): self.checker._check_keyword_parentheses(_tokenize_str(code), 0)
def testKeywordSpacingBad(self): with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "No", "allowed", "before", "keyword argument assignment", "(foo =bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo =bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "No", "allowed", "after", "keyword argument assignment", "(foo= bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo= bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "No", "allowed", "around", "keyword argument assignment", "(foo = bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo = bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "Exactly one", "required", "before", "keyword argument assignment", "(foo: int= bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo: int= bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "Exactly one", "required", "after", "keyword argument assignment", "(foo: int =bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo: int =bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "Exactly one", "required", "around", "keyword argument assignment", "(foo: int=bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo: int=bar)\n")) with self.assertAddsMessages( Message( "bad-whitespace", line=1, args=( "Exactly one", "required", "around", "keyword argument assignment", "(foo: List[int]=bar)\n ^", ), ) ): self.checker.process_tokens(_tokenize_str("(foo: List[int]=bar)\n")) # Regression test for #1831 with self.assertNoMessages(): self.checker.process_tokens( _tokenize_str("(arg: Tuple[\n int, str] = None):\n") )
def test_issue_2321_should_trigger(self): code = "# TODO this should not trigger a fixme" with self.assertAddsMessages( Message(msg_id="fixme", line=1, args="TODO this should not trigger a fixme") ): self.checker.process_tokens(_tokenize_str(code))
def test_without_space_fixme(self): code = """a = 1 #FIXME """ with self.assertAddsMessages(Message(msg_id="fixme", line=2, args="FIXME")): self.checker.process_tokens(_tokenize_str(code))
def test_missing_docstring_module(self): module = astroid.parse("something") message = Message("missing-module-docstring", node=module) with self.assertAddsMessages(message): self.checker.visit_module(module)
def test_empty_docstring_module(self): module = astroid.parse("''''''") message = Message("empty-docstring", node=module, args=("module", )) with self.assertAddsMessages(message): self.checker.visit_module(module)
def test_comparison(self): node = astroid.extract_node("foo == True") message = Message( "singleton-comparison", node=node, args=( "'foo == True'", "'foo is True' if checking for the singleton value True, or 'bool(foo)' if testing for truthiness", ), ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node("foo == False") message = Message( "singleton-comparison", node=node, args=( "'foo == False'", "'foo is False' if checking for the singleton value False, or 'not foo' if testing for falsiness", ), ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node("foo == None") message = Message( "singleton-comparison", node=node, args=("'foo == None'", "'foo is None'") ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node("foo is float('nan')") message = Message( "nan-comparison", node=node, args=("'foo is float('nan')'", "'math.isnan(foo)'"), ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node( """ import numpy foo != numpy.NaN """ ) message = Message( "nan-comparison", node=node, args=("'foo != numpy.NaN'", "'not math.isnan(foo)'"), ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node( """ import numpy as nmp foo is not nmp.NaN """ ) message = Message( "nan-comparison", node=node, args=("'foo is not nmp.NaN'", "'not math.isnan(foo)'"), ) with self.assertAddsMessages(message): self.checker.visit_compare(node) node = astroid.extract_node("True == foo") messages = ( Message("misplaced-comparison-constant", node=node, args=("foo == True",)), Message( "singleton-comparison", node=node, args=( "'True == foo'", "'True is foo' if checking for the singleton value True, or 'bool(foo)' if testing for truthiness", ), ), ) with self.assertAddsMessages(*messages): self.checker.visit_compare(node) node = astroid.extract_node("False == foo") messages = ( Message("misplaced-comparison-constant", node=node, args=("foo == False",)), Message( "singleton-comparison", node=node, args=( "'False == foo'", "'False is foo' if checking for the singleton value False, or 'not foo' if testing for falsiness", ), ), ) with self.assertAddsMessages(*messages): self.checker.visit_compare(node) node = astroid.extract_node("None == foo") messages = ( Message("misplaced-comparison-constant", node=node, args=("foo == None",)), Message( "singleton-comparison", node=node, args=("'None == foo'", "'None is foo'"), ), ) with self.assertAddsMessages(*messages): self.checker.visit_compare(node)
def testComma(self): with self.assertAddsMessages( Message('bad-whitespace', line=1, args=('No', 'allowed', 'before', 'comma', '(a , b)\n ^'))): self.checker.process_tokens(tokenize_str('(a , b)\n'))
def test_invalid_docstring_characters(self): stmt = astroid.extract_node('def fff():\n """test\\x00"""\n pass') with self.assertAddsMessages( Message("invalid-characters-in-docstring", line=2, args=("test\x00",)) ): self.checker.visit_functiondef(stmt)
def test_raising_bad_type_python3(self): node = test_utils.extract_node('raise (ZeroDivisionError, None) #@') message = Message('raising-bad-type', node=node, args='tuple') with self.assertAddsMessages(message): self.checker.visit_raise(node)
def test_wrong_name_of_func_params_in_numpy_docstring(self): """Example of functions with inconsistent parameter names in the signature and in the Numpy style documentation """ node = astroid.extract_node(""" def function_foo(xarg, yarg, zarg): '''function foo ... Parameters ---------- xarg1: int bla xarg yarg: float bla yarg zarg1: str bla zarg ''' return xarg + yarg """) with self.assertAddsMessages( Message( msg_id='missing-param-doc', node=node, args=('xarg, zarg',)), Message( msg_id='missing-type-doc', node=node, args=('xarg, zarg',)), Message( msg_id='differing-param-doc', node=node, args=('xarg1, zarg1',)), Message( msg_id='differing-type-doc', node=node, args=('xarg1, zarg1',)), ): self.checker.visit_functiondef(node) node = astroid.extract_node(""" def function_foo(xarg, yarg): '''function foo ... Parameters ---------- yarg1: float bla yarg For the other parameters, see bla. ''' return xarg + yarg """) with self.assertAddsMessages( Message( msg_id='differing-param-doc', node=node, args=('yarg1',)), Message( msg_id='differing-type-doc', node=node, args=('yarg1',)) ): self.checker.visit_functiondef(node)