mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
ZEPPELIN-3343. Interpreter Hook is broken
This commit is contained in:
parent
c6f7f2bdb3
commit
3c55f077f4
15 changed files with 407 additions and 114 deletions
|
|
@ -259,7 +259,11 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
|
|||
// Add matplotlib display hook
|
||||
InterpreterGroup intpGroup = getInterpreterGroup();
|
||||
if (intpGroup != null && intpGroup.getInterpreterHookRegistry() != null) {
|
||||
registerHook(HookType.POST_EXEC_DEV, "__zeppelin__._displayhook()");
|
||||
try {
|
||||
registerHook(HookType.POST_EXEC_DEV.getName(), "__zeppelin__._displayhook()");
|
||||
} catch (InvalidHookException e) {
|
||||
throw new InterpreterException(e);
|
||||
}
|
||||
}
|
||||
// Add matplotlib display hook
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,29 @@ class PyZeppelinContext(object):
|
|||
#)
|
||||
body_buf.close(); header_buf.close()
|
||||
|
||||
def registerHook(self, event, cmd, replName=None):
|
||||
if replName is None:
|
||||
self.z.registerHook(event, cmd)
|
||||
else:
|
||||
self.z.registerHook(event, cmd, replName)
|
||||
|
||||
def unregisterHook(self, event, replName=None):
|
||||
if replName is None:
|
||||
self.z.unregisterHook(event)
|
||||
else:
|
||||
self.z.unregisterHook(event, replName)
|
||||
|
||||
def registerNoteHook(self, event, cmd, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.registerNoteHook(event, cmd, noteId)
|
||||
else:
|
||||
self.z.registerNoteHook(event, cmd, noteId, replName)
|
||||
|
||||
def unregisterNoteHook(self, event, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.unregisterNoteHook(event, noteId)
|
||||
else:
|
||||
self.z.unregisterNoteHook(event, noteId, replName)
|
||||
|
||||
# start JVM gateway
|
||||
client = GatewayClient(address='127.0.0.1', port=${JVM_GATEWAY_PORT})
|
||||
|
|
|
|||
|
|
@ -84,6 +84,30 @@ class PyZeppelinContext(object):
|
|||
def noteCheckbox(self, name, options, defaultChecked=[]):
|
||||
return self.z.noteCheckbox(name, self.getDefaultChecked(defaultChecked), self.getParamOptions(options))
|
||||
|
||||
def registerHook(self, event, cmd, replName=None):
|
||||
if replName is None:
|
||||
self.z.registerHook(event, cmd)
|
||||
else:
|
||||
self.z.registerHook(event, cmd, replName)
|
||||
|
||||
def unregisterHook(self, event, replName=None):
|
||||
if replName is None:
|
||||
self.z.unregisterHook(event)
|
||||
else:
|
||||
self.z.unregisterHook(event, replName)
|
||||
|
||||
def registerNoteHook(self, event, cmd, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.registerNoteHook(event, cmd, noteId)
|
||||
else:
|
||||
self.z.registerNoteHook(event, cmd, noteId, replName)
|
||||
|
||||
def unregisterNoteHook(self, event, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.unregisterNoteHook(event, noteId)
|
||||
else:
|
||||
self.z.unregisterNoteHook(event, noteId, replName)
|
||||
|
||||
def getParamOptions(self, options):
|
||||
javaOptions = gateway.new_array(self.paramOption, len(options))
|
||||
i = 0
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType;
|
|||
import org.apache.zeppelin.interpreter.InterpreterResult;
|
||||
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
|
||||
import org.apache.zeppelin.interpreter.InterpreterResultMessage;
|
||||
import org.apache.zeppelin.interpreter.InvalidHookException;
|
||||
import org.apache.zeppelin.interpreter.LazyOpenInterpreter;
|
||||
import org.apache.zeppelin.interpreter.WrappedInterpreter;
|
||||
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
|
||||
|
|
@ -152,7 +153,11 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
|
|||
// Add matplotlib display hook
|
||||
InterpreterGroup intpGroup = getInterpreterGroup();
|
||||
if (intpGroup != null && intpGroup.getInterpreterHookRegistry() != null) {
|
||||
registerHook(HookType.POST_EXEC_DEV, "__zeppelin__._displayhook()");
|
||||
try {
|
||||
registerHook(HookType.POST_EXEC_DEV.getName(), "__zeppelin__._displayhook()");
|
||||
} catch (InvalidHookException e) {
|
||||
throw new InterpreterException(e);
|
||||
}
|
||||
}
|
||||
DepInterpreter depInterpreter = getDepInterpreter();
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,18 @@ class PyZeppelinContext(dict):
|
|||
else:
|
||||
self.z.unregisterHook(event, replName)
|
||||
|
||||
def registerNoteHook(self, event, cmd, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.registerNoteHook(event, cmd, noteId)
|
||||
else:
|
||||
self.z.registerNoteHook(event, cmd, noteId, replName)
|
||||
|
||||
def unregisterNoteHook(self, event, noteId, replName=None):
|
||||
if replName is None:
|
||||
self.z.unregisterNoteHook(event, noteId)
|
||||
else:
|
||||
self.z.unregisterNoteHook(event, noteId, replName)
|
||||
|
||||
def getHook(self, event, replName=None):
|
||||
if replName is None:
|
||||
return self.z.getHook(event)
|
||||
|
|
|
|||
|
|
@ -202,9 +202,6 @@ public abstract class BaseZeppelinContext {
|
|||
this.noteGui = noteGui;
|
||||
}
|
||||
|
||||
private void restartInterpreter() {
|
||||
}
|
||||
|
||||
public InterpreterContext getInterpreterContext() {
|
||||
return interpreterContext;
|
||||
}
|
||||
|
|
@ -743,15 +740,10 @@ public abstract class BaseZeppelinContext {
|
|||
* Get the interpreter class name from name entered in paragraph
|
||||
* @param replName if replName is a valid className, return that instead.
|
||||
*/
|
||||
public String getClassNameFromReplName(String replName) {
|
||||
for (String name : getInterpreterClassMap().keySet()) {
|
||||
if (replName.equals(name)) {
|
||||
return replName;
|
||||
}
|
||||
}
|
||||
|
||||
if (replName.contains("spark.")) {
|
||||
replName = replName.replace("spark.", "");
|
||||
private String getClassNameFromReplName(String replName) {
|
||||
String[] splits = replName.split(".");
|
||||
if (splits.length > 1) {
|
||||
replName = splits[splits.length - 1];
|
||||
}
|
||||
return getInterpreterClassMap().get(replName);
|
||||
}
|
||||
|
|
@ -763,10 +755,9 @@ public abstract class BaseZeppelinContext {
|
|||
* @param replName Name of the interpreter
|
||||
*/
|
||||
@Experimental
|
||||
public void registerHook(String event, String cmd, String replName) {
|
||||
String noteId = interpreterContext.getNoteId();
|
||||
public void registerHook(String event, String cmd, String replName) throws InvalidHookException {
|
||||
String className = getClassNameFromReplName(replName);
|
||||
hooks.register(noteId, className, event, cmd);
|
||||
hooks.register(null, className, event, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -775,43 +766,42 @@ public abstract class BaseZeppelinContext {
|
|||
* @param cmd The code to be executed by the interpreter on given event
|
||||
*/
|
||||
@Experimental
|
||||
public void registerHook(String event, String cmd) {
|
||||
String className = interpreterContext.getInterpreterClassName();
|
||||
registerHook(event, cmd, className);
|
||||
public void registerHook(String event, String cmd) throws InvalidHookException {
|
||||
String replClassName = interpreterContext.getInterpreterClassName();
|
||||
hooks.register(null, replClassName, event, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hook code
|
||||
* @param event The type of event to hook to (pre_exec, post_exec)
|
||||
* @param replName Name of the interpreter
|
||||
*
|
||||
* @param event
|
||||
* @param cmd
|
||||
* @param noteId
|
||||
* @throws InvalidHookException
|
||||
*/
|
||||
@Experimental
|
||||
public String getHook(String event, String replName) {
|
||||
String noteId = interpreterContext.getNoteId();
|
||||
public void registerNoteHook(String event, String cmd, String noteId)
|
||||
throws InvalidHookException {
|
||||
String replClassName = interpreterContext.getInterpreterClassName();
|
||||
hooks.register(noteId, replClassName, event, cmd);
|
||||
}
|
||||
|
||||
@Experimental
|
||||
public void registerNoteHook(String event, String cmd, String noteId, String replName)
|
||||
throws InvalidHookException {
|
||||
String className = getClassNameFromReplName(replName);
|
||||
return hooks.get(noteId, className, event);
|
||||
hooks.register(noteId, className, event, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* getHook() wrapper for current repl
|
||||
* @param event The type of event to hook to (pre_exec, post_exec)
|
||||
*/
|
||||
@Experimental
|
||||
public String getHook(String event) {
|
||||
String className = interpreterContext.getInterpreterClassName();
|
||||
return getHook(event, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind code from given hook event
|
||||
* Unbind code from given hook event and given repl
|
||||
*
|
||||
* @param event The type of event to hook to (pre_exec, post_exec)
|
||||
* @param replName Name of the interpreter
|
||||
*/
|
||||
@Experimental
|
||||
public void unregisterHook(String event, String replName) {
|
||||
String noteId = interpreterContext.getNoteId();
|
||||
String className = getClassNameFromReplName(replName);
|
||||
hooks.unregister(noteId, className, event);
|
||||
hooks.unregister(null, className, event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -820,10 +810,35 @@ public abstract class BaseZeppelinContext {
|
|||
*/
|
||||
@Experimental
|
||||
public void unregisterHook(String event) {
|
||||
String className = interpreterContext.getInterpreterClassName();
|
||||
unregisterHook(event, className);
|
||||
unregisterHook(event, interpreterContext.getReplName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind code from given hook event and given note
|
||||
*
|
||||
* @param noteId The id of note
|
||||
* @param event The type of event to hook to (pre_exec, post_exec)
|
||||
*/
|
||||
@Experimental
|
||||
public void unregisterNoteHook(String noteId, String event) {
|
||||
String className = interpreterContext.getInterpreterClassName();
|
||||
hooks.unregister(noteId, className, event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unbind code from given hook event, given note and given repl
|
||||
* @param noteId The id of note
|
||||
* @param event The type of event to hook to (pre_exec, post_exec)
|
||||
* @param replName Name of the interpreter
|
||||
*/
|
||||
@Experimental
|
||||
public void unregisterNoteHook(String noteId, String event, String replName) {
|
||||
String className = getClassNameFromReplName(replName);
|
||||
hooks.unregister(noteId, className, event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add object into resource pool
|
||||
* @param name
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ public abstract class Interpreter {
|
|||
* @param cmd The code to be executed by the interpreter on given event
|
||||
*/
|
||||
@Experimental
|
||||
public void registerHook(String noteId, String event, String cmd) {
|
||||
public void registerHook(String noteId, String event, String cmd) throws InvalidHookException {
|
||||
InterpreterHookRegistry hooks = interpreterGroup.getInterpreterHookRegistry();
|
||||
String className = getClassName();
|
||||
hooks.register(noteId, className, event, cmd);
|
||||
|
|
@ -253,7 +253,7 @@ public abstract class Interpreter {
|
|||
* @param cmd The code to be executed by the interpreter on given event
|
||||
*/
|
||||
@Experimental
|
||||
public void registerHook(String event, String cmd) {
|
||||
public void registerHook(String event, String cmd) throws InvalidHookException {
|
||||
registerHook(null, event, cmd);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,16 @@ public class InterpreterContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setInterpreterClassName(String intpClassName) {
|
||||
context.interpreterClassName = intpClassName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setReplName(String replName) {
|
||||
context.replName = replName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InterpreterContext build() {
|
||||
return context;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,41 +18,29 @@
|
|||
package org.apache.zeppelin.interpreter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The InterpreterinterpreterHookRegistry specifies code to be conditionally executed by an
|
||||
* The InterpreterHookRegistry specifies code to be conditionally executed by an
|
||||
* interpreter. The constants defined in this class denote currently
|
||||
* supported events. Each instance is bound to a single InterpreterGroup.
|
||||
* Scope is determined on a per-note basis (except when null for global scope).
|
||||
*/
|
||||
public class InterpreterHookRegistry {
|
||||
public static final String GLOBAL_KEY = "_GLOBAL_";
|
||||
private String interpreterId;
|
||||
static final String GLOBAL_KEY = "_GLOBAL_";
|
||||
|
||||
// Scope (noteId/global scope) -> (ClassName -> (EventType -> Hook Code))
|
||||
private Map<String, Map<String, Map<String, String>>> registry = new HashMap<>();
|
||||
|
||||
/**
|
||||
* hookRegistry constructor.
|
||||
*
|
||||
* @param interpreterId The Id of the InterpreterGroup instance to bind to
|
||||
*/
|
||||
public InterpreterHookRegistry(final String interpreterId) {
|
||||
this.interpreterId = interpreterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interpreterGroup id this instance is bound to
|
||||
*/
|
||||
public String getInterpreterId() {
|
||||
return interpreterId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a note to the registry
|
||||
*
|
||||
* @param noteId The Id of the Note instance to add
|
||||
*/
|
||||
public void addNote(String noteId) {
|
||||
private void addNote(String noteId) {
|
||||
synchronized (registry) {
|
||||
if (registry.get(noteId) == null) {
|
||||
registry.put(noteId, new HashMap<String, Map<String, String>>());
|
||||
|
|
@ -66,7 +54,7 @@ public class InterpreterHookRegistry {
|
|||
* @param noteId The note id
|
||||
* @param className The name of the interpreter repl to map the hooks to
|
||||
*/
|
||||
public void addRepl(String noteId, String className) {
|
||||
private void addRepl(String noteId, String className) {
|
||||
synchronized (registry) {
|
||||
addNote(noteId);
|
||||
if (registry.get(noteId).get(className) == null) {
|
||||
|
|
@ -84,19 +72,15 @@ public class InterpreterHookRegistry {
|
|||
* @param cmd Code to be executed by the interpreter
|
||||
*/
|
||||
public void register(String noteId, String className,
|
||||
String event, String cmd) throws IllegalArgumentException {
|
||||
String event, String cmd) throws InvalidHookException {
|
||||
synchronized (registry) {
|
||||
if (!HookType.ValidEvents.contains(event)) {
|
||||
throw new InvalidHookException("event " + event + " is not valid hook event");
|
||||
}
|
||||
if (noteId == null) {
|
||||
noteId = GLOBAL_KEY;
|
||||
}
|
||||
addRepl(noteId, className);
|
||||
if (!event.equals(HookType.POST_EXEC) && !event.equals(HookType.PRE_EXEC) &&
|
||||
!event.equals(HookType.POST_EXEC_DEV) && !event.equals(HookType.PRE_EXEC_DEV)) {
|
||||
throw new IllegalArgumentException("Must be " + HookType.POST_EXEC + ", " +
|
||||
HookType.POST_EXEC_DEV + ", " +
|
||||
HookType.PRE_EXEC + " or " +
|
||||
HookType.PRE_EXEC_DEV);
|
||||
}
|
||||
registry.get(noteId).get(className).put(event, cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -138,18 +122,36 @@ public class InterpreterHookRegistry {
|
|||
/**
|
||||
* Container for hook event type constants
|
||||
*/
|
||||
public static final class HookType {
|
||||
public enum HookType {
|
||||
|
||||
// Execute the hook code PRIOR to main paragraph code execution
|
||||
public static final String PRE_EXEC = "pre_exec";
|
||||
PRE_EXEC("pre_exec"),
|
||||
|
||||
// Execute the hook code AFTER main paragraph code execution
|
||||
public static final String POST_EXEC = "post_exec";
|
||||
POST_EXEC("post_exec"),
|
||||
|
||||
// Same as above but reserved for interpreter developers, in order to allow
|
||||
// notebook users to use the above without overwriting registry settings
|
||||
// that are initialized directly in subclasses of Interpreter.
|
||||
public static final String PRE_EXEC_DEV = "pre_exec_dev";
|
||||
public static final String POST_EXEC_DEV = "post_exec_dev";
|
||||
PRE_EXEC_DEV("pre_exec_dev"),
|
||||
POST_EXEC_DEV("post_exec_dev");
|
||||
|
||||
private String name;
|
||||
|
||||
HookType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Set<String> ValidEvents = new HashSet();
|
||||
static {
|
||||
for (HookType type : values()) {
|
||||
ValidEvents.add(type.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.zeppelin.interpreter;
|
||||
|
||||
/**
|
||||
* Exception for invalid hook
|
||||
*/
|
||||
public class InvalidHookException extends Exception {
|
||||
|
||||
public InvalidHookException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -165,12 +165,12 @@ public class LazyOpenInterpreter
|
|||
}
|
||||
|
||||
@Override
|
||||
public void registerHook(String noteId, String event, String cmd) {
|
||||
public void registerHook(String noteId, String event, String cmd) throws InvalidHookException {
|
||||
intp.registerHook(noteId, event, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerHook(String event, String cmd) {
|
||||
public void registerHook(String event, String cmd) throws InvalidHookException {
|
||||
intp.registerHook(event, cmd);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ public class RemoteInterpreterServer extends Thread
|
|||
if (interpreterGroup == null) {
|
||||
interpreterGroup = new InterpreterGroup(interpreterGroupId);
|
||||
angularObjectRegistry = new AngularObjectRegistry(interpreterGroup.getId(), this);
|
||||
hookRegistry = new InterpreterHookRegistry(interpreterGroup.getId());
|
||||
hookRegistry = new InterpreterHookRegistry();
|
||||
resourcePool = new DistributedResourcePool(interpreterGroup.getId(), eventClient);
|
||||
interpreterGroup.setInterpreterHookRegistry(hookRegistry);
|
||||
interpreterGroup.setAngularObjectRegistry(angularObjectRegistry);
|
||||
|
|
@ -563,8 +563,8 @@ public class RemoteInterpreterServer extends Thread
|
|||
InterpreterHookListener hookListener = new InterpreterHookListener() {
|
||||
@Override
|
||||
public void onPreExecute(String script) {
|
||||
String cmdDev = interpreter.getHook(noteId, HookType.PRE_EXEC_DEV);
|
||||
String cmdUser = interpreter.getHook(noteId, HookType.PRE_EXEC);
|
||||
String cmdDev = interpreter.getHook(noteId, HookType.PRE_EXEC_DEV.getName());
|
||||
String cmdUser = interpreter.getHook(noteId, HookType.PRE_EXEC.getName());
|
||||
|
||||
// User defined hook should be executed before dev hook
|
||||
List<String> cmds = Arrays.asList(cmdDev, cmdUser);
|
||||
|
|
@ -579,8 +579,8 @@ public class RemoteInterpreterServer extends Thread
|
|||
|
||||
@Override
|
||||
public void onPostExecute(String script) {
|
||||
String cmdDev = interpreter.getHook(noteId, HookType.POST_EXEC_DEV);
|
||||
String cmdUser = interpreter.getHook(noteId, HookType.POST_EXEC);
|
||||
String cmdDev = interpreter.getHook(noteId, HookType.POST_EXEC_DEV.getName());
|
||||
String cmdUser = interpreter.getHook(noteId, HookType.POST_EXEC.getName());
|
||||
|
||||
// User defined hook should be executed after dev hook
|
||||
List<String> cmds = Arrays.asList(cmdUser, cmdDev);
|
||||
|
|
@ -616,9 +616,16 @@ public class RemoteInterpreterServer extends Thread
|
|||
|
||||
if (result == null || result.code() == Code.SUCCESS) {
|
||||
// Add hooks to script from registry.
|
||||
// Global scope first, followed by notebook scope
|
||||
processInterpreterHooks(null);
|
||||
// note scope first, followed by global scope.
|
||||
// Here's the code after hooking:
|
||||
// global_pre_hook
|
||||
// note_pre_hook
|
||||
// script
|
||||
// note_post_hook
|
||||
// global_post_hook
|
||||
processInterpreterHooks(context.getNoteId());
|
||||
processInterpreterHooks(null);
|
||||
logger.debug("Script after hooks: " + script);
|
||||
result = interpreter.interpret(script, context);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.zeppelin.interpreter;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
public class BaseZeppelinContextTest {
|
||||
|
||||
@Test
|
||||
public void testHooks() throws InvalidHookException {
|
||||
InterpreterHookRegistry hookRegistry = new InterpreterHookRegistry();
|
||||
TestZeppelinContext z = new TestZeppelinContext(hookRegistry, 10);
|
||||
InterpreterContext context = InterpreterContext.builder()
|
||||
.setNoteId("note_1")
|
||||
.setParagraphId("paragraph_1")
|
||||
.setInterpreterClassName("Test1Interpreter")
|
||||
.setReplName("test1")
|
||||
.build();
|
||||
z.setInterpreterContext(context);
|
||||
|
||||
// register global hook for current interpreter
|
||||
z.registerHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "pre_cmd");
|
||||
z.registerHook(InterpreterHookRegistry.HookType.POST_EXEC.getName(), "post_cmd");
|
||||
assertEquals("pre_cmd", hookRegistry.get(null, "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals("post_cmd", hookRegistry.get(null, "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
z.unregisterHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName());
|
||||
z.unregisterHook(InterpreterHookRegistry.HookType.POST_EXEC.getName());
|
||||
assertEquals(null, hookRegistry.get(null, "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals(null, hookRegistry.get(null, "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
// register global hook for interpreter test2
|
||||
z.registerHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "pre_cmd2", "test2");
|
||||
z.registerHook(InterpreterHookRegistry.HookType.POST_EXEC.getName(), "post_cmd2", "test2");
|
||||
assertEquals("pre_cmd2", hookRegistry.get(null, "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals("post_cmd2", hookRegistry.get(null, "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
z.unregisterHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "test2");
|
||||
z.unregisterHook(InterpreterHookRegistry.HookType.POST_EXEC.getName(), "test2");
|
||||
assertEquals(null, hookRegistry.get(null, "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals(null, hookRegistry.get(null, "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
// register hook for note_1 and current interpreter
|
||||
z.registerNoteHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "pre_cmd", "note_1");
|
||||
z.registerNoteHook(InterpreterHookRegistry.HookType.POST_EXEC.getName(), "post_cmd", "note_1");
|
||||
assertEquals("pre_cmd", hookRegistry.get("note_1", "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals("post_cmd", hookRegistry.get("note_1", "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
z.unregisterNoteHook("note_1", InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "test1");
|
||||
z.unregisterNoteHook("note_1", InterpreterHookRegistry.HookType.POST_EXEC.getName(), "test1");
|
||||
assertEquals(null, hookRegistry.get("note_1", "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals(null, hookRegistry.get("note_1", "Test1Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
// register hook for note_1 and interpreter test2
|
||||
z.registerNoteHook(InterpreterHookRegistry.HookType.PRE_EXEC.getName(),
|
||||
"pre_cmd2", "note_1", "test2");
|
||||
z.registerNoteHook(InterpreterHookRegistry.HookType.POST_EXEC.getName(),
|
||||
"post_cmd2", "note_1", "test2");
|
||||
assertEquals("pre_cmd2", hookRegistry.get("note_1", "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals("post_cmd2", hookRegistry.get("note_1", "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
|
||||
z.unregisterNoteHook("note_1", InterpreterHookRegistry.HookType.PRE_EXEC.getName(), "test2");
|
||||
z.unregisterNoteHook("note_1", InterpreterHookRegistry.HookType.POST_EXEC.getName(), "test2");
|
||||
assertEquals(null, hookRegistry.get("note_1", "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.PRE_EXEC.getName()));
|
||||
assertEquals(null, hookRegistry.get("note_1", "Test2Interpreter",
|
||||
InterpreterHookRegistry.HookType.POST_EXEC.getName()));
|
||||
}
|
||||
|
||||
|
||||
public static class TestZeppelinContext extends BaseZeppelinContext {
|
||||
|
||||
public TestZeppelinContext(InterpreterHookRegistry hooks, int maxResult) {
|
||||
super(hooks, maxResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getInterpreterClassMap() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("test1", "Test1Interpreter");
|
||||
map.put("test2", "Test2Interpreter");
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class> getSupportedClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String showData(Object obj) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -19,54 +19,54 @@ package org.apache.zeppelin.interpreter;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType.POST_EXEC;
|
||||
import static org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType.POST_EXEC_DEV;
|
||||
import static org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType.PRE_EXEC;
|
||||
import static org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType.PRE_EXEC_DEV;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class InterpreterHookRegistryTest {
|
||||
|
||||
@Test
|
||||
public void testBasic() {
|
||||
final String PRE_EXEC = InterpreterHookRegistry.HookType.PRE_EXEC;
|
||||
final String POST_EXEC = InterpreterHookRegistry.HookType.POST_EXEC;
|
||||
final String PRE_EXEC_DEV = InterpreterHookRegistry.HookType.PRE_EXEC_DEV;
|
||||
final String POST_EXEC_DEV = InterpreterHookRegistry.HookType.POST_EXEC_DEV;
|
||||
public void testBasic() throws InvalidHookException {
|
||||
final String GLOBAL_KEY = InterpreterHookRegistry.GLOBAL_KEY;
|
||||
final String noteId = "note";
|
||||
final String className = "class";
|
||||
final String preExecHook = "pre";
|
||||
final String postExecHook = "post";
|
||||
InterpreterHookRegistry registry = new InterpreterHookRegistry("intpId");
|
||||
InterpreterHookRegistry registry = new InterpreterHookRegistry();
|
||||
|
||||
// Test register()
|
||||
registry.register(noteId, className, PRE_EXEC, preExecHook);
|
||||
registry.register(noteId, className, POST_EXEC, postExecHook);
|
||||
registry.register(noteId, className, PRE_EXEC_DEV, preExecHook);
|
||||
registry.register(noteId, className, POST_EXEC_DEV, postExecHook);
|
||||
registry.register(noteId, className, PRE_EXEC.getName(), preExecHook);
|
||||
registry.register(noteId, className, POST_EXEC.getName(), postExecHook);
|
||||
registry.register(noteId, className, PRE_EXEC_DEV.getName(), preExecHook);
|
||||
registry.register(noteId, className, POST_EXEC_DEV.getName(), postExecHook);
|
||||
|
||||
// Test get()
|
||||
assertEquals(registry.get(noteId, className, PRE_EXEC), preExecHook);
|
||||
assertEquals(registry.get(noteId, className, POST_EXEC), postExecHook);
|
||||
assertEquals(registry.get(noteId, className, PRE_EXEC_DEV), preExecHook);
|
||||
assertEquals(registry.get(noteId, className, POST_EXEC_DEV), postExecHook);
|
||||
assertEquals(registry.get(noteId, className, PRE_EXEC.getName()), preExecHook);
|
||||
assertEquals(registry.get(noteId, className, POST_EXEC.getName()), postExecHook);
|
||||
assertEquals(registry.get(noteId, className, PRE_EXEC_DEV.getName()), preExecHook);
|
||||
assertEquals(registry.get(noteId, className, POST_EXEC_DEV.getName()), postExecHook);
|
||||
|
||||
// Test Unregister
|
||||
registry.unregister(noteId, className, PRE_EXEC);
|
||||
registry.unregister(noteId, className, POST_EXEC);
|
||||
registry.unregister(noteId, className, PRE_EXEC_DEV);
|
||||
registry.unregister(noteId, className, POST_EXEC_DEV);
|
||||
assertNull(registry.get(noteId, className, PRE_EXEC));
|
||||
assertNull(registry.get(noteId, className, POST_EXEC));
|
||||
assertNull(registry.get(noteId, className, PRE_EXEC_DEV));
|
||||
assertNull(registry.get(noteId, className, POST_EXEC_DEV));
|
||||
registry.unregister(noteId, className, PRE_EXEC.getName());
|
||||
registry.unregister(noteId, className, POST_EXEC.getName());
|
||||
registry.unregister(noteId, className, PRE_EXEC_DEV.getName());
|
||||
registry.unregister(noteId, className, POST_EXEC_DEV.getName());
|
||||
assertNull(registry.get(noteId, className, PRE_EXEC.getName()));
|
||||
assertNull(registry.get(noteId, className, POST_EXEC.getName()));
|
||||
assertNull(registry.get(noteId, className, PRE_EXEC_DEV.getName()));
|
||||
assertNull(registry.get(noteId, className, POST_EXEC_DEV.getName()));
|
||||
|
||||
// Test Global Scope
|
||||
registry.register(null, className, PRE_EXEC, preExecHook);
|
||||
assertEquals(registry.get(GLOBAL_KEY, className, PRE_EXEC), preExecHook);
|
||||
registry.register(null, className, PRE_EXEC.getName(), preExecHook);
|
||||
assertEquals(registry.get(GLOBAL_KEY, className, PRE_EXEC.getName()), preExecHook);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testValidEventCode() {
|
||||
InterpreterHookRegistry registry = new InterpreterHookRegistry("intpId");
|
||||
@Test(expected = InvalidHookException.class)
|
||||
public void testValidEventCode() throws InvalidHookException {
|
||||
InterpreterHookRegistry registry = new InterpreterHookRegistry();
|
||||
|
||||
// Test that only valid event codes ("pre_exec", "post_exec") are accepted
|
||||
registry.register("foo", "bar", "baz", "whatever");
|
||||
|
|
|
|||
|
|
@ -379,7 +379,36 @@ public class ZeppelinSparkClusterTest extends AbstractTestRestApi {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void pySparkDepLoaderTest() throws IOException, InterpreterException {
|
||||
public void testZeppelinContextHook() throws IOException {
|
||||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
|
||||
// register global hook & note1 hook
|
||||
Paragraph p1 = note.addNewParagraph(anonymous);
|
||||
p1.setText("%python from __future__ import print_function\n" +
|
||||
"z.registerHook('pre_exec', 'print(1)')\n" +
|
||||
"z.registerHook('post_exec', 'print(2)')\n" +
|
||||
"z.registerNoteHook('pre_exec', 'print(3)', '" + note.getId() + "')\n" +
|
||||
"z.registerNoteHook('post_exec', 'print(4)', '" + note.getId() + "')\n");
|
||||
|
||||
Paragraph p2 = note.addNewParagraph(anonymous);
|
||||
p2.setText("%python print(5)");
|
||||
|
||||
note.run(p1.getId(), true);
|
||||
note.run(p2.getId(), true);
|
||||
|
||||
assertEquals(Status.FINISHED, p1.getStatus());
|
||||
assertEquals(Status.FINISHED, p2.getStatus());
|
||||
assertEquals("1\n3\n5\n4\n2\n", p2.getResult().message().get(0).getData());
|
||||
|
||||
Note note2 = ZeppelinServer.notebook.createNote(anonymous);
|
||||
Paragraph p3 = note2.addNewParagraph(anonymous);
|
||||
p3.setText("%python print(6)");
|
||||
note2.run(p3.getId(), true);
|
||||
assertEquals("1\n6\n2\n", p3.getResult().message().get(0).getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pySparkDepLoaderTest() throws IOException {
|
||||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
|
||||
// restart spark interpreter to make dep loader work
|
||||
|
|
|
|||
Loading…
Reference in a new issue