PY-53979: Activate Conda with PowerShell in terminal.
authorIlya.Kazakevich <ilya.kazakevich@jetbrains.com>
Fri, 27 May 2022 01:03:02 +0000 (04:03 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Fri, 27 May 2022 02:45:24 +0000 (02:45 +0000)
Since we don't store conda path in SDK, we only can ask user to run `conda init powershell` to patch her profile and add ``conda.exe`` to ``PATH``.

After that, we can run ``conda activate``.

GitOrigin-RevId: c6cdac9252f022d7bcd1e020c8aaeffaa89b3fbf

python/python-terminal/resources/messages/PyTerminalBundle.properties
python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt

index 67c26961381bc32e0d195f79311796626ba49083..7f06a6d13336db897fa2617cdaaa3f9698a4ba95 100644 (file)
@@ -1 +1,2 @@
-activate.virtualenv.checkbox.text=Activate virtualenv
\ No newline at end of file
+activate.virtualenv.checkbox.text=Activate virtualenv
+powershell.conda.not.activated=Failed to activate conda environment. Please open Anaconda prompt, and run `conda init powershell` there.
\ No newline at end of file
index 33efc40e43dc8084235cbba2eea33155a07ce0fd..dd4ca8f0e94cec7f813f12c689bf04b170d0c25c 100644 (file)
@@ -9,18 +9,33 @@ import com.intellij.openapi.options.UnnamedConfigurable
 import com.intellij.openapi.project.Project
 import com.intellij.openapi.projectRoots.Sdk
 import com.intellij.openapi.util.SystemInfo
-import com.intellij.util.io.exists
+import com.intellij.openapi.vfs.VirtualFile
 import com.jetbrains.python.run.findActivateScript
+import com.jetbrains.python.sdk.flavors.CondaEnvSdkFlavor
 import org.jetbrains.plugins.terminal.LocalTerminalCustomizer
 import org.jetbrains.plugins.terminal.TerminalOptionsProvider
 import java.io.File
-import java.nio.file.Path
 import javax.swing.JCheckBox
 import kotlin.io.path.Path
 import kotlin.io.path.name
-import kotlin.io.path.pathString
 
 class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() {
+  private fun generateCommandForPowerShell(sdk: Sdk, sdkHomePath: VirtualFile): Array<out String>? {
+    if ((sdk.sdkAdditionalData as? PythonSdkAdditionalData)?.flavor is CondaEnvSdkFlavor) {
+      // Activate conda
+
+      // ' are in "Write-Host"
+      val errorMessage = PyTerminalBundle.message("powershell.conda.not.activated").replace('\'', '"')
+      // No need to escape path: conda can't have spaces
+      val condaActivateCommand = "try { conda activate ${sdkHomePath.parent.path} } catch { Write-Host('$errorMessage') }"
+      return arrayOf("powershell.exe", "-NoExit", "-Command", condaActivateCommand)
+    }
+
+    // Activate convenient virtualenv
+    val virtualEnvProfile = sdkHomePath.parent.findChild("activate.ps1") ?: return null
+    return if (virtualEnvProfile.exists()) arrayOf("powershell.exe", "-NoExit", "-File", virtualEnvProfile.path) else null
+  }
+
   override fun customizeCommandAndEnvironment(project: Project,
                                               command: Array<out String>,
                                               envs: MutableMap<String, String>): Array<out String> {
@@ -30,23 +45,22 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() {
         (PythonSdkUtil.isVirtualEnv(sdk) || PythonSdkUtil.isConda(sdk)) &&
         PyVirtualEnvTerminalSettings.getInstance(project).virtualEnvActivate) {
       // in case of virtualenv sdk on unix we activate virtualenv
-      val path = sdk.homePath
+      val sdkHomePath = sdk.homeDirectory
 
-      if (path != null && command.isNotEmpty()) {
+      if (sdkHomePath != null && command.isNotEmpty()) {
         val shellPath = command[0]
 
         if (Path(shellPath).name == "powershell.exe") {
-          val powerShellActivator = Path.of(path).parent?.resolve("activate.ps1") ?: return command
-          return if (powerShellActivator.exists()) arrayOf("powershell.exe", "-NoExit", "-File", powerShellActivator.pathString) else command
+          return generateCommandForPowerShell(sdk, sdkHomePath) ?: command
         }
 
         if (isShellIntegrationAvailable(shellPath)) { //fish shell works only for virtualenv and not for conda
           //for bash we pass activate script to jediterm shell integration (see jediterm-bash.in) to source it there
           //TODO: fix conda for fish
 
-          findActivateScript(path, shellPath)?.let { activate ->
-            envs.put("JEDITERM_SOURCE",  activate.first)
-            envs.put("JEDITERM_SOURCE_ARGS", activate.second?:"")
+          findActivateScript(sdkHomePath.path, shellPath)?.let { activate ->
+            envs.put("JEDITERM_SOURCE", activate.first)
+            envs.put("JEDITERM_SOURCE_ARGS", activate.second ?: "")
           }
         }
         else {