summaryrefslogtreecommitdiff
path: root/pylint/test/unittest_checker_python3.py
diff options
context:
space:
mode:
Diffstat (limited to 'pylint/test/unittest_checker_python3.py')
-rw-r--r--pylint/test/unittest_checker_python3.py301
1 files changed, 301 insertions, 0 deletions
diff --git a/pylint/test/unittest_checker_python3.py b/pylint/test/unittest_checker_python3.py
new file mode 100644
index 0000000..a7d31ba
--- /dev/null
+++ b/pylint/test/unittest_checker_python3.py
@@ -0,0 +1,301 @@
+# Copyright 2014 Google Inc.
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+"""Tests for the python3 checkers."""
+from __future__ import absolute_import
+
+import sys
+import unittest
+import textwrap
+
+from astroid import test_utils
+
+from pylint import testutils
+from pylint.checkers import python3 as checker
+
+
+def python2_only(test):
+ """Decorator for any tests that will fail under Python 3."""
+ return unittest.skipIf(sys.version_info[0] > 2, 'Python 2 only')(test)
+
+# TODO(cpopa): Port these to the functional test framework instead.
+
+class Python3CheckerTest(testutils.CheckerTestCase):
+ CHECKER_CLASS = checker.Python3Checker
+
+ def check_bad_builtin(self, builtin_name):
+ node = test_utils.extract_node(builtin_name + ' #@')
+ message = builtin_name.lower() + '-builtin'
+ with self.assertAddsMessages(testutils.Message(message, node=node)):
+ self.checker.visit_name(node)
+
+ @python2_only
+ def test_bad_builtins(self):
+ builtins = [
+ 'apply',
+ 'buffer',
+ 'cmp',
+ 'coerce',
+ 'execfile',
+ 'file',
+ 'input',
+ 'intern',
+ 'long',
+ 'raw_input',
+ 'round',
+ 'reduce',
+ 'StandardError',
+ 'unichr',
+ 'unicode',
+ 'xrange',
+ 'reload',
+ ]
+ for builtin in builtins:
+ self.check_bad_builtin(builtin)
+
+ def _test_defined_method(self, method, warning):
+ node = test_utils.extract_node("""
+ class Foo(object):
+ def __{0}__(self, other): #@
+ pass""".format(method))
+ message = testutils.Message(warning, node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_function(node)
+
+ def test_delslice_method(self):
+ self._test_defined_method('delslice', 'delslice-method')
+
+ def test_getslice_method(self):
+ self._test_defined_method('getslice', 'getslice-method')
+
+ def test_setslice_method(self):
+ self._test_defined_method('setslice', 'setslice-method')
+
+ def test_coerce_method(self):
+ self._test_defined_method('coerce', 'coerce-method')
+
+ def test_oct_method(self):
+ self._test_defined_method('oct', 'oct-method')
+
+ def test_hex_method(self):
+ self._test_defined_method('hex', 'hex-method')
+
+ def test_nonzero_method(self):
+ self._test_defined_method('nonzero', 'nonzero-method')
+
+ def test_cmp_method(self):
+ self._test_defined_method('cmp', 'cmp-method')
+
+ @python2_only
+ def test_print_statement(self):
+ node = test_utils.extract_node('print "Hello, World!" #@')
+ message = testutils.Message('print-statement', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_print(node)
+
+ @python2_only
+ def test_backtick(self):
+ node = test_utils.extract_node('`test`')
+ message = testutils.Message('backtick', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_backquote(node)
+
+ def test_relative_import(self):
+ node = test_utils.extract_node('import string #@')
+ message = testutils.Message('no-absolute-import', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_import(node)
+
+ def test_relative_from_import(self):
+ node = test_utils.extract_node('from os import path #@')
+ message = testutils.Message('no-absolute-import', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_import(node)
+
+ def test_absolute_import(self):
+ module_import = test_utils.build_module(
+ 'from __future__ import absolute_import; import os')
+ module_from = test_utils.build_module(
+ 'from __future__ import absolute_import; from os import path')
+ with self.assertNoMessages():
+ for module in (module_import, module_from):
+ self.walk(module)
+
+ def test_division(self):
+ node = test_utils.extract_node('3 / 2 #@')
+ message = testutils.Message('old-division', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_binop(node)
+
+ def test_division_with_future_statement(self):
+ module = test_utils.build_module('from __future__ import division; 3 / 2')
+ with self.assertNoMessages():
+ self.walk(module)
+
+ def test_floor_division(self):
+ node = test_utils.extract_node(' 3 // 2 #@')
+ with self.assertNoMessages():
+ self.checker.visit_binop(node)
+
+ def test_division_by_float(self):
+ left_node = test_utils.extract_node('3.0 / 2 #@')
+ right_node = test_utils.extract_node(' 3 / 2.0 #@')
+ with self.assertNoMessages():
+ for node in (left_node, right_node):
+ self.checker.visit_binop(node)
+
+ def test_dict_iter_method(self):
+ for meth in ('keys', 'values', 'items'):
+ node = test_utils.extract_node('x.iter%s() #@' % meth)
+ message = testutils.Message('dict-iter-method', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_callfunc(node)
+
+ def test_dict_iter_method_on_dict(self):
+ node = test_utils.extract_node('{}.iterkeys()')
+ message = testutils.Message('dict-iter-method', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_callfunc(node)
+
+ def test_dict_not_iter_method(self):
+ arg_node = test_utils.extract_node('x.iterkeys(x) #@')
+ stararg_node = test_utils.extract_node('x.iterkeys(*x) #@')
+ kwarg_node = test_utils.extract_node('x.iterkeys(y=x) #@')
+ non_dict_node = test_utils.extract_node('x=[]\nx.iterkeys() #@')
+ with self.assertNoMessages():
+ for node in (arg_node, stararg_node, kwarg_node, non_dict_node):
+ self.checker.visit_callfunc(node)
+
+ def test_dict_view_method(self):
+ for meth in ('keys', 'values', 'items'):
+ node = test_utils.extract_node('x.view%s() #@' % meth)
+ message = testutils.Message('dict-view-method', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_callfunc(node)
+
+ def test_dict_view_method_on_dict(self):
+ node = test_utils.extract_node('{}.viewkeys()')
+ message = testutils.Message('dict-view-method', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_callfunc(node)
+
+ def test_dict_not_view_method(self):
+ arg_node = test_utils.extract_node('x.viewkeys(x) #@')
+ stararg_node = test_utils.extract_node('x.viewkeys(*x) #@')
+ kwarg_node = test_utils.extract_node('x.viewkeys(y=x) #@')
+ non_dict_node = test_utils.extract_node('x=[]\nx.viewkeys() #@')
+ with self.assertNoMessages():
+ for node in (arg_node, stararg_node, kwarg_node, non_dict_node):
+ self.checker.visit_callfunc(node)
+
+ def test_next_method(self):
+ node = test_utils.extract_node('x.next() #@')
+ message = testutils.Message('next-method-called', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_callfunc(node)
+
+ @python2_only
+ def test_implicit_map_evaluation(self):
+ node = test_utils.extract_node('map(str, [1, 2, 3])')
+ discard = node.parent
+ message = testutils.Message('implicit-map-evaluation', node=discard)
+ with self.assertAddsMessages(message):
+ # Use node.parent because extract_node returns the value
+ # of a discard node, not the discard itself.
+ self.checker.visit_discard(discard)
+
+ def test_not_next_method(self):
+ arg_node = test_utils.extract_node('x.next(x) #@')
+ stararg_node = test_utils.extract_node('x.next(*x) #@')
+ kwarg_node = test_utils.extract_node('x.next(y=x) #@')
+ with self.assertNoMessages():
+ for node in (arg_node, stararg_node, kwarg_node):
+ self.checker.visit_callfunc(node)
+
+ def test_metaclass_assignment(self):
+ node = test_utils.extract_node("""
+ class Foo(object): #@
+ __metaclass__ = type""")
+ message = testutils.Message('metaclass-assignment', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_class(node)
+
+ def test_metaclass_global_assignment(self):
+ module = test_utils.build_module('__metaclass__ = type')
+ with self.assertNoMessages():
+ self.walk(module)
+
+ @python2_only
+ def test_parameter_unpacking(self):
+ node = test_utils.extract_node('def func((a, b)):#@\n pass')
+ arg = node.args.args[0]
+ with self.assertAddsMessages(testutils.Message('parameter-unpacking', node=arg)):
+ self.checker.visit_arguments(node.args)
+
+ @python2_only
+ def test_old_raise_syntax(self):
+ node = test_utils.extract_node('raise Exception, "test"')
+ message = testutils.Message('old-raise-syntax', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_raise(node)
+
+ @python2_only
+ def test_raising_string(self):
+ node = test_utils.extract_node('raise "Test"')
+ message = testutils.Message('raising-string', node=node)
+ with self.assertAddsMessages(message):
+ self.checker.visit_raise(node)
+
+ @python2_only
+ def test_checker_disabled_by_default(self):
+ node = test_utils.build_module(textwrap.dedent("""
+ abc = 1l
+ raise Exception, "test"
+ raise "test"
+ `abc`
+ """))
+ with self.assertNoMessages():
+ self.walk(node)
+
+
+@python2_only
+class Python3TokenCheckerTest(testutils.CheckerTestCase):
+
+ CHECKER_CLASS = checker.Python3TokenChecker
+
+ def _test_token_message(self, code, symbolic_message):
+ tokens = testutils.tokenize_str(code)
+ message = testutils.Message(symbolic_message, line=1)
+ with self.assertAddsMessages(message):
+ self.checker.process_tokens(tokens)
+
+ def test_long_suffix(self):
+ for code in ("1l", "1L"):
+ self._test_token_message(code, 'long-suffix')
+
+ def test_old_ne_operator(self):
+ self._test_token_message("1 <> 2", "old-ne-operator")
+
+ def test_old_octal_literal(self):
+ for octal in ("045", "055", "075", "077", "076543"):
+ self._test_token_message(octal, "old-octal-literal")
+
+ # Make sure we are catching only octals.
+ for non_octal in ("45", "00", "085", "08", "1"):
+ tokens = testutils.tokenize_str(non_octal)
+ with self.assertNoMessages():
+ self.checker.process_tokens(tokens)
+
+
+if __name__ == '__main__':
+ unittest.main()