diff --git a/interpreter/lib/python/backend_zinline.py b/interpreter/lib/python/backend_zinline.py index adc5fd9e5f9..1c846993087 100644 --- a/interpreter/lib/python/backend_zinline.py +++ b/interpreter/lib/python/backend_zinline.py @@ -18,6 +18,7 @@ from __future__ import print_function +import sys import uuid import warnings import base64 @@ -94,7 +95,10 @@ def get_bytes(self, **kwargs): buf = BytesIO() self.print_figure(buf, **kwargs) fmt = fmt.encode() - byte_str = b"data:image/%s;base64," %fmt + if sys.version_info >= (3, 4) and sys.version_info < (3, 5): + byte_str = bytes("data:image/%s;base64," %fmt, "utf-8") + else: + byte_str = b"data:image/%s;base64," %fmt byte_str += base64.b64encode(buf.getvalue()) # Python3 forces all strings to default to unicode, but for raster image diff --git a/python/src/main/java/org/apache/zeppelin/python/PythonDockerInterpreter.java b/python/src/main/java/org/apache/zeppelin/python/PythonDockerInterpreter.java index 582debd4cde..cb0f62078f2 100644 --- a/python/src/main/java/org/apache/zeppelin/python/PythonDockerInterpreter.java +++ b/python/src/main/java/org/apache/zeppelin/python/PythonDockerInterpreter.java @@ -89,8 +89,9 @@ public InterpreterResult interpret(String st, InterpreterContext context) { mountPythonScript + mountPy4j + "-e PYTHONPATH=\"" + pythonPath + "\" " + - image + - " python /_zeppelin_tmp/" + pythonScript.getName()); + image + " " + + getPythonInterpreter().getPythonBindPath() + " " + + "/_zeppelin_tmp/" + pythonScript.getName()); restartPythonProcess(); out.clear(); return new InterpreterResult(InterpreterResult.Code.SUCCESS, "\"" + image + "\" activated"); diff --git a/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java b/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java index f8255681c23..df624061dd5 100644 --- a/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java +++ b/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java @@ -395,6 +395,10 @@ public InterpreterResult interpret(String cmd, InterpreterContext contextInterpr } } + public InterpreterContext getCurrentInterpreterContext() { + return context; + } + public void interrupt() throws IOException { if (pythonPid > -1) { logger.info("Sending SIGINT signal to PID : " + pythonPid); @@ -440,14 +444,23 @@ public void setPythonCommand(String cmd) { pythonCommand = cmd; } - public String getPythonCommand() { + private String getPythonCommand() { if (pythonCommand == null) { - return DEFAULT_ZEPPELIN_PYTHON; + return getPythonBindPath(); } else { return pythonCommand; } } + public String getPythonBindPath() { + String path = getProperty("zeppelin.python"); + if (path == null) { + return DEFAULT_ZEPPELIN_PYTHON; + } else { + return path; + } + } + private Job getRunningJob(String paragraphId) { Job foundJob = null; Collection jobsRunning = getScheduler().getJobsRunning(); diff --git a/python/src/main/resources/python/zeppelin_python.py b/python/src/main/resources/python/zeppelin_python.py index 0a36cbafe94..a537c5dcf57 100644 --- a/python/src/main/resources/python/zeppelin_python.py +++ b/python/src/main/resources/python/zeppelin_python.py @@ -48,25 +48,41 @@ def flush(self): class PyZeppelinContext(object): - """ If py4j is detected, these class will be override - with the implementation in bootstrap_input.py + """ A context impl that uses Py4j to communicate to JVM """ - errorMsg = "You must install py4j Python module " \ - "(pip install py4j) to use Zeppelin dynamic forms features" - def __init__(self): + def __init__(self, z): + self.z = z + self.paramOption = gateway.jvm.org.apache.zeppelin.display.Input.ParamOption + self.javaList = gateway.jvm.java.util.ArrayList self.max_result = 1000 self._displayhook = lambda *args: None self._setup_matplotlib() + def getInterpreterContext(self): + return self.z.getCurrentInterpreterContext() + def input(self, name, defaultValue=""): - print(self.errorMsg) + return self.z.getGui().input(name, defaultValue) def select(self, name, options, defaultValue=""): - print(self.errorMsg) + javaOptions = gateway.new_array(self.paramOption, len(options)) + i = 0 + for tuple in options: + javaOptions[i] = self.paramOption(tuple[0], tuple[1]) + i += 1 + return self.z.getGui().select(name, defaultValue, javaOptions) def checkbox(self, name, options, defaultChecked=[]): - print(self.errorMsg) + javaOptions = gateway.new_array(self.paramOption, len(options)) + i = 0 + for tuple in options: + javaOptions[i] = self.paramOption(tuple[0], tuple[1]) + i += 1 + javaDefaultCheck = self.javaList() + for check in defaultChecked: + javaDefaultCheck.append(check) + return self.z.getGui().checkbox(name, javaDefaultCheck, javaOptions) def show(self, p, **kwargs): if hasattr(p, '__name__') and p.__name__ == "matplotlib.pyplot": @@ -187,7 +203,8 @@ def handler_stop_signals(sig, frame): intp = gateway.entry_point intp.onPythonScriptInitialized(os.getpid()) -z = PyZeppelinContext() +java_import(gateway.jvm, "org.apache.zeppelin.display.Input") +z = PyZeppelinContext(intp) z._setup_matplotlib() output = Logger() diff --git a/spark/src/main/resources/python/zeppelin_pyspark.py b/spark/src/main/resources/python/zeppelin_pyspark.py index d9c68c28970..6c39400f147 100644 --- a/spark/src/main/resources/python/zeppelin_pyspark.py +++ b/spark/src/main/resources/python/zeppelin_pyspark.py @@ -83,6 +83,9 @@ def put(self, key, value): def get(self, key): return self.__getitem__(key) + def getInterpreterContext(self): + return self.z.getInterpreterContext() + def input(self, name, defaultValue=""): return self.z.input(name, defaultValue) diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java index 3f364056955..d0db27b470b 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java @@ -192,4 +192,8 @@ public RemoteWorksController getRemoteWorksController() { public void setRemoteWorksController(RemoteWorksController remoteWorksController) { this.remoteWorksController = remoteWorksController; } + + public InterpreterOutput out() { + return out; + } }