Bug 536451: [Python] suppress shell output for 'None' results

Change-Id: I4688bfcbec56d14d97732285c13974e1cc731073
diff --git a/plugins/org.eclipse.ease.lang.python.jython/src/org/eclipse/ease/lang/python/jython/JythonScriptEngine.java b/plugins/org.eclipse.ease.lang.python.jython/src/org/eclipse/ease/lang/python/jython/JythonScriptEngine.java
index 838c834..215a8fa 100644
--- a/plugins/org.eclipse.ease.lang.python.jython/src/org/eclipse/ease/lang/python/jython/JythonScriptEngine.java
+++ b/plugins/org.eclipse.ease.lang.python.jython/src/org/eclipse/ease/lang/python/jython/JythonScriptEngine.java
@@ -17,10 +17,9 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.eclipse.core.resources.IFile;
@@ -31,6 +30,7 @@
 import org.eclipse.ease.AbstractReplScriptEngine;
 import org.eclipse.ease.Script;
 import org.eclipse.ease.ScriptEngineException;
+import org.eclipse.ease.ScriptResult;
 import org.eclipse.ease.lang.python.PythonHelper;
 import org.eclipse.ease.lang.python.preferences.IPreferenceConstants;
 import org.eclipse.ease.tools.RunnableWithResult;
@@ -59,9 +59,9 @@
 
 	public static final String ENGINE_ID = "org.eclipse.ease.python.jython";
 
-	protected InteractiveInterpreter mEngine;
+	protected InteractiveInterpreter fEngine;
 
-	private PyObject mResult;
+	private PyObject fResult;
 
 	private class DisplayHook extends PyObject {
 
@@ -69,7 +69,7 @@
 
 		@Override
 		public PyObject __call__(final PyObject arg0) {
-			mResult = arg0;
+			fResult = arg0;
 			return Py.None;
 		}
 	}
@@ -105,7 +105,7 @@
 
 	@Override
 	protected void setupEngine() throws ScriptEngineException {
-		mEngine = new InteractiveInterpreter();
+		fEngine = new InteractiveInterpreter();
 
 		// register display callback method to extract execution result
 		final DisplayHook displayHook = new DisplayHook();
@@ -162,11 +162,12 @@
 	}
 
 	protected Object internalExecute(final Script script, final String fileName) throws Exception {
-		mResult = Py.None;
+		fResult = Py.None;
 
 		final PyObject code = Py.compile_command_flags(script.getCode(), "(none)", CompileMode.exec, new CompilerFlags(), true);
 		if (code == Py.None)
-			throw new RuntimeException("Could not compile code");
+			throw new IllegalArgumentException("Could not compile code");
+
 		final Object file = script.getFile();
 		File f = null;
 		if (file instanceof IFile) {
@@ -187,7 +188,7 @@
 		if (newString != null) {
 			Py.getSystemState().path.remove(newString);
 		}
-		return toJava(mResult);
+		return toJava(fResult);
 	}
 
 	private static Object toJava(final PyObject result) {
@@ -243,24 +244,19 @@
 	}
 
 	protected Collection<String> getPythonLibraries() {
-		final List<String> result = new ArrayList<>();
 		final IPreferenceStore preferences = Activator.getDefault().getPreferenceStore();
 		final String libraries = preferences.getString(IPreferenceConstants.PYTHON_LIBRARIES);
-		final String[] libs = libraries.split(";");
-		for (final String lib : libs) {
-			result.add(lib);
-		}
-		return result;
+		return Arrays.asList(libraries.split(";"));
 	}
 
 	@Override
 	public void registerJar(final URL url) {
 		// FIXME implement jar classloader
-		throw new RuntimeException("Registering JARs is not supported for python");
+		throw new UnsupportedOperationException("Registering JARs is not supported for python");
 	}
 
 	protected InteractiveInterpreter getEngine() {
-		return mEngine;
+		return fEngine;
 	}
 
 	@Override
@@ -301,4 +297,12 @@
 		getEngine().set(name, content);
 		getEngine().getSystemState().builtins.__setitem__(name, Py.java2py(content));
 	}
