mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
Support reading virtualenv variables on Windows
This enables on Windows having the correct env variables for Python processes started by PyCharm (PY-15085) and starts the terminal in a virtualenv aware mode (PY-10498)
This commit is contained in:
@@ -177,46 +177,52 @@ public class EnvironmentUtil {
|
||||
|
||||
LOG.info("loading shell env: " + StringUtil.join(command, " "));
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(command).redirectErrorStream(true);
|
||||
builder.environment().put(DISABLE_OMZ_AUTO_UPDATE, "true");
|
||||
Process process = builder.start();
|
||||
StreamGobbler gobbler = new StreamGobbler(process.getInputStream());
|
||||
int rv = waitAndTerminateAfter(process, SHELL_ENV_READING_TIMEOUT);
|
||||
gobbler.stop();
|
||||
|
||||
String lines = FileUtil.loadFile(envFile);
|
||||
if (rv != 0 || lines.isEmpty()) {
|
||||
throw new Exception("rv:" + rv + " text:" + lines.length() + " out:" + StringUtil.trimEnd(gobbler.getText(), '\n'));
|
||||
}
|
||||
return parseEnv(lines);
|
||||
return runProcessAndReadEnvs(command, envFile, "\0");
|
||||
}
|
||||
finally {
|
||||
FileUtil.delete(envFile);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static Map<String, String> runProcessAndReadEnvs(@NotNull List<String> command, @NotNull File envFile, String lineSeparator) throws Exception {
|
||||
ProcessBuilder builder = new ProcessBuilder(command).redirectErrorStream(true);
|
||||
builder.environment().put(DISABLE_OMZ_AUTO_UPDATE, "true");
|
||||
Process process = builder.start();
|
||||
StreamGobbler gobbler = new StreamGobbler(process.getInputStream());
|
||||
int rv = waitAndTerminateAfter(process, SHELL_ENV_READING_TIMEOUT);
|
||||
gobbler.stop();
|
||||
|
||||
String lines = FileUtil.loadFile(envFile);
|
||||
if (rv != 0 || lines.isEmpty()) {
|
||||
throw new Exception("rv:" + rv + " text:" + lines.length() + " out:" + StringUtil.trimEnd(gobbler.getText(), '\n'));
|
||||
}
|
||||
return parseEnv(lines, lineSeparator);
|
||||
}
|
||||
|
||||
protected List<String> getShellProcessCommand() throws Exception {
|
||||
String shell = getShell();
|
||||
|
||||
if (shell == null || !new File(shell).canExecute()) {
|
||||
throw new Exception("shell:" + shell);
|
||||
}
|
||||
|
||||
return new ArrayList<String>(Arrays.asList(shell, "-l", "-i"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
protected String getShell() throws Exception {
|
||||
String shell = System.getenv("SHELL");
|
||||
if (shell == null || !new File(shell).canExecute()) {
|
||||
throw new Exception("shell:" + shell);
|
||||
}
|
||||
return shell;
|
||||
return System.getenv("SHELL");
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> parseEnv(String text) throws Exception {
|
||||
@NotNull
|
||||
private static Map<String, String> parseEnv(String text, String lineSeparator) throws Exception {
|
||||
Set<String> toIgnore = new HashSet<String>(Arrays.asList("_", "PWD", "SHLVL", DISABLE_OMZ_AUTO_UPDATE));
|
||||
Map<String, String> env = System.getenv();
|
||||
Map<String, String> newEnv = new HashMap<String, String>();
|
||||
|
||||
String[] lines = text.split("\0");
|
||||
String[] lines = text.split(lineSeparator);
|
||||
for (String line : lines) {
|
||||
int pos = line.indexOf('=');
|
||||
if (pos <= 0) {
|
||||
@@ -318,7 +324,7 @@ public class EnvironmentUtil {
|
||||
@TestOnly
|
||||
static Map<String, String> testParser(@NotNull String lines) {
|
||||
try {
|
||||
return parseEnv(lines);
|
||||
return parseEnv(lines, "\0");
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
@@ -36,7 +36,7 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() {
|
||||
envs: MutableMap<String, String>): Array<out String> {
|
||||
val sdk: Sdk? = findSdk(project)
|
||||
|
||||
if (sdk != null && PythonSdkType.isVirtualEnv(sdk) && SystemInfo.isUnix) {
|
||||
if (sdk != null && PythonSdkType.isVirtualEnv(sdk)) {
|
||||
// in case of virtualenv sdk on unix we activate virtualenv
|
||||
val path = sdk.homePath
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.jetbrains.python.run
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.util.EnvironmentUtil
|
||||
import java.io.File
|
||||
|
||||
@@ -26,17 +28,49 @@ import java.io.File
|
||||
class PyVirtualEnvReader(virtualEnvSdkPath: String) : EnvironmentUtil.ShellEnvReader() {
|
||||
val activate = findActivateScript(virtualEnvSdkPath, shell)
|
||||
|
||||
override fun getShellProcessCommand(): MutableList<String>? {
|
||||
override fun readShellEnv(): MutableMap<String, String> {
|
||||
if (SystemInfo.isUnix) {
|
||||
return super.readShellEnv()
|
||||
}
|
||||
else {
|
||||
return readVirtualEnvOnWindows();
|
||||
}
|
||||
}
|
||||
|
||||
return if (activate != null) mutableListOf(shell, "--rcfile", activate, "-i")
|
||||
private fun readVirtualEnvOnWindows(): 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.appendToFile(activateFile, "\n\nset")
|
||||
val command = listOf<String>(activateFile.path, ">", envFile.absolutePath)
|
||||
|
||||
return runProcessAndReadEnvs(command, envFile, "\r\n")
|
||||
}
|
||||
finally {
|
||||
FileUtil.delete(activateFile)
|
||||
FileUtil.delete(envFile)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getShellProcessCommand(): MutableList<String>? {
|
||||
val shellPath = shell
|
||||
|
||||
if (shellPath == null || !File(shellPath).canExecute()) {
|
||||
throw Exception("shell:" + shellPath)
|
||||
}
|
||||
|
||||
return if (activate != null) mutableListOf(shellPath, "--rcfile", activate, "-i")
|
||||
else super.getShellProcessCommand()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun findActivateScript(path: String?, shellPath: String): String? {
|
||||
val shellName = File(shellPath).name
|
||||
val activate = if (shellName == "fish" || shellName == "csh") File(File(path).parentFile, "activate." + shellName)
|
||||
fun findActivateScript(path: String?, shellPath: 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
|
||||
|
||||
Reference in New Issue
Block a user