diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
index 83d039eb0ff8..4e751db39380 100644
--- a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
@@ -22,6 +22,7 @@ import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
+import com.jetbrains.python.psi.types.PyTypeChecker;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -135,8 +136,9 @@ public class PyPropertyDefinitionInspection extends PyInspection {
Callable callable = null;
if (argument instanceof PyReferenceExpression) {
PsiElement resolved = ((PyReferenceExpression)argument).getReference(resolveWithoutImplicits()).resolve();
- if (resolved instanceof PyFunction) callable = (PyFunction)resolved;
- else if (resolved instanceof PyLambdaExpression) callable = (PyLambdaExpression)resolved;
+ if (resolved instanceof Callable) {
+ callable = (Callable)resolved;
+ }
else {
reportNonCallableArg(resolved, argument);
return;
@@ -161,19 +163,19 @@ public class PyPropertyDefinitionInspection extends PyInspection {
}
}
- private void reportNonCallableArg(PsiElement resolved, PsiElement being_checked) {
- if (! PyUtil.instanceOf(resolved, PySubscriptionExpression.class, PyNoneLiteralExpression.class)) {
- boolean is_not_callable = true;
- if (resolved instanceof PyExpression) {
- PyType expr_type = ((PyExpression)resolved).getType(myTypeEvalContext);
- if (expr_type instanceof PyClassType) {
- final PyClassType cls_type = (PyClassType)expr_type;
- PyClass cls = cls_type.getPyClass();
- if (!cls_type.isDefinition()) is_not_callable = cls.findMethodByName("__call__", true) == null;
- }
+ private void reportNonCallableArg(PsiElement resolved, PsiElement element) {
+ if (resolved instanceof PySubscriptionExpression || resolved instanceof PyNoneLiteralExpression) {
+ return;
+ }
+ if (PyNames.NONE.equals(element.getText())) {
+ return;
+ }
+ if (resolved instanceof PyTypedElement) {
+ final PyType type = ((PyTypedElement)resolved).getType(myTypeEvalContext);
+ final Boolean isCallable = PyTypeChecker.isCallable(type);
+ if (isCallable != null && !isCallable) {
+ registerProblem(element, PyBundle.message("INSP.strange.arg.want.callable"));
}
- if (is_not_callable && !"None".equals(being_checked.getText()))
- registerProblem(being_checked, PyBundle.message("INSP.strange.arg.want.callable"));
}
}
diff --git a/python/testData/inspections/PyPropertyDefinitionInspection25/expected.xml b/python/testData/inspections/PyPropertyDefinitionInspection25/expected.xml
index 400806dc8848..38414607ac1f 100644
--- a/python/testData/inspections/PyPropertyDefinitionInspection25/expected.xml
+++ b/python/testData/inspections/PyPropertyDefinitionInspection25/expected.xml
@@ -45,10 +45,5 @@
48
Getter should return something
-
- prop_test.py
- 76
- Strange argument; a callable expected
-
diff --git a/python/testData/inspections/PyPropertyDefinitionInspection25/src/prop_test.py b/python/testData/inspections/PyPropertyDefinitionInspection25/src/prop_test.py
index a7377526fbde..60d6413106d5 100644
--- a/python/testData/inspections/PyPropertyDefinitionInspection25/src/prop_test.py
+++ b/python/testData/inspections/PyPropertyDefinitionInspection25/src/prop_test.py
@@ -73,7 +73,7 @@ gb = Ghostbusters()
class B(object):
x = property(gb) # pass
y = property(Ghostbusters()) # pass
- z = property(Ghostbusters) # fail: not callable
+ z = property(Ghostbusters) # pass
class Eternal(object):
def give(self):
diff --git a/python/testData/inspections/PyPropertyDefinitionInspection26/src/prop_test.py b/python/testData/inspections/PyPropertyDefinitionInspection26/src/prop_test.py
index 62ad2f15021f..5823e797f197 100644
--- a/python/testData/inspections/PyPropertyDefinitionInspection26/src/prop_test.py
+++ b/python/testData/inspections/PyPropertyDefinitionInspection26/src/prop_test.py
@@ -59,3 +59,7 @@ class A(object):
def xoo(self, x):
self._x = x
return
+
+ get_foo2 = lambda self: 'foo2'
+
+ foo2 = property(get_foo2)