+
+	@Override
+	public String toString(Object object) {
+		if ((object == null) || (ScriptResult.VOID.equals(object)))
+			return null;
+
+		return super.toString(object);
+	}
 }
diff --git a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jScriptEngine.java b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jScriptEngine.java
index c06b094..7e24c5b 100644
--- a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jScriptEngine.java
+++ b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jScriptEngine.java
@@ -369,10 +369,7 @@
 
 	@Override
 	public String toString(Object object) {
-		if (object == null)
-			return "None";
-
-		if (ScriptResult.VOID.equals(object))
+		if ((object == null) || (ScriptResult.VOID.equals(object)))
 			return null;
 
 		return super.toString(object);
diff --git a/tests/org.eclipse.ease.lang.python.jython.test/src/org/eclipse/ease/lang/python/jython/JythonScriptEngineTest.java b/tests/org.eclipse.ease.lang.python.jython.test/src/org/eclipse/ease/lang/python/jython/JythonScriptEngineTest.java
new file mode 100644
index 0000000..c48693b
--- /dev/null
+++ b/tests/org.eclipse.ease.lang.python.jython.test/src/org/eclipse/ease/lang/python/jython/JythonScriptEngineTest.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Christian Pontesegger and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License_Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Christian Pontesegger - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ease.lang.python.jython;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ease.ScriptResult;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+public class JythonScriptEngineTest {
+
+	@Test
+	@DisplayName("toString(VOID) is null")
+	public void toString_of_VOID_is_null() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertNull(new JythonScriptEngine().toString(ScriptResult.VOID));
+	}
+
+	@Test
+	@DisplayName("toString(null) is null")
+	public void toString_of_null_is_null() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertNull(new JythonScriptEngine().toString(null));
+	}
+
+	@Test
+	@DisplayName("toString(Object) is not empty")
+	public void toString_of_Object_is_not_empty() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertEquals("foo", new JythonScriptEngine().toString("foo"));
+	}
+
+}
diff --git a/tests/org.eclipse.ease.lang.python.py4j.test/src/org/eclipse/ease/lang/python/py4j/Py4jScriptEngineTest.java b/tests/org.eclipse.ease.lang.python.py4j.test/src/org/eclipse/ease/lang/python/py4j/Py4jScriptEngineTest.java
index 6428628..979b80a 100644
--- a/tests/org.eclipse.ease.lang.python.py4j.test/src/org/eclipse/ease/lang/python/py4j/Py4jScriptEngineTest.java
+++ b/tests/org.eclipse.ease.lang.python.py4j.test/src/org/eclipse/ease/lang/python/py4j/Py4jScriptEngineTest.java
@@ -13,6 +13,8 @@
 
 package org.eclipse.ease.lang.python.py4j;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
@@ -56,10 +58,21 @@
 	}
 
 	@Test
-	@DisplayName("xxPYTHONPATH contains project root folder")
-	public void PYTHONPfATH_contains_project_root_folder() throws ExecutionException, CoreException, URISyntaxException, IOException {
-		final IProject project = WorkspaceTestHelper.importProject("org.eclipse.ease.lang.python.py4j.test", "resources/genericproject");
-		pathTest(Pattern.compile(".*resources.testproject"), project.getFile("hello.py"));
+	@DisplayName("toString(VOID) is null")
+	public void toString_of_VOID_is_null() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertNull(new Py4jScriptEngine().toString(ScriptResult.VOID));
+	}
+
+	@Test
+	@DisplayName("toString(null) is null")
+	public void toString_of_null_is_null() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertNull(new Py4jScriptEngine().toString(null));
+	}
+
+	@Test
+	@DisplayName("toString(Object) is not empty")
+	public void toString_of_Object_is_not_empty() throws ExecutionException, CoreException, URISyntaxException, IOException {
+		assertEquals("foo", new Py4jScriptEngine().toString("foo"));
 	}
 
 	private void pathTest(Pattern pathPattern) throws ExecutionException {