diff options
| author | Roy Williams <roy.williams.iii@gmail.com> | 2016-11-30 08:40:01 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-30 08:40:01 -0800 |
| commit | 76677b4118c5201f0aa8e96af26f60e2fc2a3da6 (patch) | |
| tree | fd0daf6ed66e9c3ff3dbf67a36e6e171e5e4f116 /pylint/checkers/python3.py | |
| parent | 4ba16605d52a331bcc466f7f5d101dae7244a303 (diff) | |
| download | pylint-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.py | 43 |
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): |
