summaryrefslogtreecommitdiff
path: root/python/testSrc/com/jetbrains/python/PyTypingTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'python/testSrc/com/jetbrains/python/PyTypingTest.java')
-rw-r--r--python/testSrc/com/jetbrains/python/PyTypingTest.java267
1 files changed, 267 insertions, 0 deletions
diff --git a/python/testSrc/com/jetbrains/python/PyTypingTest.java b/python/testSrc/com/jetbrains/python/PyTypingTest.java
new file mode 100644
index 000000000000..9513795cb5b7
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/PyTypingTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python;
+
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.jetbrains.python.documentation.PythonDocumentationProvider;
+import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyExpression;
+import com.jetbrains.python.psi.types.PyType;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Tests for a type system based on mypy's typing module.
+ *
+ * @author vlan
+ */
+public class PyTypingTest extends PyTestCase {
+ @Nullable
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return ourPy3Descriptor;
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ setLanguageLevel(LanguageLevel.PYTHON32);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ setLanguageLevel(null);
+ super.tearDown();
+ }
+
+ public void testClassType() {
+ doTest("Foo",
+ "class Foo:" +
+ " pass\n" +
+ "\n" +
+ "def f(expr: Foo):\n" +
+ " pass\n");
+ }
+
+ public void testClassReturnType() {
+ doTest("Foo",
+ "class Foo:" +
+ " pass\n" +
+ "\n" +
+ "def f() -> Foo:\n" +
+ " pass\n" +
+ "\n" +
+ "expr = f()\n");
+
+ }
+
+ public void testNoneType() {
+ doTest("None",
+ "def f(expr: None):\n" +
+ " pass\n");
+ }
+
+ public void testNoneReturnType() {
+ doTest("None",
+ "def f() -> None:\n" +
+ " return 0\n" +
+ "expr = f()\n");
+ }
+
+ public void testUnionType() {
+ doTest("int | str",
+ "from typing import Union\n" +
+ "\n" +
+ "def f(expr: Union[int, str]):\n" +
+ " pass\n");
+ }
+
+ public void testBuiltinList() {
+ doTest("list",
+ "from typing import List\n" +
+ "\n" +
+ "def f(expr: List):\n" +
+ " pass\n");
+ }
+
+ public void testBuiltinListWithParameter() {
+ doTest("list[int]",
+ "from typing import List\n" +
+ "\n" +
+ "def f(expr: List[int]):\n" +
+ " pass\n");
+ }
+
+ public void testBuiltinDictWithParameters() {
+ doTest("dict[str, int]",
+ "from typing import Dict\n" +
+ "\n" +
+ "def f(expr: Dict[str, int]):\n" +
+ " pass\n");
+ }
+
+ public void testBuiltinTuple() {
+ doTest("tuple",
+ "from typing import Tuple\n" +
+ "\n" +
+ "def f(expr: Tuple):\n" +
+ " pass\n");
+ }
+
+ public void testBuiltinTupleWithParameters() {
+ doTest("(int, str)",
+ "from typing import Tuple\n" +
+ "\n" +
+ "def f(expr: Tuple[int, str]):\n" +
+ " pass\n");
+ }
+
+ public void testAnyType() {
+ doTest("unknown",
+ "from typing import Any\n" +
+ "\n" +
+ "def f(expr: Any):\n" +
+ " pass\n");
+ }
+
+ public void testGenericType() {
+ doTest("A",
+ "from typing import typevar\n" +
+ "\n" +
+ "T = typevar('A')\n" +
+ "\n" +
+ "def f(expr: T):\n" +
+ " pass\n");
+ }
+
+ public void testGenericBoundedType() {
+ doTest("T <= int | str",
+ "from typing import typevar\n" +
+ "\n" +
+ "T = typevar('T', values=(int, str))\n" +
+ "\n" +
+ "def f(expr: T):\n" +
+ " pass\n");
+ }
+
+ public void testParameterizedClass() {
+ doTest("C[int]",
+ "from typing import Generic, typevar\n" +
+ "\n" +
+ "T = typevar('T')\n" +
+ "\n" +
+ "class C(Generic[T]):\n" +
+ " def __init__(self, x: T):\n" +
+ " pass\n" +
+ "\n" +
+ "expr = C(10)\n");
+ }
+
+ public void testParameterizedClassMethod() {
+ doTest("int",
+ "from typing import Generic, typevar\n" +
+ "\n" +
+ "T = typevar('T')\n" +
+ "\n" +
+ "class C(Generic[T]):\n" +
+ " def __init__(self, x: T):\n" +
+ " pass\n" +
+ " def foo(self) -> T:\n" +
+ " pass\n" +
+ "\n" +
+ "expr = C(10).foo()\n");
+ }
+
+ public void testParameterizedClassInheritance() {
+ doTest("int",
+ "from typing import Generic, typevar\n" +
+ "\n" +
+ "T = typevar('T')\n" +
+ "\n" +
+ "class B(Generic[T]):\n" +
+ " def foo(self) -> T:\n" +
+ " pass\n" +
+ "class C(B[T]):\n" +
+ " def __init__(self, x: T):\n" +
+ " pass\n" +
+ "\n" +
+ "expr = C(10).foo()\n");
+ }
+
+ public void testAnyStrUnification() {
+ doTest("bytes",
+ "from typing import AnyStr\n" +
+ "\n" +
+ "def foo(x: AnyStr) -> AnyStr:\n" +
+ " pass\n" +
+ "\n" +
+ "expr = foo(b'bar')\n");
+ }
+
+ public void testAnyStrForUnknown() {
+ doTest("str | bytes",
+ "from typing import AnyStr\n" +
+ "\n" +
+ "def foo(x: AnyStr) -> AnyStr:\n" +
+ " pass\n" +
+ "\n" +
+ "def bar(x):\n" +
+ " expr = foo(x)\n");
+ }
+
+ public void testFunctionType() {
+ doTest("(int, str) -> str",
+ "from typing import Function\n" +
+ "\n" +
+ "def foo(expr: Function[[int, str], str]):\n" +
+ " pass\n");
+ }
+
+ public void testTypeInStringLiteral() {
+ doTest("C",
+ "class C:\n" +
+ " def foo(self, expr: 'C'):\n" +
+ " pass\n");
+ }
+
+ public void testQualifiedTypeInStringLiteral() {
+ doTest("str",
+ "import typing\n" +
+ "\n" +
+ "def foo(x: 'typing.AnyStr') -> typing.AnyStr:\n" +
+ " pass\n" +
+ "\n" +
+ "expr = foo('bar')\n");
+ }
+
+ private void doTest(@NotNull String expectedType, @NotNull String text) {
+ myFixture.copyDirectoryToProject("typing", "");
+ myFixture.configureByText(PythonFileType.INSTANCE, text);
+ final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
+ final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getContainingFile());
+ final TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getContainingFile()).withTracing();
+ assertType(expectedType, expr, codeAnalysis, "code analysis");
+ assertType(expectedType, expr, userInitiated, "user initiated");
+ }
+
+ private static void assertType(String expectedType, PyExpression expr, TypeEvalContext context, String contextName) {
+ final PyType actual = context.getType(expr);
+ final String actualType = PythonDocumentationProvider.getTypeName(actual, context);
+ assertEquals("Failed in " + contextName + " context", expectedType, actualType);
+ }
+}