Support typing.Supports* in PyABCUtil.

PY-24789, PY-23391, PY-24194, PY-23289 Fixed.
This commit is contained in:
Semyon Proshev
2017-08-22 11:08:54 +03:00
parent 11dda5cbe9
commit 0d3f684496
5 changed files with 79 additions and 12 deletions
@@ -183,6 +183,12 @@ public class PyNames {
public static final String SIZEOF = "__sizeof__";
public static final String INIT_SUBCLASS = "__init_subclass__";
public static final String FSPATH = "__fspath__";
public static final String COMPLEX = "__complex__";
public static final String FLOAT = "__float__";
public static final String INT = "__int__";
public static final String BYTES = "__bytes__";
public static final String ABS = "__abs__";
public static final String ROUND = "__round__";
public static final String NAME = "__name__";
public static final String ENTER = "__enter__";
@@ -295,7 +301,7 @@ public class PyNames {
private static final BuiltinDescription _exit_descr = new BuiltinDescription("(self, exc_type, exc_val, exc_tb)");
private static final ImmutableMap<String, BuiltinDescription> BuiltinMethods = ImmutableMap.<String, BuiltinDescription>builder()
.put("__abs__", _only_self_descr)
.put(ABS, _only_self_descr)
.put("__add__", _self_other_descr)
.put("__and__", _self_other_descr)
//_BuiltinMethods.put("__all__", _only_self_descr);
@@ -306,7 +312,7 @@ public class PyNames {
//_BuiltinMethods.put("__class__", _only_self_descr);
.put("__cmp__", _self_other_descr)
.put("__coerce__", _self_other_descr)
.put("__complex__", _only_self_descr)
.put(COMPLEX, _only_self_descr)
.put("__contains__", _self_item_descr)
.put("__copy__", _only_self_descr)
//_BuiltinMethods.put("__debug__", _only_self_descr);
@@ -324,7 +330,7 @@ public class PyNames {
.put("__exit__", _exit_descr)
.put("__eq__", _self_other_descr)
//_BuiltinMethods.put("__file__", _only_self_descr);
.put("__float__", _only_self_descr)
.put(FLOAT, _only_self_descr)
.put("__floor__", _only_self_descr)
.put("__floordiv__", _self_other_descr)
//_BuiltinMethods.put("__future__", _only_self_descr);
@@ -350,7 +356,7 @@ public class PyNames {
.put("__imul__", _self_other_descr)
.put("__index__", _only_self_descr)
.put(INIT, _only_self_descr)
.put("__int__", _only_self_descr)
.put(INT, _only_self_descr)
.put("__invert__", _only_self_descr)
.put("__ior__", _self_other_descr)
.put("__ipow__", _self_other_descr)
@@ -425,11 +431,11 @@ public class PyNames {
public static final ImmutableMap<String, BuiltinDescription> PY3_BUILTIN_METHODS = ImmutableMap.<String, BuiltinDescription>builder()
.putAll(BuiltinMethods)
.put("__bool__", _only_self_descr)
.put("__bytes__", _only_self_descr)
.put(BYTES, _only_self_descr)
.put("__format__", new BuiltinDescription("(self, format_spec)"))
.put("__instancecheck__", new BuiltinDescription("(self, instance)"))
.put("__prepare__", new BuiltinDescription("(metacls, name, bases)"))
.put("__round__", new BuiltinDescription("(self, n=None)"))
.put(ROUND, new BuiltinDescription("(self, n=None)"))
.put("__subclasscheck__", new BuiltinDescription("(self, subclass)"))
.put(DUNDER_NEXT, _only_self_descr)
.build();
@@ -75,6 +75,12 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
private static final String CALLABLE = "typing.Callable";
public static final String NAMEDTUPLE_SIMPLE = "NamedTuple";
public static final String SUPPORTS_INT_SIMPLE = "SupportsInt";
public static final String SUPPORTS_FLOAT_SIMPLE = "SupportsFloat";
public static final String SUPPORTS_COMPLEX_SIMPLE = "SupportsComplex";
public static final String SUPPORTS_BYTES_SIMPLE = "SupportsBytes";
public static final String SUPPORTS_ABS_SIMPLE = "SupportsAbs";
public static final String SUPPORTS_ROUND_SIMPLE = "SupportsRound";
public static final Pattern TYPE_COMMENT_PATTERN = Pattern.compile("# *type: *(.*)");
@@ -16,6 +16,7 @@
package com.jetbrains.python.psi.types;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
import com.jetbrains.python.psi.PyClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -82,14 +83,14 @@ public class PyABCUtil {
hasMethod(subClass, "discard", inherited, context) &&
hasMethod(subClass, "add", inherited, context);
}
if (PyNames.ABC_COMPLEX.equals(superClassName)) {
return hasMethod(subClass, "__complex__", inherited, context);
if (PyNames.ABC_COMPLEX.equals(superClassName) || PyTypingTypeProvider.SUPPORTS_COMPLEX_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.COMPLEX, inherited, context);
}
if (PyNames.ABC_REAL.equals(superClassName)) {
return hasMethod(subClass, "__float__", inherited, context);
if (PyNames.ABC_REAL.equals(superClassName) || PyTypingTypeProvider.SUPPORTS_FLOAT_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.FLOAT, inherited, context);
}
if (PyNames.ABC_INTEGRAL.equals(superClassName)) {
return hasMethod(subClass, "__int__", inherited, context);
if (PyNames.ABC_INTEGRAL.equals(superClassName) || PyTypingTypeProvider.SUPPORTS_INT_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.INT, inherited, context);
}
if (PyNames.ABC_NUMBER.equals(superClassName) && "Decimal".equals(subClass.getName())) {
return true;
@@ -100,6 +101,15 @@ public class PyABCUtil {
if (PyNames.PATH_LIKE.equals(superClassName)) {
return hasMethod(subClass, PyNames.FSPATH, inherited, context);
}
if (PyTypingTypeProvider.SUPPORTS_BYTES_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.BYTES, inherited, context);
}
if (PyTypingTypeProvider.SUPPORTS_ABS_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.ABS, inherited, context);
}
if (PyTypingTypeProvider.SUPPORTS_ROUND_SIMPLE.equals(superClassName)) {
return hasMethod(subClass, PyNames.ROUND, inherited, context);
}
return false;
}
@@ -0,0 +1,37 @@
import typing
def check_complex(p: typing.SupportsComplex):
print(p.__complex__())
class A:
def __int__(self):
return 5
def __float__(self):
return 5.0
def __complex__(self):
return complex(5.0, 0.0)
def __bytes__(self):
return b'bytes'
def __abs__(self):
return 5
def __round__(self, n=None):
return 5
a = A()
print(int(a))
print(float(a))
check_complex(a)
print(bytes(a))
print(abs(a))
print(round(a))
@@ -260,4 +260,12 @@ public class Py3TypeCheckerInspectionTest extends PyTestCase {
public void testUnionOfIntAndFloatShouldBeConsideredAsDividable() {
doTest();
}
// PY-23289
// PY-23391
// PY-24194
// PY-24789
public void testTypingSupports() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);
}
}