From 1bea08c4b2b3b5a1f14936156dadcf8110c26a56 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 22 May 2012 17:20:05 +0400 Subject: [PATCH 1/3] Extracted some type checking tests --- .../PyTypeCheckerInspection/DictGenerics.py | 8 +++ .../EnumerateIterator.py | 12 +++++ .../GenericUserClasses.py | 27 ++++++++++ .../PyTypeCheckerInspection/OldTests.py | 49 ------------------- .../PyTypeCheckerInspectionTest.java | 12 +++++ 5 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 python/testData/inspections/PyTypeCheckerInspection/DictGenerics.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/EnumerateIterator.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py diff --git a/python/testData/inspections/PyTypeCheckerInspection/DictGenerics.py b/python/testData/inspections/PyTypeCheckerInspection/DictGenerics.py new file mode 100644 index 000000000000..46f6ff06ac25 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/DictGenerics.py @@ -0,0 +1,8 @@ +def test_dict_generics(d): + """ + :type d: dict from int to unicode + """ + xs = d.items() + d2 = dict(xs) + for k, v in d2.items(): + print k + v diff --git a/python/testData/inspections/PyTypeCheckerInspection/EnumerateIterator.py b/python/testData/inspections/PyTypeCheckerInspection/EnumerateIterator.py new file mode 100644 index 000000000000..d66ce9192a59 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/EnumerateIterator.py @@ -0,0 +1,12 @@ +def test(): + def f(x): + """ + :type x: str + """ + pass + xs = [1.1, 2.2, 3.3] + for i, x in enumerate(xs): + f(i) + f(x) + + diff --git a/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py b/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py new file mode 100644 index 000000000000..d8a5472a0408 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py @@ -0,0 +1,27 @@ +def test_generic_user_class(): + class User1(object): + def __init__(self, x): + """ + :type x: T + :rtype: User1 of T + """ + self.x = x + + def get(self): + """ + :rtype: T + """ + return self.x + + def put(self, value): + """ + :type value: T + """ + self.x = value + + c = User1(10) + print(c.get() + 'foo') + c.put(14) + c.put('foo') + + diff --git a/python/testData/inspections/PyTypeCheckerInspection/OldTests.py b/python/testData/inspections/PyTypeCheckerInspection/OldTests.py index e6a7a6c7fc73..caebe6ac8f1b 100644 --- a/python/testData/inspections/PyTypeCheckerInspection/OldTests.py +++ b/python/testData/inspections/PyTypeCheckerInspection/OldTests.py @@ -425,45 +425,6 @@ def test_union_return_types(): f3(x1.strip()) -def test_enumerate_iterator(): - def f(x): - """ - :type x: str - """ - pass - xs = [1.1, 2.2, 3.3] - for i, x in enumerate(xs): - f(i) - f(x) - - -def test_generic_user_class(): - class User1(object): - def __init__(self, x): - """ - :type x: T - :rtype: User1 of T - """ - self.x = x - - def get(self): - """ - :rtype: T - """ - return self.x - - def put(self, value): - """ - :type value: T - """ - self.x = value - - c = User1(10) - print(c.get() + 'foo') - c.put(14) - c.put('foo') - - def test_generic_user_functions(): def f1(xs): """ @@ -512,16 +473,6 @@ def test_generic_user_functions(): f4(result) -def test_dict_generics(d): - """ - :type d: dict from int to unicode - """ - xs = d.items() - d2 = dict(xs) - for k, v in d2.items(): - print k + v - - # PY-5474 def test_bad_subsription_expr(): x = r"""\x"" diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java index 7cde689bf721..985d4589da3d 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java @@ -17,6 +17,18 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { doTest(); } + public void testEnumerateIterator() { + doTest(); + } + + public void testGenericUserClasses() { + doTest(); + } + + public void testDictGenerics() { + doTest(); + } + // PY-6570 public void testDictLiteralIndexing() { doTest(); From 14df77a76705df511869be7c3962fc0baf3b978a Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 22 May 2012 17:36:18 +0400 Subject: [PATCH 2/3] Fixed type checker for classes with builtin base classes (PY-6606) --- .../jetbrains/python/psi/impl/PyCallExpressionImpl.java | 9 +++++++++ .../PyTypeCheckerInspection/BuiltinBaseClass.py | 9 +++++++++ .../python/inspections/PyTypeCheckerInspectionTest.java | 5 +++++ 3 files changed, 23 insertions(+) create mode 100644 python/testData/inspections/PyTypeCheckerInspection/BuiltinBaseClass.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java index e94a347d72d5..ebdc76bddee1 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionImpl.java @@ -133,6 +133,15 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress } if (init != null) { final PyType t = init.getReturnType(context, (PyReferenceExpression)callee); + if (cls != null) { + if (init.getContainingClass() != cls) { + if (t instanceof PyCollectionType) { + final PyType elementType = ((PyCollectionType)t).getElementType(context); + return new PyCollectionTypeImpl(cls, false, elementType); + } + return new PyClassType(cls, false); + } + } if (t != null && !(t instanceof PyNoneType)) { return t; } diff --git a/python/testData/inspections/PyTypeCheckerInspection/BuiltinBaseClass.py b/python/testData/inspections/PyTypeCheckerInspection/BuiltinBaseClass.py new file mode 100644 index 000000000000..63980f17de96 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/BuiltinBaseClass.py @@ -0,0 +1,9 @@ +def test(): + class MyInt(int): + pass + def f(x): + """ + :type x: MyInt + """ + i = MyInt(2) + f(i) diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java index 985d4589da3d..4321691d85d4 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java @@ -33,4 +33,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { public void testDictLiteralIndexing() { doTest(); } + + // PY-6606 + public void testBuiltinBaseClass() { + doTest(); + } } From ff69ebbe8ce9652270871eddbacf61c28b999852 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 22 May 2012 20:44:12 +0400 Subject: [PATCH 3/3] Split type checker tests --- .../BadSubscriptExpression.py | 4 + .../BuiltinFunctions.py | 5 + .../PyTypeCheckerInspection/BuiltinNumeric.py | 12 + .../ComparisonOperators.py | 19 + .../PyTypeCheckerInspection/DictLiterals.py | 10 + .../FunctionAssignments.py | 11 + .../PyTypeCheckerInspection/Generator.py | 98 ++++ .../GenericUserFunctions.py | 46 ++ .../IsInstanceImplicitSelfTypes.py | 4 + .../PyTypeCheckerInspection/ListTuple.py | 11 + .../LocalTypeResolve.py | 8 + .../PyTypeCheckerInspection/NotNone.py | 31 ++ .../OldStyleClasses.py | 9 + .../PyTypeCheckerInspection/OldTests.py | 510 ------------------ .../PartlyUnknownType.py | 10 + .../PyTypeCheckerInspection/RightOperators.py | 5 + .../PyTypeCheckerInspection/Simple.py | 24 + .../PyTypeCheckerInspection/StrUnicode.py | 48 ++ .../PyTypeCheckerInspection/StringInteger.py | 8 + .../PyTypeCheckerInspection/Subscript.py | 17 + .../PyTypeCheckerInspection/TypeAssertions.py | 47 ++ .../TypeOfRaiseException.py | 13 + .../UnionReturnTypes.py | 25 + .../PyTypeCheckerInspectionTest.java | 91 +++- 24 files changed, 554 insertions(+), 512 deletions(-) create mode 100644 python/testData/inspections/PyTypeCheckerInspection/BadSubscriptExpression.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/BuiltinFunctions.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/BuiltinNumeric.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/ComparisonOperators.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/DictLiterals.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/FunctionAssignments.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/Generator.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/IsInstanceImplicitSelfTypes.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/ListTuple.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/LocalTypeResolve.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/NotNone.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/OldStyleClasses.py delete mode 100644 python/testData/inspections/PyTypeCheckerInspection/OldTests.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/PartlyUnknownType.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/RightOperators.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/Simple.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/StrUnicode.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/StringInteger.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/Subscript.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/TypeAssertions.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/TypeOfRaiseException.py create mode 100644 python/testData/inspections/PyTypeCheckerInspection/UnionReturnTypes.py diff --git a/python/testData/inspections/PyTypeCheckerInspection/BadSubscriptExpression.py b/python/testData/inspections/PyTypeCheckerInspection/BadSubscriptExpression.py new file mode 100644 index 000000000000..c46bf665b27c --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/BadSubscriptExpression.py @@ -0,0 +1,4 @@ +def test(): + x = r"""\x"" + r"""[\t\r\v]""" + """ diff --git a/python/testData/inspections/PyTypeCheckerInspection/BuiltinFunctions.py b/python/testData/inspections/PyTypeCheckerInspection/BuiltinFunctions.py new file mode 100644 index 000000000000..9a261da172e7 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/BuiltinFunctions.py @@ -0,0 +1,5 @@ +def test(): + print(map(str, [1, 2, 3]) + ['foo']) #pass + print(map(lambda x: x.upper(), 'foo')) #pass + print(filter(lambda x: x % 2 == 0, [1, 2, 3]) + [4, 5, 6]) #pass + print(filter(lambda x: x != 'f', 'foo') + 'bar') #pass diff --git a/python/testData/inspections/PyTypeCheckerInspection/BuiltinNumeric.py b/python/testData/inspections/PyTypeCheckerInspection/BuiltinNumeric.py new file mode 100644 index 000000000000..6a68a41ff541 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/BuiltinNumeric.py @@ -0,0 +1,12 @@ +def test(): + abs(False) + int(10) + long(False) + float(False) + complex(False) + divmod(False, False) + divmod('foo', + u'bar') + pow(False, True) + round(False, + 'foo') diff --git a/python/testData/inspections/PyTypeCheckerInspection/ComparisonOperators.py b/python/testData/inspections/PyTypeCheckerInspection/ComparisonOperators.py new file mode 100644 index 000000000000..20b2f9d17358 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/ComparisonOperators.py @@ -0,0 +1,19 @@ +def test(): + def f(x): + """ + :type x: str + """ + pass + class C(object): + def __gt__(self, other): + return [] + o = object() + c = C() + f(1 < 2) + f(o == o) + f(o >= o) + f('foo' > o) + f(c < 1) + f(c > 1) + f(c == 1) + f(c in [1, 2, 3]) diff --git a/python/testData/inspections/PyTypeCheckerInspection/DictLiterals.py b/python/testData/inspections/PyTypeCheckerInspection/DictLiterals.py new file mode 100644 index 000000000000..5b55ba3c4a69 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/DictLiterals.py @@ -0,0 +1,10 @@ +def test(): + xs = {'foo': 1, 'bar': 2} + for v in xs.values(): + print(v + None) + for k in xs.keys(): + print(k + None) + for k in xs: + print(k + None) + ys = filter(lambda x: x, xs.keys()) + ys.append(0) diff --git a/python/testData/inspections/PyTypeCheckerInspection/FunctionAssignments.py b/python/testData/inspections/PyTypeCheckerInspection/FunctionAssignments.py new file mode 100644 index 000000000000..abc17391ec4f --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/FunctionAssignments.py @@ -0,0 +1,11 @@ +def test(): + def g(x): + """ + :type x: int + """ + return x + g("str") #fail + h = g + h("str") #fail + + diff --git a/python/testData/inspections/PyTypeCheckerInspection/Generator.py b/python/testData/inspections/PyTypeCheckerInspection/Generator.py new file mode 100644 index 000000000000..c2434456cc22 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/Generator.py @@ -0,0 +1,98 @@ +def test(): + def gen(n): + for x in xrange(n): + yield str(x) + def f_1(xs): + """ + :type xs: list of int + """ + return xs + def f_2(xs): + """ + :type xs: Sequence of int + """ + return xs + def f_3(xs): + """ + :type xs: Container of int + """ + return xs + def f_4(xs): + """ + :type xs: Iterator of int + """ + return xs + def f_5(xs): + """ + :type xs: Iterable of int + """ + return xs + def f_6(xs): + """ + :type xs: list + """ + return xs + def f_7(xs): + """ + :type xs: Sequence + """ + return xs + def f_8(xs): + """ + :type xs: Container + """ + return xs + def f_9(xs): + """ + :type xs: Iterator + """ + return xs + def f_10(xs): + """ + :type xs: Iterable + """ + return xs + def f_11(xs): + """ + :type xs: list of string + """ + return xs + def f_12(xs): + """ + :type xs: Sequence of string + """ + return xs + def f_13(xs): + """ + :type xs: Container of string + """ + return xs + def f_14(xs): + """ + :type xs: Iterator of string + """ + return xs + def f_15(xs): + """ + :type xs: Iterable of string + """ + return xs + return [ + ''.join(gen(10)), + f_1(gen(11)), + f_2(gen(11)), + f_3(gen(11)), + f_4(gen(11)), + f_5(gen(11)), + f_6(gen(11)), + f_7(gen(11)), + f_8(gen(11)), + f_9(gen(11)), + f_10(gen(11)), + f_11(gen(11)), + f_12(gen(11)), + f_13(gen(11)), + f_14(gen(11)), + f_15(gen(11)), + f_15('foo'.split('o')), + ] diff --git a/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py b/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py new file mode 100644 index 000000000000..f2a882768c90 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py @@ -0,0 +1,46 @@ +def test(): + def f1(xs): + """ + :type xs: collections.Iterable of T + """ + return iter(xs).next() + + def f2(x, xs, z): + """ + :type x: T + :type xs: list of T + :type z: U + """ + return x in xs + + def id(x): + """ + :type x: T + :rtype: T + """ + return x + + def f3(x, y, z): + """ + :type x: T + :type y: U + :type z: V + """ + r1 = id(x) + r2 = id(y) + r3 = id(z) + return r1, r2, r3 + + def f4(x): + """ + :type x: (bool, int, str) + """ + + result = f1([1, 2, 3]) + print(result) + print(result + 'foo') + + f2(1, ['foo'], 'bar') + + result = f3(1, 'foo', True) + f4(result) diff --git a/python/testData/inspections/PyTypeCheckerInspection/IsInstanceImplicitSelfTypes.py b/python/testData/inspections/PyTypeCheckerInspection/IsInstanceImplicitSelfTypes.py new file mode 100644 index 000000000000..4af33b01c848 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/IsInstanceImplicitSelfTypes.py @@ -0,0 +1,4 @@ +def test(): + x = 1 + if isinstance(x, unicode): + x.encode('UTF-8') #pass diff --git a/python/testData/inspections/PyTypeCheckerInspection/ListTuple.py b/python/testData/inspections/PyTypeCheckerInspection/ListTuple.py new file mode 100644 index 000000000000..95306f40c8eb --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/ListTuple.py @@ -0,0 +1,11 @@ +def f(spam, eggs): + """ + :type spam: list of string + :type eggs: (bool, int, unicode) + """ + return spam, eggs + + +def test(): + f([1, 2, 3], + (False, 2, '')) diff --git a/python/testData/inspections/PyTypeCheckerInspection/LocalTypeResolve.py b/python/testData/inspections/PyTypeCheckerInspection/LocalTypeResolve.py new file mode 100644 index 000000000000..9d86b619c827 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/LocalTypeResolve.py @@ -0,0 +1,8 @@ +def test(): + class C(): + def f(self): + return 2 + c = C() + x = c.f() + y = x + return y + 'foo' diff --git a/python/testData/inspections/PyTypeCheckerInspection/NotNone.py b/python/testData/inspections/PyTypeCheckerInspection/NotNone.py new file mode 100644 index 000000000000..fa41abfeafdd --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/NotNone.py @@ -0,0 +1,31 @@ +def test(): + def f(x): + """ + :type x: int or str or list + """ + def f1(): + """ + :rtype: int or None + """ + def f2(): + """ + :rtype: int or str or None + """ + x1 = f1() + x2 = f2() + x3 = 1 + f(x1) + f(x2) + f(x3) + if x1: + f(x1) + if x2: + f(x2) + if x3: + f(x3) + if x1 is not None: + f(x1) + elif x2 is not None: + f(x2) + elif x3 is not None: + f(x3) diff --git a/python/testData/inspections/PyTypeCheckerInspection/OldStyleClasses.py b/python/testData/inspections/PyTypeCheckerInspection/OldStyleClasses.py new file mode 100644 index 000000000000..7d85c496714f --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/OldStyleClasses.py @@ -0,0 +1,9 @@ +def test_old_style_classes(): + class C: + pass + def f(x): + """ + :type x: object + """ + pass + f(C()) #pass diff --git a/python/testData/inspections/PyTypeCheckerInspection/OldTests.py b/python/testData/inspections/PyTypeCheckerInspection/OldTests.py deleted file mode 100644 index caebe6ac8f1b..000000000000 --- a/python/testData/inspections/PyTypeCheckerInspection/OldTests.py +++ /dev/null @@ -1,510 +0,0 @@ -def f1(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10=10, p11='11'): - """ - :type p1: integer - :type p2: integer - :type p3: float - :type p4: float - :type p5: int - :type p6: integer - :type p7: integer - :type p8: int - :type p9: int - :type p10: int - :type p11: string - """ - return p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + int(p11) - - -def test_1(): - p7 = int('7') - f1(1, - '2', - 3.0, 4, 5, int('6'), p7, p8=-8, - p9='foo', - p10='foo') - - -def str_to_none(b): - """ - :type b: str - """ - pass - - -def unicode_to_none(s): - """ - :type s: unicode - """ - pass - - -def string_to_none(s): - """ - :type s: string - """ - pass - - -def str_or_unicode_to_none(s): - """ - :type s: str or unicode - """ - pass - - -def test_str_unicode(): - b1 = 'hello' - s1 = u'привет' - b2 = str(-1) - s2 = unicode(3.14) - ENC = 'utf-8' - str_to_none(b1.decode(ENC)) - unicode_to_none(b1.decode(ENC)) - string_to_none(b1.decode(ENC)) - str_or_unicode_to_none(b1.decode(ENC)) - b1.encode(ENC) - s1.decode(ENC) - str_to_none(s1.encode(ENC)) - unicode_to_none(s1.encode(ENC)) - string_to_none(s1.encode(ENC)) - str_or_unicode_to_none(s1.encode(ENC)) - b2.decode(ENC) - b2.encode(ENC) - s2.decode(ENC) - s2.encode(ENC) - - -def f_list_tuple(spam, eggs): - """ - :type spam: list of string - :type eggs: (bool, int, unicode) - """ - return spam, eggs - - -def test_list_tuple(): - f_list_tuple([1, 2, 3], - (False, 2, '')) - - -def test_builtin_numerics(): - abs(False) - int(10) - long(False) - float(False) - complex(False) - divmod(False, False) - divmod('foo', - u'bar') - pow(False, True) - round(False, - 'foo') - - -def test_generator(): - def gen(n): - for x in xrange(n): - yield str(x) - def f_1(xs): - """ - :type xs: list of int - """ - return xs - def f_2(xs): - """ - :type xs: Sequence of int - """ - return xs - def f_3(xs): - """ - :type xs: Container of int - """ - return xs - def f_4(xs): - """ - :type xs: Iterator of int - """ - return xs - def f_5(xs): - """ - :type xs: Iterable of int - """ - return xs - def f_6(xs): - """ - :type xs: list - """ - return xs - def f_7(xs): - """ - :type xs: Sequence - """ - return xs - def f_8(xs): - """ - :type xs: Container - """ - return xs - def f_9(xs): - """ - :type xs: Iterator - """ - return xs - def f_10(xs): - """ - :type xs: Iterable - """ - return xs - def f_11(xs): - """ - :type xs: list of string - """ - return xs - def f_12(xs): - """ - :type xs: Sequence of string - """ - return xs - def f_13(xs): - """ - :type xs: Container of string - """ - return xs - def f_14(xs): - """ - :type xs: Iterator of string - """ - return xs - def f_15(xs): - """ - :type xs: Iterable of string - """ - return xs - return [ - ''.join(gen(10)), - f_1(gen(11)), - f_2(gen(11)), - f_3(gen(11)), - f_4(gen(11)), - f_5(gen(11)), - f_6(gen(11)), - f_7(gen(11)), - f_8(gen(11)), - f_9(gen(11)), - f_10(gen(11)), - f_11(gen(11)), - f_12(gen(11)), - f_13(gen(11)), - f_14(gen(11)), - f_15(gen(11)), - f_15('foo'.split('o')), - ] - - -# PY-4025 -def test_function_assignments(): - def g(x): - """ - :type x: int - """ - return x - g("str") #fail - h = g - h("str") #fail - - -def test_old_style_classes(): - class C: - pass - def f(x): - """ - :type x: object - """ - pass - f(C()) #pass - - -def test_partly_unknown_type(): - def f(): - """ - :rtype: None or unknown or int or long - """ - def g(x): - """ - :type x: object - """ - g(f()) - - -def test_type_assertions(): - def f_1(): - """ - :rtype: int or str or None - """ - def f_2(): - """ - :rtype: int or None - """ - def f_3(): - """ - :rtype: unknown - """ - def f_4(): - """ - :rtype: object - """ - def f_5(): - """ - :rtype: int or object - """ - def f_6(): - """ - :rtype: int or unknown or float - """ - def f_7(): - """ - :rtype: int or unknown - """ - def print_int(x): - """ - :type x: int - """ - print(x) - def print_int_or_str(x): - """ - :type x: int or str - """ - x_1 = f_1() - print_int(x_1) - print_int_or_str(x_1) - if isinstance(x_1, int): - print_int(x_1) - if isinstance(x_1, str): - print_int_or_str(x_1) - x_7 = f_7() - print_int(x_7) - - -def test_local_type_resolve(): - class C(): - def f(self): - return 2 - c = C() - x = c.f() - y = x - return y + 'foo' - - -def test_subscription(): - def f(x): - """ - :type x: str - """ - class C(object): - def __getitem__(self, item): - """ - :type item: str - :rtype: int - """ - xs = [1, 2, 3] - x = xs[0] - f(x) - c = C() - c_0 = c[0] - f(c_0) - - -def test_comparison_operators(): - def f(x): - """ - :type x: str - """ - pass - class C(object): - def __gt__(self, other): - return [] - o = object() - c = C() - f(1 < 2) - f(o == o) - f(o >= o) - f('foo' > o) - f(c < 1) - f(c > 1) - f(c == 1) - f(c in [1, 2, 3]) - - -def test_right_operators(): - o = object() - xs = [ - o * [], - ] - - -def test_string_integer(): - print('foo' + 'bar') - print(2 + 3) - print('foo' + 3) - print(3 + 'foo') - print('foo' + 'bar' * 3) - print('foo' + 3 * 'bar') - print('foo' + 2 * 3) - - -def test_isinstance_implicit_self_types(): - x = 1 - if isinstance(x, unicode): - x.encode('UTF-8') #pass - - -def test_not_none(): - def test(x): - """ - :type x: int or str or list - """ - def f1(): - """ - :rtype: int or None - """ - def f2(): - """ - :rtype: int or str or None - """ - x1 = f1() - x2 = f2() - x3 = 1 - test(x1) - test(x2) - test(x3) - if x1: - test(x1) - if x2: - test(x2) - if x3: - test(x3) - if x1 is not None: - test(x1) - elif x2 is not None: - test(x2) - elif x3 is not None: - test(x3) - - -def test_builtin_functions(): - print(map(str, [1, 2, 3]) + ['foo']) #pass - print(map(lambda x: x.upper(), 'foo')) #pass - print(filter(lambda x: x % 2 == 0, [1, 2, 3]) + [4, 5, 6]) #pass - print(filter(lambda x: x != 'f', 'foo') + 'bar') #pass - - -def test_union_return_types(): - def f1(c): - if c < 0: - return [] - elif c > 0: - return 'foo' - else: - return None - def f2(x): - """ - :type x: str - """ - pass - def f3(x): - """ - :type x: int - """ - x1 = f1(42) - f2(x1) - f3(x1) - - f2(x1.count('')) - f3(x1.count('')) - f2(x1.strip()) - f3(x1.strip()) - - -def test_generic_user_functions(): - def f1(xs): - """ - :type xs: collections.Iterable of T - """ - return iter(xs).next() - - def f2(x, xs, z): - """ - :type x: T - :type xs: list of T - :type z: U - """ - return x in xs - - def id(x): - """ - :type x: T - :rtype: T - """ - return x - - def f3(x, y, z): - """ - :type x: T - :type y: U - :type z: V - """ - r1 = id(x) - r2 = id(y) - r3 = id(z) - return r1, r2, r3 - - def f4(x): - """ - :type x: (bool, int, str) - """ - - result = f1([1, 2, 3]) - print(result) - print(result + 'foo') - - f2(1, ['foo'], 'bar') - - result = f3(1, 'foo', True) - f4(result) - - -# PY-5474 -def test_bad_subsription_expr(): - x = r"""\x"" - r"""[\t\r\v]""" - """ - - -# PY-5873 -def test_type_of_raise_exception(): - def f1(x): - """ - :type x: int - """ - pass - - class C: - def f(self): - raise NotImplementedError() - - x = C() - f1(x.f()) - - -# PY-6542 -def test_dict_literals(): - xs = {'foo': 1, 'bar': 2} - for v in xs.values(): - print(v + None) - for k in xs.keys(): - print(k + None) - for k in xs: - print(k + None) - ys = filter(lambda x: x, xs.keys()) - ys.append(0) - diff --git a/python/testData/inspections/PyTypeCheckerInspection/PartlyUnknownType.py b/python/testData/inspections/PyTypeCheckerInspection/PartlyUnknownType.py new file mode 100644 index 000000000000..9d00032de8f8 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/PartlyUnknownType.py @@ -0,0 +1,10 @@ +def test(): + def f(): + """ + :rtype: None or unknown or int or long + """ + def g(x): + """ + :type x: object + """ + g(f()) diff --git a/python/testData/inspections/PyTypeCheckerInspection/RightOperators.py b/python/testData/inspections/PyTypeCheckerInspection/RightOperators.py new file mode 100644 index 000000000000..465db07b7514 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/RightOperators.py @@ -0,0 +1,5 @@ +def test_right_operators(): + o = object() + xs = [ + o * [], + ] diff --git a/python/testData/inspections/PyTypeCheckerInspection/Simple.py b/python/testData/inspections/PyTypeCheckerInspection/Simple.py new file mode 100644 index 000000000000..8d0f516dc315 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/Simple.py @@ -0,0 +1,24 @@ +def f1(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10=10, p11='11'): + """ + :type p1: integer + :type p2: integer + :type p3: float + :type p4: float + :type p5: int + :type p6: integer + :type p7: integer + :type p8: int + :type p9: int + :type p10: int + :type p11: string + """ + return p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + int(p11) + + +def test(): + p7 = int('7') + f1(1, + '2', + 3.0, 4, 5, int('6'), p7, p8=-8, + p9='foo', + p10='foo') diff --git a/python/testData/inspections/PyTypeCheckerInspection/StrUnicode.py b/python/testData/inspections/PyTypeCheckerInspection/StrUnicode.py new file mode 100644 index 000000000000..24869b10e77b --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/StrUnicode.py @@ -0,0 +1,48 @@ +def str_to_none(b): + """ + :type b: str + """ + pass + + +def unicode_to_none(s): + """ + :type s: unicode + """ + pass + + +def string_to_none(s): + """ + :type s: string + """ + pass + + +def str_or_unicode_to_none(s): + """ + :type s: str or unicode + """ + pass + + +def test(): + b1 = 'hello' + s1 = u'привет' + b2 = str(-1) + s2 = unicode(3.14) + ENC = 'utf-8' + str_to_none(b1.decode(ENC)) + unicode_to_none(b1.decode(ENC)) + string_to_none(b1.decode(ENC)) + str_or_unicode_to_none(b1.decode(ENC)) + b1.encode(ENC) + s1.decode(ENC) + str_to_none(s1.encode(ENC)) + unicode_to_none(s1.encode(ENC)) + string_to_none(s1.encode(ENC)) + str_or_unicode_to_none(s1.encode(ENC)) + b2.decode(ENC) + b2.encode(ENC) + s2.decode(ENC) + s2.encode(ENC) diff --git a/python/testData/inspections/PyTypeCheckerInspection/StringInteger.py b/python/testData/inspections/PyTypeCheckerInspection/StringInteger.py new file mode 100644 index 000000000000..a551543eddec --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/StringInteger.py @@ -0,0 +1,8 @@ +def test(): + print('foo' + 'bar') + print(2 + 3) + print('foo' + 3) + print(3 + 'foo') + print('foo' + 'bar' * 3) + print('foo' + 3 * 'bar') + print('foo' + 2 * 3) diff --git a/python/testData/inspections/PyTypeCheckerInspection/Subscript.py b/python/testData/inspections/PyTypeCheckerInspection/Subscript.py new file mode 100644 index 000000000000..0a3ffe35fe3d --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/Subscript.py @@ -0,0 +1,17 @@ +def test(): + def f(x): + """ + :type x: str + """ + class C(object): + def __getitem__(self, item): + """ + :type item: str + :rtype: int + """ + xs = [1, 2, 3] + x = xs[0] + f(x) + c = C() + c_0 = c[0] + f(c_0) diff --git a/python/testData/inspections/PyTypeCheckerInspection/TypeAssertions.py b/python/testData/inspections/PyTypeCheckerInspection/TypeAssertions.py new file mode 100644 index 000000000000..11f268a00509 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/TypeAssertions.py @@ -0,0 +1,47 @@ +def test(): + def f_1(): + """ + :rtype: int or str or None + """ + def f_2(): + """ + :rtype: int or None + """ + def f_3(): + """ + :rtype: unknown + """ + def f_4(): + """ + :rtype: object + """ + def f_5(): + """ + :rtype: int or object + """ + def f_6(): + """ + :rtype: int or unknown or float + """ + def f_7(): + """ + :rtype: int or unknown + """ + def print_int(x): + """ + :type x: int + """ + print(x) + def print_int_or_str(x): + """ + :type x: int or str + """ + x_1 = f_1() + print_int(x_1) + print_int_or_str(x_1) + if isinstance(x_1, int): + print_int(x_1) + if isinstance(x_1, str): + print_int_or_str(x_1) + x_7 = f_7() + print_int(x_7) diff --git a/python/testData/inspections/PyTypeCheckerInspection/TypeOfRaiseException.py b/python/testData/inspections/PyTypeCheckerInspection/TypeOfRaiseException.py new file mode 100644 index 000000000000..f1b110f0b5d2 --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/TypeOfRaiseException.py @@ -0,0 +1,13 @@ +def test(): + def f1(x): + """ + :type x: int + """ + pass + + class C: + def f(self): + raise NotImplementedError() + + x = C() + f1(x.f()) diff --git a/python/testData/inspections/PyTypeCheckerInspection/UnionReturnTypes.py b/python/testData/inspections/PyTypeCheckerInspection/UnionReturnTypes.py new file mode 100644 index 000000000000..f32cd95e5f0c --- /dev/null +++ b/python/testData/inspections/PyTypeCheckerInspection/UnionReturnTypes.py @@ -0,0 +1,25 @@ +def test(): + def f1(c): + if c < 0: + return [] + elif c > 0: + return 'foo' + else: + return None + def f2(x): + """ + :type x: str + """ + pass + def f3(x): + """ + :type x: int + """ + x1 = f1(42) + f2(x1) + f3(x1) + + f2(x1.count('')) + f3(x1.count('')) + f2(x1.strip()) + f3(x1.strip()) diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java index 4321691d85d4..de9ed8955a9e 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java @@ -12,8 +12,76 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { myFixture.checkHighlighting(true, false, true); } - public void testOldTests() { - // TODO: Split these tests into files + public void testSimple() { + doTest(); + } + + public void testStrUnicode() { + doTest(); + } + + public void testListTuple() { + doTest(); + } + + public void testBuiltinNumeric() { + doTest(); + } + + public void testGenerator() { + doTest(); + } + + // PY-4025 + public void testFunctionAssignments() { + doTest(); + } + + public void testOldStyleClasses() { + doTest(); + } + + public void testPartlyUnknownType() { + doTest(); + } + + public void testTypeAssertions() { + doTest(); + } + + public void testLocalTypeResolve() { + doTest(); + } + + public void testSubscript() { + doTest(); + } + + public void testComparisonOperators() { + doTest(); + } + + public void testRightOperators() { + doTest(); + } + + public void testStringInteger() { + doTest(); + } + + public void testIsInstanceImplicitSelfTypes() { + doTest(); + } + + public void testNotNone() { + doTest(); + } + + public void testBuiltinFunctions() { + doTest(); + } + + public void testUnionReturnTypes() { doTest(); } @@ -21,6 +89,10 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { doTest(); } + public void testGenericUserFunctions() { + doTest(); + } + public void testGenericUserClasses() { doTest(); } @@ -29,6 +101,21 @@ public class PyTypeCheckerInspectionTest extends PyTestCase { doTest(); } + // PY-5474 + public void testBadSubscriptExpression() { + doTest(); + } + + // PY-5873 + public void testTypeOfRaiseException() { + doTest(); + } + + // PY-6542 + public void testDictLiterals() { + doTest(); + } + // PY-6570 public void testDictLiteralIndexing() { doTest();