Fix conda env auto activation in the terminal (PY-21643)

This commit is contained in:
Dmitry Trofimov
2016-12-06 16:19:08 +01:00
parent b9e8b9386f
commit 81da26178f
3 changed files with 26 additions and 12 deletions
@@ -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")
})
}
}
@@ -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<String, String?>? = 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<String, String> {
private fun readVirtualEnvOnWindows(activate: Pair<String, String?>): MutableMap<String, String> {
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<String>(activateFile.path, ">", envFile.absolutePath)
val command = if (activate.second != null) listOf<String>(activateFile.path, activate.second!!, ">", envFile.absolutePath)
else listOf<String>(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<String, String?>? {
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
}
@@ -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);
}