mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-26492 Warning about Pipenv interpreter not associated with the current project
This commit is contained in:
@@ -29,7 +29,9 @@ import com.intellij.util.PlatformUtils;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.sdk.PySdkExtKt;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.sdk.flavors.PipenvKt;
|
||||
import com.jetbrains.python.sdk.flavors.UsePipEnvQuickFix;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -66,34 +68,43 @@ public class PyInterpreterInspection extends PyInspection {
|
||||
public void visitPyFile(PyFile node) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(node);
|
||||
if (module == null) return;
|
||||
final Sdk sdk = PythonSdkType.findPythonSdk(module);
|
||||
|
||||
final boolean pyCharm = PlatformUtils.isPyCharm();
|
||||
|
||||
final String interpreterOwner = pyCharm ? "project" : "module";
|
||||
final List<LocalQuickFix> fixes = new ArrayList<>();
|
||||
if (UsePipEnvQuickFix.Companion.isApplicable(module)) {
|
||||
fixes.add(new UsePipEnvQuickFix(sdk, module));
|
||||
}
|
||||
if (pyCharm) {
|
||||
if (UsePipEnvQuickFix.Companion.isApplicable(module)) {
|
||||
fixes.add(new UsePipEnvQuickFix());
|
||||
}
|
||||
fixes.add(new ConfigureInterpreterFix());
|
||||
}
|
||||
|
||||
final String product = pyCharm ? "PyCharm" : "Python plugin";
|
||||
|
||||
final Sdk sdk = PythonSdkType.findPythonSdk(module);
|
||||
|
||||
if (sdk == null) {
|
||||
registerProblem(node, "No Python interpreter configured for the " + interpreterOwner, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
else if (PythonSdkType.isInvalid(sdk)) {
|
||||
registerProblem(node, "Invalid Python interpreter selected for the " + interpreterOwner, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
else {
|
||||
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
|
||||
if (!LanguageLevel.SUPPORTED_LEVELS.contains(languageLevel)) {
|
||||
registerProblem(node,
|
||||
"Python " + languageLevel + " has reached its end-of-life and is no longer supported by " + product,
|
||||
fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
final Module associatedModule = PySdkExtKt.getAssociatedModule(sdk);
|
||||
final String associatedName = associatedModule != null ? associatedModule.getName() : PySdkExtKt.getAssociatedModulePath(sdk);
|
||||
if (PipenvKt.isPipEnv(sdk) && associatedModule != module) {
|
||||
final String message = associatedName != null ?
|
||||
"Pipenv interpreter is associated with another " + interpreterOwner + ": '" + associatedName + "'" :
|
||||
"Pipenv interpreter is not associated with any " + interpreterOwner;
|
||||
registerProblem(node, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
else if (PythonSdkType.isInvalid(sdk)) {
|
||||
registerProblem(node, "Invalid Python interpreter selected for the " + interpreterOwner, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
else {
|
||||
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
|
||||
if (!LanguageLevel.SUPPORTED_LEVELS.contains(languageLevel)) {
|
||||
registerProblem(node,
|
||||
"Python " + languageLevel + " has reached its end-of-life and is no longer supported by " + product,
|
||||
fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ package com.jetbrains.python.sdk
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.progress.Task
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.project.rootManager
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
|
||||
@@ -46,6 +48,7 @@ import java.nio.file.Paths
|
||||
*/
|
||||
|
||||
fun findBaseSdks(existingSdks: List<Sdk>): List<Sdk> {
|
||||
// TODO: Filter out non-Python SDKs
|
||||
val existing = existingSdks.filter { it.isSystemWide }
|
||||
val detected = detectSystemWideSdks(existingSdks)
|
||||
return existing + detected
|
||||
@@ -117,6 +120,15 @@ val Sdk.associatedModulePath: String?
|
||||
// TODO: Support .project associations
|
||||
get() = associatedPathFromAdditionalData /*?: associatedPathFromDotProject*/
|
||||
|
||||
val Sdk.associatedModule: Module?
|
||||
get() {
|
||||
val associatedPath = associatedModulePath
|
||||
return ProjectManager.getInstance().openProjects
|
||||
.asSequence()
|
||||
.flatMap { ModuleManager.getInstance(it).modules.asSequence() }
|
||||
.firstOrNull { it?.basePath == associatedPath }
|
||||
}
|
||||
|
||||
fun Sdk.adminPermissionsNeeded(): Boolean {
|
||||
val homePath = homePath ?: return false
|
||||
return !Files.isWritable(Paths.get(homePath))
|
||||
|
||||
@@ -133,12 +133,13 @@ public class PythonSdkAdditionalData implements SdkAdditionalData {
|
||||
|
||||
if (myAssociatedModulePath != null) {
|
||||
rootElement.setAttribute(ASSOCIATED_PROJECT_PATH, myAssociatedModulePath);
|
||||
// XXX: We have to persist the pipenv flag since pipenv is no different from a regular
|
||||
// virtualenv and currently we want to handle pipenvs differently. Consider adding an SDK
|
||||
// extension mechanism for that
|
||||
if (myIsPipEnv) {
|
||||
rootElement.setAttribute(IS_PIPENV, "true");
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: We have to persist the pipenv flag since pipenv is no different from a regular
|
||||
// virtualenv and currently we want to handle pipenvs differently. Consider adding an SDK
|
||||
// extension mechanism for that
|
||||
if (myIsPipEnv) {
|
||||
rootElement.setAttribute(IS_PIPENV, "true");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import com.jetbrains.python.run.PyVirtualEnvReader;
|
||||
import com.jetbrains.python.sdk.flavors.CPythonSdkFlavor;
|
||||
import com.jetbrains.python.sdk.flavors.PipenvKt;
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
|
||||
import icons.PythonIcons;
|
||||
import org.jdom.Element;
|
||||
@@ -220,6 +221,9 @@ public final class PythonSdkType extends SdkType {
|
||||
return false;
|
||||
}
|
||||
final VirtualFile interpreter = sdk.getHomeDirectory();
|
||||
if (PipenvKt.isPipEnv(sdk) && PySdkExtKt.getAssociatedModule(sdk) == null) {
|
||||
return true;
|
||||
}
|
||||
return interpreter == null || !interpreter.exists();
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,12 @@ private val Sdk.packageManager: PyPackageManager
|
||||
/**
|
||||
* A quick-fix for setting up the pipenv for the module of the current PSI element.
|
||||
*/
|
||||
class UsePipEnvQuickFix : LocalQuickFix {
|
||||
class UsePipEnvQuickFix(sdk: Sdk?, module: Module) : LocalQuickFix {
|
||||
private val quickFixName = when {
|
||||
sdk != null && sdk.associatedModule != module -> "Fix Pipenv interpreter"
|
||||
else -> "Use Pipenv interpreter"
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun isApplicable(module: Module): Boolean = module.pipFile != null
|
||||
|
||||
@@ -234,12 +239,15 @@ class UsePipEnvQuickFix : LocalQuickFix {
|
||||
if (sdk == newSdk) {
|
||||
SdkConfigurationUtil.addSdk(newSdk)
|
||||
}
|
||||
else {
|
||||
sdk.associateWithModule(module, false)
|
||||
}
|
||||
project.pythonSdk = sdk
|
||||
module.pythonSdk = sdk
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFamilyName() = "Use Pipenv interpreter"
|
||||
override fun getFamilyName() = quickFixName
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val element = descriptor.psiElement ?: return
|
||||
@@ -259,6 +267,7 @@ class PipEnvInstallQuickFix : LocalQuickFix {
|
||||
companion object {
|
||||
fun pipEnvInstall(project: Project, module: Module) {
|
||||
val sdk = module.pythonSdk ?: return
|
||||
if (!sdk.isPipEnv) return
|
||||
val listener = PyPackageRequirementsInspection.RunningPackagingTasksListener(module)
|
||||
val ui = PyPackageManagerUI(project, sdk, listener)
|
||||
ui.install(null, listOf("--dev"))
|
||||
|
||||
Reference in New Issue
Block a user