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>
|
||||
<version>2.0.0-alpha0</version>
|
||||
</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>
|
||||
|
||||
<repositories>
|
||||
|
@ -1,9 +1,165 @@
|
||||
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 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;
|
||||
|
||||
import gearth.Main;
|
||||
import gearth.services.extensionhandler.ExtensionConnectedListener;
|
||||
import gearth.services.extensionhandler.ExtensionHandler;
|
||||
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.ExtensionRunnerFactory;
|
||||
import gearth.services.gpython.GPythonShell;
|
||||
import gearth.services.gpython.OnQtConsoleLaunch;
|
||||
import gearth.ui.SubForm;
|
||||
import gearth.ui.extensions.logger.ExtensionLogger;
|
||||
import gearth.ui.extra.ExtraController;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Jonas on 06/04/18.
|
||||
@ -103,10 +107,24 @@ public class ExtensionsController extends SubForm {
|
||||
|
||||
@Override
|
||||
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) {
|
||||
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;
|
||||
|
||||
import gearth.Main;
|
||||
import gearth.misc.Cacher;
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.connection.HState;
|
||||
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||
import gearth.protocol.connection.proxy.SocksConfiguration;
|
||||
import gearth.services.gpython.GPythonVersionUtils;
|
||||
import gearth.ui.SubForm;
|
||||
import gearth.ui.info.InfoController;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.web.WebView;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
@ -17,6 +23,8 @@ import org.json.JSONObject;
|
||||
*/
|
||||
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 SOCKS_CACHE_KEY = "socks_config";
|
||||
public static final String GPYTHON_CACHE_KEY = "use_gpython";
|
||||
@ -143,4 +151,47 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
||||
public boolean useGPython() {
|
||||
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" />
|
||||
</padding>
|
||||
</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>
|
||||
<Insets left="10.0" top="2.0" />
|
||||
</GridPane.margin>
|
||||
|
Loading…
Reference in New Issue
Block a user