Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

New extension point pydev_interpreter_provider #38

Merged
merged 2 commits into from

2 participants

@jonahkichwacoders

(One of many requests, all together at https://github.com/jonahkichwacoders/PyDev/tree/fabioz_all_requests if it is useful)

New extension point pydev_interpreter_provider

Add a new extension point to allow third parties to contribute to finding,
and possibly live installing, python (and jython/ipy) installations in
new ways.

This splits the pre-existing code for locating python/jython/ipy on the
path or in the win32 registry out of the AbstractInterpreterEditor class
hierarchy, making it potentially possible to reuse the code without the
Preferences UI being loaded.

@jonahkichwacoders jonahkichwacoders New extension point pydev_interpreter_provider
Add a new extension point to allow third parties to contribute to finding,
and possibly live installing, python (and jython/ipy) installations in
new ways.

This splits the pre-existing code for locating python/jython/ipy on the
path or in the win32 registry out of the AbstractInterpreterEditor class
hierarchy, making it potentially possible to reuse the code without the
Preferences UI being loaded.
7ee65d8
@jonahkichwacoders jonahkichwacoders Merge branch 'development' into pullrequest/pydev_interpreter_provider c2af7f7
@fabioz fabioz merged commit c2af7f7 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 26, 2013
  1. @jonahkichwacoders

    New extension point pydev_interpreter_provider

    jonahkichwacoders authored
    Add a new extension point to allow third parties to contribute to finding,
    and possibly live installing, python (and jython/ipy) installations in
    new ways.
    
    This splits the pre-existing code for locating python/jython/ipy on the
    path or in the win32 registry out of the AbstractInterpreterEditor class
    hierarchy, making it potentially possible to reuse the code without the
    Preferences UI being loaded.
  2. @jonahkichwacoders
This page is out of date. Refresh to see the latest.
Showing with 588 additions and 206 deletions.
  1. +3 −0  plugins/org.python.pydev.core/src/org/python/pydev/core/ExtensionHelper.java
  2. +13 −0 plugins/org.python.pydev/plugin.xml
  3. +69 −0 plugins/org.python.pydev/schema/pydev_interpreter_provider.exsd
  4. +160 −61 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterEditor.java
  5. +32 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
  6. +69 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AlreadyInstalledInterpreterProvider.java
  7. +44 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IInterpreterProvider.java
  8. +29 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IInterpreterProviderFactory.java
  9. +8 −5 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IronpythonInterpreterEditor.java
  10. +13 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IronpythonInterpreterProviderFactory.java
  11. +7 −44 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterEditor.java
  12. +3 −0  plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterPreferencesPage.java
  13. +55 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
  14. +3 −96 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/PythonInterpreterEditor.java
  15. +80 −0 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/PythonInterpreterProviderFactory.java
View
3  plugins/org.python.pydev.core/src/org/python/pydev/core/ExtensionHelper.java
@@ -56,6 +56,9 @@
//IInterpreterInfoBuilder
public static final String PYDEV_INTERPRETER_INFO_BUILDER = "org.python.pydev.pydev_interpreter_info_builder";
+ //IInterpreterProviderFactory
+ public static final String PYDEV_INTERPRETER_PROVIDER = "org.python.pydev.pydev_interpreter_provider";
+
//debug
public static final String PYDEV_DEBUG_CONSOLE_INPUT_LISTENER = "org.python.pydev.debug.pydev_debug_console_input_listener";
View
13 plugins/org.python.pydev/plugin.xml
@@ -1049,6 +1049,7 @@
<extension-point id="pydev_manager_observer" name="PyDev code completion manager observer" schema="schema/pydev_manager_observer.exsd"/>
<extension-point id="pydev_hover" name="PyDev hover" schema="schema/pydev_hover.exsd"/>
<extension-point id="pydev_interpreter_info_builder" name="PyDev interpreter info builder" schema="schema/pydev_interpreter_info_builder.exsd"/>
+ <extension-point id="pydev_interpreter_provider" name="PyDev interpreter provider" schema="schema/pydev_interpreter_provider.exsd"/>
<!-- wizards -->
<extension point="org.eclipse.ui.newWizards">
<category
@@ -2611,4 +2612,16 @@ if __name__ == "__main__":
</adapter>
</factory>
</extension>
+ <extension
+ point="org.python.pydev.pydev_interpreter_provider">
+ <interpreter_provider_participant
+ class="org.python.pydev.ui.pythonpathconf.PythonInterpreterProviderFactory">
+ </interpreter_provider_participant>
+ <interpreter_provider_participant
+ class="org.python.pydev.ui.pythonpathconf.JythonInterpreterProviderFactory">
+ </interpreter_provider_participant>
+ <interpreter_provider_participant
+ class="org.python.pydev.ui.pythonpathconf.IronpythonInterpreterProviderFactory">
+ </interpreter_provider_participant>
+ </extension>
</plugin>
View
69 plugins/org.python.pydev/schema/pydev_interpreter_provider.exsd
@@ -0,0 +1,69 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.python.pydev" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.python.pydev" id="pydev_interpreter_provider" name="org.python.pydev.pydev_interpreter_provider"/>
+ </appInfo>
+ <documentation>
+ Clients can implement the Interpreter Provider to contribute new interpreters to be configured when a user presses the Auto Config button. There is a two step process, this extension point returns an instance of IInterpreterProviderFactory on which getInterpreterProviders is called, and then, if the user selects it, and the interpreter is not installed already, it will be installed with runInstall.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appInfo>
+ <meta.element />
+ </appInfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="interpreter_provider_participant" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ a fully qualified identifier of the target extension point
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="interpreter_provider_participant">
+ <complexType>
+ <sequence>
+ </sequence>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ Must implement IInterpreterProviderFactory
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+
+
+
+
+
+</schema>
View
221 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterEditor.java
@@ -29,6 +29,7 @@
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.debug.ui.EnvironmentTab;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
@@ -38,6 +39,9 @@
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
@@ -63,8 +67,10 @@
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.dialogs.ListDialog;
import org.python.copiedfromeclipsesrc.JDTNotAvailableException;
import org.python.copiedfromeclipsesrc.PythonListEditor;
+import org.python.pydev.core.ExtensionHelper;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.IInterpreterManager;
import org.python.pydev.core.PropertiesHelper;
@@ -74,8 +80,8 @@
import org.python.pydev.jython.JythonPlugin;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.runners.SimpleJythonRunner;
-import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.structure.Tuple;
+import org.python.pydev.shared_ui.EditorUtils;
import org.python.pydev.shared_ui.ImageCache;
import org.python.pydev.shared_ui.UIConstants;
import org.python.pydev.shared_ui.utils.AsynchronousProgressMonitorDialog;
@@ -217,6 +223,7 @@ protected AbstractInterpreterEditor(String preferenceName, String labelText, Com
/**
* @see org.eclipse.jface.preference.FieldEditor#createControl(org.eclipse.swt.widgets.Composite)
*/
+ @Override
protected void createControl(Composite parent) {
super.createControl(parent);
treeWithInterpreters = getListControl(parent);
@@ -317,6 +324,7 @@ protected void disposeOfTreeItem(TreeItem t) {
super.disposeOfTreeItem(t);
}
+ @Override
protected void adjustForNumColumns(int numColumns) {
super.adjustForNumColumns(numColumns);
((GridData) tabFolder.getLayoutData()).horizontalSpan = numColumns;
@@ -337,6 +345,7 @@ protected void adjustForNumColumns(int numColumns) {
/**
* @see org.eclipse.jface.preference.ListEditor#doFillIntoGrid(org.eclipse.swt.widgets.Composite, int)
*/
+ @Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
super.doFillIntoGrid(parent, numColumns);
GridData gd = new GridData();
@@ -354,6 +363,7 @@ protected void doFillIntoGrid(Composite parent, int numColumns) {
//----------------------- FORCED BUILTINS
forcedBuiltins = new AbstractListWithNewRemoveControl(this) {
+ @Override
protected List<String> getStringsFromInfo(InterpreterInfo info) {
ArrayList<String> ret = new ArrayList<String>();
for (Iterator<String> iter = info.forcedLibsIterator(); iter.hasNext();) {
@@ -362,6 +372,7 @@ protected void doFillIntoGrid(Composite parent, int numColumns) {
return ret;
}
+ @Override
protected void removeSelectedFrominfo(InterpreterInfo info, String[] builtins) {
for (String builtin : builtins) {
info.removeForcedLib(builtin);
@@ -369,6 +380,7 @@ protected void removeSelectedFrominfo(InterpreterInfo info, String[] builtins) {
exeOrJarOfInterpretersWithBuiltinsChanged.add(info.getExecutableOrJar());
}
+ @Override
protected String getInput() {
IInputValidator validator = new IInputValidator() {
@@ -392,6 +404,7 @@ public String isValid(String newText) {
return builtins;
}
+ @Override
protected void addInputToInfo(InterpreterInfo info, String builtins) {
java.util.List<String> split = StringUtils.splitAndRemoveEmptyTrimmed(builtins, ',');
for (String string : split) {
@@ -411,10 +424,12 @@ protected void addInputToInfo(InterpreterInfo info, String builtins) {
private Button addAPIBt;
+ @Override
protected List<String> getStringsFromInfo(InterpreterInfo info) {
return info.getPredefinedCompletionsPath();
}
+ @Override
protected void removeSelectedFrominfo(InterpreterInfo info, String[] items) {
for (String item : items) {
info.removePredefinedCompletionPath(item);
@@ -422,6 +437,7 @@ protected void removeSelectedFrominfo(InterpreterInfo info, String[] items) {
exeOrJarOfInterpretersWithPredefinedChanged.add(info.getExecutableOrJar());
}
+ @Override
protected String getInput() {
DirectoryDialog dialog = new DirectoryDialog(getShell());
dialog.setFilterPath(lastDirectoryDialogPath);
@@ -432,16 +448,19 @@ protected String getInput() {
return filePath;
}
+ @Override
protected void addInputToInfo(InterpreterInfo info, String item) {
info.addPredefinedCompletionsPath(item);
exeOrJarOfInterpretersWithPredefinedChanged.add(info.getExecutableOrJar());
}
+ @Override
protected void createButtons(AbstractInterpreterEditor interpreterEditor) {
super.createButtons(interpreterEditor);
addAPIBt = interpreterEditor.createBt(box, "Add from QScintilla api file", this);//$NON-NLS-1$
}
+ @Override
public void widgetDisposed(DisposeEvent event) {
super.widgetDisposed(event);
if (addAPIBt != null) {
@@ -450,6 +469,7 @@ public void widgetDisposed(DisposeEvent event) {
}
}
+ @Override
public void widgetSelected(SelectionEvent event) {
super.widgetSelected(event);
Widget widget = event.widget;
@@ -584,6 +604,7 @@ private void createEnvironmentVariablesTab() {
composite.setLayout(new GridLayout(1, false));
environmentTab = new EnvironmentTab() {
+ @Override
protected void createAppendReplace(Composite parent) {
super.createAppendReplace(parent);
appendEnvironment.setVisible(false);
@@ -692,6 +713,7 @@ public void widgetDisposed(DisposeEvent event) {
private SelectionListener getSelectionListenerSystem() {
if (selectionListenerSystem == null) {
selectionListenerSystem = new SelectionAdapter() {
+ @Override
public void widgetSelected(SelectionEvent event) {
if (treeWithInterpreters.getSelectionCount() == 1) {
TreeItem[] selection = treeWithInterpreters.getSelection();
@@ -781,6 +803,7 @@ public void widgetSelected(SelectionEvent event) {
/**
* @param listControl
*/
+ @Override
public void updateTree() {
int index = this.getSelectionIndex();
if (index >= 0) {
@@ -796,6 +819,7 @@ public void updateTree() {
}
}
+ @Override
public Shell getShell() {
return super.getShell();
}
@@ -868,41 +892,29 @@ private void fillPathItemsFromName(String name) {
*/
public abstract String[] getInterpreterFilterExtensions();
+ /**
+ * @return the type of the interpreter
+ */
+ public abstract IInterpreterProviderFactory.InterpreterType getInterpreterType();
+
@Override
protected Tuple<String, String> getNewInputObject(boolean autoConfig) {
CharArrayWriter charWriter = new CharArrayWriter();
PrintWriter logger = new PrintWriter(charWriter);
logger.println("Information about process of adding new interpreter:");
try {
- Tuple<String, String> interpreterNameAndExecutable = null;
+ final Tuple<String, String> interpreterNameAndExecutable;
if (autoConfig) {
- try {
- interpreterNameAndExecutable = getAutoNewInput();
- } catch (CancelException e) {
- //user canceled.
- return null;
- }
- if (interpreterNameAndExecutable == null) {
- reportAutoConfigProblem(null);
- return null;
- }
+ interpreterNameAndExecutable = autoConfig();
} else {
-
- InterpreterInputDialog dialog = new InterpreterInputDialog(getShell(), "Select interpreter",
- "Enter the name and executable of your interpreter", this);
-
- logger.println("- Opening dialog to request executable (or jar).");
- int result = dialog.open();
-
- if (result == Window.OK) {
- interpreterNameAndExecutable = dialog.getKeyAndValueEntered();
- } else {
- return null;
- }
+ interpreterNameAndExecutable = newConfig(logger);
+ }
+ if (interpreterNameAndExecutable == null) {
+ return null;
}
- boolean foundError = checkInterpreterNameAndExecutable(interpreterNameAndExecutable, logger,
- "Error getting info on interpreter");
+ boolean foundError = checkInterpreterNameAndExecutable(
+ interpreterNameAndExecutable, logger, "Error getting info on interpreter");
if (foundError) {
return null;
@@ -1077,15 +1089,131 @@ private void fillPathItemsFromName(String name) {
return null;
}
- private boolean checkInterpreterNameAndExecutable(Tuple<String, String> interpreterNameAndExecutable,
- PrintWriter logger, String errorMsg) {
+ private Tuple<String, String> newConfig(PrintWriter logger) {
+ InterpreterInputDialog dialog = new InterpreterInputDialog(getShell(), "Select interpreter",
+ "Enter the name and executable of your interpreter", this);
+
+ logger.println("- Opening dialog to request executable (or jar).");
+ int result = dialog.open();
+
+ if (result == Window.OK) {
+ return dialog.getKeyAndValueEntered();
+ }
+ return null;
+
+ }
+
+ private Tuple<String, String> autoConfig() {
+ final Tuple<String, String> interpreterNameAndExecutable;
+ try {
+ @SuppressWarnings("unchecked")
+ List<IInterpreterProviderFactory> participants = ExtensionHelper
+ .getParticipants(ExtensionHelper.PYDEV_INTERPRETER_PROVIDER);
+ final List<IInterpreterProvider> providers = new ArrayList<IInterpreterProvider>();
+ for (final IInterpreterProviderFactory providerFactory : participants) {
+ SafeRunner.run(new SafeRunnable() {
+ public void run() throws Exception {
+ IInterpreterProvider[] ips = providerFactory.getInterpreterProviders(getInterpreterType());
+ if (ips != null) {
+ providers.addAll(Arrays.asList(ips));
+ }
+ }
+ });
+ }
+
+ if (providers.size() == 0) {
+ // If there are no providers at this point it means that
+ // the selected target (python/jython/etc)
+ // was no found to be available on any known location
+ interpreterNameAndExecutable = null;
+ } else {
+
+ final IInterpreterProvider selectedProvider;
+ if (providers.size() == 1) {
+ selectedProvider = providers.get(0);
+ } else {
+ // The user should select which one to use...
+ ListDialog listDialog = new ListDialog(EditorUtils.getShell());
+
+ listDialog.setContentProvider(new ArrayContentProvider());
+ listDialog.setLabelProvider(new LabelProvider() {
+ @Override
+ public Image getImage(Object element) {
+ return PydevPlugin.getImageCache().get(UIConstants.PY_INTERPRETER_ICON);
+ }
+
+ @Override
+ public String getText(Object element) {
+ IInterpreterProvider provider = (IInterpreterProvider) element;
+ return provider.getExecutableOrJar();
+ }
+ });
+ listDialog.setInput(providers.toArray());
+ listDialog.setMessage("Multiple possible interpreters are available.\n"
+ + "Please select which one you want to install and configure.");
+
+ int open = listDialog.open();
+ if (open != ListDialog.OK) {
+ throw cancelException;
+ }
+ Object[] result = listDialog.getResult();
+ if (result == null || result.length == 0) {
+ throw cancelException;
+ }
+
+ selectedProvider = (IInterpreterProvider) result[0];
+ }
+
+ if (!selectedProvider.isInstalled()) {
+ SafeRunner.run(new SafeRunnable() {
+ public void run() throws Exception {
+ selectedProvider.runInstall();
+ }
+ });
+
+ if (!selectedProvider.isInstalled()) {
+ // if still not installed, user pressed cancel or an
+ // error was handled and displayed to the user during
+ // the thirdparty install process
+ throw cancelException;
+ }
+ }
+ String executable = selectedProvider.getExecutableOrJar();
+ if (executable == null) {
+ interpreterNameAndExecutable = null;
+ } else {
+ String name = selectedProvider.getName();
+ if (name == null) {
+ name = executable;
+ } else {
+ name = getUniqueInterpreterName(name);
+ }
+ interpreterNameAndExecutable = new Tuple<String, String>(name, executable);
+ }
+ }
+
+ } catch (CancelException e) {
+ // user cancelled.
+ return null;
+ }
+ if (interpreterNameAndExecutable == null) {
+ reportAutoConfigProblem(null);
+ return null;
+ }
+ return interpreterNameAndExecutable;
+ }
+
+ private boolean checkInterpreterNameAndExecutable(
+ Tuple<String, String> interpreterNameAndExecutable, PrintWriter logger, String errorMsg) {
boolean foundError = false;
//Check auto config or dialog return.
if (interpreterNameAndExecutable == null) {
logger.println("- When trimmed, the chosen file was null (returning null).");
- ErrorDialog.openError(this.getShell(), errorMsg, "interpreterNameAndExecutable == null", PydevPlugin
- .makeStatus(IStatus.ERROR, "interpreterNameAndExecutable == null", new RuntimeException()));
+ ErrorDialog.openError(this.getShell(), errorMsg,
+ "interpreterNameAndExecutable == null",
+ PydevPlugin.makeStatus(IStatus.ERROR, "interpreterNameAndExecutable == null",
+ new RuntimeException()));
foundError = true;
}
if (!foundError) {
@@ -1163,16 +1291,6 @@ private void reportAutoConfigProblem(Exception e) {
public final CancelException cancelException = new CancelException();
- /**
- * @return a tuple with the name of the interpreter and the string with the file to be executed
- * (for python could be just python.exe) and for jython the jython.jar location.
- *
- * This is also be platform-dependent (so, it could be python.exe or just python)
- *
- * If it cannot be determined, the return should be null (and not a tuple with empty values)
- */
- protected abstract Tuple<String, String> getAutoNewInput() throws CancelException;
-
@Override
protected void doStore() {
//Do nothing (all handled in the preferences page regarding the store (no longer in this editor)
@@ -1194,6 +1312,7 @@ protected void doLoad() {
updateTree();
}
+ @Override
public String getPreferenceName() {
throw new RuntimeException(
"The preferences should be stored/gotten from the IInterpreterManager, and not directly.");
@@ -1202,29 +1321,9 @@ public String getPreferenceName() {
/**
* @see org.python.copiedfromeclipsesrc.PythonListEditor#doLoadDefault()
*/
+ @Override
protected void doLoadDefault() {
//do nothing
}
- public Tuple<String, String> getAutoNewInputFromPaths(java.util.List<String> pathsToSearch,
- String expectedFilename, String nameForUser) {
- for (String s : pathsToSearch) {
- if (s.trim().length() > 0) {
- File file = new File(s.trim());
- if (file.isDirectory()) {
- String[] available = file.list();
- if (available != null) {
- for (String jar : available) {
- if (jar.toLowerCase().equals(expectedFilename)) {
- return new Tuple<String, String>(getUniqueInterpreterName(nameForUser),
- FileUtils.getFileAbsolutePath(new File(file, jar)));
- }
- }
- }
- }
- }
- }
- return null;
- }
-
}
View
32 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
@@ -0,0 +1,32 @@
+package org.python.pydev.ui.pythonpathconf;
+
+import java.io.File;
+
+import org.python.pydev.shared_core.io.FileUtils;
+
+public abstract class AbstractInterpreterProviderFactory implements IInterpreterProviderFactory {
+
+ public AbstractInterpreterProviderFactory() {
+ super();
+ }
+
+ public String searchPaths(java.util.List<String> pathsToSearch, String expectedFilename) {
+ for (String s : pathsToSearch) {
+ if (s.trim().length() > 0) {
+ File file = new File(s.trim());
+ if (file.isDirectory()) {
+ String[] available = file.list();
+ if (available != null) {
+ for (String jar : available) {
+ if (jar.toLowerCase().equals(expectedFilename)) {
+ return FileUtils.getFileAbsolutePath(new File(file, jar));
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+}
View
69 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AlreadyInstalledInterpreterProvider.java
@@ -0,0 +1,69 @@
+package org.python.pydev.ui.pythonpathconf;
+
+/**
+ * Abstract IInterpreterProvider that represents an already installed
+ * InterpreterProvider.
+ *
+ * This is a convenience abstract class to simplify implementations of
+ * IInterpreterProvider that are not installable.
+ */
+public abstract class AlreadyInstalledInterpreterProvider implements IInterpreterProvider {
+ public boolean isInstalled() {
+ return true;
+ }
+
+ public void runInstall() {
+ // Nothing to do
+ }
+
+ /**
+ * Create a new array of already installed providers.
+ *
+ * Convenience method that creates an array that can be returned from
+ * {@link IInterpreterProviderFactory#getInterpreterProviders(org.python.pydev.ui.pythonpathconf.IInterpreterProviderFactory.InterpreterType)}
+ *
+ * @param name
+ * Name of the Interpreter, see
+ * {@link IInterpreterProvider#getName()}
+ * @param executableOrJar
+ * The Executable name, or Jar name, see
+ * {@link IInterpreterProvider#getExecutableOrJar()}
+ * @return An array length 1 for the provided executableOrJar
+ */
+ static public IInterpreterProvider[] create(String name, String executableOrJar) {
+ return create(name, new String[] { executableOrJar });
+ }
+
+ /**
+ * Create a new array of already installed providers.
+ *
+ * Convenience method that creates an array that can be returned from
+ * {@link IInterpreterProviderFactory#getInterpreterProviders(org.python.pydev.ui.pythonpathconf.IInterpreterProviderFactory.InterpreterType)}
+ *
+ * @param name
+ * Name of the Interpreter, see
+ * {@link IInterpreterProvider#getName()}
+ * @param executableOrJars
+ * An array of the Executable name, or Jar name, see
+ * {@link IInterpreterProvider#getExecutableOrJar()}
+ * @return An array the same length as executableOrJars
+ */
+ static public IInterpreterProvider[] create(final String name, final String[] executableOrJars) {
+ IInterpreterProvider[] providers = new IInterpreterProvider[executableOrJars.length];
+ for (int i = 0; i < executableOrJars.length; i++) {
+ final String executableOrJar = executableOrJars[i];
+
+ providers[i] = new AlreadyInstalledInterpreterProvider() {
+
+ public String getExecutableOrJar() {
+ return executableOrJar;
+ }
+
+ public String getName() {
+ return name;
+ }
+ };
+ }
+ return providers;
+ }
+}
View
44 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IInterpreterProvider.java
@@ -0,0 +1,44 @@
+package org.python.pydev.ui.pythonpathconf;
+
+/**
+ * A representation of an interpreter that exists, or can be installed, on the
+ * users machine. Created from calling all the registered
+ * {@link IInterpreterProviderFactory#getInterpreterProviders(org.python.pydev.ui.pythonpathconf.IInterpreterProviderFactory.InterpreterType)}
+ */
+public interface IInterpreterProvider {
+
+ /**
+ * Return the name of the Executable or Jar
+ *
+ * @return the name of the Executable or Jar
+ */
+ public String getExecutableOrJar();
+
+ /**
+ * Return user visible name. If the name is <code>null</code>, the
+ * {@link #getExecutableOrJar()} will be used. If the name returned is not
+ * unique within the workspace, will be made unique.
+ *
+ * @return the name displayed in the UI. May be <code>null</code>
+ */
+ public String getName();
+
+ /**
+ * Return whether the interpreter methods are returning provisional (false)
+ * or installed (true) information. If not complete, call
+ * {@link #runInstall()} to install/etc this interpreter.
+ *
+ * @return true if the Provider is ready to go
+ */
+ public boolean isInstalled();
+
+ /**
+ * Install the interpreter. If {@link #isInstalled()} returns false after
+ * the install is run, then the user either cancelled, or an error occurred
+ * that the user has already been informed about.
+ *
+ * It is up to the implementor to bundle installations up in a job to
+ * maintain UI responsiveness.
+ */
+ public void runInstall();
+}
View
29 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IInterpreterProviderFactory.java
@@ -0,0 +1,29 @@
+package org.python.pydev.ui.pythonpathconf;
+
+/**
+ * A factory for creating {@link IInterpreterProvider}s
+ *
+ * Instances of this class should be registered with the
+ * org.python.pydev.pydev_interpreter_provider extension point.
+ */
+public interface IInterpreterProviderFactory {
+
+ /**
+ * Possible types of Interpreters that a factory can create providers for.
+ */
+ public enum InterpreterType {
+ PYTHON, JYTHON, IRONPYTHON
+ }
+
+ /**
+ * Create a (possibly empty or <code>null</code>) array of
+ * {@link IInterpreterProvider}s that contain information about current, or
+ * potential, Python installations of type <code>type</code>
+ *
+ * @param type
+ * the type of Interpreter to create providers for
+ * @return Array of possible providers. Can be empty or null if no providers
+ * for given type can be created.
+ */
+ public IInterpreterProvider[] getInterpreterProviders(InterpreterType type);
+}
View
13 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IronpythonInterpreterEditor.java
@@ -8,8 +8,8 @@
import org.eclipse.swt.widgets.Composite;
import org.python.pydev.core.IInterpreterManager;
-import org.python.pydev.shared_core.structure.Tuple;
import org.python.pydev.shared_core.utils.PlatformUtils;
+import org.python.pydev.ui.pythonpathconf.IInterpreterProviderFactory.InterpreterType;
public class IronpythonInterpreterEditor extends AbstractInterpreterEditor {
@@ -25,12 +25,15 @@ public IronpythonInterpreterEditor(String labelText, Composite parent, IInterpre
return null;
}
- protected Tuple<String, String> getAutoNewInput() {
- return new Tuple<String, String>(getUniqueInterpreterName("ipy"), "ipy"); //This should be enough to find it from the PATH or any other way it's defined.
- }
-
+ @Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
super.doFillIntoGrid(parent, numColumns);
this.autoConfigButton.setToolTipText("Will try to find Iron Python on the PATH (will fail if not available)");
}
+
+ @Override
+ public InterpreterType getInterpreterType() {
+ return InterpreterType.IRONPYTHON;
+ }
+
}
View
13 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/IronpythonInterpreterProviderFactory.java
@@ -0,0 +1,13 @@
+package org.python.pydev.ui.pythonpathconf;
+
+public class IronpythonInterpreterProviderFactory extends AbstractInterpreterProviderFactory {
+
+ public IInterpreterProvider[] getInterpreterProviders(InterpreterType type) {
+ if (type != IInterpreterProviderFactory.InterpreterType.IRONPYTHON) {
+ return null;
+ }
+
+ return AlreadyInstalledInterpreterProvider.create("ipy", "ipy");
+ }
+
+}
View
51 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterEditor.java
@@ -11,17 +11,9 @@
*/
package org.python.pydev.ui.pythonpathconf;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.widgets.Composite;
import org.python.pydev.core.IInterpreterManager;
-import org.python.pydev.core.docutils.StringUtils;
-import org.python.pydev.core.log.Log;
-import org.python.pydev.runners.SimpleRunner;
-import org.python.pydev.shared_core.structure.Tuple;
+import org.python.pydev.ui.pythonpathconf.IInterpreterProviderFactory.InterpreterType;
public class JythonInterpreterEditor extends AbstractInterpreterEditor {
@@ -34,44 +26,15 @@ public JythonInterpreterEditor(String labelText, Composite parent, IInterpreterM
return new String[] { "*.jar", "*.*" };
}
- protected Tuple<String, String> getAutoNewInput() {
- try {
- Map<String, String> env = SimpleRunner.getDefaultSystemEnv(null);
- List<String> pathsToSearch = new ArrayList<String>();
- if (env.containsKey("JYTHON_HOME")) {
- pathsToSearch.add(env.get("JYTHON_HOME"));
- }
- if (env.containsKey("PYTHON_HOME")) {
- pathsToSearch.add(env.get("PYTHON_HOME"));
- }
- if (env.containsKey("JYTHONHOME")) {
- pathsToSearch.add(env.get("JYTHONHOME"));
- }
- if (env.containsKey("PYTHONHOME")) {
- pathsToSearch.add(env.get("PYTHONHOME"));
- }
- if (env.containsKey("PATH")) {
- String path = env.get("PATH");
- String separator = SimpleRunner.getPythonPathSeparator();
- final List<String> split = StringUtils.split(path, separator);
- pathsToSearch.addAll(split);
- }
- pathsToSearch.add("/usr/bin");
- pathsToSearch.add("/usr/local/bin");
- pathsToSearch.add("/usr/share/java");
-
- return super.getAutoNewInputFromPaths(pathsToSearch, "jython.jar", "jython");
-
- } catch (CoreException e) {
- Log.log(e);
- }
-
- return null;
- }
-
+ @Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
super.doFillIntoGrid(parent, numColumns);
this.autoConfigButton.setToolTipText("Will try to find Jython on the PATH (will fail if not available)");
}
+ @Override
+ public InterpreterType getInterpreterType() {
+ return InterpreterType.JYTHON;
+ }
+
}
View
3  plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterPreferencesPage.java
@@ -18,6 +18,7 @@
public class JythonInterpreterPreferencesPage extends AbstractInterpreterPreferencesPage {
+ @Override
public String getTitle() {
return "Jython Interpreters";
}
@@ -33,10 +34,12 @@ protected String getInterpretersTitle() {
* @param p this is the composite that should be the interpreter parent
* @return an interpreter editor (used to add/edit/remove the information on an editor)
*/
+ @Override
protected AbstractInterpreterEditor getInterpreterEditor(Composite p) {
return new JythonInterpreterEditor(getInterpretersTitle(), p, PydevPlugin.getJythonInterpreterManager(true));
}
+ @Override
protected void createFieldEditors() {
super.createFieldEditors();
addField(new DirectoryFieldEditor(IInterpreterManager.JYTHON_CACHE_DIR, "-Dpython.cachedir",
View
55 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
@@ -0,0 +1,55 @@
+package org.python.pydev.ui.pythonpathconf;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.python.pydev.core.docutils.StringUtils;
+import org.python.pydev.core.log.Log;
+import org.python.pydev.runners.SimpleRunner;
+
+public class JythonInterpreterProviderFactory extends AbstractInterpreterProviderFactory {
+
+ public IInterpreterProvider[] getInterpreterProviders(InterpreterType type) {
+ if (type != IInterpreterProviderFactory.InterpreterType.JYTHON) {
+ return null;
+ }
+
+ try {
+ Map<String, String> env = SimpleRunner.getDefaultSystemEnv(null);
+ List<String> pathsToSearch = new ArrayList<String>();
+ if (env.containsKey("JYTHON_HOME")) {
+ pathsToSearch.add(env.get("JYTHON_HOME"));
+ }
+ if (env.containsKey("PYTHON_HOME")) {
+ pathsToSearch.add(env.get("PYTHON_HOME"));
+ }
+ if (env.containsKey("JYTHONHOME")) {
+ pathsToSearch.add(env.get("JYTHONHOME"));
+ }
+ if (env.containsKey("PYTHONHOME")) {
+ pathsToSearch.add(env.get("PYTHONHOME"));
+ }
+ if (env.containsKey("PATH")) {
+ String path = env.get("PATH");
+ String separator = SimpleRunner.getPythonPathSeparator();
+ final List<String> split = StringUtils.split(path, separator);
+ pathsToSearch.addAll(split);
+ }
+ pathsToSearch.add("/usr/bin");
+ pathsToSearch.add("/usr/local/bin");
+ pathsToSearch.add("/usr/share/java");
+
+ String searchResult = searchPaths(pathsToSearch, "jython.jar");
+ if (searchResult != null) {
+ return AlreadyInstalledInterpreterProvider.create("jython", searchResult);
+ }
+ } catch (CoreException e) {
+ Log.log(e);
+ }
+
+ return null;
+ }
+
+}
View
99 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/PythonInterpreterEditor.java
@@ -9,25 +9,9 @@
*/
package org.python.pydev.ui.pythonpathconf;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jface.viewers.ArrayContentProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.ui.dialogs.ListDialog;
import org.python.pydev.core.IInterpreterManager;
-import org.python.pydev.core.log.Log;
-import org.python.pydev.plugin.PydevPlugin;
-import org.python.pydev.shared_core.structure.Tuple;
import org.python.pydev.shared_core.utils.PlatformUtils;
-import org.python.pydev.shared_ui.EditorUtils;
-import org.python.pydev.shared_ui.UIConstants;
-
-import at.jta.Key;
-import at.jta.Regor;
public class PythonInterpreterEditor extends AbstractInterpreterEditor {
@@ -44,88 +28,11 @@ public PythonInterpreterEditor(String labelText, Composite parent, IInterpreterM
}
@Override
- protected Tuple<String, String> getAutoNewInput() throws CancelException {
- List<String> pathsToSearch = new ArrayList<String>();
- if (!PlatformUtils.isWindowsPlatform()) {
- pathsToSearch.add("/usr/bin");
- pathsToSearch.add("/usr/local/bin");
- Tuple<String, String> ret = super.getAutoNewInputFromPaths(pathsToSearch, "python", "python");
- if (ret != null) {
- return ret;
- }
- } else {
- //On windows we can try to see the installed versions...
- List<File> foundVersions = new ArrayList<File>();
- try {
- Regor regor = new Regor();
-
- //The structure for Python is something as Software\\Python\\PythonCore\\2.6\\InstallPath
- for (Key root : new Key[] { Regor.HKEY_LOCAL_MACHINE, Regor.HKEY_CURRENT_USER }) {
- Key key = regor.openKey(root, "Software\\Python\\PythonCore", Regor.KEY_READ);
- if (key != null) {
- try {
- List l = regor.listKeys(key);
- for (Object o : l) {
- Key openKey = regor.openKey(key, (String) o + "\\InstallPath", Regor.KEY_READ);
- if (openKey != null) {
- try {
- byte buf[] = regor.readValue(openKey, "");
- if (buf != null) {
- String parseValue = Regor.parseValue(buf);
- //Ok, this should be the directory where it's installed, try to find a 'python.exe' there...
- File file = new File(parseValue, "python.exe");
- if (file.isFile()) {
- foundVersions.add(file);
- }
- }
- } finally {
- regor.closeKey(openKey);
- }
- }
- }
- } finally {
- regor.closeKey(key);
- }
- }
- }
-
- } catch (Throwable e) {
- Log.log(e);
- }
- if (foundVersions.size() == 1) {
- return new Tuple<String, String>(getUniqueInterpreterName("python"), foundVersions.get(0).toString());
- }
- if (foundVersions.size() > 1) {
- //The user should select which one to use...
- ListDialog listDialog = new ListDialog(EditorUtils.getShell());
-
- listDialog.setContentProvider(new ArrayContentProvider());
- listDialog.setLabelProvider(new LabelProvider() {
- @Override
- public Image getImage(Object element) {
- return PydevPlugin.getImageCache().get(UIConstants.PY_INTERPRETER_ICON);
- }
- });
- listDialog.setInput(foundVersions.toArray());
- listDialog
- .setMessage("Multiple interpreters were found installed.\nPlease select which one you want to configure.");
-
- int open = listDialog.open();
- if (open != ListDialog.OK) {
- throw cancelException;
- }
- Object[] result = listDialog.getResult();
- if (result == null || result.length == 0) {
- throw cancelException;
- }
- return new Tuple<String, String>(getUniqueInterpreterName("python"), result[0].toString());
-
- }
- }
-
- return new Tuple<String, String>(getUniqueInterpreterName("python"), "python"); //This should be enough to find it from the PATH or any other way it's defined.
+ public IInterpreterProviderFactory.InterpreterType getInterpreterType() {
+ return IInterpreterProviderFactory.InterpreterType.PYTHON;
}
+ @Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
super.doFillIntoGrid(parent, numColumns);
this.autoConfigButton.setToolTipText("Will try to find Python on the PATH (will fail if not available)");
View
80 plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/PythonInterpreterProviderFactory.java
@@ -0,0 +1,80 @@
+package org.python.pydev.ui.pythonpathconf;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.python.pydev.core.log.Log;
+import org.python.pydev.shared_core.utils.PlatformUtils;
+
+import at.jta.Key;
+import at.jta.Regor;
+
+public class PythonInterpreterProviderFactory extends AbstractInterpreterProviderFactory {
+
+ public IInterpreterProvider[] getInterpreterProviders(InterpreterType type) {
+ if (type != IInterpreterProviderFactory.InterpreterType.PYTHON) {
+ return null;
+ }
+
+ List<String> pathsToSearch = new ArrayList<String>();
+ if (!PlatformUtils.isWindowsPlatform()) {
+ pathsToSearch.add("/usr/bin");
+ pathsToSearch.add("/usr/local/bin");
+ final String ret = searchPaths(pathsToSearch, "python");
+ if (ret != null) {
+ return AlreadyInstalledInterpreterProvider.create("python", ret);
+ }
+ } else {
+ // On windows we can try to see the installed versions...
+ List<String> foundVersions = new ArrayList<String>();
+ try {
+ Regor regor = new Regor();
+
+ // The structure for Python is something as
+ // Software\\Python\\PythonCore\\2.6\\InstallPath
+ for (Key root : new Key[] { Regor.HKEY_LOCAL_MACHINE, Regor.HKEY_CURRENT_USER }) {
+ Key key = regor.openKey(root, "Software\\Python\\PythonCore", Regor.KEY_READ);
+ if (key != null) {
+ try {
+ @SuppressWarnings("rawtypes")
+ List l = regor.listKeys(key);
+ for (Object o : l) {
+ Key openKey = regor.openKey(key, (String) o + "\\InstallPath", Regor.KEY_READ);
+ if (openKey != null) {
+ try {
+ byte buf[] = regor.readValue(openKey, "");
+ if (buf != null) {
+ String parseValue = Regor.parseValue(buf);
+ // Ok, this should be the directory
+ // where it's installed, try to find
+ // a 'python.exe' there...
+ File file = new File(parseValue, "python.exe");
+ if (file.isFile()) {
+ foundVersions.add(file.toString());
+ }
+ }
+ } finally {
+ regor.closeKey(openKey);
+ }
+ }
+ }
+ } finally {
+ regor.closeKey(key);
+ }
+ }
+ }
+
+ } catch (Throwable e) {
+ Log.log(e);
+ }
+ return AlreadyInstalledInterpreterProvider.create("python",
+ foundVersions.toArray(new String[foundVersions.size()]));
+ }
+
+ // This should be enough to find it from the PATH or any other way it's
+ // defined.
+ return AlreadyInstalledInterpreterProvider.create("python", "python");
+ }
+
+}
Something went wrong with that request. Please try again.