From 4fcc05c33f865eff2d263b1777a3e588f791fc37 2015-04-02 22:04:01 From: Min RK Date: 2015-04-02 22:04:01 Subject: [PATCH] Don't use tokenutil in v4 msgspec adapter reimplement javascript token logic from IPython 2, instead. Avoids jupyter_client dependency on tokenutil, which should stay with IPython. --- diff --git a/jupyter_client/adapter.py b/jupyter_client/adapter.py index 2e3df01..18d9984 100644 --- a/jupyter_client/adapter.py +++ b/jupyter_client/adapter.py @@ -3,10 +3,10 @@ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. +import re import json from IPython.core.release import kernel_protocol_version_info -from IPython.utils.tokenutil import token_at_cursor def code_to_line(code, cursor_pos): @@ -26,6 +26,33 @@ def code_to_line(code, cursor_pos): return line, cursor_pos +_match_bracket = re.compile(r'\([^\(\)]+\)', re.UNICODE) +_end_bracket = re.compile(r'\([^\(]*$', re.UNICODE) +_identifier = re.compile(r'[a-z_][0-9a-z._]*', re.I|re.UNICODE) + +def extract_oname_v4(code, cursor_pos): + """Reimplement token-finding logic from IPython 2.x javascript + + for adapting object_info_request from v5 to v4 + """ + + line, _ = code_to_line(code, cursor_pos) + + oldline = line + line = _match_bracket.sub(u'', line) + while oldline != line: + oldline = line + line = _match_bracket.sub(u'', line) + + # remove everything after last open bracket + line = _end_bracket.sub('', line) + matches = _identifier.findall(line) + if matches: + return matches[-1] + else: + return '' + + class Adapter(object): """Base class for adapting messages @@ -158,7 +185,7 @@ class V5toV4(Adapter): line, _ = code_to_line(code, cursor_pos) new_content = msg['content'] = {} - new_content['oname'] = token_at_cursor(code, cursor_pos) + new_content['oname'] = extract_oname_v4(code, cursor_pos) new_content['detail_level'] = content['detail_level'] return msg diff --git a/jupyter_client/tests/test_adapter.py b/jupyter_client/tests/test_adapter.py index fe74298..34f71f0 100644 --- a/jupyter_client/tests/test_adapter.py +++ b/jupyter_client/tests/test_adapter.py @@ -311,6 +311,20 @@ class V5toV4TestCase(AdapterTest): self.assertEqual(v4c['oname'], 'apple') self.assertEqual(v5c['detail_level'], v4c['detail_level']) + def test_inspect_request_token(self): + line = 'something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,' + msg = self.msg("inspect_request", { + 'code' : line, + 'cursor_pos': len(line)-1, + 'detail_level' : 1, + }) + v5, v4 = self.adapt(msg) + self.assertEqual(v4['header']['msg_type'], 'object_info_request') + v4c = v4['content'] + v5c = v5['content'] + self.assertEqual(v4c['oname'], 'xxx.xxx.xxx') + self.assertEqual(v5c['detail_level'], v4c['detail_level']) + def test_inspect_reply(self): msg = self.msg("inspect_reply", { 'name' : 'foo',