Skip to content

Commit

Permalink
#5477 magic/empty code return value (#5736)
Browse files Browse the repository at this point in the history
*  #5586 Added support for wildcard in classpath.

*  #5477 Print message after succesfully added classpath by magic command.

* #5477 Inform only if we added new classpath.

* #5477 %classpath message are print right now on stdout.

* #5477: print

* 5477: print

* #5477 Fixed case where we got multiple magic commands and single code.
  • Loading branch information
michalgce authored and scottdraves committed Jul 25, 2017
1 parent e686363 commit 9d7150b
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ static Path createJupyterTempFolder() {
void resetEnvironment();

void removeImport(ImportPath anImport);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/
package com.twosigma.beakerx.kernel;


import com.twosigma.beakerx.DefaultJVMVariables;
import com.twosigma.beakerx.autocomplete.AutocompleteResult;
import com.twosigma.beakerx.evaluator.Evaluator;
import com.twosigma.beakerx.evaluator.EvaluatorManager;
Expand All @@ -39,7 +37,7 @@
import sun.misc.Signal;
import sun.misc.SignalHandler;

public abstract class Kernel<T extends DefaultJVMVariables> implements KernelFunctionality {
public abstract class Kernel implements KernelFunctionality {

private static final Logger logger = LoggerFactory.getLogger(Kernel.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Maps;
import com.twosigma.beakerx.kernel.Code;
import com.twosigma.beakerx.kernel.CodeWithoutCommand;
import com.twosigma.beakerx.kernel.ImportPath;
Expand All @@ -35,17 +36,18 @@
import com.twosigma.beakerx.kernel.commands.item.MagicCommandItemWithCode;
import com.twosigma.beakerx.kernel.commands.item.MagicCommandItemWithReply;
import com.twosigma.beakerx.kernel.commands.item.MagicCommandItemWithResult;
import com.twosigma.beakerx.kernel.commands.item.MagicCommandItemWithResultAndCode;
import com.twosigma.beakerx.kernel.msg.MessageCreator;
import com.twosigma.beakerx.message.Message;
import com.twosigma.beakerx.mimetype.MIMEContainer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -161,14 +163,17 @@ private MagicCommandFunctionality unimport() {
private MagicCommandFunctionality classpathShow() {
return (code, command, message, executionCount) -> {
MIMEContainer result = Text(kernel.getClasspath());

if (code.takeCodeWithoutCommand().isPresent()) {
return new MagicCommandItemWithCode(code.takeCodeWithoutCommand().get());
return new MagicCommandItemWithResultAndCode(
messageCreator.buildOutputMessage(message, result.getCode(), false),
messageCreator.buildReplyWithoutStatus(message, executionCount),
code.takeCodeWithoutCommand().get());
}

return new MagicCommandItemWithResult(
messageCreator
.buildMessage(message, result.getMime().asString(), result.getCode(), executionCount),
messageCreator.buildReplyWithoutStatus(message, executionCount)
);
messageCreator.buildOutputMessage(message, result.getCode(), false),
messageCreator.buildReplyWithoutStatus(message, executionCount));
};
}

Expand All @@ -179,41 +184,37 @@ private MagicCommandFunctionality classpathRemove() {
private MagicCommandFunctionality classpathAddJar() {
return (code, command, message, executionCount) -> {
String[] split = command.split(" ");
List<String> addedJarsName = Lists.newLinkedList();

try {
if (split.length != 4) {
throw new IllegalStateException("Wrong command format: " + CLASSPATH_ADD_JAR);
}

String path = split[3];
if (doesPathContainsWildCards(path)) {
validateWildcardPath(path);
List<PathToJar> pathsToJars = getPaths(path).stream()
.map(PathToJar::new)
.collect(Collectors.toList());
List<Path> addedPaths = kernel.addJarsToClasspath(pathsToJars);
addedJarsName.addAll(addedPaths.stream().map(Path::toString).collect(Collectors.toList()));

} else {
validatePath(path);
Path currentPath = Paths.get(path);
if (this.kernel.addJarToClasspath(new PathToJar(path))) {
addedJarsName.add(currentPath.getFileName().toString());
}
}

return getMagicCommandItem(code, message, executionCount);
} catch (IllegalStateException e) {
if (split.length != 4) {
return new MagicCommandItemWithResult(
messageCreator
.buildOutputMessage(message, e.getMessage(), true),
.buildOutputMessage(message, "Wrong command format: " + CLASSPATH_ADD_JAR, true),
messageCreator.buildReplyWithoutStatus(message, executionCount)
);
}
String path = split[3];
return getMagicCommandItem(addJars(path), code, message, executionCount);
};
}

private Collection<String> addJars(String path) {
Map<Path, String> addedJars = Maps.newHashMap();
if (doesPathContainsWildCards(path)) {
validateWildcardPath(path);
Map<Path, String> collect = getPaths(path).keySet().stream()
.filter(
currentPath -> kernel.addJarToClasspath(new PathToJar(currentPath.toString())))
.collect(Collectors.toMap(o -> o, Path::toString));
addedJars.putAll(collect);
} else {
validatePath(path);
Path currentPath = Paths.get(path);
if (this.kernel.addJarToClasspath(new PathToJar(path))) {
addedJars.put(currentPath, currentPath.getFileName().toString());
}
}
return addedJars.values();
}

private void validateWildcardPath(String path) {
if (!containsSingleWildcardSymbol(path) || !path.endsWith("*")) {
throw new IllegalStateException("Wildcard can only appear at end of classpath: " + path);
Expand All @@ -224,14 +225,13 @@ private Boolean containsSingleWildcardSymbol(String path) {
return path.length() - path.replace("*", "").length() == 1;
}

private List<String> getPaths(String pathWithWildcard) {
private Map<Path, String> getPaths(String pathWithWildcard) {
String pathWithoutWildcards = pathWithWildcard.replace("*", "");
try {

List<String> paths = Files.list(Paths.get(pathWithoutWildcards))
.map(Path::toString)
.filter(path -> path.toLowerCase().endsWith(".jar"))
.collect(Collectors.toList());
Map<Path, String> paths = Files.list(Paths.get(pathWithoutWildcards))
.filter(path -> path.toString().toLowerCase().endsWith(".jar"))
.collect(Collectors.toMap(p -> p, o -> o.getFileName().toString()));

if (paths == null || paths.isEmpty()) {
throw new IllegalStateException("Cannot find any jars files in selected path");
Expand All @@ -248,10 +248,31 @@ private Boolean doesPathContainsWildCards(String path) {
return path.contains("*");
}

private MagicCommandItem getMagicCommandItem(Collection<String> newAddedJars, Code code, Message message, int executionCount) {
if (newAddedJars.isEmpty()) {
return getMagicCommandItem(code, message, executionCount);
}

String textMessage = "Added jar" + (newAddedJars.size() > 1 ? "s: " : ": ") + newAddedJars + "\n";

if (code.takeCodeWithoutCommand().isPresent()) {
return new MagicCommandItemWithResultAndCode(
messageCreator.buildOutputMessage(message, textMessage, false),
messageCreator.buildReplyWithoutStatus(message, executionCount),
code.takeCodeWithoutCommand().get());
}

return new MagicCommandItemWithResult(
messageCreator
.buildOutputMessage(message, textMessage, false),
messageCreator.buildReplyWithoutStatus(message, executionCount));
}

private MagicCommandItem getMagicCommandItem(Code code, Message message, int executionCount) {
if (code.takeCodeWithoutCommand().isPresent()) {
return new MagicCommandItemWithCode(code.takeCodeWithoutCommand().get());
}

return new MagicCommandItemWithReply(
messageCreator.buildReplyWithoutStatus(message, executionCount));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@
*/
package com.twosigma.beakerx.kernel.commands;

import com.twosigma.beakerx.kernel.CodeWithoutCommand;
import com.twosigma.beakerx.kernel.commands.item.MagicCommandItem;
import com.twosigma.beakerx.message.Message;

import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

public class MagicCommandResult {

Expand All @@ -31,28 +28,6 @@ public void addItem(MagicCommandItem magicCommandResultItem) {
this.items.add(magicCommandResultItem);
}

public boolean hasCodeToExecute() {
MagicCommandItem last = items.getLast();
return last.hasCodeToExecute();
}

public boolean hasResult() {
MagicCommandItem last = items.getLast();
return last.hasResult();
}

public Optional<Message> getResultMessage() {
return items.getLast().getResult();
}

public Optional<Message> replyMessage() {
return items.getLast().getReply();
}

public Optional<CodeWithoutCommand> getCode() {
return items.getLast().getCode();
}

public List<MagicCommandItem> getItems() {
return items;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.twosigma.beakerx.kernel.commands.item;

import com.twosigma.beakerx.kernel.CodeWithoutCommand;
import com.twosigma.beakerx.message.Message;
import java.util.Optional;

public class MagicCommandItemWithResultAndCode implements MagicCommandItem {

private Message resultMessage;
private Message replyMessage;
private CodeWithoutCommand code;

public MagicCommandItemWithResultAndCode(Message resultMessage,
Message replyMessage, CodeWithoutCommand code) {
this.resultMessage = resultMessage;
this.replyMessage = replyMessage;
this.code = code;
}

@Override
public boolean hasCodeToExecute() {
return getCode().isPresent();
}

@Override
public boolean hasResult() {
return getResult().isPresent();
}

@Override
public Optional<Message> getResult() {
return Optional.ofNullable(resultMessage);
}

@Override
public Optional<Message> getReply() {
return Optional.ofNullable(replyMessage);
}

@Override
public Optional<CodeWithoutCommand> getCode() {
return Optional.ofNullable(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,23 @@ private void handleMsg(Message message) throws InterruptedException {

private void handleMagicCommand(Message message, Code code) {
MagicCommandResult magicCommandResult = magicCommand.process(code, message, executionCount);
if (magicCommandResult.hasCodeToExecute()) {
runCode(magicCommandResult.getCode().get().asString(), message);
} else if (magicCommandResult.hasResult()) {
sendMagicCommandReplyAndResult(message, magicCommandResult.replyMessage().get(), magicCommandResult.getResultMessage().get());
} else {
sendMagicCommandReply(message, magicCommandResult.replyMessage().get());

magicCommandResult.getItems().forEach( item -> {
if(item.hasCodeToExecute()){
if(item.hasResult()){
kernel.publish(item.getResult().get());
}
} else if (item.hasResult()) {
sendMagicCommandReplyAndResult(message, item.getReply().get(), item.getResult().get());
} else {
sendMagicCommandReply(message, item.getReply().get());
}
} );

if (!magicCommandResult.getItems().isEmpty()) {
magicCommandResult.getItems().get(0).getCode().ifPresent(codeToExecute -> runCode(codeToExecute.asString(), message));
}

}

private Code takeCodeFrom(Message message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.twosigma.beakerx.kernel.msg;

import static com.twosigma.beakerx.kernel.Utils.timestamp;
import static com.twosigma.beakerx.kernel.msg.JupyterMessages.COMPLETE_REPLY;
import static com.twosigma.beakerx.kernel.msg.JupyterMessages.EXECUTE_REPLY;
import static com.twosigma.beakerx.kernel.msg.JupyterMessages.EXECUTE_RESULT;
import static com.twosigma.beakerx.kernel.msg.JupyterMessages.STATUS;
Expand Down
Loading

0 comments on commit 9d7150b

Please sign in to comment.