mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Support display in hex
This commit is contained in:
parent
7d73c1a22e
commit
7ac28225ff
2 changed files with 68 additions and 43 deletions
|
|
@ -29,10 +29,12 @@ class SafeRepr(object):
|
|||
string_types = (str, bytes)
|
||||
set_info = (set, '{', '}', False)
|
||||
frozenset_info = (frozenset, 'frozenset({', '})', False)
|
||||
int_types = (int)
|
||||
else:
|
||||
string_types = (str, unicode)
|
||||
set_info = (set, 'set([', '])', False)
|
||||
frozenset_info = (frozenset, 'frozenset([', '])', False)
|
||||
int_types = (int, long)
|
||||
|
||||
# Collection types are recursively iterated for each limit in
|
||||
# maxcollection.
|
||||
|
|
@ -67,16 +69,16 @@ class SafeRepr(object):
|
|||
maxother_outer = 2 ** 16
|
||||
maxother_inner = 30
|
||||
|
||||
def __call__(self, obj):
|
||||
def __call__(self, obj, convert_to_hex=False):
|
||||
try:
|
||||
return ''.join(self._repr(obj, 0))
|
||||
return ''.join(self._repr(obj, 0, convert_to_hex=convert_to_hex))
|
||||
except Exception:
|
||||
try:
|
||||
return 'An exception was raised: %r' % sys.exc_info()[1]
|
||||
except Exception:
|
||||
return 'An exception was raised'
|
||||
|
||||
def _repr(self, obj, level):
|
||||
def _repr(self, obj, level, convert_to_hex=False):
|
||||
'''Returns an iterable of the parts in the final repr string.'''
|
||||
|
||||
try:
|
||||
|
|
@ -93,21 +95,21 @@ class SafeRepr(object):
|
|||
|
||||
for t, prefix, suffix, comma in self.collection_types:
|
||||
if isinstance(obj, t) and has_obj_repr(t):
|
||||
return self._repr_iter(obj, level, prefix, suffix, comma)
|
||||
return self._repr_iter(obj, level, prefix, suffix, comma, convert_to_hex=convert_to_hex)
|
||||
|
||||
for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types: # noqa
|
||||
if isinstance(obj, t) and has_obj_repr(t):
|
||||
return self._repr_dict(obj, level, prefix, suffix,
|
||||
item_prefix, item_sep, item_suffix)
|
||||
item_prefix, item_sep, item_suffix, convert_to_hex=convert_to_hex)
|
||||
|
||||
for t in self.string_types:
|
||||
if isinstance(obj, t) and has_obj_repr(t):
|
||||
return self._repr_str(obj, level)
|
||||
return self._repr_str(obj, level, convert_to_hex=convert_to_hex)
|
||||
|
||||
if self._is_long_iter(obj):
|
||||
return self._repr_long_iter(obj)
|
||||
return self._repr_long_iter(obj, convert_to_hex=convert_to_hex)
|
||||
|
||||
return self._repr_other(obj, level)
|
||||
return self._repr_other(obj, level, convert_to_hex=convert_to_hex)
|
||||
|
||||
# Determines whether an iterable exceeds the limits set in
|
||||
# maxlimits, and is therefore unsafe to repr().
|
||||
|
|
@ -164,7 +166,7 @@ class SafeRepr(object):
|
|||
return True
|
||||
|
||||
def _repr_iter(self, obj, level, prefix, suffix,
|
||||
comma_after_single_element=False):
|
||||
comma_after_single_element=False, convert_to_hex=False):
|
||||
yield prefix
|
||||
|
||||
if level >= len(self.maxcollection):
|
||||
|
|
@ -182,7 +184,7 @@ class SafeRepr(object):
|
|||
yield '...'
|
||||
break
|
||||
|
||||
for p in self._repr(item, 100 if item is obj else level + 1):
|
||||
for p in self._repr(item, 100 if item is obj else level + 1, convert_to_hex=convert_to_hex):
|
||||
yield p
|
||||
else:
|
||||
if comma_after_single_element:
|
||||
|
|
@ -190,9 +192,10 @@ class SafeRepr(object):
|
|||
yield ','
|
||||
yield suffix
|
||||
|
||||
def _repr_long_iter(self, obj):
|
||||
def _repr_long_iter(self, obj, convert_to_hex=False):
|
||||
try:
|
||||
obj_repr = '<%s, len() = %s>' % (type(obj).__name__, len(obj))
|
||||
length = hex(len(obj)) if convert_to_hex else len(obj)
|
||||
obj_repr = '<%s, len() = %s>' % (type(obj).__name__, length)
|
||||
except Exception:
|
||||
try:
|
||||
obj_repr = '<' + type(obj).__name__ + '>'
|
||||
|
|
@ -201,7 +204,7 @@ class SafeRepr(object):
|
|||
yield obj_repr
|
||||
|
||||
def _repr_dict(self, obj, level, prefix, suffix,
|
||||
item_prefix, item_sep, item_suffix):
|
||||
item_prefix, item_sep, item_suffix, convert_to_hex=False):
|
||||
if not obj:
|
||||
yield prefix + suffix
|
||||
return
|
||||
|
|
@ -230,7 +233,7 @@ class SafeRepr(object):
|
|||
break
|
||||
|
||||
yield item_prefix
|
||||
for p in self._repr(key, level + 1):
|
||||
for p in self._repr(key, level + 1, convert_to_hex=convert_to_hex):
|
||||
yield p
|
||||
|
||||
yield item_sep
|
||||
|
|
@ -240,23 +243,26 @@ class SafeRepr(object):
|
|||
except Exception:
|
||||
yield '<?>'
|
||||
else:
|
||||
for p in self._repr(item, 100 if item is obj else level + 1):
|
||||
for p in self._repr(item, 100 if item is obj else level + 1, convert_to_hex=convert_to_hex):
|
||||
yield p
|
||||
yield item_suffix
|
||||
|
||||
yield suffix
|
||||
|
||||
def _repr_str(self, obj, level):
|
||||
def _repr_str(self, obj, level, convert_to_hex=False):
|
||||
return self._repr_obj(obj, level,
|
||||
self.maxstring_inner, self.maxstring_outer)
|
||||
self.maxstring_inner, self.maxstring_outer, convert_to_hex=convert_to_hex)
|
||||
|
||||
def _repr_other(self, obj, level):
|
||||
def _repr_other(self, obj, level, convert_to_hex=False):
|
||||
return self._repr_obj(obj, level,
|
||||
self.maxother_inner, self.maxother_outer)
|
||||
self.maxother_inner, self.maxother_outer, convert_to_hex=convert_to_hex)
|
||||
|
||||
def _repr_obj(self, obj, level, limit_inner, limit_outer):
|
||||
def _repr_obj(self, obj, level, limit_inner, limit_outer, convert_to_hex=False):
|
||||
try:
|
||||
obj_repr = repr(obj)
|
||||
if isinstance(obj, self.int_types) and convert_to_hex:
|
||||
obj_repr = hex(obj)
|
||||
else:
|
||||
obj_repr = repr(obj)
|
||||
except Exception:
|
||||
try:
|
||||
obj_repr = object.__repr__(obj)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,31 @@ ptvsd_sys_exit_code = 0
|
|||
WAIT_FOR_DISCONNECT_REQUEST_TIMEOUT = 2
|
||||
WAIT_FOR_THREAD_FINISH_TIMEOUT = 1
|
||||
|
||||
|
||||
class SafeReprPresentationProvider(pydevd_extapi.StrPresentationProvider):
|
||||
"""
|
||||
Computes string representation of Python values by delegating them
|
||||
to SafeRepr.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
from ptvsd.safe_repr import SafeRepr
|
||||
self.safe_repr = SafeRepr()
|
||||
self.convert_to_hex = False
|
||||
|
||||
def can_provide(self, type_object, type_name):
|
||||
return True
|
||||
|
||||
def get_str(self, val):
|
||||
return self.safe_repr(val, self.convert_to_hex)
|
||||
|
||||
# Register our presentation provider as the first item on the list,
|
||||
# so that we're in full control of presentation.
|
||||
str_handlers = pydevd_extutil.EXTENSION_MANAGER_INSTANCE.type_to_instance.setdefault(pydevd_extapi.StrPresentationProvider, []) # noqa
|
||||
safe_repr_provider = SafeReprPresentationProvider()
|
||||
str_handlers.insert(0, safe_repr_provider)
|
||||
|
||||
|
||||
class UnsupportedPyDevdCommandError(Exception):
|
||||
|
||||
def __init__(self, cmdid):
|
||||
|
|
@ -575,6 +600,7 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
supportsSetVariable=True,
|
||||
supportsExceptionOptions=True,
|
||||
supportsEvaluateForHovers=True,
|
||||
supportsValueFormattingOptions=True,
|
||||
exceptionBreakpointFilters=[
|
||||
{
|
||||
'filter': 'raised',
|
||||
|
|
@ -759,6 +785,8 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
# TODO: docstring
|
||||
vsc_var = int(args['variablesReference'])
|
||||
pyd_var = self.var_map.to_pydevd(vsc_var)
|
||||
|
||||
safe_repr_provider.convert_to_hex = args.get('format', {}).get('hex', False)
|
||||
|
||||
if len(pyd_var) == 3:
|
||||
cmd = pydevd_comm.CMD_GET_FRAME
|
||||
|
|
@ -794,6 +822,9 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
var['evaluateName'] = eval_name
|
||||
|
||||
variables.append(var)
|
||||
|
||||
# Reset hex format since this is per request.
|
||||
safe_repr_provider.convert_to_hex = False
|
||||
self.send_response(request, variables=variables.get_sorted_variables())
|
||||
|
||||
def __get_variable_evaluate_name(self, pyd_var_parent, var_name):
|
||||
|
|
@ -836,6 +867,8 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
vsc_var = int(args['variablesReference'])
|
||||
pyd_var = self.var_map.to_pydevd(vsc_var)
|
||||
|
||||
safe_repr_provider.convert_to_hex = args.get('format', {}).get('hex', False)
|
||||
|
||||
# VSC gives us variablesReference to the parent of the variable
|
||||
# being set, and variable name; but pydevd wants the ID
|
||||
# (or rather path) of the variable itself.
|
||||
|
|
@ -856,6 +889,9 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
}
|
||||
if bool(xvar['isContainer']):
|
||||
response['variablesReference'] = vsc_var
|
||||
|
||||
# Reset hex format since this is per request.
|
||||
safe_repr_provider.convert_to_hex = False
|
||||
self.send_response(request, **response)
|
||||
|
||||
@async_handler
|
||||
|
|
@ -866,6 +902,8 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
vsc_fid = int(args['frameId'])
|
||||
pyd_tid, pyd_fid = self.frame_map.to_pydevd(vsc_fid)
|
||||
|
||||
safe_repr_provider.convert_to_hex = args.get('format', {}).get('hex', False)
|
||||
|
||||
cmd_args = (pyd_tid, pyd_fid, 'LOCAL', expr, '1')
|
||||
_, _, resp_args = yield self.pydevd_request(
|
||||
pydevd_comm.CMD_EVALUATE_EXPRESSION,
|
||||
|
|
@ -890,6 +928,9 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
}
|
||||
if bool(xvar['isContainer']):
|
||||
response['variablesReference'] = vsc_var
|
||||
|
||||
# Reset hex format since this is per request.
|
||||
safe_repr_provider.convert_to_hex = False
|
||||
self.send_response(request, **response)
|
||||
|
||||
@async_handler
|
||||
|
|
@ -1283,25 +1324,3 @@ def start_client(host, port):
|
|||
pydevd_comm.start_server = start_server
|
||||
pydevd_comm.start_client = start_client
|
||||
|
||||
|
||||
class SafeReprPresentationProvider(pydevd_extapi.StrPresentationProvider):
|
||||
"""
|
||||
Computes string representation of Python values by delegating them
|
||||
to SafeRepr.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
from ptvsd.safe_repr import SafeRepr
|
||||
self.safe_repr = SafeRepr()
|
||||
|
||||
def can_provide(self, type_object, type_name):
|
||||
return True
|
||||
|
||||
def get_str(self, val):
|
||||
return self.safe_repr(val)
|
||||
|
||||
|
||||
# Register our presentation provider as the first item on the list,
|
||||
# so that we're in full control of presentation.
|
||||
str_handlers = pydevd_extutil.EXTENSION_MANAGER_INSTANCE.type_to_instance.setdefault(pydevd_extapi.StrPresentationProvider, []) # noqa
|
||||
str_handlers.insert(0, SafeReprPresentationProvider())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue