summaryrefslogtreecommitdiff
path: root/pylint/checkers/python3.py
diff options
context:
space:
mode:
authorRoy Williams <roy.williams.iii@gmail.com>2016-11-30 08:40:01 -0800
committerGitHub <noreply@github.com>2016-11-30 08:40:01 -0800
commit76677b4118c5201f0aa8e96af26f60e2fc2a3da6 (patch)
treefd0daf6ed66e9c3ff3dbf67a36e6e171e5e4f116 /pylint/checkers/python3.py
parent4ba16605d52a331bcc466f7f5d101dae7244a303 (diff)
downloadpylint-git-76677b4118c5201f0aa8e96af26f60e2fc2a3da6.tar.gz
Add a Python 3 Checker to find invalid imports in Python 3 (#1182)
Diffstat (limited to 'pylint/checkers/python3.py')
-rw-r--r--pylint/checkers/python3.py43
1 files changed, 39 insertions, 4 deletions
diff --git a/pylint/checkers/python3.py b/pylint/checkers/python3.py
index 0eeaa4e9e..92afc269a 100644
--- a/pylint/checkers/python3.py
+++ b/pylint/checkers/python3.py
@@ -82,6 +82,14 @@ def _in_iterating_context(node):
return False
+def _is_conditional_import(node):
+ """Checks if a import node is in the context of a conditional.
+ """
+ parent = node.parent
+ return isinstance(parent, (astroid.TryExcept, astroid.ExceptHandler,
+ astroid.If, astroid.IfExp))
+
+
class Python3Checker(checkers.BaseChecker):
__implements__ = interfaces.IAstroidChecker
@@ -371,6 +379,10 @@ class Python3Checker(checkers.BaseChecker):
'sys-max-int',
'Used when accessing sys.maxint. Use sys.maxsize instead.',
{'maxversion': (3, 0)}),
+ 'W1648': ('Module moved in Python 3',
+ 'bad-python3-import',
+ 'Used when importing a module that no longer exists in Python 3.',
+ {'maxversion': (3, 0)}),
}
_bad_builtins = frozenset([
@@ -429,6 +441,23 @@ class Python3Checker(checkers.BaseChecker):
'rot_13',
])
+ _bad_imports = frozenset([
+ 'anydbm', 'BaseHTTPServer', '__builtin__', 'CGIHTTPServer', 'ConfigParser', 'copy_reg',
+ 'cPickle', 'cProfile', 'cStringIO', 'Cookie', 'cookielib', 'dbhash', 'dbm', 'dumbdbm',
+ 'dumbdb', 'Dialog', 'DocXMLRPCServer', 'FileDialog', 'FixTk', 'gdbm', 'htmlentitydefs',
+ 'HTMLParser', 'httplib', 'markupbase', 'Queue', 'repr', 'robotparser', 'ScrolledText',
+ 'SimpleDialog', 'SimpleHTTPServer', 'SimpleXMLRPCServer', 'StringIO', 'dummy_thread',
+ 'SocketServer', 'test.test_support', 'Tkinter', 'Tix', 'Tkconstants', 'tkColorChooser',
+ 'tkCommonDialog', 'Tkdnd', 'tkFileDialog', 'tkFont', 'tkMessageBox', 'tkSimpleDialog',
+ 'turtle', 'UserList', 'UserString', 'whichdb', '_winreg', 'xmlrpclib', 'audiodev',
+ 'Bastion', 'bsddb185', 'bsddb3', 'Canvas', 'cfmfile', 'cl', 'commands', 'compiler',
+ 'dircache', 'dl', 'exception', 'fpformat', 'htmllib', 'ihooks', 'imageop', 'imputil',
+ 'linuxaudiodev', 'md5', 'mhlib', 'mimetools', 'MimeWriter', 'mimify', 'multifile',
+ 'mutex', 'new', 'popen2', 'posixfile', 'pure', 'rexec', 'rfc822', 'sha', 'sgmllib',
+ 'sre', 'stat', 'stringold', 'sunaudio', 'sv', 'test.testall', 'thread', 'timing',
+ 'toaiff', 'user', 'urllib2', 'urlparse'
+ ])
+
def __init__(self, *args, **kwargs):
self._future_division = False
self._future_absolute_import = False
@@ -471,18 +500,24 @@ class Python3Checker(checkers.BaseChecker):
self._future_division = True
elif name == 'absolute_import':
self._future_absolute_import = True
- elif not self._future_absolute_import:
- if self.linter.is_message_enabled('no-absolute-import'):
- self.add_message('no-absolute-import', node=node)
+ else:
+ if not self._future_absolute_import:
+ if self.linter.is_message_enabled('no-absolute-import'):
+ self.add_message('no-absolute-import', node=node)
+ if node.modname in self._bad_imports and not _is_conditional_import(node):
+ self.add_message('bad-python3-import', node=node)
+
if node.names[0][0] == '*':
if self.linter.is_message_enabled('import-star-module-level'):
if not isinstance(node.scope(), astroid.Module):
self.add_message('import-star-module-level', node=node)
- @utils.check_messages('no-absolute-import')
def visit_import(self, node):
if not self._future_absolute_import:
self.add_message('no-absolute-import', node=node)
+ for name in node.names:
+ if name[0] in self._bad_imports and not _is_conditional_import(node):
+ self.add_message('bad-python3-import', node=node)
@utils.check_messages('metaclass-assignment')
def visit_classdef(self, node):