You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by zj...@apache.org on 2019/08/07 08:14:59 UTC
[zeppelin] branch master updated: [ZEPPELIN-4265]. Support more
types of output for IPythonInterpreter
This is an automated email from the ASF dual-hosted git repository.
zjffdu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new a04bdb3 [ZEPPELIN-4265]. Support more types of output for IPythonInterpreter
a04bdb3 is described below
commit a04bdb349bc9ff8f3ccf68687f60f5938a88cec0
Author: Jeff Zhang <zj...@apache.org>
AuthorDate: Mon Aug 5 10:31:44 2019 +0800
[ZEPPELIN-4265]. Support more types of output for IPythonInterpreter
### What is this PR for?
The final target of IPythonInterpreter is to make zeppelin IPythonInterpreter compatible with jupyter. I tried several popular python viz tools. And find some of them doesn't work due to IPythonInterpreter's limitation. This PR is trying to support more types of output for IPythonInterpreter.
### What type of PR is it?
[Improvement]
### Todos
* [ ] - Task
### What is the Jira issue?
* Open an issue on Jira https://issues.apache.org/jira/browse/ZEPPELIN/
* Put link here, and add [ZEPPELIN-*Jira number*] in PR title, eg. [ZEPPELIN-533]
### How should this be tested?
### Screenshots (if appropriate)
**Pands**
![image](https://user-images.githubusercontent.com/164491/62295599-fe414180-b49f-11e9-930c-461c83fb7285.png)
**Altair**
![image](https://user-images.githubusercontent.com/164491/62284745-d1ccfb80-b486-11e9-9c97-01fc2dda5975.png)
**HoloView**
![image](https://user-images.githubusercontent.com/164491/62285001-5ddf2300-b487-11e9-825f-0de4bc051012.png)
**HvPlot**
![image](https://user-images.githubusercontent.com/164491/62285038-6d5e6c00-b487-11e9-8eed-39bd6a405545.png)
**Pandas Bokeh**
![image](https://user-images.githubusercontent.com/164491/62285342-fd9cb100-b487-11e9-94c8-b4da33cfe672.png)
**Plotnine**
![image](https://user-images.githubusercontent.com/164491/62304961-9a277900-b4b1-11e9-91d3-51687cab90be.png)
### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Author: Jeff Zhang <zj...@apache.org>
Closes #3419 from zjffdu/ZEPPELIN-4265 and squashes the following commits:
475a91f16 [Jeff Zhang] revert changes in ipython_client.py
2ebac7568 [Jeff Zhang] [ZEPPELIN-4265]. Support more types of output for IPythonInterpreter
---
.../org/apache/zeppelin/python/IPythonClient.java | 42 ++-
python/src/main/proto/ipython.proto | 7 +-
.../src/main/resources/grpc/python/ipython_pb2.py | 398 ++++++---------------
.../main/resources/grpc/python/ipython_server.py | 70 +++-
.../zeppelin/python/IPythonInterpreterTest.java | 35 +-
.../apache/zeppelin/dep/DependencyResolver.java | 6 +-
.../zeppelin/notebook/repo/VFSNotebookRepo.java | 4 +
7 files changed, 239 insertions(+), 323 deletions(-)
diff --git a/python/src/main/java/org/apache/zeppelin/python/IPythonClient.java b/python/src/main/java/org/apache/zeppelin/python/IPythonClient.java
index c729898..ec0c052 100644
--- a/python/src/main/java/org/apache/zeppelin/python/IPythonClient.java
+++ b/python/src/main/java/org/apache/zeppelin/python/IPythonClient.java
@@ -88,35 +88,47 @@ public class IPythonClient {
LOGGER.debug("stream_execute code:\n" + request.getCode());
asyncStub.execute(request, new StreamObserver<ExecuteResponse>() {
int index = 0;
- boolean isPreviousOutputImage = false;
@Override
public void onNext(ExecuteResponse executeResponse) {
+ LOGGER.debug("Interpreter Streaming Output: " + executeResponse.getType() +
+ "\t" + executeResponse.getOutput());
+ if (index != 0) {
+ try {
+ // We need to add line separator first, because zeppelin only recoginize the % at
+ // the line beginning.
+ interpreterOutput.write("\n".getBytes());
+ } catch (IOException e) {
+ LOGGER.error("Unexpected IOException", e);
+ }
+ }
+
if (executeResponse.getType() == OutputType.TEXT) {
try {
- LOGGER.debug("Interpreter Streaming Output: " + executeResponse.getOutput());
- if (isPreviousOutputImage) {
- // add '\n' when switch from image to text
- interpreterOutput.write("\n%text ".getBytes());
+ if (executeResponse.getOutput().startsWith("%")) {
+ // the output from ipython kernel maybe specify format already.
+ interpreterOutput.write((executeResponse.getOutput()).getBytes());
+ } else {
+ interpreterOutput.write(("%text " + executeResponse.getOutput()).getBytes());
}
- isPreviousOutputImage = false;
- interpreterOutput.write(executeResponse.getOutput().getBytes());
interpreterOutput.getInterpreterOutput().flush();
} catch (IOException e) {
LOGGER.error("Unexpected IOException", e);
}
}
- if (executeResponse.getType() == OutputType.IMAGE) {
+ if (executeResponse.getType() == OutputType.PNG ||
+ executeResponse.getType() == OutputType.JPEG) {
try {
- LOGGER.debug("Interpreter Streaming Output: IMAGE_DATA");
- if (index != 0) {
- // add '\n' if this is the not the first element. otherwise it would mix the image
- // with the text
- interpreterOutput.write("\n".getBytes());
- }
interpreterOutput.write(("%img " + executeResponse.getOutput()).getBytes());
interpreterOutput.getInterpreterOutput().flush();
- isPreviousOutputImage = true;
+ } catch (IOException e) {
+ LOGGER.error("Unexpected IOException", e);
+ }
+ }
+ if (executeResponse.getType() == OutputType.HTML) {
+ try {
+ interpreterOutput.write(("%html\n" + executeResponse.getOutput()).getBytes());
+ interpreterOutput.getInterpreterOutput().flush();
} catch (IOException e) {
LOGGER.error("Unexpected IOException", e);
}
diff --git a/python/src/main/proto/ipython.proto b/python/src/main/proto/ipython.proto
index a54f36d..16a7ebe 100644
--- a/python/src/main/proto/ipython.proto
+++ b/python/src/main/proto/ipython.proto
@@ -53,7 +53,12 @@ enum IPythonStatus {
enum OutputType {
TEXT = 0;
- IMAGE = 1;
+ PNG = 1;
+ JPEG = 2;
+ HTML = 3;
+ SVG = 4;
+ JSON = 5;
+ LaTeX = 6;
}
// The request message containing the code
diff --git a/python/src/main/resources/grpc/python/ipython_pb2.py b/python/src/main/resources/grpc/python/ipython_pb2.py
index eca3dfe..0bad160 100644
--- a/python/src/main/resources/grpc/python/ipython_pb2.py
+++ b/python/src/main/resources/grpc/python/ipython_pb2.py
@@ -23,7 +23,6 @@ from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
@@ -35,7 +34,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
name='ipython.proto',
package='ipython',
syntax='proto3',
- serialized_pb=_b('\n\ripython.proto\x12\x07ipython\"\x1e\n\x0e\x45xecuteRequest\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\"l\n\x0f\x45xecuteResponse\x12&\n\x06status\x18\x01 \x01(\x0e\x32\x16.ipython.ExecuteStatus\x12!\n\x04type\x18\x02 \x01(\x0e\x32\x13.ipython.OutputType\x12\x0e\n\x06output\x18\x03 \x01(\t\"\x0f\n\rCancelRequest\"\x10\n\x0e\x43\x61ncelResponse\"1\n\x11\x43ompletionRequest\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0e\n\x06\x63ursor\x18\x02 \x01(\x05\"%\n\x12\x43ompletionRe [...]
+ serialized_options=_b('\n org.apache.zeppelin.python.protoB\014IPythonProtoP\001\242\002\007IPython'),
+ serialized_pb=_b('\n\ripython.proto\x12\x07ipython\"\x1e\n\x0e\x45xecuteRequest\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\"l\n\x0f\x45xecuteResponse\x12&\n\x06status\x18\x01 \x01(\x0e\x32\x16.ipython.ExecuteStatus\x12!\n\x04type\x18\x02 \x01(\x0e\x32\x13.ipython.OutputType\x12\x0e\n\x06output\x18\x03 \x01(\t\"\x0f\n\rCancelRequest\"\x10\n\x0e\x43\x61ncelResponse\"1\n\x11\x43ompletionRequest\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0e\n\x06\x63ursor\x18\x02 \x01(\x05\"%\n\x12\x43ompletionRe [...]
)
_EXECUTESTATUS = _descriptor.EnumDescriptor(
@@ -46,15 +46,15 @@ _EXECUTESTATUS = _descriptor.EnumDescriptor(
values=[
_descriptor.EnumValueDescriptor(
name='SUCCESS', index=0, number=0,
- options=None,
+ serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ERROR', index=1, number=1,
- options=None,
+ serialized_options=None,
type=None),
],
containing_type=None,
- options=None,
+ serialized_options=None,
serialized_start=399,
serialized_end=438,
)
@@ -69,15 +69,15 @@ _IPYTHONSTATUS = _descriptor.EnumDescriptor(
values=[
_descriptor.EnumValueDescriptor(
name='STARTING', index=0, number=0,
- options=None,
+ serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='RUNNING', index=1, number=1,
- options=None,
+ serialized_options=None,
type=None),
],
containing_type=None,
- options=None,
+ serialized_options=None,
serialized_start=440,
serialized_end=482,
)
@@ -92,17 +92,37 @@ _OUTPUTTYPE = _descriptor.EnumDescriptor(
values=[
_descriptor.EnumValueDescriptor(
name='TEXT', index=0, number=0,
- options=None,
+ serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
- name='IMAGE', index=1, number=1,
- options=None,
+ name='PNG', index=1, number=1,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='JPEG', index=2, number=2,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HTML', index=3, number=3,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SVG', index=4, number=4,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='JSON', index=5, number=5,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LaTeX', index=6, number=6,
+ serialized_options=None,
type=None),
],
containing_type=None,
- options=None,
+ serialized_options=None,
serialized_start=484,
- serialized_end=517,
+ serialized_end=565,
)
_sym_db.RegisterEnumDescriptor(_OUTPUTTYPE)
@@ -112,7 +132,12 @@ ERROR = 1
STARTING = 0
RUNNING = 1
TEXT = 0
-IMAGE = 1
+PNG = 1
+JPEG = 2
+HTML = 3
+SVG = 4
+JSON = 5
+LaTeX = 6
@@ -129,14 +154,14 @@ _EXECUTEREQUEST = _descriptor.Descriptor(
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -160,28 +185,28 @@ _EXECUTERESPONSE = _descriptor.Descriptor(
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='type', full_name='ipython.ExecuteResponse.type', index=1,
number=2, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='output', full_name='ipython.ExecuteResponse.output', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -205,7 +230,7 @@ _CANCELREQUEST = _descriptor.Descriptor(
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -229,7 +254,7 @@ _CANCELRESPONSE = _descriptor.Descriptor(
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -253,21 +278,21 @@ _COMPLETIONREQUEST = _descriptor.Descriptor(
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='cursor', full_name='ipython.CompletionRequest.cursor', index=1,
number=2, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -291,14 +316,14 @@ _COMPLETIONRESPONSE = _descriptor.Descriptor(
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -322,7 +347,7 @@ _STATUSREQUEST = _descriptor.Descriptor(
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -346,14 +371,14 @@ _STATUSRESPONSE = _descriptor.Descriptor(
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- options=None),
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -377,7 +402,7 @@ _STOPREQUEST = _descriptor.Descriptor(
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -401,7 +426,7 @@ _STOPRESPONSE = _descriptor.Descriptor(
nested_types=[],
enum_types=[
],
- options=None,
+ serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
@@ -500,252 +525,65 @@ StopResponse = _reflection.GeneratedProtocolMessageType('StopResponse', (_messag
_sym_db.RegisterMessage(StopResponse)
-DESCRIPTOR.has_options = True
-DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n org.apache.zeppelin.python.protoB\014IPythonProtoP\001\242\002\007IPython'))
-try:
- # THESE ELEMENTS WILL BE DEPRECATED.
- # Please use the generated *_pb2_grpc.py files instead.
- import grpc
- from grpc.beta import implementations as beta_implementations
- from grpc.beta import interfaces as beta_interfaces
- from grpc.framework.common import cardinality
- from grpc.framework.interfaces.face import utilities as face_utilities
-
-
- class IPythonStub(object):
- """The IPython service definition.
- """
-
- def __init__(self, channel):
- """Constructor.
-
- Args:
- channel: A grpc.Channel.
- """
- self.execute = channel.unary_stream(
- '/ipython.IPython/execute',
- request_serializer=ExecuteRequest.SerializeToString,
- response_deserializer=ExecuteResponse.FromString,
- )
- self.complete = channel.unary_unary(
- '/ipython.IPython/complete',
- request_serializer=CompletionRequest.SerializeToString,
- response_deserializer=CompletionResponse.FromString,
- )
- self.cancel = channel.unary_unary(
- '/ipython.IPython/cancel',
- request_serializer=CancelRequest.SerializeToString,
- response_deserializer=CancelResponse.FromString,
- )
- self.status = channel.unary_unary(
- '/ipython.IPython/status',
- request_serializer=StatusRequest.SerializeToString,
- response_deserializer=StatusResponse.FromString,
- )
- self.stop = channel.unary_unary(
- '/ipython.IPython/stop',
- request_serializer=StopRequest.SerializeToString,
- response_deserializer=StopResponse.FromString,
- )
-
-
- class IPythonServicer(object):
- """The IPython service definition.
- """
-
- def execute(self, request, context):
- """Sends code
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
- def complete(self, request, context):
- """Get completion
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
- def cancel(self, request, context):
- """Cancel the running statement
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
- def status(self, request, context):
- """Get ipython kernel status
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
- def stop(self, request, context):
- # missing associated documentation comment in .proto file
- pass
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
-
- def add_IPythonServicer_to_server(servicer, server):
- rpc_method_handlers = {
- 'execute': grpc.unary_stream_rpc_method_handler(
- servicer.execute,
- request_deserializer=ExecuteRequest.FromString,
- response_serializer=ExecuteResponse.SerializeToString,
- ),
- 'complete': grpc.unary_unary_rpc_method_handler(
- servicer.complete,
- request_deserializer=CompletionRequest.FromString,
- response_serializer=CompletionResponse.SerializeToString,
- ),
- 'cancel': grpc.unary_unary_rpc_method_handler(
- servicer.cancel,
- request_deserializer=CancelRequest.FromString,
- response_serializer=CancelResponse.SerializeToString,
- ),
- 'status': grpc.unary_unary_rpc_method_handler(
- servicer.status,
- request_deserializer=StatusRequest.FromString,
- response_serializer=StatusResponse.SerializeToString,
- ),
- 'stop': grpc.unary_unary_rpc_method_handler(
- servicer.stop,
- request_deserializer=StopRequest.FromString,
- response_serializer=StopResponse.SerializeToString,
- ),
- }
- generic_handler = grpc.method_handlers_generic_handler(
- 'ipython.IPython', rpc_method_handlers)
- server.add_generic_rpc_handlers((generic_handler,))
-
-
- class BetaIPythonServicer(object):
- """The Beta API is deprecated for 0.15.0 and later.
-
- It is recommended to use the GA API (classes and functions in this
- file not marked beta) for all further purposes. This class was generated
- only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0."""
- """The IPython service definition.
- """
- def execute(self, request, context):
- """Sends code
- """
- context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
- def complete(self, request, context):
- """Get completion
- """
- context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
- def cancel(self, request, context):
- """Cancel the running statement
- """
- context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
- def status(self, request, context):
- """Get ipython kernel status
- """
- context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
- def stop(self, request, context):
- # missing associated documentation comment in .proto file
- pass
- context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
-
-
- class BetaIPythonStub(object):
- """The Beta API is deprecated for 0.15.0 and later.
-
- It is recommended to use the GA API (classes and functions in this
- file not marked beta) for all further purposes. This class was generated
- only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0."""
- """The IPython service definition.
- """
- def execute(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
- """Sends code
- """
- raise NotImplementedError()
- def complete(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
- """Get completion
- """
- raise NotImplementedError()
- complete.future = None
- def cancel(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
- """Cancel the running statement
- """
- raise NotImplementedError()
- cancel.future = None
- def status(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
- """Get ipython kernel status
- """
- raise NotImplementedError()
- status.future = None
- def stop(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
- # missing associated documentation comment in .proto file
- pass
- raise NotImplementedError()
- stop.future = None
-
-
- def beta_create_IPython_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
- """The Beta API is deprecated for 0.15.0 and later.
-
- It is recommended to use the GA API (classes and functions in this
- file not marked beta) for all further purposes. This function was
- generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"""
- request_deserializers = {
- ('ipython.IPython', 'cancel'): CancelRequest.FromString,
- ('ipython.IPython', 'complete'): CompletionRequest.FromString,
- ('ipython.IPython', 'execute'): ExecuteRequest.FromString,
- ('ipython.IPython', 'status'): StatusRequest.FromString,
- ('ipython.IPython', 'stop'): StopRequest.FromString,
- }
- response_serializers = {
- ('ipython.IPython', 'cancel'): CancelResponse.SerializeToString,
- ('ipython.IPython', 'complete'): CompletionResponse.SerializeToString,
- ('ipython.IPython', 'execute'): ExecuteResponse.SerializeToString,
- ('ipython.IPython', 'status'): StatusResponse.SerializeToString,
- ('ipython.IPython', 'stop'): StopResponse.SerializeToString,
- }
- method_implementations = {
- ('ipython.IPython', 'cancel'): face_utilities.unary_unary_inline(servicer.cancel),
- ('ipython.IPython', 'complete'): face_utilities.unary_unary_inline(servicer.complete),
- ('ipython.IPython', 'execute'): face_utilities.unary_stream_inline(servicer.execute),
- ('ipython.IPython', 'status'): face_utilities.unary_unary_inline(servicer.status),
- ('ipython.IPython', 'stop'): face_utilities.unary_unary_inline(servicer.stop),
- }
- server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
- return beta_implementations.server(method_implementations, options=server_options)
-
-
- def beta_create_IPython_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
- """The Beta API is deprecated for 0.15.0 and later.
-
- It is recommended to use the GA API (classes and functions in this
- file not marked beta) for all further purposes. This function was
- generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"""
- request_serializers = {
- ('ipython.IPython', 'cancel'): CancelRequest.SerializeToString,
- ('ipython.IPython', 'complete'): CompletionRequest.SerializeToString,
- ('ipython.IPython', 'execute'): ExecuteRequest.SerializeToString,
- ('ipython.IPython', 'status'): StatusRequest.SerializeToString,
- ('ipython.IPython', 'stop'): StopRequest.SerializeToString,
- }
- response_deserializers = {
- ('ipython.IPython', 'cancel'): CancelResponse.FromString,
- ('ipython.IPython', 'complete'): CompletionResponse.FromString,
- ('ipython.IPython', 'execute'): ExecuteResponse.FromString,
- ('ipython.IPython', 'status'): StatusResponse.FromString,
- ('ipython.IPython', 'stop'): StopResponse.FromString,
- }
- cardinalities = {
- 'cancel': cardinality.Cardinality.UNARY_UNARY,
- 'complete': cardinality.Cardinality.UNARY_UNARY,
- 'execute': cardinality.Cardinality.UNARY_STREAM,
- 'status': cardinality.Cardinality.UNARY_UNARY,
- 'stop': cardinality.Cardinality.UNARY_UNARY,
- }
- stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size)
- return beta_implementations.dynamic_stub(channel, 'ipython.IPython', cardinalities, options=stub_options)
-except ImportError:
- pass
+DESCRIPTOR._options = None
+
+_IPYTHON = _descriptor.ServiceDescriptor(
+ name='IPython',
+ full_name='ipython.IPython',
+ file=DESCRIPTOR,
+ index=0,
+ serialized_options=None,
+ serialized_start=568,
+ serialized_end=891,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='execute',
+ full_name='ipython.IPython.execute',
+ index=0,
+ containing_service=None,
+ input_type=_EXECUTEREQUEST,
+ output_type=_EXECUTERESPONSE,
+ serialized_options=None,
+ ),
+ _descriptor.MethodDescriptor(
+ name='complete',
+ full_name='ipython.IPython.complete',
+ index=1,
+ containing_service=None,
+ input_type=_COMPLETIONREQUEST,
+ output_type=_COMPLETIONRESPONSE,
+ serialized_options=None,
+ ),
+ _descriptor.MethodDescriptor(
+ name='cancel',
+ full_name='ipython.IPython.cancel',
+ index=2,
+ containing_service=None,
+ input_type=_CANCELREQUEST,
+ output_type=_CANCELRESPONSE,
+ serialized_options=None,
+ ),
+ _descriptor.MethodDescriptor(
+ name='status',
+ full_name='ipython.IPython.status',
+ index=3,
+ containing_service=None,
+ input_type=_STATUSREQUEST,
+ output_type=_STATUSRESPONSE,
+ serialized_options=None,
+ ),
+ _descriptor.MethodDescriptor(
+ name='stop',
+ full_name='ipython.IPython.stop',
+ index=4,
+ containing_service=None,
+ input_type=_STOPREQUEST,
+ output_type=_STOPRESPONSE,
+ serialized_options=None,
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_IPYTHON)
+
+DESCRIPTOR.services_by_name['IPython'] = _IPYTHON
+
# @@protoc_insertion_point(module_scope)
diff --git a/python/src/main/resources/grpc/python/ipython_server.py b/python/src/main/resources/grpc/python/ipython_server.py
index 36e0a13..3fd0a8c 100644
--- a/python/src/main/resources/grpc/python/ipython_server.py
+++ b/python/src/main/resources/grpc/python/ipython_server.py
@@ -49,23 +49,37 @@ class IPython(ipython_pb2_grpc.IPythonServicer):
print("execute code:\n")
print(request.code.encode('utf-8'))
sys.stdout.flush()
- stdout_queue = queue.Queue(maxsize = 10)
stderr_queue = queue.Queue(maxsize = 10)
- image_queue = queue.Queue(maxsize = 5)
+ text_queue = queue.Queue(maxsize = 10)
+ png_queue = queue.Queue(maxsize = 5)
+ jpeg_queue = queue.Queue(maxsize = 5)
+ html_queue = queue.Queue(maxsize = 10)
def _output_hook(msg):
msg_type = msg['header']['msg_type']
content = msg['content']
+ print("******************* CONTENT ******************")
+ print(str(content)[:400])
if msg_type == 'stream':
- stdout_queue.put(content['text'])
+ text_queue.put(content['text'])
elif msg_type in ('display_data', 'execute_result'):
- stdout_queue.put(content['data'].get('text/plain', ''))
- if 'image/png' in content['data']:
- image_queue.put(content['data']['image/png'])
+ if 'text/html' in content['data']:
+ html_queue.put(content['data']['text/html'])
+ elif 'image/png' in content['data']:
+ png_queue.put(content['data']['image/png'])
+ elif 'image/jpeg' in content['data']:
+ jpeg_queue.put(content['data']['image/jpeg'])
+ elif 'text/plain' in content['data']:
+ text_queue.put(content['data']['text/plain'])
+ elif 'application/javascript' in content['data']:
+ print('add to html queue: ' + str(content)[:100])
+ html_queue.put('<script> ' + content['data']['application/javascript'] + ' </script>\n')
+ elif 'application/vnd.holoviews_load.v0+json' in content['data']:
+ html_queue.put('<script> ' + content['data']['application/vnd.holoviews_load.v0+json'] + ' </script>\n')
+
elif msg_type == 'error':
stderr_queue.put('\n'.join(content['traceback']))
-
payload_reply = []
def execute_worker():
reply = self._kc.execute_interactive(request.code,
@@ -80,22 +94,33 @@ class IPython(ipython_pb2_grpc.IPythonServicer):
# Execution might be stuck there:
# https://github.com/jupyter/jupyter_client/blob/master/jupyter_client/blocking/client.py#L32
while t.is_alive() and self.isKernelAlive():
- while not stdout_queue.empty():
- output = stdout_queue.get()
+ while not text_queue.empty():
+ output = text_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
type=ipython_pb2.TEXT,
output=output)
+ while not html_queue.empty():
+ output = html_queue.get()
+ yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
+ type=ipython_pb2.HTML,
+ output=output)
while not stderr_queue.empty():
output = stderr_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.ERROR,
type=ipython_pb2.TEXT,
output=output)
- while not image_queue.empty():
- output = image_queue.get()
+ while not png_queue.empty():
+ output = png_queue.get()
+ yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
+ type=ipython_pb2.PNG,
+ output=output)
+ while not jpeg_queue.empty():
+ output = jpeg_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
- type=ipython_pb2.IMAGE,
+ type=ipython_pb2.JPEG,
output=output)
+
# if kernel is not alive (should be same as thread is still alive), means that we face
# an unexpected issue.
if not self.isKernelAlive() or t.is_alive():
@@ -104,22 +129,31 @@ class IPython(ipython_pb2_grpc.IPythonServicer):
output="Ipython kernel has been stopped. Please check logs. It might be because of an out of memory issue.")
return
- while not stdout_queue.empty():
- output = stdout_queue.get()
+ while not text_queue.empty():
+ output = text_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
type=ipython_pb2.TEXT,
output=output)
+ while not html_queue.empty():
+ output = html_queue.get()
+ yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
+ type=ipython_pb2.HTML,
+ output=output)
while not stderr_queue.empty():
output = stderr_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.ERROR,
type=ipython_pb2.TEXT,
output=output)
- while not image_queue.empty():
- output = image_queue.get()
+ while not png_queue.empty():
+ output = png_queue.get()
yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
- type=ipython_pb2.IMAGE,
+ type=ipython_pb2.PNG,
+ output=output)
+ while not jpeg_queue.empty():
+ output = jpeg_queue.get()
+ yield ipython_pb2.ExecuteResponse(status=ipython_pb2.SUCCESS,
+ type=ipython_pb2.JPEG,
output=output)
-
if payload_reply:
result = []
for payload in payload_reply[0]['content']['payload']:
diff --git a/python/src/test/java/org/apache/zeppelin/python/IPythonInterpreterTest.java b/python/src/test/java/org/apache/zeppelin/python/IPythonInterpreterTest.java
index 4a4c809..e084bfe 100644
--- a/python/src/test/java/org/apache/zeppelin/python/IPythonInterpreterTest.java
+++ b/python/src/test/java/org/apache/zeppelin/python/IPythonInterpreterTest.java
@@ -185,7 +185,6 @@ public class IPythonInterpreterTest extends BasePythonInterpreterTest {
// check there must be one IMAGE output
boolean hasImageOutput = false;
boolean hasLineText = false;
- boolean hasFigureText = false;
for (InterpreterResultMessage msg : interpreterResultMessages) {
if (msg.getType() == InterpreterResult.Type.IMG) {
hasImageOutput = true;
@@ -194,14 +193,9 @@ public class IPythonInterpreterTest extends BasePythonInterpreterTest {
&& msg.getData().contains("matplotlib.lines.Line2D")) {
hasLineText = true;
}
- if (msg.getType() == InterpreterResult.Type.TEXT
- && msg.getData().contains("matplotlib.figure.Figure")) {
- hasFigureText = true;
- }
}
assertTrue("No Image Output", hasImageOutput);
assertTrue("No Line Text", hasLineText);
- assertTrue("No Figure Text", hasFigureText);
// bokeh
// bokeh initialization
@@ -256,6 +250,35 @@ public class IPythonInterpreterTest extends BasePythonInterpreterTest {
assertTrue("No Image Output", hasImageOutput);
}
+
+ // TODO(zjffdu) Enable it after new altair is released with this PR.
+ // https://github.com/altair-viz/altair/pull/1620
+ //@Test
+ public void testHtmlOutput() throws InterpreterException, IOException {
+ // html output
+ InterpreterContext context = getInterpreterContext();
+ InterpreterResult result = interpreter.interpret(
+ " import altair as alt\n" +
+ " print(alt.renderers.active)\n" +
+ " alt.renderers.enable(\"colab\")\n" +
+ " import altair as alt\n" +
+ " # load a simple dataset as a pandas DataFrame\n" +
+ " from vega_datasets import data\n" +
+ " cars = data.cars()\n" +
+ " \n" +
+ " alt.Chart(cars).mark_point().encode(\n" +
+ " x='Horsepower',\n" +
+ " y='Miles_per_Gallon',\n" +
+ " color='Origin',\n" +
+ " ).interactive()", context);
+ assertEquals(InterpreterResult.Code.SUCCESS, result.code());
+ assertEquals(2, context.out.size());
+ assertEquals(InterpreterResult.Type.TEXT,
+ context.out.toInterpreterResultMessage().get(0).getType());
+ assertEquals(InterpreterResult.Type.HTML,
+ context.out.toInterpreterResultMessage().get(1).getType());
+ }
+
@Test
public void testGrpcFrameSize() throws InterpreterException, IOException {
tearDown();
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/dep/DependencyResolver.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/dep/DependencyResolver.java
index 0acfca9..495c69b 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/dep/DependencyResolver.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/dep/DependencyResolver.java
@@ -96,7 +96,7 @@ public class DependencyResolver extends AbstractDependencyResolver {
File destFile = new File(destPath, srcFile.getName());
if (!destFile.exists() || !FileUtils.contentEquals(srcFile, destFile)) {
FileUtils.copyFile(srcFile, destFile);
- logger.info("copy {} to {}", srcFile.getAbsolutePath(), destPath);
+ logger.debug("copy {} to {}", srcFile.getAbsolutePath(), destPath);
}
}
}
@@ -114,7 +114,7 @@ public class DependencyResolver extends AbstractDependencyResolver {
if (!destFile.exists() || !FileUtils.contentEquals(srcFile, destFile)) {
FileUtils.copyFile(srcFile, destFile);
- logger.info("copy {} to {}", srcFile.getAbsolutePath(), destPath);
+ logger.debug("copy {} to {}", srcFile.getAbsolutePath(), destPath);
}
}
@@ -142,7 +142,7 @@ public class DependencyResolver extends AbstractDependencyResolver {
List<File> files = new LinkedList<>();
for (ArtifactResult artifactResult : listOfArtifact) {
files.add(artifactResult.getArtifact().getFile());
- logger.info("load {}", artifactResult.getArtifact().getFile().getAbsolutePath());
+ logger.debug("load {}", artifactResult.getArtifact().getFile().getAbsolutePath());
}
return files;
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java
index 012f6a4..d8d8df0 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepo.java
@@ -102,6 +102,10 @@ public class VFSNotebookRepo implements NotebookRepo {
private Map<String, NoteInfo> listFolder(FileObject fileObject) throws IOException {
Map<String, NoteInfo> noteInfos = new HashMap<>();
if (fileObject.isFolder()) {
+ if (fileObject.getName().getBaseName().startsWith(".")) {
+ LOGGER.warn("Skip hidden folder: " + fileObject.getName().getPath());
+ return noteInfos;
+ }
for (FileObject child : fileObject.getChildren()) {
noteInfos.putAll(listFolder(child));
}