mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Fix lint issues.
This commit is contained in:
parent
b822afd603
commit
1155724346
3 changed files with 190 additions and 121 deletions
|
|
@ -71,6 +71,6 @@ class Message(object):
|
|||
|
||||
|
||||
# Force registration.
|
||||
from .message import ProtocolMessage, Request, Response, Event
|
||||
from .message import ProtocolMessage, Request, Response, Event # noqa
|
||||
from .requests import * # noqa
|
||||
from .events import * # noqa
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import sys
|
|||
|
||||
# Py3 compat - alias unicode to str, and xrange to range
|
||||
try:
|
||||
unicode
|
||||
except:
|
||||
unicode # noqa
|
||||
except NameError:
|
||||
unicode = str
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange # noqa
|
||||
except NameError:
|
||||
xrange = range
|
||||
|
||||
|
||||
|
|
@ -50,29 +50,30 @@ class SafeRepr(object):
|
|||
try:
|
||||
from collections import deque
|
||||
collection_types.append((deque, 'deque([', '])', False))
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# type, prefix string, suffix string, item prefix string, item key/value separator, item suffix string
|
||||
# type, prefix string, suffix string, item prefix string,
|
||||
# item key/value separator, item suffix string
|
||||
dict_types = [(dict, '{', '}', '', ': ', '')]
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
dict_types.append((OrderedDict, 'OrderedDict([', '])', '(', ', ', ')'))
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# All other types are treated identically to strings, but using
|
||||
# different limits.
|
||||
maxother_outer = 2 ** 16
|
||||
maxother_inner = 30
|
||||
|
||||
|
||||
def __call__(self, obj):
|
||||
try:
|
||||
return ''.join(self._repr(obj, 0))
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
return 'An exception was raised: %r' % sys.exc_info()[1]
|
||||
except:
|
||||
except Exception:
|
||||
return 'An exception was raised'
|
||||
|
||||
def _repr(self, obj, level):
|
||||
|
|
@ -80,23 +81,24 @@ class SafeRepr(object):
|
|||
|
||||
try:
|
||||
obj_repr = type(obj).__repr__
|
||||
except:
|
||||
except Exception:
|
||||
obj_repr = None
|
||||
|
||||
def has_obj_repr(t):
|
||||
r = t.__repr__
|
||||
try:
|
||||
return obj_repr == r
|
||||
except:
|
||||
except Exception:
|
||||
return obj_repr is r
|
||||
|
||||
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)
|
||||
|
||||
for t, prefix, suffix, item_prefix, item_sep, item_suffix in self.dict_types:
|
||||
|
||||
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)
|
||||
return self._repr_dict(obj, level, prefix, suffix,
|
||||
item_prefix, item_sep, item_suffix)
|
||||
|
||||
for t in self.string_types:
|
||||
if isinstance(obj, t) and has_obj_repr(t):
|
||||
|
|
@ -104,14 +106,16 @@ class SafeRepr(object):
|
|||
|
||||
if self._is_long_iter(obj):
|
||||
return self._repr_long_iter(obj)
|
||||
|
||||
|
||||
return self._repr_other(obj, level)
|
||||
|
||||
# Determines whether an iterable exceeds the limits set in maxlimits, and is therefore unsafe to repr().
|
||||
def _is_long_iter(self, obj, level = 0):
|
||||
# Determines whether an iterable exceeds the limits set in
|
||||
# maxlimits, and is therefore unsafe to repr().
|
||||
def _is_long_iter(self, obj, level=0):
|
||||
try:
|
||||
# Strings have their own limits (and do not nest). Because they don't have __iter__ in 2.x, this
|
||||
# check goes before the next one.
|
||||
# Strings have their own limits (and do not nest). Because
|
||||
# they don't have __iter__ in 2.x, this check goes before
|
||||
# the next one.
|
||||
if isinstance(obj, self.string_types):
|
||||
return len(obj) > self.maxstring_inner
|
||||
|
||||
|
|
@ -119,9 +123,10 @@ class SafeRepr(object):
|
|||
if not hasattr(obj, '__iter__'):
|
||||
return False
|
||||
|
||||
# Iterable is its own iterator - this is a one-off iterable like generator or enumerate(). We can't
|
||||
# really count that, but repr() for these should not include any elements anyway, so we can treat it
|
||||
# the same as non-iterables.
|
||||
# Iterable is its own iterator - this is a one-off iterable
|
||||
# like generator or enumerate(). We can't really count that,
|
||||
# but repr() for these should not include any elements anyway,
|
||||
# so we can treat it the same as non-iterables.
|
||||
if obj is iter(obj):
|
||||
return False
|
||||
|
||||
|
|
@ -129,36 +134,39 @@ class SafeRepr(object):
|
|||
if isinstance(obj, xrange):
|
||||
return False
|
||||
|
||||
# numpy and scipy collections (ndarray etc) have self-truncating repr, so they're always safe.
|
||||
# numpy and scipy collections (ndarray etc) have
|
||||
# self-truncating repr, so they're always safe.
|
||||
try:
|
||||
module = type(obj).__module__.partition('.')[0]
|
||||
if module in ('numpy', 'scipy'):
|
||||
return False
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Iterables that nest too deep are considered long.
|
||||
if level >= len(self.maxcollection):
|
||||
return True
|
||||
|
||||
# It is too long if the length exceeds the limit, or any of its elements are long iterables.
|
||||
# It is too long if the length exceeds the limit, or any
|
||||
# of its elements are long iterables.
|
||||
if hasattr(obj, '__len__'):
|
||||
try:
|
||||
l = len(obj)
|
||||
except:
|
||||
l = None
|
||||
if l is not None and l > self.maxcollection[level]:
|
||||
size = len(obj)
|
||||
except Exception:
|
||||
size = None
|
||||
if size is not None and size > self.maxcollection[level]:
|
||||
return True
|
||||
return any((self._is_long_iter(item, level + 1) for item in obj))
|
||||
return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj))
|
||||
return any((self._is_long_iter(item, level + 1) for item in obj)) # noqa
|
||||
return any(i > self.maxcollection[level] or self._is_long_iter(item, level + 1) for i, item in enumerate(obj)) # noqa
|
||||
|
||||
except:
|
||||
except Exception:
|
||||
# If anything breaks, assume the worst case.
|
||||
return True
|
||||
|
||||
def _repr_iter(self, obj, level, prefix, suffix, comma_after_single_element = False):
|
||||
|
||||
def _repr_iter(self, obj, level, prefix, suffix,
|
||||
comma_after_single_element=False):
|
||||
yield prefix
|
||||
|
||||
|
||||
if level >= len(self.maxcollection):
|
||||
yield '...'
|
||||
else:
|
||||
|
|
@ -168,7 +176,7 @@ class SafeRepr(object):
|
|||
if yield_comma:
|
||||
yield ', '
|
||||
yield_comma = True
|
||||
|
||||
|
||||
count -= 1
|
||||
if count <= 0:
|
||||
yield '...'
|
||||
|
|
@ -177,48 +185,50 @@ class SafeRepr(object):
|
|||
for p in self._repr(item, 100 if item is obj else level + 1):
|
||||
yield p
|
||||
else:
|
||||
if comma_after_single_element and count == self.maxcollection[level] - 1:
|
||||
yield ','
|
||||
if comma_after_single_element:
|
||||
if count == self.maxcollection[level] - 1:
|
||||
yield ','
|
||||
yield suffix
|
||||
|
||||
def _repr_long_iter(self, obj):
|
||||
try:
|
||||
obj_repr = '<%s, len() = %s>' % (type(obj).__name__, len(obj))
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
obj_repr = '<' + type(obj).__name__ + '>'
|
||||
except:
|
||||
except Exception:
|
||||
obj_repr = '<no repr available for object>'
|
||||
yield obj_repr
|
||||
|
||||
def _repr_dict(self, obj, level, prefix, suffix, item_prefix, item_sep, item_suffix):
|
||||
|
||||
def _repr_dict(self, obj, level, prefix, suffix,
|
||||
item_prefix, item_sep, item_suffix):
|
||||
if not obj:
|
||||
yield prefix + suffix
|
||||
return
|
||||
if level >= len(self.maxcollection):
|
||||
yield prefix + '...' + suffix
|
||||
return
|
||||
|
||||
|
||||
yield prefix
|
||||
|
||||
|
||||
count = self.maxcollection[level]
|
||||
yield_comma = False
|
||||
|
||||
|
||||
try:
|
||||
sorted_keys = sorted(obj)
|
||||
except Exception:
|
||||
sorted_keys = list(obj)
|
||||
|
||||
|
||||
for key in sorted_keys:
|
||||
if yield_comma:
|
||||
yield ', '
|
||||
yield_comma = True
|
||||
|
||||
|
||||
count -= 1
|
||||
if count <= 0:
|
||||
yield '...'
|
||||
break
|
||||
|
||||
|
||||
yield item_prefix
|
||||
for p in self._repr(key, level + 1):
|
||||
yield p
|
||||
|
|
@ -233,56 +243,57 @@ class SafeRepr(object):
|
|||
for p in self._repr(item, 100 if item is obj else level + 1):
|
||||
yield p
|
||||
yield item_suffix
|
||||
|
||||
|
||||
yield suffix
|
||||
|
||||
def _repr_str(self, obj, level):
|
||||
return self._repr_obj(obj, level, self.maxstring_inner, self.maxstring_outer)
|
||||
return self._repr_obj(obj, level,
|
||||
self.maxstring_inner, self.maxstring_outer)
|
||||
|
||||
def _repr_other(self, obj, level):
|
||||
return self._repr_obj(obj, level, self.maxother_inner, self.maxother_outer)
|
||||
|
||||
return self._repr_obj(obj, level,
|
||||
self.maxother_inner, self.maxother_outer)
|
||||
|
||||
def _repr_obj(self, obj, level, limit_inner, limit_outer):
|
||||
try:
|
||||
obj_repr = repr(obj)
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
obj_repr = object.__repr__(obj)
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
obj_repr = '<no repr available for ' + type(obj).__name__ + '>'
|
||||
except:
|
||||
obj_repr = '<no repr available for ' + type(obj).__name__ + '>' # noqa
|
||||
except Exception:
|
||||
obj_repr = '<no repr available for object>'
|
||||
|
||||
|
||||
limit = limit_inner if level > 0 else limit_outer
|
||||
|
||||
|
||||
if limit >= len(obj_repr):
|
||||
yield obj_repr
|
||||
return
|
||||
|
||||
|
||||
# Slightly imprecise calculations - we may end up with a string that is
|
||||
# up to 3 characters longer than limit. If you need precise formatting,
|
||||
# you are using the wrong class.
|
||||
left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3))
|
||||
|
||||
left_count, right_count = max(1, int(2 * limit / 3)), max(1, int(limit / 3)) # noqa
|
||||
|
||||
yield obj_repr[:left_count]
|
||||
yield '...'
|
||||
yield obj_repr[-right_count:]
|
||||
|
||||
|
||||
|
||||
def _selftest(self):
|
||||
# Test the string limiting somewhat automatically
|
||||
tests = []
|
||||
tests.append((7, 9, 'A' * (5)))
|
||||
tests.append((self.maxstring_outer + 3, self.maxstring_inner + 3 + 2, 'A' * (self.maxstring_outer + 10)))
|
||||
tests.append((self.maxstring_outer + 3, self.maxstring_inner + 3 + 2, 'A' * (self.maxstring_outer + 10))) # noqa
|
||||
if sys.version_info >= (3, 0):
|
||||
tests.append((self.maxstring_outer + 4, self.maxstring_inner + 4 + 2, bytes('A', 'ascii') * (self.maxstring_outer + 10)))
|
||||
tests.append((self.maxstring_outer + 4, self.maxstring_inner + 4 + 2, bytes('A', 'ascii') * (self.maxstring_outer + 10))) # noqa
|
||||
else:
|
||||
tests.append((self.maxstring_outer + 4, self.maxstring_inner + 4 + 2, unicode('A') * (self.maxstring_outer + 10)))
|
||||
|
||||
tests.append((self.maxstring_outer + 4, self.maxstring_inner + 4 + 2, unicode('A') * (self.maxstring_outer + 10))) # noqa
|
||||
|
||||
for limit1, limit2, value in tests:
|
||||
assert len(self(value)) <= limit1 <= len(repr(value)), (len(self(value)), limit1, len(repr(value)), value)
|
||||
assert len(self([value])) <= limit2 <= len(repr([value])), (len(self([value])), limit2, len(repr([value])), self([value]))
|
||||
assert len(self(value)) <= limit1 <= len(repr(value)), (len(self(value)), limit1, len(repr(value)), value) # noqa
|
||||
assert len(self([value])) <= limit2 <= len(repr([value])), (len(self([value])), limit2, len(repr([value])), self([value])) # noqa
|
||||
|
||||
def test(source, expected):
|
||||
actual = self(source)
|
||||
|
|
@ -292,7 +303,7 @@ class SafeRepr(object):
|
|||
print("Actual " + actual)
|
||||
print("")
|
||||
assert False
|
||||
|
||||
|
||||
def re_test(source, pattern):
|
||||
import re
|
||||
actual = self(source)
|
||||
|
|
@ -302,7 +313,7 @@ class SafeRepr(object):
|
|||
print("Actual " + actual)
|
||||
print("")
|
||||
assert False
|
||||
|
||||
|
||||
for ctype, _prefix, _suffix, comma in self.collection_types:
|
||||
for i in range(len(self.maxcollection)):
|
||||
prefix = _prefix * (i + 1)
|
||||
|
|
@ -310,7 +321,8 @@ class SafeRepr(object):
|
|||
suffix = _suffix + ("," + _suffix) * i
|
||||
else:
|
||||
suffix = _suffix * (i + 1)
|
||||
#print("ctype = " + ctype.__name__ + ", maxcollection[" + str(i) + "] == " + str(self.maxcollection[i]))
|
||||
#print("ctype = " + ctype.__name__ + ", maxcollection[" +
|
||||
# str(i) + "] == " + str(self.maxcollection[i]))
|
||||
c1 = ctype(range(self.maxcollection[i] - 1))
|
||||
inner_repr = prefix + ', '.join(str(j) for j in c1)
|
||||
c2 = ctype(range(self.maxcollection[i]))
|
||||
|
|
@ -329,10 +341,10 @@ class SafeRepr(object):
|
|||
# test with lists.
|
||||
c1 = list(range(self.maxcollection[0] * 2))
|
||||
c2 = [c1 for _ in range(self.maxcollection[0] * 2)]
|
||||
c1_expect = '[' + ', '.join(str(j) for j in range(self.maxcollection[0] - 1)) + ', ...]'
|
||||
c1_expect = '[' + ', '.join(str(j) for j in range(self.maxcollection[0] - 1)) + ', ...]' # noqa
|
||||
test(c1, c1_expect)
|
||||
c1_expect2 = '[' + ', '.join(str(j) for j in range(self.maxcollection[1] - 1)) + ', ...]'
|
||||
c2_expect = '[' + ', '.join(c1_expect2 for _ in range(self.maxcollection[0] - 1)) + ', ...]'
|
||||
c1_expect2 = '[' + ', '.join(str(j) for j in range(self.maxcollection[1] - 1)) + ', ...]' # noqa
|
||||
c2_expect = '[' + ', '.join(c1_expect2 for _ in range(self.maxcollection[0] - 1)) + ', ...]' # noqa
|
||||
test(c2, c2_expect)
|
||||
|
||||
# Ensure dict keys and values are limited correctly
|
||||
|
|
@ -340,13 +352,13 @@ class SafeRepr(object):
|
|||
d1_key = 'a' * self.maxstring_inner * 2
|
||||
d1[d1_key] = d1_key
|
||||
re_test(d1, "{'a+\.\.\.a+': 'a+\.\.\.a+'}")
|
||||
d2 = {d1_key : d1}
|
||||
d2 = {d1_key: d1}
|
||||
re_test(d2, "{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}")
|
||||
d3 = {d1_key : d2}
|
||||
d3 = {d1_key: d2}
|
||||
if len(self.maxcollection) == 2:
|
||||
re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}")
|
||||
else:
|
||||
re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}")
|
||||
re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}") # noqa
|
||||
|
||||
# Ensure empty dicts work
|
||||
test({}, '{}')
|
||||
|
|
@ -384,23 +396,32 @@ class SafeRepr(object):
|
|||
# Test with objects with long repr implementations
|
||||
class TestClass(object):
|
||||
repr_str = '<' + 'A' * self.maxother_outer * 2 + '>'
|
||||
|
||||
def __repr__(self):
|
||||
return self.repr_str
|
||||
re_test(TestClass(), r'\<A+\.\.\.A+\>')
|
||||
|
||||
# Test collections that don't override repr
|
||||
class TestClass(dict): pass
|
||||
class TestClass(dict):
|
||||
pass
|
||||
test(TestClass(), '{}')
|
||||
class TestClass(list): pass
|
||||
|
||||
class TestClass(list):
|
||||
pass
|
||||
test(TestClass(), '[]')
|
||||
|
||||
# Test collections that override repr
|
||||
class TestClass(dict):
|
||||
def __repr__(self): return 'MyRepr'
|
||||
def __repr__(self):
|
||||
return 'MyRepr'
|
||||
test(TestClass(), 'MyRepr')
|
||||
|
||||
class TestClass(list):
|
||||
def __init__(self, iter = ()): list.__init__(self, iter)
|
||||
def __repr__(self): return 'MyRepr'
|
||||
def __init__(self, iter=()):
|
||||
list.__init__(self, iter)
|
||||
|
||||
def __repr__(self):
|
||||
return 'MyRepr'
|
||||
test(TestClass(), 'MyRepr')
|
||||
|
||||
# Test collections and iterables with long repr
|
||||
|
|
@ -410,15 +431,18 @@ class SafeRepr(object):
|
|||
test(TestClass([TestClass(xrange(0, 11))]), '<TestClass, len() = 1>')
|
||||
|
||||
# Test strings inside long iterables
|
||||
test(TestClass(['a' * (self.maxcollection[1] + 1)]), 'MyRepr')
|
||||
test(TestClass(['a' * (self.maxstring_inner + 1)]), '<TestClass, len() = 1>')
|
||||
test(TestClass(['a' * (self.maxcollection[1] + 1)]),
|
||||
'MyRepr')
|
||||
test(TestClass(['a' * (self.maxstring_inner + 1)]),
|
||||
'<TestClass, len() = 1>')
|
||||
|
||||
# Test range
|
||||
if sys.version[0] == '2':
|
||||
range_name = 'xrange'
|
||||
else:
|
||||
range_name = 'range'
|
||||
test(xrange(1, self.maxcollection[0] + 1), '%s(1, %s)' % (range_name, self.maxcollection[0] + 1))
|
||||
test(xrange(1, self.maxcollection[0] + 1),
|
||||
'%s(1, %s)' % (range_name, self.maxcollection[0] + 1))
|
||||
|
||||
# Test directly recursive collections
|
||||
c1 = [1, 2]
|
||||
|
|
@ -442,15 +466,21 @@ class SafeRepr(object):
|
|||
#except MemoryError:
|
||||
# print('Memory error raised while creating repr of test data')
|
||||
# text_repr = ''
|
||||
#print('len(SafeRepr()(dcoll)) = ' + str(len(text)) + ', len(repr(coll)) = ' + str(len(text_repr)))
|
||||
#print('len(SafeRepr()(dcoll)) = ' + str(len(text)) +
|
||||
# ', len(repr(coll)) = ' + str(len(text_repr)))
|
||||
assert len(text) < 8192
|
||||
|
||||
# Test numpy types - they should all use their native reprs, even arrays exceeding limits
|
||||
# Test numpy types - they should all use their native reprs,
|
||||
# even arrays exceeding limits
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
print('WARNING! could not import numpy - skipping all numpy tests.')
|
||||
msg = 'WARNING! could not import numpy - skipping all numpy tests.'
|
||||
print(msg)
|
||||
else:
|
||||
test(np.int32(123), repr(np.int32(123)))
|
||||
test(np.float64(123.456), repr(np.float64(123.456)))
|
||||
test(np.zeros(self.maxcollection[0] + 1), repr(np.zeros(self.maxcollection[0] + 1)));
|
||||
test(np.int32(123),
|
||||
repr(np.int32(123)))
|
||||
test(np.float64(123.456),
|
||||
repr(np.float64(123.456)))
|
||||
test(np.zeros(self.maxcollection[0] + 1),
|
||||
repr(np.zeros(self.maxcollection[0] + 1)))
|
||||
|
|
|
|||
|
|
@ -6,14 +6,13 @@
|
|||
from __future__ import print_function, with_statement, absolute_import
|
||||
|
||||
import atexit
|
||||
import itertools
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
import untangle
|
||||
import platform
|
||||
import platform
|
||||
|
||||
try:
|
||||
import urllib
|
||||
|
|
@ -234,6 +233,7 @@ class PydevdSocket(object):
|
|||
os.write(self.pipe_w, s.encode('utf8'))
|
||||
return fut
|
||||
|
||||
|
||||
class ExceptionsManager(object):
|
||||
def __init__(self, proc):
|
||||
self.proc = proc
|
||||
|
|
@ -244,14 +244,14 @@ class ExceptionsManager(object):
|
|||
with self.lock:
|
||||
for exception in self.exceptions:
|
||||
self.proc.pydevd_notify(pydevd_comm.CMD_REMOVE_EXCEPTION_BREAK,
|
||||
'python-{}'.format(exception))
|
||||
'python-{}'.format(exception))
|
||||
self.exceptions = []
|
||||
|
||||
def add_exception_break(self, exception, break_raised, break_uncaught):
|
||||
|
||||
|
||||
# notify_always options:
|
||||
# 1 is deprecated, you will see a warning message
|
||||
# 2 notify on first raise only
|
||||
# 2 notify on first raise only
|
||||
# 3 or greater, notify always
|
||||
notify_always = 3 if break_raised else 0
|
||||
|
||||
|
|
@ -261,38 +261,66 @@ class ExceptionsManager(object):
|
|||
notify_on_terminate = 1 if break_uncaught else 0
|
||||
|
||||
# ignore_libraries options:
|
||||
# Less than or equal to 0 DO NOT ignore libraries (required for notify_always)
|
||||
# Less than or equal to 0 DO NOT ignore libraries (required
|
||||
# for notify_always)
|
||||
# Greater than 0 ignore libraries
|
||||
ignore_libraries = 0
|
||||
cmdargs = (exception, notify_always, notify_on_terminate, ignore_libraries)
|
||||
cmdargs = (
|
||||
exception,
|
||||
notify_always,
|
||||
notify_on_terminate,
|
||||
ignore_libraries,
|
||||
)
|
||||
msg = 'python-{}\t{}\t{}\t{}'.format(*cmdargs)
|
||||
with self.lock:
|
||||
self.proc.pydevd_notify(pydevd_comm.CMD_ADD_EXCEPTION_BREAK, msg)
|
||||
self.proc.pydevd_notify(
|
||||
pydevd_comm.CMD_ADD_EXCEPTION_BREAK, msg)
|
||||
self.exceptions.append(exception)
|
||||
|
||||
|
||||
def apply_exception_options(self, exception_options):
|
||||
"""Applies exception options after removing any existing exception breaks.
|
||||
"""
|
||||
Applies exception options after removing any existing exception
|
||||
breaks.
|
||||
"""
|
||||
self.remove_all_exception_breaks()
|
||||
pyex_options = (o for o in exception_options if self.__is_python_exception_category(o))
|
||||
pyex_options = (opt
|
||||
for opt in exception_options
|
||||
if self.__is_python_exception_category(opt))
|
||||
for option in pyex_options:
|
||||
exception_paths = option['path']
|
||||
if not exception_paths:
|
||||
continue
|
||||
|
||||
mode = option['breakMode']
|
||||
break_raised = True if mode == 'always' else False
|
||||
break_uncaught = True if mode in ['unhandled', 'userUnhandled'] else False
|
||||
break_raised = (mode == 'always')
|
||||
break_uncaught = (mode in ['unhandled', 'userUnhandled'])
|
||||
|
||||
# Special case for the entire python exceptions category
|
||||
if len(exception_paths) == 1 and exception_paths[0]['names'][0] == 'Python Exceptions':
|
||||
self.add_exception_break('BaseException', break_raised, break_uncaught)
|
||||
is_category = False
|
||||
if len(exception_paths) == 1:
|
||||
# TODO: isn't the first one always the category?
|
||||
if exception_paths[0]['names'][0] == 'Python Exceptions':
|
||||
is_category = True
|
||||
if is_category:
|
||||
self.add_exception_break(
|
||||
'BaseException', break_raised, break_uncaught)
|
||||
else:
|
||||
# Skip the first one. It will always be the category "Python Exceptions"
|
||||
path_iterator = itertools.islice(exception_paths, 1, None)
|
||||
exception_names = (ex_name for path in path_iterator for ex_name in path['names'])
|
||||
path_iterator = iter(exception_paths)
|
||||
# Skip the first one. It will always be the category
|
||||
# "Python Exceptions"
|
||||
next(path_iterator)
|
||||
exception_names = []
|
||||
for path in path_iterator:
|
||||
for ex_name in path['names']:
|
||||
exception_names.append(ex_name)
|
||||
for exception_name in exception_names:
|
||||
self.add_exception_break(exception_name, break_raised, break_uncaught)
|
||||
|
||||
self.add_exception_break(
|
||||
exception_name, break_raised, break_uncaught)
|
||||
|
||||
def __is_python_exception_category(self, option):
|
||||
"""Check if the option has entires and that the first entry is 'Python Exceptions'
|
||||
"""
|
||||
Check if the option has entires and that the first entry
|
||||
is 'Python Exceptions'.
|
||||
"""
|
||||
exception_paths = option['path']
|
||||
if not exception_paths:
|
||||
|
|
@ -301,7 +329,7 @@ class ExceptionsManager(object):
|
|||
category = exception_paths[0]['names']
|
||||
if category is None or len(category) != 1:
|
||||
return False
|
||||
|
||||
|
||||
return category[0] == 'Python Exceptions'
|
||||
|
||||
|
||||
|
|
@ -456,7 +484,12 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
self.send_event('process', **evt)
|
||||
|
||||
def is_debugger_internal_thread(self, thread_name):
|
||||
return thread_name and (thread_name.startswith('pydevd.') or thread_name.startswith('ptvsd.'))
|
||||
if thread_name:
|
||||
if thread_name.startswith('pydevd.'):
|
||||
return True
|
||||
elif thread_name.startswith('ptvsd.'):
|
||||
return True
|
||||
return False
|
||||
|
||||
@async_handler
|
||||
def on_threads(self, request, args):
|
||||
|
|
@ -704,7 +737,8 @@ class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
|
|||
break_raised = 'raised' in filters
|
||||
break_uncaught = 'uncaught' in filters
|
||||
if break_raised or break_uncaught:
|
||||
self.exceptions_mgr.add_exception_break('BaseException', break_raised, break_uncaught)
|
||||
self.exceptions_mgr.add_exception_break(
|
||||
'BaseException', break_raised, break_uncaught)
|
||||
self.send_response(request)
|
||||
|
||||
@async_handler
|
||||
|
|
@ -866,7 +900,10 @@ pydevd_comm.start_client = start_client
|
|||
|
||||
|
||||
class SafeReprPresentationProvider(pydevd_extapi.StrPresentationProvider):
|
||||
"""Computes string representation of Python values by delegating them to SafeRepr."""
|
||||
"""
|
||||
Computes string representation of Python values by delegating them
|
||||
to SafeRepr.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
from ptvsd.safe_repr import SafeRepr
|
||||
|
|
@ -878,6 +915,8 @@ class SafeReprPresentationProvider(pydevd_extapi.StrPresentationProvider):
|
|||
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, [])
|
||||
|
||||
# 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