Skip to content

Commit 22d8b90

Browse files
committed
Python debugger support for Python 3 (in addition to Python 2)
- Added safe_ord compatibility to pass through int arguments - Fixed JerryDebugger to decode bytes as utf8 strings when necessary - Fixed WebSocket send_message method to use packed_data[0:1] bytes slice JerryScript-DCO-1.0-Signed-off-by: Zac Medico <zmedico@gmail.com>
1 parent a6ab5e9 commit 22d8b90

File tree

3 files changed

+74
-36
lines changed

3 files changed

+74
-36
lines changed

jerry-debugger/jerry_client_main.py

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ def arguments_parse():
149149
return args
150150

151151

152+
if sys.version_info.major >= 3:
153+
def safe_ord(c):
154+
if isinstance(c, int):
155+
return c
156+
return ord(c)
157+
else:
158+
safe_ord = ord
159+
160+
152161
class JerryBreakpoint(object):
153162

154163
def __init__(self, line, offset, function):
@@ -307,12 +316,12 @@ def __init__(self, channel):
307316
# cpointer_size [1]
308317
result = self.channel.connect(config_size)
309318

310-
if len(result) != config_size or ord(result[0]) != JERRY_DEBUGGER_CONFIGURATION:
319+
if len(result) != config_size or safe_ord(result[0]) != JERRY_DEBUGGER_CONFIGURATION:
311320
raise Exception("Unexpected configuration")
312321

313-
self.little_endian = ord(result[1]) & JERRY_DEBUGGER_LITTLE_ENDIAN
314-
self.max_message_size = ord(result[6])
315-
self.cp_size = ord(result[7])
322+
self.little_endian = safe_ord(result[1]) & JERRY_DEBUGGER_LITTLE_ENDIAN
323+
self.max_message_size = safe_ord(result[6])
324+
self.cp_size = safe_ord(result[7])
316325

317326
if self.little_endian:
318327
self.byte_order = "<"
@@ -400,7 +409,7 @@ def delete(self, args):
400409
"to clear all the given breakpoints\n "
401410
elif args in ['all', 'pending', 'active']:
402411
if args != "pending":
403-
for i in self.active_breakpoint_list.values():
412+
for i in list(self.active_breakpoint_list.values()):
404413
breakpoint = self.active_breakpoint_list[i.active_index]
405414
del self.active_breakpoint_list[i.active_index]
406415
breakpoint.active_index = -1
@@ -561,6 +570,7 @@ def memstats(self):
561570
self._exec_command(JERRY_DEBUGGER_MEMSTATS)
562571

563572
def _send_string(self, args, message_type, index=0):
573+
args = args.encode("utf8")
564574

565575
# 1: length of type byte
566576
# 4: length of an uint32 value
@@ -684,7 +694,7 @@ def process_messages(self):
684694
if not data: # Break the while loop if there is no more data.
685695
return DebuggerAction(DebuggerAction.END, "")
686696

687-
buffer_type = ord(data[0])
697+
buffer_type = safe_ord(data[0])
688698
buffer_size = len(data) -1
689699

690700
logging.debug("Main buffer type: %d, message size: %d", buffer_type, buffer_size)
@@ -738,10 +748,10 @@ def process_messages(self):
738748
return DebuggerAction(DebuggerAction.TEXT, result)
739749

740750
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR:
741-
self.exception_string += data[1:]
751+
self.exception_string += data[1:].decode("utf8")
742752

743753
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR_END:
744-
self.exception_string += data[1:]
754+
self.exception_string += data[1:].decode("utf8")
745755

746756
elif buffer_type == JERRY_DEBUGGER_BACKTRACE_TOTAL:
747757
total = struct.unpack(self.byte_order + self.idx_format, data[1:])[0]
@@ -808,7 +818,7 @@ def process_messages(self):
808818
return DebuggerAction(DebuggerAction.TEXT, result)
809819

810820
elif buffer_type in [JERRY_DEBUGGER_SCOPE_VARIABLES, JERRY_DEBUGGER_SCOPE_VARIABLES_END]:
811-
self.scope_vars += "".join(data[1:])
821+
self.scope_vars += "".join(data[1:].decode("utf8"))
812822

813823
if buffer_type == JERRY_DEBUGGER_SCOPE_VARIABLES_END:
814824
result = self._process_scope_variables()
@@ -864,9 +874,9 @@ def print_source(self, line_num, offset):
864874

