summaryrefslogtreecommitdiff
path: root/python/src/com/jetbrains/python/sdk/PySdkUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'python/src/com/jetbrains/python/sdk/PySdkUtil.java')
-rw-r--r--python/src/com/jetbrains/python/sdk/PySdkUtil.java153
1 files changed, 64 insertions, 89 deletions
diff --git a/python/src/com/jetbrains/python/sdk/PySdkUtil.java b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
index 8f2b62b1b414..97d5ee545cbb 100644
--- a/python/src/com/jetbrains/python/sdk/PySdkUtil.java
+++ b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
@@ -15,10 +15,13 @@
*/
package com.jetbrains.python.sdk;
+import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
+import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.SystemInfo;
@@ -29,8 +32,10 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.remote.RemoteSdkAdditionalData;
-import com.intellij.util.ArrayUtil;
+import com.intellij.util.SystemProperties;
import com.intellij.util.containers.HashMap;
+import com.jetbrains.python.packaging.PyPackageUtil;
+import com.jetbrains.python.packaging.PyRequirement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,8 +43,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -56,6 +60,7 @@ public class PySdkUtil {
// Windows EOF marker, Ctrl+Z
public static final int SUBSTITUTE = 26;
+ public static final String PATH_ENV_VARIABLE = "PATH";
private PySdkUtil() {
// explicitly none
@@ -87,57 +92,29 @@ public class PySdkUtil {
return getProcessOutput(homePath, command, null, timeout);
}
- /**
- * Executes a process and returns its stdout and stderr outputs as lists of lines.
- * Waits for process for possibly limited duration.
- *
- * @param homePath process run directory
- * @param command command to execute and its arguments
- * @param addEnv items are prepended to same-named values of inherited process environment.
- * @param timeout how many milliseconds to wait until the process terminates; non-positive means inifinity.
- * @return a tuple of (stdout lines, stderr lines, exit_code), lines in them have line terminators stripped, or may be null.
- */
@NotNull
public static ProcessOutput getProcessOutput(String homePath,
@NonNls String[] command,
- @Nullable @NonNls String[] addEnv,
+ @Nullable @NonNls Map<String, String> extraEnv,
final int timeout) {
- return getProcessOutput(homePath, command, addEnv, timeout, null, true);
+ return getProcessOutput(homePath, command, extraEnv, timeout, null, true);
}
- /**
- * Executes a process and returns its stdout and stderr outputs as lists of lines.
- * Waits for process for possibly limited duration.
- *
- * @param homePath process run directory
- * @param command command to execute and its arguments
- * @param addEnv items are prepended to same-named values of inherited process environment.
- * @param timeout how many milliseconds to wait until the process terminates; non-positive means infinity.
- * @param stdin the data to write to the process standard input stream
- * @param needEOFMarker
- * @return a tuple of (stdout lines, stderr lines, exit_code), lines in them have line terminators stripped, or may be null.
- */
@NotNull
public static ProcessOutput getProcessOutput(String homePath,
@NonNls String[] command,
- @Nullable @NonNls String[] addEnv,
+ @Nullable @NonNls Map<String, String> extraEnv,
final int timeout,
@Nullable byte[] stdin,
boolean needEOFMarker) {
- final ProcessOutput failureOutput = new ProcessOutput();
if (homePath == null || !new File(homePath).exists()) {
- return failureOutput;
+ return new ProcessOutput();
}
+ final Map<String, String> systemEnv = System.getenv();
+ final Map<String, String> env = extraEnv != null ? mergeEnvVariables(systemEnv, extraEnv) : systemEnv;
try {
- List<String> commands = new ArrayList<String>();
- if (SystemInfo.isWindows && StringUtil.endsWithIgnoreCase(command[0], ".bat")) {
- commands.add("cmd");
- commands.add("/c");
- }
- Collections.addAll(commands, command);
- String[] newEnv = buildAdditionalEnv(addEnv);
- Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(commands), newEnv, new File(homePath));
- CapturingProcessHandler processHandler = new CapturingProcessHandler(process);
+ final Process process = ExecUtil.exec(Arrays.asList(command), homePath, env);
+ final CapturingProcessHandler processHandler = new CapturingProcessHandler(process);
if (stdin != null) {
final OutputStream processInput = processHandler.getProcessInput();
assert processInput != null;
@@ -152,72 +129,61 @@ public class PySdkUtil {
}
return processHandler.runProcess(timeout);
}
- catch (final IOException ex) {
- LOG.warn(ex);
- return new ProcessOutput() {
- @Override
- public String getStderr() {
- String err = super.getStderr();
- if (!StringUtil.isEmpty(err)) {
- err += "\n" + ex.getMessage();
- }
- else {
- err = ex.getMessage();
- }
- return err;
- }
- };
+ catch (ExecutionException e) {
+ return getOutputForException(e);
+ }
+ catch (IOException e) {
+ return getOutputForException(e);
}
}
- private static String[] buildAdditionalEnv(String[] addEnv) {
- String[] newEnv = null;
- if (addEnv != null) {
- Map<String, String> envMap = buildEnvMap(addEnv);
- newEnv = new String[envMap.size()];
- int i = 0;
- for (Map.Entry<String, String> entry : envMap.entrySet()) {
- newEnv[i] = entry.getKey() + "=" + entry.getValue();
- i += 1;
+ private static ProcessOutput getOutputForException(final Exception e) {
+ LOG.warn(e);
+ return new ProcessOutput() {
+ @Override
+ public String getStderr() {
+ String err = super.getStderr();
+ if (!StringUtil.isEmpty(err)) {
+ err += "\n" + e.getMessage();
+ }
+ else {
+ err = e.getMessage();
+ }
+ return err;
}
- }
- return newEnv;
+ };
}
- public static Map<String, String> buildEnvMap(String[] addEnv) {
- Map<String, String> envMap = new HashMap<String, String>(System.getenv());
- // turn additional ent into map
- Map<String, String> addMap = new HashMap<String, String>();
- for (String envItem : addEnv) {
- int pos = envItem.indexOf('=');
- if (pos > 0) {
- String key = envItem.substring(0, pos);
- String value = envItem.substring(pos + 1, envItem.length());
- addMap.put(key, value);
- }
- else {
- LOG.warn(String.format("Invalid env value: '%s'", envItem));
- }
- }
- // fuse old and new
- for (Map.Entry<String, String> entry : addMap.entrySet()) {
- final String key = entry.getKey();
- final String value = entry.getValue();
- final String oldValue = envMap.get(key);
- if (oldValue != null) {
- envMap.put(key, value + oldValue);
+ @NotNull
+ public static Map<String, String> mergeEnvVariables(@NotNull Map<String, String> environment,
+ @NotNull Map<String, String> extraEnvironment) {
+ final Map<String, String> result = new HashMap<String, String>(environment);
+ for (Map.Entry<String, String> entry : extraEnvironment.entrySet()) {
+ if (PATH_ENV_VARIABLE.equals(entry.getKey()) && result.containsKey(PATH_ENV_VARIABLE)) {
+ result.put(PATH_ENV_VARIABLE, result.get(PATH_ENV_VARIABLE) + File.pathSeparator + entry.getValue());
}
else {
- envMap.put(key, value);
+ result.put(entry.getKey(), entry.getValue());
}
}
- return envMap;
+ return result;
}
public static boolean isRemote(@Nullable Sdk sdk) {
return sdk != null && sdk.getSdkAdditionalData() instanceof RemoteSdkAdditionalData;
}
+ public static String getUserSite() {
+ if (SystemInfo.isWindows) {
+ final String appdata = System.getenv("APPDATA");
+ return appdata + File.separator + "Python";
+ }
+ else {
+ final String userHome = SystemProperties.getUserHome();
+ return userHome + File.separator + ".local";
+ }
+ }
+
public static boolean isElementInSkeletons(@NotNull final PsiElement element) {
final PsiFile file = element.getContainingFile();
if (file != null) {
@@ -266,4 +232,13 @@ public class PySdkUtil {
}
return null;
}
+
+ @Nullable
+ public static List<PyRequirement> getRequirementsFromTxt(Module module) {
+ final VirtualFile requirementsTxt = PyPackageUtil.findRequirementsTxt(module);
+ if (requirementsTxt != null) {
+ return PyRequirement.parse(requirementsTxt);
+ }
+ return null;
+ }
}