Skip to content

Commit 12e4808

Browse files
brycepgPCManticore
authored andcommitted
Suppress false-positive not-callable messages from class descriptors (#1911)
This is a holdover until astroid can be fixed. Astroid needs to understand descriptors or at least raise Uninferable instead of allowing the descriptor instance through Close #1699
1 parent 9dd978a commit 12e4808

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ What's New in Pylint 2.0?
9797

9898
Close #1599
9999

100+
* Suppress false-positive ``not-callable`` messages from certain
101+
staticmethod descriptors
102+
103+
Close #1699
104+
100105
What's New in Pylint 1.8.1?
101106
=========================
102107

doc/whatsnew/2.0.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ Other Changes
4545

4646
* Fix false positive ``undefined-variable`` for lambda argument in
4747
class definitions
48+
49+
* Suppress false-positive ``not-callable`` messages from certain
50+
staticmethod descriptors

pylint/checkers/typecheck.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,8 +875,13 @@ def visit_call(self, node):
875875

876876
called = safe_infer(node.func)
877877
# only function, generator and object defining __call__ are allowed
878+
# Ignore instances of descriptors since astroid cannot properly handle them
879+
# yet
878880
if called and not called.callable():
879-
if isinstance(called, astroid.Instance) and not has_known_bases(called):
881+
if isinstance(called, astroid.Instance) and (
882+
not has_known_bases(called)
883+
or (isinstance(called.scope(), astroid.ClassDef)
884+
and '__get__' in called.locals)):
880885
# Don't emit if we can't make sure this object is callable.
881886
pass
882887
else:

pylint/test/unittest_checker_typecheck.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,36 @@ def test_typing_namedtuple_unsubscriptable_object_issue1295(self):
229229
subscript = module.body[-1].value
230230
with self.assertNoMessages():
231231
self.checker.visit_subscript(subscript)
232+
233+
def test_staticmethod_multiprocessing_call(self):
234+
"""Make sure not-callable isn't raised for descriptors
235+
236+
astroid can't process descriptors correctly so
237+
pylint needs to ignore not-callable for them
238+
right now
239+
240+
Test for https://github.com/PyCQA/pylint/issues/1699
241+
"""
242+
call = astroid.extract_node("""
243+
import multiprocessing
244+
multiprocessing.current_process() #@
245+
""")
246+
with self.assertNoMessages():
247+
self.checker.visit_call(call)
248+
249+
def test_descriptor_call(self):
250+
call = astroid.extract_node("""
251+
def func():
252+
pass
253+
254+
class ADescriptor:
255+
def __get__(self, instance, owner):
256+
return func
257+
258+
class AggregateCls:
259+
a = ADescriptor()
260+
261+
AggregateCls().a() #@
262+
""")
263+
with self.assertNoMessages():
264+
self.checker.visit_call(call)

0 commit comments

Comments
 (0)