Support for typing.NewType (PY-21302)

This commit is contained in:
Elizaveta Shashkova
2018-02-06 20:24:29 +03:00
parent e0a1256b1d
commit 79cc4d9ef4
18 changed files with 487 additions and 59 deletions
@@ -24,10 +24,7 @@ import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyFileImpl;
import com.jetbrains.python.psi.resolve.PyResolveImportUtil;
import com.jetbrains.python.psi.stubs.*;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -972,4 +969,27 @@ public class PyStubsTest extends PyTestCase {
}
);
}
// PY-27398
public void testTypingNewType() {
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> {
final PyFile file = getTestFile("typingNewType/new_type.py");
final PyTargetExpression type = file.findTopLevelAttribute("UserId");
final PyTypingNewTypeStub stub = type.getStub().getCustomStub(PyTypingNewTypeStub.class);
assertNotNull(stub);
assertTrue("UserId".equals(stub.getName()));
assertTrue("int".equals(stub.getClassType()));
final TypeEvalContext context = TypeEvalContext.codeInsightFallback(myFixture.getProject());
final PyType typeDef = context.getType(type);
assertTrue(typeDef instanceof PyTypingNewType);
assertNotParsed(file);
}
);
}
}
@@ -8,10 +8,7 @@ import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -3078,6 +3075,92 @@ public class PyTypeTest extends PyTestCase {
);
}
// PY-21302
public void testNewTypeReferenceTarget() {
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> {
final PyExpression definition = parseExpr("from typing import NewType\n" +
"UserId = NewType('UserId', int)\n" +
"expr = UserId");
for (TypeEvalContext context : getTypeEvalContexts(definition)) {
assertInstanceOf(context.getType(definition), PyTypingNewType.class);
}
final PyExpression instance = parseExpr("from typing import NewType\n" +
"UserId = NewType('UserId', int)\n" +
"expr = UserId(12)");
for (TypeEvalContext context : getTypeEvalContexts(instance)) {
assertInstanceOf(context.getType(instance), PyTypingNewType.class);
}
}
);
}
// PY-21302
public void testNewType() {
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("UserId",
"from typing import NewType\n" +
"UserId = NewType('UserId', int)\n" +
"expr = UserId(12)")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("Type[UserId]",
"from typing import Dict, NewType\n" +
"UserId = NewType('UserId', Dict[int, str])\n" +
"expr = UserId\n")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("(a: UserId) -> str",
"from typing import Dict, NewType\n" +
"UserId = NewType('UserId', int)\n" +
"def foo(a: UserId) -> str\n" +
" pass\n" +
"expr = foo\n")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("UserId",
"from typing import NewType as nt\n" +
"UserId = nt('UserId', int)\n" +
"expr = UserId(12)\n")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("UserId",
"import typing\n" +
"UserId = typing.NewType('UserId', int)\n" +
"expr = UserId(12)\n")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("UserId",
"import typing as t\n" +
"UserId = t.NewType('UserId', int)\n" +
"expr = UserId(12)\n")
);
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("SuperId",
"from typing import NewType\n" +
"UserId = NewType('UserId', int)\n" +
"SuperId = NewType('SuperId', UserId)\n" +
"expr = SuperId(UserId(12))\n")
);
}
// PY-26992
public void testImportedOrderedDict() {
doTest("OrderedDict[str, str]",
@@ -246,6 +246,21 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase {
doTest();
}
// PY-21302
public void testInitializingNewType() {
runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
}
// PY-21302
public void testNewTypeAsParameter() {
runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
}
// PY-21302
public void testNewTypeInheritance() {
runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
}
// PY-24287
public void testPromotingBytearrayToBytes() {
doTest();