mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-23 08:50:52 +01:00
g-python shell part1
This commit is contained in:
parent
f5c8422da1
commit
dccf2a573d
@ -164,6 +164,14 @@
|
|||||||
<artifactId>slf4j-jdk14</artifactId>
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
<version>2.0.0-alpha0</version>
|
<version>2.0.0-alpha0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.maven/maven-artifact -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-artifact</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
@ -1,9 +1,165 @@
|
|||||||
package gearth.services.gpython;
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
|
import gearth.ui.extra.ExtraController;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.FlowPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class GPythonShell {
|
public class GPythonShell {
|
||||||
|
|
||||||
public void launch() {
|
private final String extensionName;
|
||||||
|
private final String cookie;
|
||||||
|
|
||||||
|
public GPythonShell(String extensionName, String cookie) {
|
||||||
|
this.extensionName = extensionName;
|
||||||
|
this.cookie = cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launch(OnQtConsoleLaunch onLaunch) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
// launch the jupyter console
|
||||||
|
ProcessBuilder gConsoleBuilder = new ProcessBuilder("python", "-m", "jupyter", "console", "--simple-prompt");
|
||||||
|
Process gConsole = gConsoleBuilder.start();
|
||||||
|
|
||||||
|
InputStreamReader in = new InputStreamReader(gConsole.getInputStream());
|
||||||
|
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(gConsole.getOutputStream()));
|
||||||
|
|
||||||
|
readUntilExpectInput(in);
|
||||||
|
|
||||||
|
// obtain jupyter kernel name
|
||||||
|
List<String> sysargs = enterCommandAndAwait(out, in, "import sys; sys.argv");
|
||||||
|
String kernelName = extractKernelName(sysargs);
|
||||||
|
|
||||||
|
|
||||||
|
onLaunch.launched(false);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
showError();
|
||||||
|
onLaunch.launched(true);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> readUntilExpectInput(InputStreamReader in) throws IOException {
|
||||||
|
List<String> readings = new ArrayList<>();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = in.read()) != -1) {
|
||||||
|
char character = (char)c;
|
||||||
|
if (character == '\n') {
|
||||||
|
String reading = builder.toString();
|
||||||
|
if (reading.endsWith("\r")) {
|
||||||
|
reading = reading.substring(0, reading.length() - 1);
|
||||||
|
}
|
||||||
|
if (reading.matches("Out\\[[0-9+]]: .*")) {
|
||||||
|
reading = reading.replaceAll("^Out\\[[0-9+]]: ", "");
|
||||||
|
if (reading.equals("")) {
|
||||||
|
builder = new StringBuilder();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readings.add(reading);
|
||||||
|
builder = new StringBuilder();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.append(character);
|
||||||
|
|
||||||
|
if (builder.toString().matches("In \\[[0-9]+]: ") && !in.ready()) {
|
||||||
|
return readings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private void enterCommand(BufferedWriter out, String command) throws IOException {
|
||||||
|
out.write(command);
|
||||||
|
out.newLine();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
private List<String> enterCommandAndAwait(BufferedWriter out, InputStreamReader in, String command) throws IOException {
|
||||||
|
enterCommand(out, command);
|
||||||
|
return readUntilExpectInput(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractKernelName(List<String> inputArgs) {
|
||||||
|
// null if not found
|
||||||
|
|
||||||
|
String joined = String.join("", inputArgs);
|
||||||
|
String paramsFull = joined.replaceAll("^[^\\[]*\\[", "").replaceAll("][^]]*$", "");
|
||||||
|
List<String> params = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean backslashed = false;
|
||||||
|
int beginParameterIndex = -1;
|
||||||
|
for (int i = 0; i < paramsFull.length(); i++) {
|
||||||
|
char c = paramsFull.charAt(i);
|
||||||
|
if (c == '\'' && !backslashed) {
|
||||||
|
if (beginParameterIndex == -1) {
|
||||||
|
beginParameterIndex = i + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.add(paramsFull.substring(beginParameterIndex, i));
|
||||||
|
beginParameterIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
backslashed = c == '\\' && !backslashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < params.size() - 1; i++) {
|
||||||
|
if (params.get(i).equals("-f")) {
|
||||||
|
return params.get(i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showError() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR, "G-Python error", ButtonType.OK);
|
||||||
|
alert.setTitle("G-Python error");
|
||||||
|
|
||||||
|
FlowPane fp = new FlowPane();
|
||||||
|
Label lbl = new Label("Something went wrong launching the G-Python shell," +
|
||||||
|
System.lineSeparator() + "are you sure you followed the installation guide correctly?" +
|
||||||
|
System.lineSeparator() + System.lineSeparator() + "More information here:");
|
||||||
|
Hyperlink link = new Hyperlink(ExtraController.INFO_URL_GPYTHON);
|
||||||
|
fp.getChildren().addAll(lbl, link);
|
||||||
|
link.setOnAction(event -> {
|
||||||
|
Main.main.getHostServices().showDocument(link.getText());
|
||||||
|
event.consume();
|
||||||
|
});
|
||||||
|
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.getDialogPane().setContent(fp);
|
||||||
|
alert.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtensionName() {
|
||||||
|
return extensionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
GPythonShell shell = new GPythonShell("test", "cookie");
|
||||||
|
shell.launch((b) -> {
|
||||||
|
System.out.println("launched");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.versioning.ComparableVersion;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GPythonVersionUtils {
|
||||||
|
|
||||||
|
private static final String MIN_GPYTHON_VERSION = "0.1";
|
||||||
|
private static final String MIN_PYTHON_VERSION = "3.2";
|
||||||
|
|
||||||
|
// returns null if python not installed
|
||||||
|
public static String pythonVersion() {
|
||||||
|
List<String> commandOutput = executeCommand("python", "--version");
|
||||||
|
if (commandOutput.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String maybeVersion = commandOutput.get(0);
|
||||||
|
if (!maybeVersion.contains("Python")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maybeVersion.split(" ")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validInstallation() {
|
||||||
|
// validates if user has all dependencies installed
|
||||||
|
String pythonVersion = pythonVersion();
|
||||||
|
if (pythonVersion == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparableVersion version = new ComparableVersion(pythonVersion);
|
||||||
|
if (version.compareTo(new ComparableVersion(MIN_PYTHON_VERSION)) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> allPackages = executeCommand("python", "-m", "pip", "list");
|
||||||
|
allPackages = allPackages.subList(2, allPackages.size());
|
||||||
|
|
||||||
|
String qtconsole = getPackageVersion(allPackages, "qtconsole");
|
||||||
|
String pyqt5 = getPackageVersion(allPackages, "pyqt5");
|
||||||
|
String jupyterConsole = getPackageVersion(allPackages, "jupyter-console");
|
||||||
|
String gPython = getPackageVersion(allPackages, "g-python");
|
||||||
|
|
||||||
|
if (qtconsole == null || pyqt5 == null || jupyterConsole == null || gPython == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparableVersion gVersion = new ComparableVersion(gPython);
|
||||||
|
return gVersion.compareTo(new ComparableVersion(MIN_GPYTHON_VERSION)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// null if not found
|
||||||
|
private static String getPackageVersion(List<String> allPackages, String pkg) {
|
||||||
|
pkg = pkg.toLowerCase();
|
||||||
|
|
||||||
|
for (String maybePkg : allPackages) {
|
||||||
|
String[] split = maybePkg.split(" +");
|
||||||
|
if (split[0].toLowerCase().equals(pkg)) {
|
||||||
|
return split[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> executeCommand(String... command) {
|
||||||
|
List<String> output = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
output.add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// System.out.println(validInstallation());
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
package gearth.services.gpython;
|
|
||||||
|
|
||||||
public class JupyterConsole {
|
|
||||||
}
|
|
@ -0,0 +1,7 @@
|
|||||||
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
public interface OnQtConsoleLaunch {
|
||||||
|
|
||||||
|
void launched(boolean failed);
|
||||||
|
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
package gearth.services.gpython;
|
|
||||||
|
|
||||||
public class PythonUtils {
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package gearth.ui.extensions;
|
package gearth.ui.extensions;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
import gearth.services.extensionhandler.ExtensionConnectedListener;
|
import gearth.services.extensionhandler.ExtensionConnectedListener;
|
||||||
import gearth.services.extensionhandler.ExtensionHandler;
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
import gearth.services.extensionhandler.extensions.ExtensionListener;
|
import gearth.services.extensionhandler.extensions.ExtensionListener;
|
||||||
@ -9,18 +10,21 @@ import gearth.services.extensionhandler.extensions.implementations.network.execu
|
|||||||
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunner;
|
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunner;
|
||||||
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunnerFactory;
|
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunnerFactory;
|
||||||
import gearth.services.gpython.GPythonShell;
|
import gearth.services.gpython.GPythonShell;
|
||||||
|
import gearth.services.gpython.OnQtConsoleLaunch;
|
||||||
import gearth.ui.SubForm;
|
import gearth.ui.SubForm;
|
||||||
import gearth.ui.extensions.logger.ExtensionLogger;
|
import gearth.ui.extensions.logger.ExtensionLogger;
|
||||||
|
import gearth.ui.extra.ExtraController;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.scene.control.TextField;
|
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 06/04/18.
|
* Created by Jonas on 06/04/18.
|
||||||
@ -103,10 +107,24 @@ public class ExtensionsController extends SubForm {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTabOpened() {
|
protected void onTabOpened() {
|
||||||
btn_gpython.setDisable(!parentController.extraController.useGPython());
|
updateGPythonStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateGPythonStatus() {
|
||||||
|
if (!pythonShellLaunching) {
|
||||||
|
btn_gpython.setDisable(!parentController.extraController.useGPython());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private volatile boolean pythonShellLaunching = false;
|
||||||
public void gpythonBtnClicked(ActionEvent actionEvent) {
|
public void gpythonBtnClicked(ActionEvent actionEvent) {
|
||||||
new GPythonShell().launch();
|
pythonShellLaunching = true;
|
||||||
|
Platform.runLater(() -> btn_gpython.setDisable(true));
|
||||||
|
GPythonShell shell = new GPythonShell("test", "cookie");
|
||||||
|
shell.launch((b) -> {
|
||||||
|
pythonShellLaunching = false;
|
||||||
|
Platform.runLater(this::updateGPythonStatus);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
package gearth.ui.extra;
|
package gearth.ui.extra;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HState;
|
import gearth.protocol.connection.HState;
|
||||||
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||||
import gearth.protocol.connection.proxy.SocksConfiguration;
|
import gearth.protocol.connection.proxy.SocksConfiguration;
|
||||||
|
import gearth.services.gpython.GPythonVersionUtils;
|
||||||
import gearth.ui.SubForm;
|
import gearth.ui.SubForm;
|
||||||
import gearth.ui.info.InfoController;
|
import gearth.ui.info.InfoController;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.web.WebView;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,6 +23,8 @@ import org.json.JSONObject;
|
|||||||
*/
|
*/
|
||||||
public class ExtraController extends SubForm implements SocksConfiguration {
|
public class ExtraController extends SubForm implements SocksConfiguration {
|
||||||
|
|
||||||
|
public static final String INFO_URL_GPYTHON = "www.placeholder.com";
|
||||||
|
|
||||||
public static final String NOTEPAD_CACHE_KEY = "notepad_text";
|
public static final String NOTEPAD_CACHE_KEY = "notepad_text";
|
||||||
public static final String SOCKS_CACHE_KEY = "socks_config";
|
public static final String SOCKS_CACHE_KEY = "socks_config";
|
||||||
public static final String GPYTHON_CACHE_KEY = "use_gpython";
|
public static final String GPYTHON_CACHE_KEY = "use_gpython";
|
||||||
@ -143,4 +151,47 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
public boolean useGPython() {
|
public boolean useGPython() {
|
||||||
return cbx_gpython.isSelected();
|
return cbx_gpython.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void gpythonCbxClick(ActionEvent actionEvent) {
|
||||||
|
if (cbx_gpython.isSelected()) {
|
||||||
|
new Thread(() -> {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbx_gpython.setSelected(false);
|
||||||
|
cbx_gpython.setDisable(true);
|
||||||
|
});
|
||||||
|
if (!GPythonVersionUtils.validInstallation()) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR, "G-Python installation", ButtonType.OK);
|
||||||
|
alert.setTitle("G-Python installation");
|
||||||
|
|
||||||
|
FlowPane fp = new FlowPane();
|
||||||
|
Label lbl = new Label("Before using G-Python, install the right packages using pip!" +
|
||||||
|
System.lineSeparator() + System.lineSeparator() + "More information here:");
|
||||||
|
Hyperlink link = new Hyperlink(INFO_URL_GPYTHON);
|
||||||
|
fp.getChildren().addAll( lbl, link);
|
||||||
|
link.setOnAction(event -> {
|
||||||
|
Main.main.getHostServices().showDocument(link.getText());
|
||||||
|
event.consume();
|
||||||
|
});
|
||||||
|
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.getDialogPane().setContent(fp);
|
||||||
|
alert.show();
|
||||||
|
|
||||||
|
cbx_gpython.setDisable(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbx_gpython.setSelected(true);
|
||||||
|
cbx_gpython.setDisable(false);
|
||||||
|
parentController.extensionsController.updateGPythonStatus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
<Insets top="2.0" />
|
<Insets top="2.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
<CheckBox fx:id="cbx_gpython" mnemonicParsing="false" text="Enable G-Python scripting" textFill="#000000ba" GridPane.rowIndex="1">
|
<CheckBox fx:id="cbx_gpython" mnemonicParsing="false" onAction="#gpythonCbxClick" text="Enable G-Python scripting" textFill="#000000ba" GridPane.rowIndex="1">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="10.0" top="2.0" />
|
<Insets left="10.0" top="2.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
|
Loading…
Reference in New Issue
Block a user