summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-12-03 22:04:38 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2015-12-03 22:04:38 +0200
commite54a5ec5bf41840de96df649e62e9b2fac316fa7 (patch)
tree8d9362fc3891822496b2c1f6594916b6242d830a
parentb2e4b5796db6c165460a6b37e7360bffe84d734e (diff)
downloadpylint-e54a5ec5bf41840de96df649e62e9b2fac316fa7.tar.gz
Accept only functions and methods for the deprecated-method checker.
This prevents a crash which can occur when an object doesn't have .qname() method after the inference.
-rw-r--r--ChangeLog9
-rw-r--r--pylint/checkers/stdlib.py12
-rw-r--r--pylint/test/unittest_checker_stdlib.py65
3 files changed, 83 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5e7b4b3..0e6433e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,11 @@ ChangeLog for Pylint
--------------------
--
+ * Accept only functions and methods for the deprecated-method checker.
+
+ This prevents a crash which can occur when an object doesn't have
+ .qname() method after the inference.
+
* Added a new warning, 'unsupported-assignment-operation', which is
emitted when item assignment is tried on an object which doesn't
have this ability. Closes issue #591.
@@ -10,6 +15,10 @@ ChangeLog for Pylint
emitted when item deletion is tried on an object which doesn't
have this ability. Closes issue #592.
+
+2015-12-02 -- 1.5.1
+
+
* Fix a crash which occurred when old visit methods are encountered
in plugin modules. Closes issue #711.
diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py
index afb4541..0ec3d6c 100644
--- a/pylint/checkers/stdlib.py
+++ b/pylint/checkers/stdlib.py
@@ -211,7 +211,7 @@ class StdlibChecker(BaseChecker):
for value in node.values:
self._check_datetime(value)
- def _check_deprecated_method(self, node, infer):
+ def _check_deprecated_method(self, node, inferred):
py_vers = sys.version_info[0]
if isinstance(node.func, astroid.Attribute):
@@ -222,7 +222,14 @@ class StdlibChecker(BaseChecker):
# Not interested in other nodes.
return
- qname = infer.qname()
+ # Reject nodes which aren't of interest to us.
+ acceptable_nodes = (astroid.BoundMethod,
+ astroid.UnboundMethod,
+ astroid.FunctionDef)
+ if not isinstance(inferred, acceptable_nodes):
+ return
+
+ qname = inferred.qname()
if qname in self.deprecated[0]:
self.add_message('deprecated-method', node=node,
args=(func_name, ))
@@ -233,7 +240,6 @@ class StdlibChecker(BaseChecker):
args=(func_name, ))
break
-
def _check_redundant_assert(self, node, infer):
if (isinstance(infer, astroid.BoundMethod) and
node.args and isinstance(node.args[0], astroid.Const) and
diff --git a/pylint/test/unittest_checker_stdlib.py b/pylint/test/unittest_checker_stdlib.py
new file mode 100644
index 0000000..82c1f17
--- /dev/null
+++ b/pylint/test/unittest_checker_stdlib.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2003-2015 LOGILAB S.A. (Paris, FRANCE).
+# http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# 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.
+
+import contextlib
+import unittest
+
+import astroid
+from astroid import test_utils
+
+from pylint.checkers import stdlib
+from pylint.testutils import CheckerTestCase
+
+
+@contextlib.contextmanager
+def _add_transform(manager, node, transform, predicate=None):
+ manager.register_transform(node, transform, predicate)
+ try:
+ yield
+ finally:
+ manager.unregister_transform(node, transform, predicate)
+
+
+class StdlibCheckerTest(CheckerTestCase):
+ CHECKER_CLASS = stdlib.StdlibChecker
+
+ def test_deprecated_no_qname_on_unexpected_nodes(self):
+ # Test that we don't crash on nodes which don't have
+ # a qname method. While this test might seem weird since
+ # it uses a transform, it's actually testing a crash that
+ # happened in production, but there was no way to retrieve
+ # the code for which this occurred (how an AssignAttr
+ # got to be the result of a function inference
+ # beats me..)
+
+ def infer_func(node, context=None):
+ new_node = astroid.AssignAttr()
+ new_node.parent = node
+ yield new_node
+
+ manager = astroid.MANAGER
+ transform = astroid.inference_tip(infer_func)
+ with _add_transform(manager, astroid.Name, transform):
+ node = test_utils.extract_node('''
+ call_something()
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_call(node)
+
+
+
+if __name__ == '__main__':
+ unittest.main()