diff --git a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt index f05678cddaaa..a4b0ed7d88a4 100644 --- a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt +++ b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt @@ -52,9 +52,11 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() { val shellName = File(shellPath).name if (shellName == "bash" || (SystemInfo.isMac && shellName == "sh") || (shellName == "zsh") || - ((shellName == "fish") && PythonSdkType.isVirtualEnv(sdk))) { //fish shell works only for virtualenv and not for conda + ((shellName == "fish") && PythonSdkType.isVirtualEnv(sdk))) { //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 - findActivateScript(path, shellPath)?.let { activate -> envs.put("JEDITERM_SOURCE", activate) } + findActivateScript(path, shellPath)?.let { activate -> + envs.put("JEDITERM_SOURCE", if (activate.second != null) "${activate.first} ${activate.second}" else activate.first) + } } else { //for other shells we read envs from activate script by the default shell and pass them to the process @@ -63,7 +65,8 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() { // we add only envs that are setup by the activate script, because adding other variables from the different shell // can break the actual shell envs.putAll(reader.readShellEnv().mapKeys { k -> k.key.toUpperCase() }.filterKeys { k -> - k in arrayOf("PATH", "PS1", "VIRTUAL_ENV", "PYTHONHOME", "PROMPT", "_OLD_VIRTUAL_PROMPT", "_OLD_VIRTUAL_PYTHONHOME", "_OLD_VIRTUAL_PATH") + k in arrayOf("PATH", "PS1", "VIRTUAL_ENV", "PYTHONHOME", "PROMPT", "_OLD_VIRTUAL_PROMPT", "_OLD_VIRTUAL_PYTHONHOME", + "_OLD_VIRTUAL_PATH") }) } } diff --git a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt index 9aa8a7ccf0d3..961577934eb0 100644 --- a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt +++ b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.io.FileUtil import com.intellij.util.EnvironmentUtil import com.intellij.util.LineSeparator +import com.jetbrains.python.sdk.PythonSdkType import java.io.File /** @@ -30,7 +31,8 @@ import java.io.File class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellEnvReader() { private val LOG = Logger.getInstance("#com.jetbrains.python.run.PyVirtualEnvReader") - val activate = findActivateScript(virtualEnvSdkPath, shell) + // in case of Conda we need to pass an argument to an activate script that tells which exactly environment to activate + val activate: Pair? = findActivateScript(virtualEnvSdkPath, shell) override fun getShell(): String? { if (File("/bin/bash").exists()) { @@ -60,13 +62,15 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE } } - private fun readVirtualEnvOnWindows(activate: String): MutableMap { + private fun readVirtualEnvOnWindows(activate: Pair): MutableMap { val activateFile = FileUtil.createTempFile("pycharm-virualenv-activate.", ".bat", false) val envFile = FileUtil.createTempFile("pycharm-virualenv-envs.", ".tmp", false) try { - FileUtil.copy(File(activate), activateFile); + FileUtil.copy(File(activate.first), activateFile); FileUtil.appendToFile(activateFile, "\n\nset") - val command = listOf(activateFile.path, ">", envFile.absolutePath) + + val command = if (activate.second != null) listOf(activateFile.path, activate.second!!, ">", envFile.absolutePath) + else listOf(activateFile.path, ">", envFile.absolutePath) return runProcessAndReadEnvs(command, envFile, LineSeparator.CRLF.separatorString) } @@ -84,18 +88,25 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE throw Exception("shell:" + shellPath) } - return if (activate != null) - mutableListOf(shellPath, "-c", ". '$activate'") + return if (activate != null) { + val activateArg = if (activate.second != null) "'${activate.first}' '${activate.second}'" else "'${activate.first}'" + mutableListOf(shellPath, "-c", ". $activateArg") + } else super.getShellProcessCommand() } } -fun findActivateScript(path: String?, shellPath: String?): String? { +fun findActivateScript(path: String?, shellPath: String?): Pair? { val shellName = if (shellPath != null) File(shellPath).name else null val activate = if (SystemInfo.isWindows) File(File(path).parentFile, "activate.bat") else if (shellName == "fish" || shellName == "csh") File(File(path).parentFile, "activate." + shellName) else File(File(path).parentFile, "activate") - return if (activate.exists()) activate.absolutePath else null + return if (activate.exists()) { + val sdk = PythonSdkType.findSdkByPath(path) + if (sdk != null && PythonSdkType.isCondaVirtualEnv(sdk)) Pair(activate.absolutePath, File(path).parentFile.parent) + else Pair(activate.absolutePath, null) + } + else null } \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 6e72a55782c8..ad437e20a644 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -312,7 +312,7 @@ public final class PythonSdkType extends SdkType { return path != null && getVirtualEnvRoot(path) != null; } - public static boolean isCondaVirtualEnv(Sdk sdk) { + public static boolean isCondaVirtualEnv(@NotNull Sdk sdk) { final String path = sdk.getHomePath(); return path != null && PyCondaPackageManagerImpl.isCondaVEnv(sdk); }