865875
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
866876
def _parse_source(self, data):
867-
source_code = ""
868-
source_code_name = ""
869-
function_name = ""
877+
source_code = b""
878+
source_code_name = b""
879+
function_name = b""
870880
stack = [{"line": 1,
871881
"column": 1,
872882
"name": "",
@@ -879,7 +889,7 @@ def _parse_source(self, data):
879889
if data is None:
880890
return "Error: connection lost during source code receiving"
881891

882-
buffer_type = ord(data[0])
892+
buffer_type = safe_ord(data[0])
883893
buffer_size = len(data) - 1
884894

885895
logging.debug("Parser buffer type: %d, message size: %d", buffer_type, buffer_size)
@@ -903,14 +913,14 @@ def _parse_source(self, data):
903913
position = struct.unpack(self.byte_order + self.idx_format + self.idx_format,
904914
data[1: 1 + 4 + 4])
905915

906-
stack.append({"source": source_code,
907-
"source_name": source_code_name,
916+
stack.append({"source": source_code.decode("utf8"),
917+
"source_name": source_code_name.decode("utf8"),
908918
"line": position[0],
909919
"column": position[1],
910-
"name": function_name,
920+
"name": function_name.decode("utf8"),
911921
"lines": [],
912922
"offsets": []})
913-
function_name = ""
923+
function_name = b""
914924

915925
elif buffer_type in [JERRY_DEBUGGER_BREAKPOINT_LIST, JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST]:
916926
name = "lines"
@@ -937,8 +947,8 @@ def _parse_source(self, data):
937947

938948
# We know the last item in the list is the general byte code.
939949
if not stack:
940-
func_desc["source"] = source_code
941-
func_desc["source_name"] = source_code_name
950+
func_desc["source"] = source_code.decode("utf8")
951+
func_desc["source_name"] = source_code_name.decode("utf8")
942952

943953
function = JerryFunction(stack,
944954
byte_code_cp,
@@ -989,7 +999,7 @@ def _parse_source(self, data):
989999
logging.debug("Pending breakpoints available")
9901000
bp_list = self.pending_breakpoint_list
9911001

992-
for breakpoint_index, breakpoint in bp_list.items():
1002+
for breakpoint_index, breakpoint in list(bp_list.items()):
9931003
source_lines = 0
9941004
for src in new_function_list.values():
9951005
if (src.source_name == breakpoint.source_name or
@@ -1132,14 +1142,14 @@ def _process_incoming_text(self, buffer_type, data):
11321142
while True:
11331143
if buffer_type in [JERRY_DEBUGGER_EVAL_RESULT_END,
11341144
JERRY_DEBUGGER_OUTPUT_RESULT_END]:
1135-
subtype = ord(data[-1])
1145+
subtype = safe_ord(data[-1])
11361146
message += data[1:-1]
11371147
break
11381148
else:
11391149
message += data[1:]
11401150

11411151
data = self.channel.get_message(True)
1142-
buffer_type = ord(data[0])
1152+
buffer_type = safe_ord(data[0])
11431153
# Checks if the next frame would be an invalid data frame.
11441154
# If it is not the message type, or the end type of it, an exception is thrown.
11451155
if buffer_type not in [msg_type, msg_type + 1]:
@@ -1151,20 +1161,21 @@ def _process_incoming_text(self, buffer_type, data):
11511161
log_type = "%sout:%s " % (self.blue, self.nocolor)
11521162

11531163
message = self.current_out + message
1154-
lines = message.split("\n")
1155-
self.current_out = lines.pop()
1164+
lines = message.decode("utf8").split("\n")
1165+
self.current_out = lines.pop().encode("utf8")
11561166

11571167
return "".join(["%s%s\n" % (log_type, line) for line in lines])
11581168

11591169
if subtype == JERRY_DEBUGGER_OUTPUT_DEBUG:
11601170
log_type = "%slog:%s " % (self.yellow, self.nocolor)
11611171

11621172
message = self.current_log + message
1163-
lines = message.split("\n")
1164-
self.current_log = lines.pop()
1173+
lines = message.decode("utf8").split("\n")
1174+
self.current_log = lines.pop().encode("utf8")
11651175

11661176
return "".join(["%s%s\n" % (log_type, line) for line in lines])
11671177

1178+
message = message.decode("utf8")
11681179
if not message.endswith("\n"):
11691180
message += "\n"
11701181

@@ -1174,6 +1185,9 @@ def _process_incoming_text(self, buffer_type, data):
11741185
return "%serr: %s%s" % (self.red, self.nocolor, message)
11751186
elif subtype == JERRY_DEBUGGER_OUTPUT_TRACE:
11761187
return "%strace: %s%s" % (self.blue, self.nocolor, message)
1188+
else:
1189+
message = message.decode("utf8")
1190+
11771191

11781192
# Subtypes of eval
11791193
self.prompt = True
@@ -1193,17 +1207,17 @@ def _process_scope_variables(self):
11931207

11941208
while buff_pos != buff_size:
11951209
# Process name
1196-
name_length = ord(self.scope_vars[buff_pos:buff_pos + 1])
1210+
name_length = safe_ord(self.scope_vars[buff_pos:buff_pos + 1])
11971211
buff_pos += 1
11981212
name = self.scope_vars[buff_pos:buff_pos + name_length]
11991213
buff_pos += name_length
12001214

12011215
# Process type
1202-
value_type = ord(self.scope_vars[buff_pos:buff_pos + 1])
1216+
value_type = safe_ord(self.scope_vars[buff_pos:buff_pos + 1])
12031217

12041218
buff_pos += 1
12051219

1206-
value_length = ord(self.scope_vars[buff_pos:buff_pos + 1])
1220+
value_length = safe_ord(self.scope_vars[buff_pos:buff_pos + 1])
12071221
buff_pos += 1
12081222
value = self.scope_vars[buff_pos: buff_pos + value_length]
12091223
buff_pos += value_length
@@ -1234,16 +1248,16 @@ def _process_scope(self):
12341248
table = [['level', 'type']]
12351249

12361250
for i, level in enumerate(self.scope_data):
1237-
if ord(level) == JERRY_DEBUGGER_SCOPE_WITH:
1251+
if safe_ord(level) == JERRY_DEBUGGER_SCOPE_WITH:
12381252
table.append([str(i), 'with'])
1239-
elif ord(level) == JERRY_DEBUGGER_SCOPE_GLOBAL:
1253+
elif safe_ord(level) == JERRY_DEBUGGER_SCOPE_GLOBAL:
12401254
table.append([str(i), 'global'])
1241-
elif ord(level) == JERRY_DEBUGGER_SCOPE_NON_CLOSURE:
1255+
elif safe_ord(level) == JERRY_DEBUGGER_SCOPE_NON_CLOSURE:
12421256
# Currently it is only marks the catch closure.
12431257
table.append([str(i), 'catch'])
1244-
elif ord(level) == JERRY_DEBUGGER_SCOPE_LOCAL:
1258+
elif safe_ord(level) == JERRY_DEBUGGER_SCOPE_LOCAL:
12451259
table.append([str(i), 'local'])
1246-
elif ord(level) == JERRY_DEBUGGER_SCOPE_CLOSURE:
1260+
elif safe_ord(level) == JERRY_DEBUGGER_SCOPE_CLOSURE:
12471261
table.append([str(i), 'closure'])
12481262
else:
12491263
raise Exception("Unexpected scope chain element")

jerry-debugger/jerry_client_rawpacket.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,20 @@
1515
# limitations under the License.
1616

1717
import struct
18+
import sys
1819

1920
MAX_BUFFER_SIZE = 256
2021

22+
23+
if sys.version_info.major >= 3:
24+
def safe_ord(c):
25+
if isinstance(c, int):
26+
return c
27+
return ord(c)
28+
else:
29+
safe_ord = ord
30+
31+
2132
class RawPacket(object):
2233
""" Simplified transmission layer. """
2334
def __init__(self, protocol):
@@ -70,7 +81,7 @@ def get_message(self, blocking):
7081

7182
while True:
7283
if len(self.data_buffer) >= 1:
73-
size = ord(self.data_buffer[0])
84+
size = safe_ord(self.data_buffer[0])
7485
if size == 0:
7586
raise Exception("Unexpected data frame")
7687

jerry-debugger/jerry_client_websocket.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,24 @@
1515
# limitations under the License.
1616

1717
import struct
18+
import sys
1819

1920
MAX_BUFFER_SIZE = 128
2021
WEBSOCKET_BINARY_FRAME = 2
2122
WEBSOCKET_FIN_BIT = 0x80
2223

24+
25+
if sys.version_info.major >= 3:
26+
# pylint: disable=invalid-name
27+
_ord_orig = ord
28+
def _ord_compat(c):
29+
if isinstance(c, int):
30+
return c
31+
return _ord_orig(c)
32+
# pylint: disable=redefined-builtin
33+
ord = _ord_compat
34+
35+
2336
class WebSocket(object):
2437
def __init__(self, protocol):
2538

@@ -92,7 +105,7 @@ def send_message(self, byte_order, packed_data):
92105
""" Send message. """
93106
message = struct.pack(byte_order + "BBI",
94107
WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT,
95-
WEBSOCKET_FIN_BIT + struct.unpack(byte_order + "B", packed_data[0])[0],
108+
WEBSOCKET_FIN_BIT + struct.unpack(byte_order + "B", packed_data[0:1])[0],
96109
0) + packed_data[1:]
97110

98111
self.__send_data(message)

0 commit comments

Comments
 (0)