Fix conda auto-activation for bash (PY-23417)

This commit is contained in:
Dmitry Trofimov
2018-11-09 00:15:21 +01:00
parent 6f00c0e0ae
commit b9945804d0
8 changed files with 75 additions and 29 deletions
+2 -1
View File
@@ -80,8 +80,9 @@ fi
if [ -n "$JEDITERM_SOURCE" ]
then
source "$JEDITERM_SOURCE"
source "$JEDITERM_SOURCE" $JEDITERM_SOURCE_ARGS
unset JEDITERM_SOURCE
unset JEDITERM_SOURCE_ARGS
fi
function configureCommandHistory {
@@ -39,14 +39,17 @@ 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"))) { //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 ->
val pathEnv = EnvironmentUtil.getEnvironmentMap().get("PATH")
if (pathEnv != null) {
envs.put("PATH", pathEnv)
}
envs.put("JEDITERM_SOURCE", if (activate.second != null) "${activate.first} ${activate.second}" else activate.first)
envs.put("JEDITERM_SOURCE", activate.first)
envs.put("JEDITERM_SOURCE_ARGS", activate.second?:"")
}
}
else {
@@ -79,7 +79,7 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
private ProcessOutput getCondaOutput(@NotNull final String command, List<String> arguments) throws ExecutionException {
final Sdk sdk = getSdk();
final String condaExecutable = PyCondaPackageService.getCondaExecutable(sdk.getHomeDirectory());
final String condaExecutable = PyCondaPackageService.getCondaExecutable(sdk.getHomePath());
if (condaExecutable == null) throw new PyExecutionException("Cannot find conda", "Conda", Collections.emptyList(), new ProcessOutput());
final String path = getCondaDirectory();
@@ -10,6 +10,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
@@ -87,7 +88,7 @@ public class PyCondaPackageService implements PersistentStateComponent<PyCondaPa
}
}
}
return getCondaExecutable(pythonName);
return getCondaExecutableByName(pythonName);
}
@Nullable
@@ -95,12 +96,32 @@ public class PyCondaPackageService implements PersistentStateComponent<PyCondaPa
final String condaName = SystemInfo.isWindows ? "conda.exe" : "conda";
final File condaInPath = PathEnvironmentVariableUtil.findInPath(condaName);
if (condaInPath != null) return condaInPath.getPath();
return getCondaExecutable(condaName);
return getCondaExecutableByName(condaName);
}
@Nullable
public static String getCondaExecutable(VirtualFile sdkPath) {
final VirtualFile bin = sdkPath.getParent();
public static String getCondaExecutable(@Nullable String sdkPath) {
if (sdkPath == null) {
return null;
}
String condaPath = findCondaExecutableRelativeToEnv(sdkPath);
if (condaPath != null) return condaPath;
if (StringUtil.isNotEmpty(getInstance().PREFERRED_CONDA_PATH)) {
return getInstance().PREFERRED_CONDA_PATH;
}
return getSystemCondaExecutable();
}
private static String findCondaExecutableRelativeToEnv(@NotNull String sdkPath) {
VirtualFile sdkHomeDir = StandardFileSystems.local().findFileByPath(sdkPath);
if (sdkHomeDir == null) {
return null;
}
final VirtualFile bin = sdkHomeDir.getParent();
String condaName = "conda";
if (SystemInfo.isWindows) {
condaName = bin.findChild("envs") != null ? "conda.exe" : "conda.bat";
@@ -108,13 +129,12 @@ public class PyCondaPackageService implements PersistentStateComponent<PyCondaPa
final VirtualFile conda = bin.findChild(condaName);
if (conda != null) return conda.getPath();
final VirtualFile condaFolder = bin.getParent();
final String condaPath = findExecutable(condaName, condaFolder);
if (condaPath != null) return condaPath;
return getSystemCondaExecutable();
return findExecutable(condaName, condaFolder);
}
@Nullable
public static String getCondaExecutable(@NotNull final String condaName) {
public static String getCondaExecutableByName(@NotNull final String condaName) {
final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\', '/'));
if (userHome != null) {
for (String root : CondaEnvSdkFlavor.CONDA_DEFAULT_ROOTS) {
@@ -42,7 +42,7 @@ public class PyPackageManagersImpl extends PyPackageManagers {
}
else if (PyCondaPackageManagerImpl.isConda(sdk) &&
homeDirectory != null &&
PyCondaPackageService.getCondaExecutable(homeDirectory) != null) {
PyCondaPackageService.getCondaExecutable(sdk.getHomePath()) != null) {
manager = new PyCondaPackageManagerImpl(sdk);
}
else {
@@ -86,7 +86,7 @@ public class PyCondaManagementService extends PyPackageManagementService {
@Override
public void addRepository(String repositoryUrl) {
if (useConda()) {
final String conda = PyCondaPackageService.getCondaExecutable(mySdk.getHomeDirectory());
final String conda = PyCondaPackageService.getCondaExecutable(mySdk.getHomePath());
final ArrayList<String> parameters = Lists.newArrayList(conda, "config", "--add", "channels", repositoryUrl, "--force");
final GeneralCommandLine commandLine = new GeneralCommandLine(parameters);
@@ -113,7 +113,7 @@ public class PyCondaManagementService extends PyPackageManagementService {
@Override
public void removeRepository(String repositoryUrl) {
if (useConda()) {
final String conda = PyCondaPackageService.getCondaExecutable(mySdk.getHomeDirectory());
final String conda = PyCondaPackageService.getCondaExecutable(mySdk.getHomePath());
final ArrayList<String> parameters = Lists.newArrayList(conda, "config", "--remove", "channels", repositoryUrl, "--force");
final GeneralCommandLine commandLine = new GeneralCommandLine(parameters);
@@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.SystemInfo
import com.intellij.util.EnvironmentUtil
import com.intellij.util.containers.ContainerUtil
import com.jetbrains.python.packaging.PyCondaPackageService
import com.jetbrains.python.sdk.PythonSdkType
import java.io.File
@@ -18,7 +19,7 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE
companion object {
val virtualEnvVars: List<String> = listOf("PATH", "PS1", "VIRTUAL_ENV", "PYTHONHOME", "PROMPT", "_OLD_VIRTUAL_PROMPT", "_OLD_VIRTUAL_PYTHONHOME",
"_OLD_VIRTUAL_PATH")
"_OLD_VIRTUAL_PATH", "CONDA_SHLVL", "CONDA_PROMPT_MODIFIER", "CONDA_PREFIX", "CONDA_DEFAULT_ENV")
}
// in case of Conda we need to pass an argument to an activate script that tells which exactly environment to activate
@@ -74,18 +75,33 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE
}
fun findActivateScript(path: String?, shellPath: String?): Pair<String, String?>? {
val shellName = if (shellPath != null) File(shellPath).name else null
val activate = if (SystemInfo.isWindows) findActivateOnWindows(path)
else if (shellName == "fish" || shellName == "csh") File(File(path).parentFile, "activate." + shellName)
else File(File(path).parentFile, "activate")
fun findActivateScript(sdkPath: String?, shellPath: String?): Pair<String, String?>? {
if (PythonSdkType.isVirtualEnv(sdkPath)) {
val shellName = if (shellPath != null) File(shellPath).name else null
val activate = findActivateInPath(sdkPath!!, shellName)
return if (activate != null && activate.exists()) {
val sdk = PythonSdkType.findSdkByPath(path)
if (sdk != null && PythonSdkType.isCondaVirtualEnv(sdk)) Pair(activate.absolutePath, condaEnvFolder(path))
else Pair(activate.absolutePath, null)
return if (activate != null && activate.exists()) {
Pair(activate.absolutePath, null)
} else null
} else if (PythonSdkType.isCondaEnv(sdkPath)) {
val condaExecutable = PyCondaPackageService.getCondaExecutable(sdkPath!!)
if (condaExecutable != null) {
val activate = findActivateInPath(File(condaExecutable).path, null)
if (activate != null && activate.exists()) {
return Pair(activate.path, condaEnvFolder(sdkPath))
}
}
}
else null
return null
}
private fun findActivateInPath(path: String, shellName: String?): File? {
return if (SystemInfo.isWindows) findActivateOnWindows(path)
else if (shellName == "fish" || shellName == "csh") File(File(path).parentFile, "activate.$shellName")
else File(File(path).parentFile, "activate")
}
private fun condaEnvFolder(path: String?) = if (SystemInfo.isWindows) File(path).parent else File(path).parentFile.parent
@@ -68,6 +68,7 @@ import com.jetbrains.python.sdk.pipenv.PyPipEnvSdkAdditionalData;
import icons.PythonIcons;
import one.util.streamex.StreamEx;
import org.jdom.Element;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -258,7 +259,8 @@ public final class PythonSdkType extends SdkType {
return isVirtualEnv(path);
}
public static boolean isVirtualEnv(String path) {
@Contract("null -> false")
public static boolean isVirtualEnv(@Nullable String path) {
return path != null && getVirtualEnvRoot(path) != null;
}
@@ -268,8 +270,12 @@ public final class PythonSdkType extends SdkType {
}
public static boolean isCondaVirtualEnv(@NotNull Sdk sdk) {
final String path = sdk.getHomePath();
return path != null && PyCondaPackageManagerImpl.isCondaVEnv(sdk);
return isCondaEnv(sdk.getHomePath());
}
@Contract("null -> false")
public static boolean isCondaEnv(@Nullable String sdkPath) {
return sdkPath != null && PyCondaPackageManagerImpl.isCondaEnv(sdkPath);
}
@Nullable