Fix lint issues.

This commit is contained in:
Eric Snow 2018-02-14 00:28:54 +00:00
parent b822afd603
commit 1155724346
3 changed files with 190 additions and 121 deletions

View file

@ -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

View file

@ -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)))

View file

@ -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())