|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- # -*- coding: utf-8 -*-
- # Copyright (c) 2013-2014 Google, Inc.
- # Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
- # Copyright (c) 2014 Arun Persaud <arun@nubati.net>
- # Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
- # Copyright (c) 2015 Aru Sahni <arusahni@gmail.com>
- # Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
- # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
- # Copyright (c) 2016 Glenn Matthews <glenn@e-dad.net>
- # Copyright (c) 2017 ttenhoeve-aa <ttenhoeve@appannie.com>
- # Copyright (c) 2017 Anthony Sottile <asottile@umich.edu>
- # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
-
- # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- # For details: https://github.com/PyCQA/pylint/blob/master/COPYING
-
- import io
- import re
- import warnings
-
- import astroid
-
- from pylint import utils
- from pylint.checkers.utils import check_messages, get_node_last_lineno
- from pylint.exceptions import InvalidMessageError
- import pytest
-
-
- class TestPyLintASTWalker(object):
- class MockLinter(object):
- def __init__(self, msgs):
- self._msgs = msgs
-
- def is_message_enabled(self, msgid):
- return self._msgs.get(msgid, True)
-
- class Checker(object):
- def __init__(self):
- self.called = set()
-
- @check_messages('first-message')
- def visit_module(self, module):
- self.called.add('module')
-
- @check_messages('second-message')
- def visit_call(self, module):
- raise NotImplementedError
-
- @check_messages('second-message', 'third-message')
- def visit_assignname(self, module):
- self.called.add('assignname')
-
- @check_messages('second-message')
- def leave_assignname(self, module):
- raise NotImplementedError
-
- def test_check_messages(self):
- linter = self.MockLinter({'first-message': True,
- 'second-message': False,
- 'third-message': True})
- walker = utils.PyLintASTWalker(linter)
- checker = self.Checker()
- walker.add_checker(checker)
- walker.walk(astroid.parse("x = func()"))
- assert {'module', 'assignname'} == checker.called
-
- def test_deprecated_methods(self):
- class Checker(object):
- def __init__(self):
- self.called = False
-
- @check_messages('first-message')
- def visit_assname(self, node):
- self.called = True
-
- linter = self.MockLinter({'first-message': True})
- walker = utils.PyLintASTWalker(linter)
- checker = Checker()
- walker.add_checker(checker)
- with warnings.catch_warnings(record=True):
- warnings.simplefilter('always')
- walker.walk(astroid.parse("x = 1"))
-
- assert not checker.called
-
-
- def test__basename_in_blacklist_re_match():
- patterns = [re.compile(".*enchilada.*"), re.compile("unittest_.*")]
- assert utils._basename_in_blacklist_re("unittest_utils.py", patterns)
- assert utils._basename_in_blacklist_re("cheese_enchiladas.xml", patterns)
-
-
- def test__basename_in_blacklist_re_nomatch():
- patterns = [re.compile(".*enchilada.*"), re.compile("unittest_.*")]
- assert not utils._basename_in_blacklist_re("test_utils.py", patterns)
- assert not utils._basename_in_blacklist_re("enchilad.py", patterns)
-
-
- @pytest.fixture
- def store():
- return utils.MessagesStore()
-
-
- @pytest.mark.parametrize("messages,expected", [
- ({'W1234': ('message one', 'msg-symbol-one', 'msg description'),
- 'W4321': ('message two', 'msg-symbol-two', 'msg description')},
- r"Inconsistent checker part in message id 'W4321' (expected 'x12xx')"),
-
- ({'W1233': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1234', 'old-symbol')]}),
- 'W1234': ('message one', 'msg-symbol-one', 'msg description')},
- "Message id 'W1234' is already defined"),
-
- ({'W1234': ('message one', 'msg-symbol-one', 'msg description'),
- 'W1235': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1234', 'old-symbol')]})},
- "Message id 'W1234' is already defined"),
-
- ({'W1234': ('message one', 'msg-symbol-one', 'msg description',
- {'old_names': [('W1201', 'old-symbol-one')]}),
- 'W1235': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1201', 'old-symbol-two')]})},
- "Message id 'W1201' is already defined"),
- ({'W1234': ('message one', 'msg-symbol', 'msg description'),
- 'W1235': ('message two', 'msg-symbol', 'msg description')},
- "Message symbol 'msg-symbol' is already defined"),
-
- ({'W1233': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1230', 'msg-symbol-one')]}),
- 'W1234': ('message one', 'msg-symbol-one', 'msg description')},
- "Message symbol 'msg-symbol-one' is already defined"),
-
- ({'W1234': ('message one', 'msg-symbol-one', 'msg description'),
- 'W1235': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1230', 'msg-symbol-one')]})},
- "Message symbol 'msg-symbol-one' is already defined"),
-
- ({'W1234': ('message one', 'msg-symbol-one', 'msg description',
- {'old_names': [('W1230', 'old-symbol-one')]}),
- 'W1235': ('message two', 'msg-symbol-two', 'msg description',
- {'old_names': [('W1231', 'old-symbol-one')]})},
- "Message alternate name 'old-symbol-one' is already defined"),
-
- ])
- def test_register_error(store, messages, expected):
- class Checker(object):
- name = 'checker'
- msgs = messages
- with pytest.raises(InvalidMessageError) as cm:
- store.register_messages(Checker())
- assert str(cm.value) == expected
-
-
- def test_register_error_new_id_duplicate_of_new(store):
- class CheckerOne(object):
- name = 'checker_one'
- msgs = {
- 'W1234': ('message one', 'msg-symbol-one', 'msg description.'),
- }
-
- class CheckerTwo(object):
- name = 'checker_two'
- msgs = {
- 'W1234': ('message two', 'msg-symbol-two', 'another msg description.'),
- }
- store.register_messages(CheckerOne())
- test_register_error(store,
- {'W1234': ('message two', 'msg-symbol-two', 'another msg description.')},
- "Message id 'W1234' is already defined")
-
-
- @pytest.mark.parametrize("msgid,expected", [
- ("Q1234", "Bad message type Q in 'Q1234'"),
- ("W12345", "Invalid message id 'W12345'"),
- ])
- def test_create_invalid_message_type(msgid, expected):
- with pytest.raises(InvalidMessageError) as cm:
- utils.MessageDefinition('checker', msgid,
- 'msg', 'descr', 'symbol', 'scope')
- assert str(cm.value) == expected
-
-
- def test__decoding_readline():
- """_decoding_readline should yield line at a time even if the binary
- representation of the text is not splittable line-by-line.
-
- For convenience this test uses a codec that is easy to understand, though
- this *specific* codec is unlikely to be seen in the wild for files.
- """
- binary_io = io.BytesIO(b'foo\\nbaz\\n')
- readline = utils._decoding_readline(binary_io, 'unicode_escape')
-
- ret = []
- s = readline()
- while s != '':
- ret.append(s)
- s = readline()
-
- assert ret == ['foo\n', 'baz\n']
-
-
- def test_decoding_stream_unknown_encoding():
- """decoding_stream should fall back to *some* decoding when given an
- unknown encoding.
- """
- binary_io = io.BytesIO(b'foo\nbar')
- stream = utils.decoding_stream(binary_io, 'garbage-encoding')
- # should still act like a StreamReader
- ret = stream.readlines()
- assert ret == ['foo\n', 'bar']
-
-
- def test_decoding_stream_known_encoding():
- binary_io = io.BytesIO(u'€'.encode('cp1252'))
- stream = utils.decoding_stream(binary_io, 'cp1252')
- assert stream.read() == u'€'
-
- class TestGetNodeLastLineno:
-
- def test_get_node_last_lineno_simple(self):
- node = astroid.extract_node("""
- pass
- """)
- assert get_node_last_lineno(node) == 2
-
-
- def test_get_node_last_lineno_if_simple(self):
- node = astroid.extract_node("""
- if True:
- print(1)
- pass
- """)
- assert get_node_last_lineno(node) == 4
-
-
- def test_get_node_last_lineno_if_elseif_else(self):
- node = astroid.extract_node("""
- if True:
- print(1)
- elif False:
- print(2)
- else:
- print(3)
- """)
- assert get_node_last_lineno(node) == 7
-
-
- def test_get_node_last_lineno_while(self):
- node = astroid.extract_node("""
- while True:
- print(1)
- """)
- assert get_node_last_lineno(node) == 3
-
-
- def test_get_node_last_lineno_while_else(self):
- node = astroid.extract_node("""
- while True:
- print(1)
- else:
- print(2)
- """)
- assert get_node_last_lineno(node) == 5
-
-
- def test_get_node_last_lineno_for(self):
- node = astroid.extract_node("""
- for x in range(0, 5):
- print(1)
- """)
- assert get_node_last_lineno(node) == 3
-
-
- def test_get_node_last_lineno_for_else(self):
- node = astroid.extract_node("""
- for x in range(0, 5):
- print(1)
- else:
- print(2)
- """)
- assert get_node_last_lineno(node) == 5
-
-
- def test_get_node_last_lineno_try(self):
- node = astroid.extract_node("""
- try:
- print(1)
- except ValueError:
- print(2)
- except Exception:
- print(3)
- """)
- assert get_node_last_lineno(node) == 7
-
-
- def test_get_node_last_lineno_try_except_else(self):
- node = astroid.extract_node("""
- try:
- print(1)
- except Exception:
- print(2)
- print(3)
- else:
- print(4)
- """)
- assert get_node_last_lineno(node) == 8
-
-
- def test_get_node_last_lineno_try_except_finally(self):
- node = astroid.extract_node("""
- try:
- print(1)
- except Exception:
- print(2)
- finally:
- print(4)
- """)
- assert get_node_last_lineno(node) == 7
-
-
- def test_get_node_last_lineno_try_except_else_finally(self):
- node = astroid.extract_node("""
- try:
- print(1)
- except Exception:
- print(2)
- else:
- print(3)
- finally:
- print(4)
- """)
- assert get_node_last_lineno(node) == 9
-
-
- def test_get_node_last_lineno_with(self):
- node = astroid.extract_node("""
- with x as y:
- print(1)
- pass
- """)
- assert get_node_last_lineno(node) == 4
-
-
- def test_get_node_last_lineno_method(self):
- node = astroid.extract_node("""
- def x(a, b):
- print(a, b)
- pass
- """)
- assert get_node_last_lineno(node) == 4
-
-
- def test_get_node_last_lineno_decorator(self):
- node = astroid.extract_node("""
- @decor()
- def x(a, b):
- print(a, b)
- pass
- """)
- assert get_node_last_lineno(node) == 5
-
- def test_get_node_last_lineno_class(self):
- node = astroid.extract_node("""
- class C(object):
- CONST = True
-
- def x(self, b):
- print(b)
-
- def y(self):
- pass
- pass
- """)
- assert get_node_last_lineno(node) == 10
-
-
- def test_get_node_last_lineno_combined(self):
- node = astroid.extract_node("""
- class C(object):
- CONST = True
-
- def y(self):
- try:
- pass
- except:
- pass
- finally:
- pass
- """)
- assert get_node_last_lineno(node) == 11
|