diff --git a/python/src/com/jetbrains/python/inspections/requirement/PyRequirementVisitor.kt b/python/src/com/jetbrains/python/inspections/requirement/PyRequirementVisitor.kt index 5cf2f279d158..c11261b78ae5 100644 --- a/python/src/com/jetbrains/python/inspections/requirement/PyRequirementVisitor.kt +++ b/python/src/com/jetbrains/python/inspections/requirement/PyRequirementVisitor.kt @@ -21,6 +21,7 @@ import com.jetbrains.python.psi.PyImportStatement import com.jetbrains.python.psi.PyQualifiedExpression import com.jetbrains.python.psi.impl.PyPsiUtils import com.jetbrains.python.psi.types.TypeEvalContext +import com.jetbrains.python.sdk.isReadOnly import com.jetbrains.python.sdk.legacy.PythonSdkUtil import com.jetbrains.python.sdk.pythonSdk import org.jetbrains.annotations.ApiStatus @@ -98,7 +99,10 @@ class PyRequirementVisitor( val message = PyPsiBundle.message(REQUIREMENT_NOT_SATISFIED, requirementsList, unsatisfied.size) val ignoreFix = IgnoreRequirementFix(unsatisfied.mapTo(mutableSetOf()) { it.presentableTextWithoutVersion }) - val quickFixes = listOf(SyncProjectQuickFix(), ignoreFix) + val quickFixes = buildList { + if (!sdk.isReadOnly) add(SyncProjectQuickFix()) + add(ignoreFix) + } registerProblem( file, diff --git a/python/src/com/jetbrains/python/packaging/pip/PipPackageManagerEngine.kt b/python/src/com/jetbrains/python/packaging/pip/PipPackageManagerEngine.kt index 491223643578..92b8595020ce 100644 --- a/python/src/com/jetbrains/python/packaging/pip/PipPackageManagerEngine.kt +++ b/python/src/com/jetbrains/python/packaging/pip/PipPackageManagerEngine.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.vfs.VirtualFile +import com.intellij.python.community.execService.Args import com.intellij.python.community.execService.ExecService import com.intellij.python.community.execService.python.HelperName import com.jetbrains.python.errorProcessing.PyResult @@ -58,7 +59,7 @@ class PipPackageManagerEngine( suspend fun syncRequirementsTxt(file: VirtualFile): PyResult { return runPackagingTool( operation = "install", - arguments = listOf("-r", file.path) + arguments = Args("-r").addLocalFile(file.toNioPath()) ).mapSuccess { } } @@ -81,15 +82,14 @@ class PipPackageManagerEngine( return PyResult.success(packages) } - suspend fun runPackagingTool(operation: String, arguments: List): PyResult = withContext(Dispatchers.IO) { - val parameters = mutableListOf(operation) + private suspend fun runPackagingTool(operation: String, arguments: Args): PyResult = withContext(Dispatchers.IO) { + val parameters = Args(operation) if (operation == "install") { PyProxyUtils.proxyString?.let { - parameters += "--proxy" - parameters += it + parameters.addArgs("--proxy", it) } } - parameters += arguments + parameters.add(arguments) thisLogger().debug("Running python packaging tool. Operation: $operation") ExecService().executeHelper( @@ -99,6 +99,9 @@ class PipPackageManagerEngine( ) } + private suspend fun runPackagingTool(operation: String, arguments: List): PyResult = + runPackagingTool(operation, Args(*arguments.toTypedArray())) + private fun partitionPackagesBySource(installRequest: PythonPackageInstallRequest): List> { when (installRequest) { diff --git a/python/src/com/jetbrains/python/packaging/pip/actions/PipPackageManagerAction.kt b/python/src/com/jetbrains/python/packaging/pip/actions/PipPackageManagerAction.kt index aefd4e40d4fe..9997b36dfffb 100644 --- a/python/src/com/jetbrains/python/packaging/pip/actions/PipPackageManagerAction.kt +++ b/python/src/com/jetbrains/python/packaging/pip/actions/PipPackageManagerAction.kt @@ -10,6 +10,7 @@ import com.jetbrains.python.packaging.management.getPythonPackageManager import com.jetbrains.python.packaging.pip.PipPythonPackageManager import com.jetbrains.python.packaging.requirementsTxt.PythonRequirementTxtSdkUtils import com.jetbrains.python.requirements.RequirementsFileType +import com.jetbrains.python.sdk.isReadOnly internal sealed class PipPackageManagerAction : PythonPackageManagerAction() { override fun isWatchedFile(virtualFile: VirtualFile?): Boolean { @@ -51,4 +52,14 @@ internal class PipUpdateEnvAction() : PipPackageManagerAction() { val currentFile = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return PyResult.success(Unit) return manager.syncRequirementsTxt(currentFile) } + + override fun update(e: AnActionEvent) { + super.update(e) + if (!e.presentation.isEnabledAndVisible) + return + val manager = e.getPythonPackageManager() ?: return + if (manager.sdk.isReadOnly) { + e.presentation.isEnabledAndVisible = false + } + } } \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/add/v2/conda/condaUtils.kt b/python/src/com/jetbrains/python/sdk/add/v2/conda/condaUtils.kt index baee771836d0..2dcd5ba88ddd 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/conda/condaUtils.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/conda/condaUtils.kt @@ -10,12 +10,16 @@ import com.jetbrains.python.PyBundle.message import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.isCondaVirtualEnv import com.jetbrains.python.onSuccess -import com.jetbrains.python.sdk.* +import com.jetbrains.python.sdk.ModuleOrProject +import com.jetbrains.python.sdk.PythonSdkType import com.jetbrains.python.sdk.add.v2.* -import com.jetbrains.python.sdk.conda.* +import com.jetbrains.python.sdk.conda.createCondaSdkAlongWithNewEnv +import com.jetbrains.python.sdk.conda.createCondaSdkFromExistingEnv import com.jetbrains.python.sdk.flavors.conda.NewCondaEnvRequest import com.jetbrains.python.sdk.flavors.conda.PyCondaCommand import com.jetbrains.python.sdk.flavors.conda.PyCondaEnv +import com.jetbrains.python.sdk.persist +import com.jetbrains.python.sdk.setAssociationToModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.takeWhile @@ -24,7 +28,7 @@ internal fun PythonAddInterpreterModel<*>.createCondaCommand(): PyResult = emptyList(), options: ExecOptions = ExecOptions(), procListener: PyProcessListener? = null, -): PyResult = - execGetStdout(sdk, Args().addHelper(helper).addArgs(helperArgs), options, procListener) +): PyResult = executeHelper(sdk, helper, Args(*helperArgs.toTypedArray()), options, procListener) + +/** + * Executes [helper] on [sdk] (copies it to the remote machine if needed) + */ +@ApiStatus.Internal +@CheckReturnValue +suspend fun ExecService.executeHelper( + sdk: Sdk, + helper: HelperName, + helperArgs: Args = Args(), + options: ExecOptions = ExecOptions(), + procListener: PyProcessListener? = null, +): PyResult = execGetStdout(sdk, Args().addHelper(helper).add(helperArgs), options, procListener) // See function it calls for more info