Skip to content

Commit

Permalink
Move some things related to conda selection to core projects.
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Sep 16, 2024
1 parent ba8f240 commit 8ff9916
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 122 deletions.
1 change: 1 addition & 0 deletions plugins/org.python.pydev.ast/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Export-Package: org.python.pydev.ast,
org.python.pydev.ast.item_pointer,
org.python.pydev.ast.listing_utils,
org.python.pydev.ast.location,
org.python.pydev.ast.package_managers,
org.python.pydev.ast.refactoring,
org.python.pydev.ast.runners,
org.python.pydev.ast.simpleassist,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package org.python.pydev.ast.interpreter_managers;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.python.pydev.ast.package_managers.CondaCore;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.IInterpreterInfo.UnableToFindExecutableException;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.preferences.PydevPrefs;
import org.python.pydev.plugin.nature.PythonNature;
import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.structure.OrderedSet;
import org.python.pydev.shared_core.utils.PlatformUtils;

public final class PyDevCondaPreferences {

private static final String CONDA_PATH = "CONDA_PATH";
private static final String DEFAULT_CONDA_PATH = "";
public static final String CONDA_PATH = "CONDA_PATH";
public static final String DEFAULT_CONDA_PATH = "";

/**
* @return the conda executable or null if it couldn't be found.
Expand Down Expand Up @@ -49,41 +45,7 @@ public static File findCondaExecutable(IInterpreterInfo interpreterInfo) throws
try {
condaExecutable = interpreterInfo.searchExecutableForInterpreter("conda", true);
} catch (UnableToFindExecutableException e) {
// Unable to find, let's see if it's in the path
OrderedSet<String> pathsToSearch = new OrderedSet<>(PythonNature.getPathsToSearch());
// use ordered set: we want to search the PATH before hard-coded paths.
String userHomeDir = System.getProperty("user.home");
if (PlatformUtils.isWindowsPlatform()) {
pathsToSearch.add("c:/tools/miniconda");
pathsToSearch.add("c:/tools/miniconda2");
pathsToSearch.add("c:/tools/miniconda3");
pathsToSearch.add("c:/tools/conda");
pathsToSearch.add("c:/tools/conda2");
pathsToSearch.add("c:/tools/conda3");
} else {
pathsToSearch.add("/opt/conda");
pathsToSearch.add("/opt/conda/bin");
pathsToSearch.add("/usr/bin");
}
pathsToSearch.add(new File(userHomeDir, "miniconda").toString());
pathsToSearch.add(new File(userHomeDir, "miniconda2").toString());
pathsToSearch.add(new File(userHomeDir, "miniconda3").toString());
pathsToSearch.add(new File(userHomeDir, "conda").toString());
pathsToSearch.add(new File(userHomeDir, "conda2").toString());
pathsToSearch.add(new File(userHomeDir, "conda3").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda2").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda3").toString());
pathsToSearch.add(new File(userHomeDir).toString());

List<File> searchedDirectories = new ArrayList<>();
for (String string : pathsToSearch) {
File file = InterpreterInfo.searchExecutableInContainer("conda", new File(string),
searchedDirectories);
if (file != null) {
condaExecutable = file;
}
}
condaExecutable = CondaCore.findCondaExecutableInSystem();
if (condaExecutable == null) {
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.python.pydev.ast.package_managers;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.python.pydev.ast.interpreter_managers.InterpreterInfo;
import org.python.pydev.ast.runners.SimpleRunner;
import org.python.pydev.core.log.Log;
import org.python.pydev.json.eclipsesource.JsonArray;
import org.python.pydev.json.eclipsesource.JsonObject;
import org.python.pydev.json.eclipsesource.JsonValue;
import org.python.pydev.plugin.nature.PythonNature;
import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.structure.OrderedSet;
import org.python.pydev.shared_core.structure.Tuple;
import org.python.pydev.shared_core.utils.PlatformUtils;

public class CondaCore {

public static List<File> listCondaEnvironments(File condaExecutable) {
String encoding = "utf-8";
Tuple<String, String> output = new SimpleRunner().runAndGetOutput(
new String[] { condaExecutable.toString(), "env", "list", "--json" }, null, null,
null,
encoding);
Log.logInfo(output.o1);
if (output.o2 != null && output.o2.length() > 0) {
Log.logInfo("STDERR when listing conda environments:\n" + output.o2);

}
JsonObject jsonOutput = JsonValue.readFrom(output.o1).asObject();
JsonArray envs = jsonOutput.get("envs").asArray();
Set<File> set = new HashSet<>();
for (JsonValue env : envs.values()) {
set.add(new File(env.asString()));
}
return new ArrayList<File>(set);
}

public static List<NameAndExecutable> getCondaEnvsAsNameAndExecutable(List<File> envs) {
List<NameAndExecutable> ret = new ArrayList<NameAndExecutable>();
if (PlatformUtils.isWindowsPlatform()) {
for (File env : envs) {
File exec = new File(env, "python.exe");
if (FileUtils.enhancedIsFile(exec)) {
ret.add(new NameAndExecutable(env.getName(), exec.getPath()));
} else {
Log.logInfo("Did not find: " + exec + " in conda environment.");
}
}
} else {
for (File env : envs) {
File exec = new File(new File(env, "bin"), "python");
if (FileUtils.enhancedIsFile(exec)) {
ret.add(new NameAndExecutable(env.getName(), exec.getPath()));
} else {
Log.logInfo("Did not find: " + exec + " in conda environment.");
}
}
}
return ret;
}

/**
* @return null if it couldn't be found, otherwise provides the conda
* executable found in the system.
*/
public static File findCondaExecutableInSystem() {
File condaExecutable = null;
// Unable to find, let's see if it's in the path
OrderedSet<String> pathsToSearch = new OrderedSet<>(PythonNature.getPathsToSearch());
// use ordered set: we want to search the PATH before hard-coded paths.
String userHomeDir = System.getProperty("user.home");
if (PlatformUtils.isWindowsPlatform()) {
pathsToSearch.add("c:/tools/miniconda");
pathsToSearch.add("c:/tools/miniconda2");
pathsToSearch.add("c:/tools/miniconda3");
pathsToSearch.add("c:/tools/conda");
pathsToSearch.add("c:/tools/conda2");
pathsToSearch.add("c:/tools/conda3");
} else {
pathsToSearch.add("/opt/conda");
pathsToSearch.add("/opt/conda/bin");
pathsToSearch.add("/usr/bin");
}
pathsToSearch.add(new File(userHomeDir, "miniconda").toString());
pathsToSearch.add(new File(userHomeDir, "miniconda2").toString());
pathsToSearch.add(new File(userHomeDir, "miniconda3").toString());
pathsToSearch.add(new File(userHomeDir, "conda").toString());
pathsToSearch.add(new File(userHomeDir, "conda2").toString());
pathsToSearch.add(new File(userHomeDir, "conda3").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda2").toString());
pathsToSearch.add(new File(userHomeDir, "Anaconda3").toString());
pathsToSearch.add(new File(userHomeDir).toString());

List<File> searchedDirectories = new ArrayList<>();
for (String string : pathsToSearch) {
File file = InterpreterInfo.searchExecutableInContainer("conda", new File(string),
searchedDirectories);
if (file != null) {
condaExecutable = file;
}
}
return condaExecutable;
}

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package org.python.pydev.ui.pythonpathconf;
package org.python.pydev.ast.package_managers;

import org.python.pydev.shared_core.string.FastStringBuffer;

public final class NameAndExecutable {

public String o1;
public final String o2;
public String name;
public final String executable;

public NameAndExecutable(String name, String executableOrJar) {
this.o1 = name;
this.o2 = executableOrJar;
this.name = name;
this.executable = executableOrJar;
}

public String getName() {
return this.o1;
return this.name;
}

public String getExecutableOrJar() {
return this.o2;
return this.executable;
}

@Override
Expand All @@ -34,9 +34,9 @@ public boolean equals(Object obj) {
public String toString() {
FastStringBuffer buffer = new FastStringBuffer();
buffer.append("NameAndExecutable [");
buffer.appendObject(o1);
buffer.appendObject(name);
buffer.append(" -- ");
buffer.appendObject(o2);
buffer.appendObject(executable);
buffer.append("]");
return buffer.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.python.pydev.ast.package_managers.NameAndExecutable;
import org.python.pydev.core.IInterpreterManager;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.log.Log;
import org.python.pydev.shared_core.image.UIConstants;
import org.python.pydev.shared_ui.ImageCache;
import org.python.pydev.shared_ui.SharedUiPlugin;
import org.python.pydev.ui.pythonpathconf.InterpreterConfigHelpers;
import org.python.pydev.ui.pythonpathconf.NameAndExecutable;
import org.python.pydev.ui.pythonpathconf.conda.CondaConfigDialog;

/**
Expand Down Expand Up @@ -158,9 +158,9 @@ protected PythonListEditor(String name, String labelText, Composite parent) {
public void addPressed(int configType) {
NameAndExecutable input = getNewInputObject(configType);
if (input != null) {
if (input.o1 != null && input.o2 != null) {
if (input.name != null && input.executable != null) {
setPresentsDefaultValue(false);
TreeItem item = createInterpreterItem(input.o1, input.o2);
TreeItem item = createInterpreterItem(input.name, input.executable);
try {
treeWithInterpreters.setSelection(item);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package org.python.pydev.ui.dialogs;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -36,23 +35,22 @@
import org.eclipse.ui.dialogs.ListDialog;
import org.python.pydev.ast.interpreter_managers.AbstractInterpreterManager;
import org.python.pydev.ast.interpreter_managers.PyDevCondaPreferences;
import org.python.pydev.ast.package_managers.CondaCore;
import org.python.pydev.ast.package_managers.NameAndExecutable;
import org.python.pydev.core.IInterpreterInfo.UnableToFindExecutableException;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.preferences.InterpreterGeneralPreferences;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.shared_core.image.UIConstants;
import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.string.StringUtils;
import org.python.pydev.shared_core.utils.ArrayUtils;
import org.python.pydev.shared_core.utils.PlatformUtils;
import org.python.pydev.shared_ui.EditorUtils;
import org.python.pydev.shared_ui.ImageCache;
import org.python.pydev.shared_ui.SharedUiPlugin;
import org.python.pydev.shared_ui.dialogs.DialogHelpers;
import org.python.pydev.shared_ui.utils.RunInUiThread;
import org.python.pydev.shared_ui.utils.UIUtils;
import org.python.pydev.ui.pythonpathconf.InterpreterConfigHelpers;
import org.python.pydev.ui.pythonpathconf.NameAndExecutable;
import org.python.pydev.ui.pythonpathconf.conda.CondaConfigDialog;
import org.python.pydev.ui.pythonpathconf.package_manager.CondaPackageManager;

Expand Down Expand Up @@ -192,6 +190,9 @@ public static int openQuestionConfigureInterpreter(AbstractInterpreterManager m)
*/
public static NameAndExecutable openCondaInterpreterSelection(Shell parentShell) {
File condaExe = PyDevCondaPreferences.getExecutable();
if (condaExe == null) {
condaExe = CondaCore.findCondaExecutableInSystem();
}
if (condaExe == null) {
new CondaConfigDialog(parentShell).open();
condaExe = PyDevCondaPreferences.getExecutable();
Expand All @@ -201,7 +202,7 @@ public static NameAndExecutable openCondaInterpreterSelection(Shell parentShell)
}

List<File> envs = CondaPackageManager.listCondaEnvironments(condaExe);
List<NameAndExecutable> nameAndExecutableList = getAsNameAndExecutable(envs);
List<NameAndExecutable> nameAndExecutableList = CondaCore.getCondaEnvsAsNameAndExecutable(envs);
if (nameAndExecutableList.size() == 0) {
openWarning("Error", "Could not find any Conda environment to choose from.");
return null;
Expand All @@ -211,7 +212,7 @@ public static NameAndExecutable openCondaInterpreterSelection(Shell parentShell)

@Override
public int compare(NameAndExecutable o1, NameAndExecutable o2) {
return o1.o1.compareToIgnoreCase(o2.o1);
return o1.name.compareToIgnoreCase(o2.name);
}
});

Expand All @@ -227,12 +228,12 @@ public Image getImage(Object element) {
public String getText(Object element) {
if (element != null && element instanceof NameAndExecutable) {
NameAndExecutable nameAndExecutable = (NameAndExecutable) element;
String name = nameAndExecutable.o1;
String name = nameAndExecutable.name;
name = StringUtils.truncateIfNeeded(name, 30);

return name
+ StringUtils.createSpaceString(35 - name.length())
+ nameAndExecutable.o2;
+ nameAndExecutable.executable;
}
return super.getText(element);
}
Expand Down Expand Up @@ -283,30 +284,6 @@ protected Control createDialogArea(Composite container) {
return null;
}

private static List<NameAndExecutable> getAsNameAndExecutable(List<File> envs) {
List<NameAndExecutable> ret = new ArrayList<NameAndExecutable>();
if (PlatformUtils.isWindowsPlatform()) {
for (File env : envs) {
File exec = new File(env, "python.exe");
if (FileUtils.enhancedIsFile(exec)) {
ret.add(new NameAndExecutable(env.getName(), exec.getPath()));
} else {
Log.logInfo("Did not find: " + exec + " in conda environment.");
}
}
} else {
for (File env : envs) {
File exec = new File(new File(env, "bin"), "python");
if (FileUtils.enhancedIsFile(exec)) {
ret.add(new NameAndExecutable(env.getName(), exec.getPath()));
} else {
Log.logInfo("Did not find: " + exec + " in conda environment.");
}
}
}
return ret;
}

/**
* @param abstractInterpreterManager
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.python.copiedfromeclipsesrc.PythonListEditor;
import org.python.pydev.ast.interpreter_managers.IInterpreterProviderFactory;
import org.python.pydev.ast.interpreter_managers.InterpreterInfo;
import org.python.pydev.ast.package_managers.NameAndExecutable;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.IInterpreterManager;
import org.python.pydev.core.IInterpreterManagerListener;
Expand Down Expand Up @@ -1064,7 +1065,7 @@ protected NameAndExecutable getNewInputObject(int configType) {
} else if (configType == InterpreterConfigHelpers.CONFIG_CONDA) {
NameAndExecutable interpreterNameAndExecutable = PyDialogHelpers
.openCondaInterpreterSelection(getShell());
if (interpreterNameAndExecutable != null && interpreterNameAndExecutable.o2 != null) {
if (interpreterNameAndExecutable != null && interpreterNameAndExecutable.executable != null) {
operation = InterpreterConfigHelpers.tryInterpreter(
interpreterNameAndExecutable, interpreterManager,
false, true, logger, this.getShell(), true);
Expand All @@ -1086,7 +1087,7 @@ protected NameAndExecutable getNewInputObject(int configType) {

logger.println("- Chosen interpreter (name and file):'" + interpreterNameAndExecutable);

if (interpreterNameAndExecutable != null && interpreterNameAndExecutable.o2 != null) {
if (interpreterNameAndExecutable != null && interpreterNameAndExecutable.executable != null) {
//ok, now that we got the file, let's see if it is valid and get the library info.
operation = InterpreterConfigHelpers.tryInterpreter(
interpreterNameAndExecutable, interpreterManager,
Expand Down
Loading

0 comments on commit 8ff9916

Please sign in to comment.