Repository: zeppelin Updated Branches: refs/heads/master 632815c35 -> 1972a5862
[HOTFIX] Dynamic form in python interpreter ### What is this PR for? https://github.com/apache/zeppelin/pull/2106 rewrote python interpreter. But dynamic form feature is not rewritten correctly. ### What type of PR is it? Hot Fix ### Todos * [x] - Bring dynamic form back ### What is the Jira issue? https://github.com/apache/zeppelin/pull/2106 ### How should this be tested? run ``` %python print("Hello "+z.input("name", "sun")) ``` ``` %python print("Hello "+z.select("day", [("1","mon"), ("2","tue"), ("3","wed"), ("4","thurs"), ("5","fri"), ("6","sat"), ("7","sun")])) ``` ``` %python options = [("apple","Apple"), ("banana","Banana"), ("orange","Orange")] print("Hello "+ " and ".join(z.checkbox("fruit", options, ["apple"]))) ``` ### Questions: * Does the licenses files need update? no * Is there breaking changes for older versions? no * Does this needs documentation? no Author: Lee moon soo <m...@apache.org> Closes #2155 from Leemoonsoo/python_get_interpreter_context and squashes the following commits: c5e584a [Lee moon soo] fix matplotlib display error on python 3.4 3e6603b [Lee moon soo] correctly handle zeppelin.python property. 5be8db4 [Lee moon soo] Expose a method to get InterpreterOutput, so user can call InterpreterOutput.clear() a405a93 [Lee moon soo] implement dynamic form Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/1972a586 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/1972a586 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/1972a586 Branch: refs/heads/master Commit: 1972a58620b16bc4ec54191fb8660cf274647bd8 Parents: 632815c Author: Lee moon soo <m...@apache.org> Authored: Sat Mar 18 10:10:00 2017 -0700 Committer: Lee moon soo <m...@apache.org> Committed: Sun Mar 19 19:49:02 2017 -0700 ---------------------------------------------------------------------- interpreter/lib/python/backend_zinline.py | 6 +++- .../python/PythonDockerInterpreter.java | 5 +-- .../zeppelin/python/PythonInterpreter.java | 17 ++++++++-- .../main/resources/python/zeppelin_python.py | 35 +++++++++++++++----- .../main/resources/python/zeppelin_pyspark.py | 3 ++ .../interpreter/InterpreterContext.java | 4 +++ 6 files changed, 56 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/interpreter/lib/python/backend_zinline.py ---------------------------------------------------------------------- diff --git a/interpreter/lib/python/backend_zinline.py b/interpreter/lib/python/backend_zinline.py index adc5fd9..1c84699 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 @@ class FigureCanvasZInline(FigureCanvasAgg): 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 http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/python/src/main/java/org/apache/zeppelin/python/PythonDockerInterpreter.java ---------------------------------------------------------------------- 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 582debd..cb0f620 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 class PythonDockerInterpreter extends Interpreter { 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"); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java ---------------------------------------------------------------------- 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 f825568..df62406 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 class PythonInterpreter extends Interpreter implements ExecuteResultHandl } } + 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 class PythonInterpreter extends Interpreter implements ExecuteResultHandl 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<Job> jobsRunning = getScheduler().getJobsRunning(); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/python/src/main/resources/python/zeppelin_python.py ---------------------------------------------------------------------- diff --git a/python/src/main/resources/python/zeppelin_python.py b/python/src/main/resources/python/zeppelin_python.py index 0a36cba..a537c5d 100644 --- a/python/src/main/resources/python/zeppelin_python.py +++ b/python/src/main/resources/python/zeppelin_python.py @@ -48,25 +48,41 @@ class Logger(object): 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 @@ gateway = JavaGateway(client) 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() http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/spark/src/main/resources/python/zeppelin_pyspark.py ---------------------------------------------------------------------- diff --git a/spark/src/main/resources/python/zeppelin_pyspark.py b/spark/src/main/resources/python/zeppelin_pyspark.py index d9c68c2..6c39400 100644 --- a/spark/src/main/resources/python/zeppelin_pyspark.py +++ b/spark/src/main/resources/python/zeppelin_pyspark.py @@ -83,6 +83,9 @@ class PyZeppelinContext(dict): 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) http://git-wip-us.apache.org/repos/asf/zeppelin/blob/1972a586/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterContext.java ---------------------------------------------------------------------- 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 3f36405..d0db27b 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 class InterpreterContext { public void setRemoteWorksController(RemoteWorksController remoteWorksController) { this.remoteWorksController = remoteWorksController; } + + public InterpreterOutput out() { + return out; + } }