Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions repl/src/main/resources/fake_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@

TOP_FRAME_REGEX = re.compile(r'\s*File "<stdin>".*in <module>')

def get_completer():
try:
__IPYTHON__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wangqiaoshi Since fake_shell runs within a standard python process and not within an ipython shell, how will IPCompleter be initialized?

from IPython.core.completer import IPCompleter
ip = get_ipython()
ip_completer = IPCompleter(ip,global_namespace=global_dict)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after ,

global_dict['ip_completer'] = ip_completer

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the completer need to be visible to user statements? Otherwise it seems you can just use a regular global variable (like job_context or local_tmp_dir_path in this file).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completer will be different when python interpreter is different. The number of completer global variable will be two,I don't know if that's appropriate?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean (ip_completer vs. p_completer).

I think it would be better to keep a single variable for the completer, and a boolean that says whether to use the IPython API.

But my main question was: do they need to be stored in global_dict or can they just be a global variable in this module instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok,I see what you mean.

except NameError:
try:
from rlcompleter import Completer
p_completer = Completer(namespace=global_dict)
global_dict['p_completer'] = p_completer
except:
pass


def execute_reply(status, content):
return {
'msg_type': 'execute_reply',
Expand Down Expand Up @@ -195,6 +211,28 @@ def processBypassJob(self, serialized_job):
def addFile(self, uri_path):
job_context.sc.addFile(uri_path)


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of blank lines. Surprising the style checker didn't complain. Should be one line between methods.



def complete(self,code,cursor_pos=None):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after ,

results = []
ip_completer =global_dict.get('ip_completer')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after =

p_completer = global_dict.get("p_completer")
if ip_completer is not None:
results = ip_completer.complete(code,cursor_pos=cursor_pos)[1]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after ,

elif p_completer is not None:
p_completer = global_dict.get("p_completer")
state = 0
result = None
while state == 0 or result is not None:
result = p_completer.complete(code,state)
if result is not None:
results.append(result)
state += 1
return ",".join(results)



def addPyFile(self, uri_path):
job_context.sc.addPyFile(uri_path)

Expand Down Expand Up @@ -555,6 +593,7 @@ def main():
sys.stderr = UnicodeDecodingStringIO()

spark_major_version = os.getenv("LIVY_SPARK_MAJOR_VERSION")
get_completer()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get assumes something is being returned. initialize_completer() is probably a better name.

try:
listening_port = 0
if os.environ.get("LIVY_TEST") != "true":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ trait PySparkJobProcessor {
def addPyFile(path: String)

def getLocalTmpDirPath: String

def complete(code: String, cursor_pos: Int): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ private class PythonInterpreter(
}
}

override def complete(code: String, cursor: Int): Array[String] = {
val r = pysparkJobProcessor.complete(code, cursor)
r.split(",")
}

private def updatePythonGatewayPort(port: Int): Unit = {
// The python gateway port can be 0 only when LivyConf.TEST_MODE is true
// Py4j 0.10 has different API signature for "getCallbackClient", use reflection to handle it.
Expand Down