diff --git a/python/resources/liveTemplates/Python.xml b/python/resources/liveTemplates/Python.xml
index 96689b16a275..47928f82d8aa 100644
--- a/python/resources/liveTemplates/Python.xml
+++ b/python/resources/liveTemplates/Python.xml
@@ -4,8 +4,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java b/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java
index 4ae7abebfeb1..1032cbdc3b16 100644
--- a/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java
+++ b/python/src/com/jetbrains/python/codeInsight/liveTemplates/PythonTemplateContextType.java
@@ -17,11 +17,15 @@ package com.jetbrains.python.codeInsight.liveTemplates;
import com.intellij.codeInsight.template.FileTypeBasedContextType;
import com.intellij.patterns.PsiElementPattern;
+import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.psi.PyParameterList;
+import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PlatformPatterns.psiElement;
@@ -39,16 +43,20 @@ public class PythonTemplateContextType extends FileTypeBasedContextType {
if (super.isInContext(file, offset)) {
final PsiElement element = file.findElementAt(offset);
if (element != null) {
- return !isAfterDot(element);
+ return !(isAfterDot(element) || element instanceof PsiComment || element instanceof PyStringLiteralExpression ||
+ isInsideParameterList(element));
}
}
return false;
}
+ private static boolean isInsideParameterList(@NotNull PsiElement element) {
+ return PsiTreeUtil.getParentOfType(element, PyParameterList.class) != null;
+ }
+
private static boolean isAfterDot(@NotNull PsiElement element) {
- ProcessingContext context = new ProcessingContext();
final PsiElementPattern.Capture capture = psiElement().afterLeafSkipping(psiElement().whitespace(),
psiElement().withElementType(PyTokenTypes.DOT));
- return capture.accepts(element, context);
+ return capture.accepts(element, new ProcessingContext());
}
}
diff --git a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
index 6934a37d723f..5df0a37e096b 100644
--- a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
+++ b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
@@ -195,7 +195,7 @@ public class PyTypeModelBuilder {
}
else if (type instanceof PyUnionType && allowUnions) {
if (type instanceof PyDynamicallyEvaluatedType || PyTypeChecker.isUnknown(type)) {
- result = new UnknownType(build(((PyUnionType)type).excludeNull(), true));
+ result = new UnknownType(build(((PyUnionType)type).excludeNull(myContext), true));
}
else {
result = new OneOf(
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 1700a49004ec..3ec28a21d64a 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -1521,7 +1521,7 @@ public class PyUtil {
public static List getParameters(@NotNull Callable callable, @NotNull TypeEvalContext context) {
PyType type = context.getType(callable);
if (type instanceof PyUnionType) {
- type = ((PyUnionType)type).excludeNull();
+ type = ((PyUnionType)type).excludeNull(context);
}
if (type instanceof PyCallableType) {
final PyCallableType callableType = (PyCallableType)type;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
index f38937daa87f..bf792fef0dae 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
@@ -239,7 +239,7 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl memberTypes = new ArrayList();
+ for (int i = 0; i < tupleType.getElementCount(); i++) {
+ memberTypes.add(tupleType.getElementType(i));
+ }
+ return PyUnionType.union(memberTypes);
+ }
else if (iterableType instanceof PyUnionType) {
final Collection members = ((PyUnionType)iterableType).getMembers();
final List iterationTypes = new ArrayList();
diff --git a/python/src/com/jetbrains/python/psi/types/PyDynamicallyEvaluatedType.java b/python/src/com/jetbrains/python/psi/types/PyDynamicallyEvaluatedType.java
index 174394764956..85624b1d0f10 100644
--- a/python/src/com/jetbrains/python/psi/types/PyDynamicallyEvaluatedType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyDynamicallyEvaluatedType.java
@@ -49,7 +49,7 @@ public class PyDynamicallyEvaluatedType extends PyUnionType {
@Override
public String getName() {
- PyType res = excludeNull();
+ PyType res = excludeNull(TypeEvalContext.codeInsightFallback());
return res != null ? res.getName() : PyNames.UNKNOWN_TYPE;
}
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
index cbdeb163e923..f4a52368a047 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
@@ -215,6 +215,17 @@ public class PyTypeChecker {
return false;
}
+ @Nullable
+ public static PyType toNonWeakType(@Nullable PyType type, @NotNull TypeEvalContext context) {
+ if (type instanceof PyUnionType) {
+ final PyUnionType unionType = (PyUnionType)type;
+ if (unionType.isWeak()) {
+ return unionType.excludeNull(context);
+ }
+ }
+ return type;
+ }
+
public static boolean hasGenerics(@Nullable PyType type, @NotNull TypeEvalContext context) {
final Set collected = new HashSet();
collectGenerics(type, context, collected, new HashSet());
diff --git a/python/src/com/jetbrains/python/psi/types/PyUnionType.java b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
index 8572b72c1771..d94eb7510d04 100644
--- a/python/src/com/jetbrains/python/psi/types/PyUnionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
@@ -184,7 +184,7 @@ public class PyUnionType implements PyType {
* @return union with excluded types
*/
@Nullable
- public PyType exclude(PyType type, TypeEvalContext context) {
+ public PyType exclude(@Nullable PyType type, @NotNull TypeEvalContext context) {
final List members = new ArrayList();
for (PyType m : getMembers()) {
if (type == null) {
@@ -202,8 +202,8 @@ public class PyUnionType implements PyType {
}
@Nullable
- public PyType excludeNull() {
- return exclude(null, null);
+ public PyType excludeNull(@NotNull TypeEvalContext context) {
+ return exclude(null, context);
}
private static PyType unit(@Nullable PyType type) {
diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java
index cfa29662898a..81b4aa46629e 100644
--- a/python/testSrc/com/jetbrains/python/PyTypeTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java
@@ -805,6 +805,20 @@ public class PyTypeTest extends PyTestCase {
"expr = iter(xs).next()\n");
}
+ // PY-10967
+ public void testDefaultTupleParameterMember() {
+ doTest("int",
+ "def foo(xs=(1, 2)):\n" +
+ " expr, foo = xs\n");
+ }
+
+ public void testTupleIterationType() {
+ doTest("int | str",
+ "xs = (1, 'a')\n" +
+ "for expr in xs:\n" +
+ " pass\n");
+ }
+
private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
}