Merge remote branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2012-04-27 15:32:39 +04:00
54 changed files with 423 additions and 106 deletions
+8 -1
View File
@@ -63,7 +63,14 @@ def patch_args(args):
return new_args
def args_to_str(args):
return ' '.join(x if x.startswith('"') and x.endswith('"') else '"%s"' % x for x in args)
quoted_args = []
for x in args:
if x.startswith('"') and x.endswith('"'):
quoted_args.append(x)
else:
quoted_args.append('"%s"' % x)
return ' '.join(quoted_args)
def remove_quotes(str):
if str.startswith('"') and str.endswith('"'):
+3
View File
@@ -25,6 +25,9 @@
<orderEntry type="module" module-name="JavaScriptDebugger" />
<orderEntry type="module" module-name="webDeployment" />
<orderEntry type="module" module-name="python-remote-interpreter" />
<orderEntry type="module" module-name="htmltools" />
<orderEntry type="module" module-name="github" />
<orderEntry type="module" module-name="jira-connector" />
</component>
</module>
@@ -1,5 +1,8 @@
package com.jetbrains.python.codeInsight;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
@@ -9,6 +12,7 @@ import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.LightNamedElement;
@@ -41,7 +45,7 @@ public class PyDunderAllReference extends PsiReferenceBase<PyStringLiteralExpres
@NotNull
@Override
public Object[] getVariants() {
final List<PsiElement> result = new ArrayList<PsiElement>();
final List<LookupElement> result = new ArrayList<LookupElement>();
PyFile containingFile = (PyFile) getElement().getContainingFile().getOriginalFile();
final List<String> dunderAll = containingFile.getDunderAll();
containingFile.processDeclarations(new PsiScopeProcessor() {
@@ -50,7 +54,13 @@ public class PyDunderAllReference extends PsiReferenceBase<PyStringLiteralExpres
if (element instanceof PsiNamedElement && !(element instanceof LightNamedElement)) {
final String name = ((PsiNamedElement)element).getName();
if (name != null && PyUtil.getInitialUnderscores(name) == 0 && (dunderAll == null || !dunderAll.contains(name))) {
result.add(element);
result.add(LookupElementBuilder.create((PsiNamedElement) element).setIcon(element.getIcon(Iconable.ICON_FLAG_CLOSED)));
}
}
else if (element instanceof PyImportElement) {
final String visibleName = ((PyImportElement)element).getVisibleName();
if (visibleName != null && (dunderAll == null || !dunderAll.contains(visibleName))) {
result.add(LookupElementBuilder.create(element, visibleName));
}
}
return true;
@@ -4,6 +4,7 @@ import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyAssignmentStatement;
import com.jetbrains.python.psi.PySequenceExpression;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import org.jetbrains.annotations.NotNull;
@@ -38,8 +39,9 @@ public class PyStdReferenceContributor extends PsiReferenceContributor {
private static void registerClassAttributeReference(PsiReferenceRegistrar registrar,
final String name,
final PsiReferenceProvider provider) {
registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class).inside(
psiElement(PyAssignmentStatement.class).withFirstChild(
psiElement(PyTargetExpression.class).withName(name))), provider);
}
registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class).withParent(
psiElement(PySequenceExpression.class).withParent(
psiElement(PyAssignmentStatement.class).withFirstChild(
psiElement(PyTargetExpression.class).withName(name)))), provider);
}
}
@@ -56,20 +56,21 @@ public class ScopeUtil {
}
@Nullable
public static ScopeOwner getResolveScopeOwner(PsiElement element) {
// References in default values of parameters are defined somewhere in outer scopes, as well as references in decorators (if they are
// not inside a lambda, see PY-6083) and superclasses
final ScopeOwner initialScopeOwner = getScopeOwner(element);
if (!(initialScopeOwner instanceof PyLambdaExpression && PsiTreeUtil.getParentOfType(element, PyDecorator.class) != null) &&
PsiTreeUtil.getParentOfType(element, PyParameter.class, PyDecorator.class) != null) {
element = initialScopeOwner;
public static ScopeOwner getResolveScopeOwner(@NotNull PsiElement element) {
final ScopeOwner firstOwner = getScopeOwner(element);
if (firstOwner == null) {
return null;
}
final ScopeOwner nextOwner = getScopeOwner(firstOwner);
final PyElement decoratorOrParameterAncestor = PsiTreeUtil.getParentOfType(element, PyDecorator.class, PyParameter.class);
if (decoratorOrParameterAncestor != null && !PsiTreeUtil.isAncestor(decoratorOrParameterAncestor, firstOwner, true)) {
return nextOwner;
}
final PyClass containingClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
if (containingClass != null && element != null &&
PsiTreeUtil.isAncestor(containingClass.getSuperClassExpressionList(), element, false)) {
element = containingClass;
if (containingClass != null && PsiTreeUtil.isAncestor(containingClass.getSuperClassExpressionList(), element, false)) {
return nextOwner;
}
return PsiTreeUtil.getParentOfType(element, ScopeOwner.class);
return firstOwner;
}
@Nullable
@@ -54,7 +54,7 @@ public class ScopeImpl implements Scope {
return null;
}
private synchronized List<DFAMap<ScopeVariable>> computeScopeVariables() throws DFALimitExceededException {
private synchronized void computeScopeVariables() throws DFALimitExceededException {
computeFlow();
if (myCachedScopeVariables == null) {
final PyReachingDefsDfaInstance dfaInstance = new PyReachingDefsDfaInstance();
@@ -62,7 +62,6 @@ public class ScopeImpl implements Scope {
final DFAMapEngine<ScopeVariable> engine = new DFAMapEngine<ScopeVariable>(myFlow, dfaInstance, semilattice);
myCachedScopeVariables = engine.performDFA();
}
return myCachedScopeVariables;
}
public boolean isGlobal(final String name) {
@@ -196,6 +195,21 @@ public class ScopeImpl implements Scope {
}
}
});
Collections.sort(nameDefiners, new Comparator<NameDefiner>() {
@Override
public int compare(NameDefiner d1, NameDefiner d2) {
return getPriority(d2) - getPriority(d1);
};
private int getPriority(NameDefiner nameDefiner) {
if (nameDefiner instanceof PyStarImportElement) {
return -10;
}
return 0;
}
});
myNamedElements = namedElements;
myNameDefiners = nameDefiners;
myNestedScopes = nestedScopes;
@@ -191,6 +191,9 @@ public class AddImportHelper {
if (target != null && existingImport.getTextRange().getStartOffset() > target.getTextRange().getStartOffset()) {
continue;
}
if (existingImport.isStarImport()) {
continue;
}
final PyQualifiedName qName = existingImport.getImportSourceQName();
if (qName != null && qName.toString().equals(path)) {
for (PyImportElement el : existingImport.getImportElements()) {
@@ -220,7 +223,7 @@ public class AddImportHelper {
else if (useQualified) {
addImportStatement(file, path, null, priority);
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(file.getProject());
element.replace(elementGenerator.createExpressionFromText(qName + "." + target.getName()));
element.replace(elementGenerator.createExpressionFromText(LanguageLevel.forElement(target), qName + "." + target.getName()));
}
else {
addImportFrom(file, null, path, target.getName(), null, priority);
@@ -7,6 +7,9 @@ import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
/**
* @author yole
*/
@@ -32,4 +35,12 @@ public class PyClassFindUsagesHandler extends FindUsagesHandler {
protected boolean isSearchForTextOccurencesAvailable(PsiElement psiElement, boolean isSingleFile) {
return true;
}
@Override
protected Collection<String> getStringsToSearch(PsiElement element) {
if (element instanceof PyFunction && PyNames.INIT.equals(((PyFunction) element).getName())) {
return Collections.emptyList();
}
return super.getStringsToSearch(element);
}
}
@@ -154,10 +154,24 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
final PyClass pyClass = ((PyClassType)type).getPyClass();
if (pyClass != null && pyClass.isNewStyleClass()) {
final List<String> slots = pyClass.getSlots();
if (slots != null && !slots.contains(node.getReferencedName()) && !slots.contains("__dict__")) {
final String attrName = node.getReferencedName();
if (slots != null && !slots.contains(attrName) && !slots.contains(PyNames.DICT)) {
for (PyClassRef ref : pyClass.iterateAncestors()) {
final PyClass ancestor = ref.getPyClass();
if (ancestor == null) {
return;
}
if (PyNames.OBJECT.equals(ancestor.getName())) {
break;
}
final List<String> ancestorSlots = ancestor.getSlots();
if (ancestorSlots == null || ancestorSlots.contains(attrName) || ancestorSlots.contains(PyNames.DICT)) {
return;
}
}
final ASTNode nameNode = node.getNameElement();
final PsiElement e = nameNode != null ? nameNode.getPsi() : node;
registerProblem(e, "'" + pyClass.getName() + "' object has no attribute '" + node.getReferencedName() + "'");
registerProblem(e, "'" + pyClass.getName() + "' object has no attribute '" + attrName + "'");
}
}
}
@@ -16,7 +16,6 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
@@ -28,7 +27,6 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyListLiteralExpression;
@@ -564,19 +562,7 @@ public class PyPackageManager {
do {
processOutput = manager.runRemoteProcess(null, remoteSdkData, ArrayUtil.toStringArray(cmdline), askForSudo);
if (askForSudo && processOutput.getStderr().contains("sudo: 3 incorrect password attempts")) {
final Ref<Boolean> cont = Ref.create(false);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
if (Messages.showOkCancelDialog("Incorrect sudo password", "Incorrect Password Attempt", Messages.getErrorIcon()) ==
Messages.OK) {
cont.set(true);
}
}
});
if (cont.get()) {
continue;
}
continue;
}
break;
}
@@ -271,7 +271,7 @@ public class PyRequirement {
@Nullable
public PyPackage match(@NotNull List<PyPackage> packages) {
for (PyPackage pkg : packages) {
if (myName.equalsIgnoreCase(pkg.getName())) {
if (normalizeName(myName).equalsIgnoreCase(pkg.getName())) {
for (VersionSpec spec : myVersionSpecs) {
final int cmp = VERSION_COMPARATOR.compare(pkg.getVersion(), spec.getVersion());
final Relation relation = spec.getRelation();
@@ -183,9 +183,11 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
return null;
}
@Nullable
private PsiElement resolveDeclaration(String name, PsiElement result) {
if (result instanceof PyImportElement) {
return findNameInImportElement(name, (PyImportElement)result);
final PyImportElement importElement = (PyImportElement)result;
return findNameInImportElement(name, importElement, importElement.getContainingImportStatement() instanceof PyFromImportStatement);
}
else if (result instanceof PyFromImportStatement) {
return ((PyFromImportStatement) result).resolveImportSource();
@@ -557,7 +559,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
@Nullable
private PsiElement findNameInImportStatement(String name, PyImportStatement child) {
for (PyImportElement importElement: child.getImportElements()) {
final PsiElement result = findNameInImportElement(name, importElement);
final PsiElement result = findNameInImportElement(name, importElement, false);
if (result != null) {
return result;
}
@@ -566,8 +568,8 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
}
@Nullable
private PsiElement findNameInImportElement(String name, PyImportElement importElement) {
final PsiElement result = importElement.getElementNamed(name, false);
private PsiElement findNameInImportElement(String name, PyImportElement importElement, final boolean resolveImportElement) {
final PsiElement result = importElement.getElementNamed(name, resolveImportElement);
if (result != null) {
return result;
}
@@ -167,7 +167,7 @@ public class PyImportReference extends PyReferenceImpl {
}
public Object[] execute() {
int relative_level = -1;
int relativeLevel = -1;
InsertHandler<LookupElement> insertHandler = null;
// NOTE: could use getPointInImport()
@@ -191,9 +191,9 @@ public class PyImportReference extends PyReferenceImpl {
}
}
else { // null source, must be a "from ... import"
relative_level = from_import.getRelativeLevel();
if (relative_level > 0) {
PsiDirectory relative_dir = ResolveImportUtil.stepBackFrom(myCurrentFile, relative_level);
relativeLevel = from_import.getRelativeLevel();
if (relativeLevel > 0) {
PsiDirectory relative_dir = ResolveImportUtil.stepBackFrom(myCurrentFile, relativeLevel);
if (relative_dir != null) {
addImportedNames(from_import.getImportElements());
fillFromDir(relative_dir, null);
@@ -204,7 +204,7 @@ public class PyImportReference extends PyReferenceImpl {
else { // in "import _" or "from _ import"
ASTNode n = myElement.getNode().getTreePrev();
while (n != null && n.getElementType() == PyTokenTypes.DOT) {
relative_level += 1;
relativeLevel += 1;
n = n.getTreePrev();
}
if (from_import != null) {
@@ -221,21 +221,21 @@ public class PyImportReference extends PyReferenceImpl {
}
}
// look at dir by level
if (myCurrentFile != null && (relative_level >= 0 || !ResolveImportUtil.isAbsoluteImportEnabledFor(myCurrentFile))) {
if (myCurrentFile != null && (relativeLevel >= 0 || !ResolveImportUtil.isAbsoluteImportEnabledFor(myCurrentFile))) {
final PsiDirectory containingDirectory = myCurrentFile.getContainingDirectory();
if (containingDirectory != null) {
PyQualifiedName thisQName = ResolveImportUtil.findShortestImportableQName(containingDirectory);
if (thisQName == null) {
fillFromDir(ResolveImportUtil.stepBackFrom(myCurrentFile, relative_level), insertHandler);
if (thisQName == null || thisQName.getComponentCount() == relativeLevel) {
fillFromDir(ResolveImportUtil.stepBackFrom(myCurrentFile, relativeLevel), insertHandler);
}
else if (thisQName.getComponentCount() >= relative_level) {
thisQName = thisQName.removeTail(relative_level);
else if (thisQName.getComponentCount() > relativeLevel) {
thisQName = thisQName.removeTail(relativeLevel);
fillFromQName(thisQName, insertHandler);
}
}
}
}
if (relative_level == -1) {
if (relativeLevel == -1) {
fillFromQName(PyQualifiedName.fromComponents(), insertHandler);
}
@@ -75,6 +75,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
}
// it is *not* final so that it can be changed in debug time. if set to false, caching is off
@SuppressWarnings("FieldCanBeLocal")
private static boolean USE_CACHE = true;
/**
@@ -4,10 +4,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
@@ -100,10 +97,10 @@ public class PyMoveClassOrFunctionProcessor extends BaseRefactoringProcessor {
PyClassRefactoringUtil.rememberNamedReferences(oldElement);
final PsiNamedElement newElement = (PsiNamedElement)(dest.add(oldElement));
for (UsageInfo usage : usages) {
final PsiElement oldExpr = usage.getElement();
final PsiElement usageElement = usage.getElement();
// TODO: Respect the qualified import style
if (oldExpr instanceof PyQualifiedExpression) {
PyQualifiedExpression qexpr = (PyQualifiedExpression)oldExpr;
if (usageElement instanceof PyQualifiedExpression) {
PyQualifiedExpression qexpr = (PyQualifiedExpression)usageElement;
if (oldElement instanceof PyClass && PyNames.INIT.equals(qexpr.getName())) {
continue;
}
@@ -112,22 +109,25 @@ public class PyMoveClassOrFunctionProcessor extends BaseRefactoringProcessor {
PyClassRefactoringUtil.insertImport(newExpr, newElement, null, true);
}
}
if (oldExpr instanceof PyStringLiteralExpression) {
final PsiReference[] references = oldExpr.getReferences();
for (PsiReference ref : references) {
if (usageElement instanceof PyStringLiteralExpression) {
for (PsiReference ref : usageElement.getReferences()) {
if (ref instanceof DocStringTypeReference && ref.isReferenceTo(oldElement)) {
ref.bindToElement(newElement);
}
}
}
else {
final PyImportStatementBase importStmt = PsiTreeUtil.getParentOfType(usage.getElement(), PyImportStatementBase.class);
final PyImportStatementBase importStmt = PsiTreeUtil.getParentOfType(usageElement, PyImportStatementBase.class);
if (importStmt != null) {
PyClassRefactoringUtil.updateImportOfElement(importStmt, newElement);
}
if (usage.getFile() == oldFile && (oldExpr == null || !PsiTreeUtil.isAncestor(oldElement, oldExpr, false))) {
if (usage.getFile() == oldFile && (usageElement == null || !PsiTreeUtil.isAncestor(oldElement, usageElement, false))) {
PyClassRefactoringUtil.insertImport(oldElement, newElement);
}
if (usageElement != null && resolvesToLocalStarImport(usageElement)) {
PyClassRefactoringUtil.insertImport(usageElement, newElement);
new PyImportOptimizer().processFile(usageElement.getContainingFile()).run();
}
}
}
PyClassRefactoringUtil.restoreNamedReferences(newElement, oldElement);
@@ -141,16 +141,38 @@ public class PyMoveClassOrFunctionProcessor extends BaseRefactoringProcessor {
}, REFACTORING_NAME, null);
}
@Override
protected String getCommandName() {
return REFACTORING_NAME;
}
private boolean resolvesToLocalStarImport(@NotNull PsiElement element) {
final PsiReference ref = element.getReference();
final List<PsiElement> resolvedElements = new ArrayList<PsiElement>();
if (ref instanceof PsiPolyVariantReference) {
for (ResolveResult result : ((PsiPolyVariantReference)ref).multiResolve(false)) {
resolvedElements.add(result.getElement());
}
}
else if (ref != null) {
resolvedElements.add(ref.resolve());
}
final PsiFile containingFile = element.getContainingFile();
if (containingFile != null) {
for (PsiElement resolved : resolvedElements) {
if (resolved instanceof PyStarImportElement && resolved.getContainingFile() == containingFile) {
return true;
}
}
}
return false;
}
private static void checkValidImportableFile(PsiElement anchor, VirtualFile file) {
final PyQualifiedName qName = ResolveImportUtil.findShortestImportableQName(anchor, file);
if (!PyClassRefactoringUtil.isValidQualifiedName(qName)) {
throw new IncorrectOperationException(PyBundle.message("refactoring.move.class.or.function.error.cannot.use.module.name.$0", qName));
}
}
@Override
protected String getCommandName() {
return REFACTORING_NAME;
}
}
@@ -4,6 +4,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringSettings;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
@@ -38,7 +39,8 @@ public class PyMoveFileHandler extends MoveFileHandler {
while (root != null && !roots.contains(root.getVirtualFile())) {
root = root.getParentDirectory();
}
if (moveDestination != root && root != null) {
final boolean searchForReferences = RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE;
if (moveDestination != root && root != null && searchForReferences) {
CreatePackageAction.createInitPyInHierarchy(moveDestination, root);
}
}
@@ -0,0 +1,10 @@
package com.jetbrains.python.remote;
/**
* @author traff
*/
public class PyRemoteCancelledException extends PyRemoteInterpreterException {
public PyRemoteCancelledException(String s) {
super(s);
}
}
@@ -2,16 +2,19 @@ package com.jetbrains.python.remote;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author traff
*/
public class RemoteFile {
private final boolean myWin;
private final String myPath;
public RemoteFile(@NotNull String path, boolean isWin) {
myPath = toSystemDependent(path, isWin);
myWin = isWin;
}
public RemoteFile(@NotNull String parent, String child) {
@@ -22,14 +25,19 @@ public class RemoteFile {
this(resolveChild(parent, child, isWin), isWin);
}
private static String resolveChild(@NotNull String parent, @NotNull String child, boolean win) {
String separator;
if (win) {
separator = "\\";
@Nullable
public String getName() {
int ind = myPath.lastIndexOf(getSeparator(myWin));
if (ind != -1 && ind < myPath.length() - 1) { //not last char
return myPath.substring(ind + 1);
}
else {
separator = "/";
return null;
}
}
private static String resolveChild(@NotNull String parent, @NotNull String child, boolean win) {
String separator = getSeparator(win);
String path;
if (parent.endsWith(separator)) {
@@ -41,6 +49,17 @@ public class RemoteFile {
return path;
}
private static String getSeparator(boolean win) {
String separator;
if (win) {
separator = "\\";
}
else {
separator = "/";
}
return separator;
}
public String getPath() {
return myPath;
@@ -24,7 +24,6 @@ import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonModuleTypeBase;
import com.jetbrains.python.debugger.remote.PyPathMappingSettings;
import com.jetbrains.python.sdk.PythonEnvUtil;
import com.jetbrains.python.sdk.PythonSdkFlavor;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
@@ -186,12 +185,6 @@ public abstract class AbstractPythonRunConfiguration<T extends AbstractRunConfig
return sdkHome;
}
@Nullable
public PythonSdkFlavor getSdkFlavor() {
final String path = getInterpreterPath();
return path == null ? null : PythonSdkFlavor.getFlavor(path);
}
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
myInterpreterOptions = JDOMExternalizerUtil.readField(element, "INTERPRETER_OPTIONS");
@@ -0,0 +1,47 @@
package com.jetbrains.python.sdk;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.remote.RemoteFile;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author traff
*/
public class PyRemoteSdkFlavor extends CPythonSdkFlavor {
private PyRemoteSdkFlavor() {
}
private final static String[] NAMES = new String[]{"python", "jython", "pypy", "python.exe", "jython.bat", "pypy.exe"};
public static PyRemoteSdkFlavor INSTANCE = new PyRemoteSdkFlavor();
@Override
public Collection<String> suggestHomePaths() {
return Lists.newArrayList();
}
@Override
public boolean isValidSdkHome(String path) {
return StringUtil.isNotEmpty(path) && path.startsWith("ssh:") && checkName(NAMES, getExecutableName(path));
}
private static boolean checkName(String[] names, @Nullable String name) {
if (name == null) {
return false;
}
for (String n : names) {
if (name.startsWith(n)) {
return true;
}
}
return false;
}
@Nullable
private static String getExecutableName(String path) {
return RemoteFile.detectSystemByPath(path).createRemoteFile(path).getName();
}
}
@@ -4,20 +4,20 @@ import com.google.common.collect.Maps;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.jetbrains.python.PythonHelpersLocator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.jetbrains.python.sdk.SkeletonVersionChecker.fromVersionString;
@@ -36,7 +36,11 @@ public class PySkeletonGenerator {
public void finishSkeletonsGeneration() {
}
static class ListBinariesResult {
public boolean exists(String name) {
return new File(name).exists();
}
protected static class ListBinariesResult {
public final int generatorVersion;
public final Map<String, PySkeletonRefresher.PyBinaryItem> modules;
@@ -18,7 +18,6 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.io.ZipUtil;
import com.jetbrains.python.PyBundle;
@@ -425,7 +424,8 @@ public class PySkeletonRefresher {
boolean canLive = headerMatcher != null && headerMatcher.matches();
if (canLive) {
String sourceName = headerMatcher.group(1);
canLive = sourceName != null && (SkeletonVersionChecker.BUILTIN_NAME.equals(sourceName) || new File(sourceName).exists());
canLive =
sourceName != null && (SkeletonVersionChecker.BUILTIN_NAME.equals(sourceName) || mySkeletonsGenerator.exists(sourceName));
}
if (!canLive) {
mySkeletonsGenerator.deleteOrLog(item);
@@ -566,7 +566,7 @@ public class PySkeletonRefresher {
return false;
}
static class PyBinaryItem {
public static class PyBinaryItem {
private String myPath;
private String myModule;
private long myLength;
@@ -647,6 +647,11 @@ public class PySkeletonRefresher {
if (versionString == null) {
return null;
}
if (PySdkUtil.isRemote(mySdk)) {
return null;
}
String version = versionString.toLowerCase().replace(" ", "-");
File f;
if (SystemInfo.isMac) {
@@ -49,7 +49,7 @@ public abstract class PythonSdkFlavor {
public static List<PythonSdkFlavor> getApplicableFlavors() {
List<PythonSdkFlavor> result = new ArrayList<PythonSdkFlavor>();
result.add(VirtualEnvSdkFlavor.INSTANCE);
if (SystemInfo.isWindows) {
result.add(WinPythonSdkFlavor.INSTANCE);
}
@@ -71,6 +71,9 @@ public abstract class PythonSdkFlavor {
result.add(JythonSdkFlavor.INSTANCE);
result.add(IronPythonSdkFlavor.INSTANCE);
result.add(PyPySdkFlavor.INSTANCE);
result.add(VirtualEnvSdkFlavor.INSTANCE);
result.add(PyRemoteSdkFlavor.INSTANCE);
return result;
}
@@ -0,0 +1,3 @@
from sys import hexversion
__all__ = ['hexversion']
@@ -0,0 +1,3 @@
from sys import hexversion
__all__ = ['hexve<caret>']
@@ -0,0 +1 @@
__author__ = 'yole'
@@ -0,0 +1 @@
from ...<caret> import
@@ -0,0 +1,2 @@
__all__ = [ name for name, obj in locals().items()
if not (name.startswith('_')) ]
@@ -0,0 +1,15 @@
class A(object):
__slots__ = ['a', 'b']
def __init__(self):
self.a = None # <- all ok here
self.b = None # <- all ok here
class C(A):
__slots__ = ['c', 'd']
def __init__(self, c):
super(C, self).__init__()
self.c = c
self.d = self.b
if self.c:
self.a = 10
@@ -0,0 +1,4 @@
from target import *
<warning descr="Unresolved reference 'xyzzy'">x<caret>yzzy</warning>
shazam()
@@ -0,0 +1,5 @@
from target import *
from target import xyzzy
x<caret>yzzy
shazam()
@@ -0,0 +1,4 @@
__all__ = ['shazam']
def shazam(): pass
def xyzzy(): pass
@@ -0,0 +1,6 @@
<warning descr="Unused import statement">from test2 import *</warning>
from test2 import f #pass
from test3 import * #pass
<warning descr="Unused import statement">from test4 import *</warning>
print(f, g)
@@ -0,0 +1,2 @@
def f(x):
return x
@@ -0,0 +1,2 @@
def g():
pass
@@ -0,0 +1,2 @@
def h():
pass
@@ -0,0 +1,3 @@
from c import f
print(f())
@@ -0,0 +1,2 @@
def f():
pass
@@ -0,0 +1,3 @@
from b import *
print(f())
@@ -0,0 +1,2 @@
def f():
pass
@@ -0,0 +1,2 @@
def f(g=lambda xx: xx):
pass # <ref>
@@ -0,0 +1,2 @@
from pack import mod
# <ref>
@@ -96,6 +96,14 @@ public class PyMultiFileResolveTest extends PyResolveTestCase {
assertTrue("is target?", elt instanceof PyTargetExpression);
}
public void testFromPackageImportIntoInit() { // PY-6305
myFixture.copyDirectoryToProject("fromPackageImportIntoInit/pack", "pack");
final PsiFile psiFile = myFixture.configureByFile("pack/__init__.py");
final PsiElement result = doResolve(psiFile);
assertInstanceOf(result, PyFile.class);
assertEquals("mod.py", ((PyFile) result).getName());
}
public void testResolveInPkg() {
ResolveResult[] results = doMultiResolve();
assertTrue(results.length == 2); // func and import stmt
@@ -36,6 +36,17 @@ public class PyQuickFixTest extends PyTestCase {
PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
}
public void testImportFromModuleStar() { // PY-6302
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.copyDirectoryToProject("importFromModuleStar", "");
myFixture.configureFromTempProjectFile("source.py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("ACT.NAME.use.import"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile("importFromModuleStar/source_after.py");
}
public void testQualifyByImport() {
final PyCodeInsightSettings settings = PyCodeInsightSettings.getInstance();
boolean oldPreferFrom = settings.PREFER_FROM_IMPORT;
@@ -462,4 +462,9 @@ public class PyResolveTest extends PyResolveTestCase {
public void testLambdaParameterInDecorator() {
assertResolvesTo(PyNamedParameter.class, "xx");
}
// PY-6435
public void testLambdaParameterInDefaultValue() {
assertResolvesTo(PyNamedParameter.class, "xx");
}
}
@@ -2,10 +2,15 @@ package com.jetbrains.python;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubUpdatingIndex;
@@ -16,6 +21,7 @@ import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyFileImpl;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PyVariableNameIndex;
import com.jetbrains.python.toolbox.Maybe;
@@ -365,4 +371,32 @@ public class PyStubsTest extends PyTestCase {
PsiFile psiFile = myFixture.getPsiManager().findFile(sourceFile);
return (PyFile)psiFile;
}
public void testStubIndexMismatch() {
VirtualFile vFile = myFixture.getTempDirFixture().createFile("foo.py");
final Project project = myFixture.getProject();
PsiFileImpl fooPyFile = (PsiFileImpl) PsiManager.getInstance(project).findFile(vFile);
final Document fooDocument = fooPyFile.getViewProvider().getDocument();
Collection<PyClass> classes = PyClassNameIndex.find("Foo", project, GlobalSearchScope.allScope(project));
assertEquals(classes.size(), 0);
new WriteCommandAction.Simple(project, fooPyFile) {
public void run() {
fooDocument.setText("class Foo: pass");
}
}.execute();
PsiDocumentManager.getInstance(project).commitDocument(fooDocument);
fooPyFile.setTreeElementPointer(null);
//classes = PyClassNameIndex.find("Foo", project, GlobalSearchScope.allScope(project));
//fooPyFile.unloadContent();
DumbServiceImpl.getInstance(project).setDumb(true);
try {
assertEquals(1, ((PyFile) fooPyFile).getTopLevelClasses().size());
}
finally {
DumbServiceImpl.getInstance(project).setDumb(false);
}
classes = PyClassNameIndex.find("Foo", project, GlobalSearchScope.allScope(project));
assertEquals(classes.size(), 1);
}
}
@@ -529,6 +529,10 @@ public class PythonCompletionTest extends PyTestCase {
doTest();
}
public void testDunderAllReferenceImport() { // PY-6306
doTest();
}
public void testOldStyleClassAttributes() {
doTest();
}
@@ -546,4 +550,17 @@ public class PythonCompletionTest extends PyTestCase {
public void testQualifiedAssignment() { // PY-6121
doTest();
}
public void testRelativeImportExcludeToplevel() { // PY-6304
setLanguageLevel(LanguageLevel.PYTHON27);
try {
myFixture.copyDirectoryToProject("completion/relativeImportExcludeToplevel", "");
myFixture.configureByFile("pack/subpack/modX.py");
myFixture.completeBasic();
assertFalse(myFixture.getLookupElementStrings().contains("sys"));
}
finally {
setLanguageLevel(null);
}
}
}
@@ -32,6 +32,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
public void testSlotsSubclass() { // PY-5939
doTest();
}
public void testImportExceptImportError() {
doTest();
}
@@ -102,6 +106,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
public void testCompoundDunderAll() { // PY-6370
doTest();
}
private void doMultiFileTest() {
myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/__init__.py", "PyUnresolvedReferencesInspection/__init__.py");
myFixture.copyFileToProject("inspections/PyUnresolvedReferencesInspection/" + getTestName(true) + ".py",
@@ -1,34 +1,40 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class PyUnusedImportTest extends PyTestCase {
public void testModuleAndSubmodule() { // PY-3626
myFixture.copyDirectoryToProject("inspections/unusedImport/moduleAndSubmodule", "");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.testHighlighting(true, false, false, "py3626.py");
// PY-3626
public void testModuleAndSubmodule() {
doTest("py3626.py");
}
public void testSubpackageInInitPy() { // PY-3201
myFixture.copyDirectoryToProject("inspections/unusedImport/subpackageInInitPy", "");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.testHighlighting(true, false, false, "package1/__init__.py");
// PY-3201
public void testSubpackageInInitPy() {
doTest("package1/__init__.py");
}
// PY-5589
public void testUnusedPackageAndSubmodule() {
myFixture.copyDirectoryToProject("inspections/unusedImport/unusedPackageAndSubmodule", "");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.testHighlighting(true, false, false, "test1.py");
doTest("test1.py");
}
// PY-5621
public void testUnusedSubmodule() {
myFixture.copyDirectoryToProject("inspections/unusedImport/unusedSubmodule", "");
doTest("test1.py");
}
// PY-6380
public void testUnusedAfterStarImport() {
doTest("test1.py");
}
private void doTest(@NotNull String filename) {
myFixture.copyDirectoryToProject("inspections/unusedImport/" + getTestName(true), "");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.testHighlighting(true, false, false, "test1.py");
myFixture.testHighlighting(true, false, false, filename);
}
}
@@ -90,6 +90,11 @@ public class PyMoveTest extends PyTestCase {
doMoveFileTest("p1/p2/m1.py", "nonp3");
}
// PY-6432
public void testStarImportUsage() {
doMoveSymbolTest("f", "c.py");
}
private void doMoveFileTest(String fileName, String toDirName) {
Project project = myFixture.getProject();
PsiManager manager = PsiManager.getInstance(project);