Just my code (#467)

* Add set debugger property to support VS just my code

* Just my code initial code

* Limit continue to stepping and exceptions

* Improve skipping non-user code

* Fix tests

* Just my code shoudl skip ptvsd files

* fixes and updates (#1)

* Fix typo

* Use CMD_STEP_INTO_MY_CODE and CMD_SET_PROJECT_ROOTS

* Update tests to reflect the new pydevd exception breakpoint cmd args

* Fixes and improvements

* Simplify and refactor debug options

* Test fix and fix for debug property request handler for VS

* More fixes

* Test fixes

* Address comments

* Bunch of test fixes (#2)

* Test fixes

* Restoring auto-continue till pydev side work is done.
This commit is contained in:
Karthik Nadig 2018-06-14 11:02:38 -07:00 committed by GitHub
parent 8427816fca
commit bbeebea696
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 208 additions and 118 deletions

View file

@ -82,6 +82,7 @@ class Capabilities(FieldsNamespace):
Field('supportsLoadedSourcesRequest', bool),
Field('supportsSetExpression', bool),
Field('supportsModulesRequest', bool),
Field('supportsDebuggerProperties', bool),
]

View file

@ -11,6 +11,7 @@ import os
import platform
import pydevd_file_utils
import re
import site
import socket
import sys
import threading
@ -111,42 +112,41 @@ SafeReprPresentationProvider._instance = SafeReprPresentationProvider()
str_handlers = pydevd_extutil.EXTENSION_MANAGER_INSTANCE.type_to_instance.setdefault(pydevd_extapi.StrPresentationProvider, []) # noqa
str_handlers.insert(0, SafeReprPresentationProvider._instance)
DONT_TRACE_FILES = set((os.path.join(*elem) for elem in [
('ptvsd', 'attach_server.py'),
('ptvsd', 'daemon.py'),
('ptvsd', 'debugger.py'),
('ptvsd', 'futures.py'),
('ptvsd', 'ipcjson.py'),
('ptvsd', 'pathutils.py'),
('ptvsd', 'pydevd_hooks.py'),
('ptvsd', 'reraise.py'),
('ptvsd', 'reraise2.py'),
('ptvsd', 'reraise3.py'),
('ptvsd', 'runner.py'),
('ptvsd', 'safe_repr.py'),
('ptvsd', 'socket.py'),
('ptvsd', 'untangle.py'),
('ptvsd', 'version.py'),
('ptvsd', 'wrapper.py'),
('ptvsd', '_main.py'),
('ptvsd', '_version.py'),
('ptvsd', '__init__.py'),
('ptvsd', '__main__.py'),
]))
PTVSD_DIR_PATH = os.path.dirname(os.path.abspath(__file__)) + os.path.sep
NORM_PTVSD_DIR_PATH = os.path.normcase(PTVSD_DIR_PATH)
def filter_ptvsd_files(file_path):
def dont_trace_ptvsd_files(file_path):
"""
Returns true if the file should not be traced.
"""
ptvsd_path_re = r"(ptvsd[\\\/].*\.py)"
matches = re.finditer(ptvsd_path_re, file_path)
return any((g in DONT_TRACE_FILES
for m in matches
for g in m.groups()))
return file_path.startswith(PTVSD_DIR_PATH)
pydevd_frame.file_tracing_filter = filter_ptvsd_files
pydevd_frame.file_tracing_filter = dont_trace_ptvsd_files
STDLIB_PATH_PREFIXES = [os.path.normcase(sys.prefix)]
if hasattr(sys, 'base_prefix'):
STDLIB_PATH_PREFIXES.append(os.path.normcase(sys.base_prefix))
if hasattr(sys, 'real_prefix'):
STDLIB_PATH_PREFIXES.append(os.path.normcase(sys.real_prefix))
if hasattr(site, 'getusersitepackages'):
site_paths = site.getusersitepackages()
if isinstance(site_paths, list):
for site_path in site_paths:
STDLIB_PATH_PREFIXES.append(os.path.normcase(site_path))
else:
STDLIB_PATH_PREFIXES.append(os.path.normcase(site_paths))
if hasattr(site, 'getsitepackages'):
site_paths = site.getsitepackages()
if isinstance(site_paths, list):
for site_path in site_paths:
STDLIB_PATH_PREFIXES.append(os.path.normcase(site_path))
else:
STDLIB_PATH_PREFIXES.append(os.path.normcase(site_paths))
class UnsupportedPyDevdCommandError(Exception):
@ -446,28 +446,17 @@ class ExceptionsManager(object):
pass
return 'unhandled'
def add_exception_break(self, exception, break_raised, break_uncaught):
def add_exception_break(self, exception, break_raised, break_uncaught,
skip_stdlib=False):
# notify_always options:
# 1 is deprecated, you will see a warning message
# 2 notify on first raise only
# 3 or greater, notify always
notify_always = 3 if break_raised else 0
notify_on_handled_exceptions = 1 if break_raised else 0
notify_on_unhandled_exceptions = 1 if break_uncaught else 0
ignore_libraries = 1 if skip_stdlib else 0
# notify_on_terminate options:
# 1 notify on terminate
# Any other value do NOT notify on terminate
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)
# Greater than 0 ignore libraries
ignore_libraries = 0
cmdargs = (
exception,
notify_always,
notify_on_terminate,
notify_on_handled_exceptions,
notify_on_unhandled_exceptions,
ignore_libraries,
)
break_mode = 'never'
@ -482,7 +471,7 @@ class ExceptionsManager(object):
pydevd_comm.CMD_ADD_EXCEPTION_BREAK, msg)
self.exceptions[exception] = break_mode
def apply_exception_options(self, exception_options):
def apply_exception_options(self, exception_options, skip_stdlib=False):
"""
Applies exception options after removing any existing exception
breaks.
@ -508,7 +497,7 @@ class ExceptionsManager(object):
is_category = True
if is_category:
self.add_exception_break(
'BaseException', break_raised, break_uncaught)
'BaseException', break_raised, break_uncaught, skip_stdlib)
else:
path_iterator = iter(exception_paths)
# Skip the first one. It will always be the category
@ -520,7 +509,8 @@ class ExceptionsManager(object):
exception_names.append(ex_name)
for exception_name in exception_names:
self.add_exception_break(
exception_name, break_raised, break_uncaught)
exception_name, break_raised,
break_uncaught, skip_stdlib)
def _is_python_exception_category(self, option):
"""
@ -794,6 +784,7 @@ def _parse_debug_options(opts):
# TODO: Embed instead of extend (inheritance -> composition).
class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
"""The base class for VSC message processors."""
@ -896,17 +887,18 @@ class VSCodeMessageProcessorBase(ipcjson.SocketIO, ipcjson.IpcChannel):
INITIALIZE_RESPONSE = dict(
supportsExceptionInfoRequest=True,
supportsConfigurationDoneRequest=True,
supportsConditionalBreakpoints=True,
supportsHitConditionalBreakpoints=True,
supportsSetVariable=True,
supportsExceptionOptions=True,
supportsConfigurationDoneRequest=True,
supportsDebuggerProperties=True,
supportsEvaluateForHovers=True,
supportsValueFormattingOptions=True,
supportsSetExpression=True,
supportsModulesRequest=True,
supportsExceptionInfoRequest=True,
supportsExceptionOptions=True,
supportsHitConditionalBreakpoints=True,
supportsLogPoints=True,
supportsModulesRequest=True,
supportsSetExpression=True,
supportsSetVariable=True,
supportsValueFormattingOptions=True,
supportTerminateDebuggee=True,
exceptionBreakpointFilters=[
{
@ -1224,6 +1216,51 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
else:
redirect_output = ''
self.pydevd_request(pydevd_comm.CMD_REDIRECT_OUTPUT, redirect_output)
self._apply_code_stepping_settings()
def _is_just_my_code_stepping_enabled(self):
"""Returns true if just-me-code stepping is enabled.
Note: for now we consider DEBUG_STDLIB = False as just-my-code.
"""
dbg_stdlib = self.debug_options.get('DEBUG_STDLIB', False)
return not dbg_stdlib
def _apply_code_stepping_settings(self):
if self._is_just_my_code_stepping_enabled():
vendored_pydevd = os.path.sep + \
os.path.join('ptvsd', '_vendored', 'pydevd')
ptvsd_path = os.path.sep + 'ptvsd'
project_dirs = []
for path in sys.path + [os.getcwd()]:
is_stdlib = False
norm_path = os.path.normcase(path)
if path.endswith(ptvsd_path) or \
path.endswith(vendored_pydevd):
is_stdlib = True
else:
for prefix in STDLIB_PATH_PREFIXES:
if norm_path.startswith(prefix):
is_stdlib = True
break
if not is_stdlib and len(path) > 0:
project_dirs.append(path)
self.pydevd_request(pydevd_comm.CMD_SET_PROJECT_ROOTS,
'\t'.join(project_dirs))
def _is_stdlib(self, filepath):
for prefix in STDLIB_PATH_PREFIXES:
if prefix != '' and filepath.startswith(prefix):
return True
return filepath.startswith(NORM_PTVSD_DIR_PATH)
def _should_debug(self, filepath):
if self._is_just_my_code_stepping_enabled() and \
self._is_stdlib(filepath):
return False
return True
def _initialize_path_maps(self, args):
pathMaps = []
@ -1783,7 +1820,10 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
def on_stepIn(self, request, args):
# TODO: docstring
tid = self.thread_map.to_pydevd(int(args['threadId']))
self.pydevd_notify(pydevd_comm.CMD_STEP_INTO, tid)
if self._is_just_my_code_stepping_enabled():
self.pydevd_notify(pydevd_comm.CMD_STEP_INTO_MY_CODE, tid)
else:
self.pydevd_notify(pydevd_comm.CMD_STEP_INTO, tid)
self.send_response(request)
@async_handler
@ -1895,16 +1935,19 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
# TODO: docstring
filters = args['filters']
exception_options = args.get('exceptionOptions', [])
jmc = self._is_just_my_code_stepping_enabled()
if exception_options:
self.exceptions_mgr.apply_exception_options(exception_options)
self.exceptions_mgr.apply_exception_options(
exception_options, jmc)
else:
self.exceptions_mgr.remove_all_exception_breaks()
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)
'BaseException', break_raised, break_uncaught,
skip_stdlib=jmc)
self.send_response(request)
@async_handler
@ -1985,6 +2028,16 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
}
self.send_response(request, **sys_info)
# VS specific custom message handlers
@async_handler
def on_setDebuggerProperty(self, request, args):
if 'JustMyCodeStepping' in args:
jmc = int(args.get('JustMyCodeStepping', 0)) > 0
self.debug_options['DEBUG_STDLIB'] = not jmc
self._apply_code_stepping_settings()
self.send_response(request)
# PyDevd protocol event handlers
@pydevd_events.handler(pydevd_comm.CMD_THREAD_CREATE)
@ -2029,16 +2082,25 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
pydevd_comm.CMD_STEP_INTO,
pydevd_comm.CMD_STEP_OVER,
pydevd_comm.CMD_STEP_RETURN,
pydevd_comm.CMD_STEP_INTO_MY_CODE,
}
EXCEPTION_REASONS = {
pydevd_comm.CMD_STEP_CAUGHT_EXCEPTION,
pydevd_comm.CMD_ADD_EXCEPTION_BREAK
}
try:
vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
except KeyError:
return
# This is needed till https://github.com/Microsoft/ptvsd/issues/477
# is done. Remove this after adding the appropriate pydevd commands to
# do step over and step out
xframes = list(xml.thread.frame)
xframe = xframes[0]
filepath = unquote(xframe['file'])
if reason in STEP_REASONS or reason in EXCEPTION_REASONS:
if not self._should_debug(filepath):
self.pydevd_notify(pydevd_comm.CMD_THREAD_RUN, pyd_tid)
return
vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
with self.stack_traces_lock:
self.stack_traces[pyd_tid] = xml.thread.frame
@ -2061,8 +2123,6 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
if reason == 'exception':
# Get exception info from frame
try:
xframes = list(xml.thread.frame)
xframe = xframes[0]
pyd_fid = xframe['id']
cmdargs = '{}\t{}\tFRAME\t__exception__'.format(pyd_tid,
pyd_fid)

View file

@ -17,6 +17,7 @@ from _pydevd_bundle.pydevd_comm import (
CMD_SEND_CURR_EXCEPTION_TRACE,
CMD_THREAD_CREATE,
CMD_GET_VARIABLE,
CMD_SET_PROJECT_ROOTS,
)
from ptvsd import wrapper
@ -139,8 +140,9 @@ class PyDevdLifecycle(object):
@contextlib.contextmanager
def _wait_for_initialized(self):
with self._fix.wait_for_command(CMD_REDIRECT_OUTPUT):
with self._fix.wait_for_command(CMD_RUN):
yield
with self._fix.wait_for_command(CMD_SET_PROJECT_ROOTS):
with self._fix.wait_for_command(CMD_RUN):
yield
def _initialize(self):
version = self._fix.fake.VERSION

View file

@ -7,6 +7,7 @@ from _pydevd_bundle.pydevd_comm import (
CMD_REDIRECT_OUTPUT,
CMD_RUN,
CMD_VERSION,
CMD_SET_PROJECT_ROOTS,
)
from . import (
@ -25,6 +26,17 @@ from ptvsd.wrapper import INITIALIZE_RESPONSE
# * sending an "exit" event.
def _get_project_dirs():
cwd = os.getcwd()
pyd_path = os.path.join('ptvsd', '_vendored', 'pydevd')
paths = []
if cwd.endswith('ptvsd') or \
cwd.endswith(pyd_path):
return ''
paths.append(cwd)
return '\t'.join(paths)
class LifecycleTests(HighlevelTest, unittest.TestCase):
"""
See https://code.visualstudio.com/docs/extensionAPI/api-debugging#_the-vs-code-debug-protocol-in-a-nutshell
@ -86,6 +98,8 @@ class LifecycleTests(HighlevelTest, unittest.TestCase):
self.debugger_msgs.new_request(CMD_VERSION,
*['1.1', expected_os_id, 'ID']),
self.debugger_msgs.new_request(CMD_REDIRECT_OUTPUT),
self.debugger_msgs.new_request(CMD_SET_PROJECT_ROOTS,
_get_project_dirs()),
self.debugger_msgs.new_request(CMD_RUN),
])
@ -116,7 +130,8 @@ class LifecycleTests(HighlevelTest, unittest.TestCase):
# configuration
req_config = self.send_request('configurationDone')
self.wait_for_pydevd('version', 'redirect-output', 'run')
self.wait_for_pydevd('version', 'redirect-output',
'run', 'set_project_roots')
# Normal ops would go here.
@ -148,5 +163,7 @@ class LifecycleTests(HighlevelTest, unittest.TestCase):
self.debugger_msgs.new_request(CMD_VERSION,
*['1.1', OS_ID, 'ID']),
self.debugger_msgs.new_request(CMD_REDIRECT_OUTPUT),
self.debugger_msgs.new_request(CMD_SET_PROJECT_ROOTS,
_get_project_dirs()),
self.debugger_msgs.new_request(CMD_RUN),
])

View file

@ -29,6 +29,7 @@ from _pydevd_bundle.pydevd_comm import (
CMD_THREAD_RUN,
CMD_THREAD_SUSPEND,
CMD_WRITE_TO_CONSOLE,
CMD_STEP_INTO_MY_CODE,
)
from . import RunningTest
@ -810,7 +811,7 @@ class NextTests(NormalRequestTest, unittest.TestCase):
class StepInTests(NormalRequestTest, unittest.TestCase):
COMMAND = 'stepIn'
PYDEVD_CMD = CMD_STEP_INTO
PYDEVD_CMD = CMD_STEP_INTO_MY_CODE
PYDEVD_RESP = None
def test_basic(self):
@ -1454,7 +1455,11 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
# TODO: We've hard-coded the currently supported modes. If other
# modes are added later then we need to add more tests. We don't
# have a programatic alternative that is very readable.
# have a programmatic alternative that is very readable.
# NOTE: The mode here depends on the default value of DEBUG_STDLIB.
# When this test was written it was assumed the DEBUG_STDLIB = False.
# this means ignore_stdlib arg to pydevd must be 1
def test_single_option_single_path_mode_never(self):
path = {
@ -1463,7 +1468,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
self._check_option(
[path],
'never',
['python-BaseException\t0\t0\t0'],
['python-BaseException\t0\t0\t1'],
)
def test_single_option_single_path_mode_always(self):
@ -1473,7 +1478,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
self._check_option(
[path],
'always',
['python-BaseException\t3\t0\t0'],
['python-BaseException\t1\t0\t1'],
)
def test_single_option_single_path_mode_unhandled(self):
@ -1483,7 +1488,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
self._check_option(
[path],
'unhandled',
['python-BaseException\t0\t1\t0'],
['python-BaseException\t0\t1\t1'],
)
def test_single_option_single_path_mode_userUnhandled(self):
@ -1493,7 +1498,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
self._check_option(
[path],
'userUnhandled',
['python-BaseException\t0\t1\t0'],
['python-BaseException\t0\t1\t1'],
)
def test_single_option_empty_paths(self):
@ -1533,7 +1538,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
self._check_option(
[path],
'always',
['python-BaseException\t3\t0\t0'],
['python-BaseException\t3\t0\t1'],
)
def test_single_option_shallow_path(self):
@ -1542,7 +1547,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
{'names': ['ImportError']},
]
self._check_option(path, 'always', [
'python-ImportError\t3\t0\t0',
'python-ImportError\t1\t0\t1',
])
def test_single_option_deep_path(self):
@ -1554,10 +1559,10 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
{'names': ['MyError']},
]
self._check_option(path, 'always', [
'python-ImportError\t3\t0\t0',
'python-RuntimeError\t3\t0\t0',
'python-ValueError\t3\t0\t0',
'python-MyError\t3\t0\t0',
'python-ImportError\t1\t0\t1',
'python-RuntimeError\t1\t0\t1',
'python-ValueError\t1\t0\t1',
'python-MyError\t1\t0\t1',
])
# TODO: verify behavior
@ -1568,9 +1573,9 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
{'names': ['ImportError', 'RuntimeError', 'ValueError']},
]
self._check_option(path, 'always', [
'python-ImportError\t3\t0\t0',
'python-RuntimeError\t3\t0\t0',
'python-ValueError\t3\t0\t0',
'python-ImportError\t1\t0\t1',
'python-RuntimeError\t1\t0\t1',
'python-ValueError\t1\t0\t1',
])
# TODO: verify behavior
@ -1631,17 +1636,17 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
]
self._check_options(options, [
# shallow path
'python-ImportError\t3\t0\t0',
'python-ImportError\t1\t0\t1',
# ignored
# deep path
'python-ModuleNotFoundError\t0\t1\t0',
'python-RuntimeError\t0\t1\t0',
'python-MyError\t0\t1\t0',
'python-ModuleNotFoundError\t0\t1\t1',
'python-RuntimeError\t0\t1\t1',
'python-MyError\t0\t1\t1',
# multiple names
'python-ValueError\t0\t0\t0',
'python-IndexError\t0\t0\t0',
'python-ValueError\t0\t0\t1',
'python-IndexError\t0\t0\t1',
# catch-all
'python-BaseException\t0\t1\t0',
'python-BaseException\t0\t1\t1',
])
def test_options_with_existing_filters(self):
@ -1649,7 +1654,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
with self.hidden():
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
p1 = self.expected_pydevd_request(
'python-BaseException\t0\t1\t0',
'python-BaseException\t0\t1\t1',
)
self.fix.send_request('setExceptionBreakpoints', dict(
filters=[
@ -1683,8 +1688,8 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
]
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, removed + [
self.expected_pydevd_request('python-ImportError\t0\t0\t0'),
self.expected_pydevd_request('python-RuntimeError\t3\t0\t0'),
self.expected_pydevd_request('python-ImportError\t0\t0\t1'),
self.expected_pydevd_request('python-RuntimeError\t1\t0\t1'),
])
def test_options_with_existing_options(self):
@ -1692,10 +1697,10 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
with self.hidden():
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
p1 = self.expected_pydevd_request(
'python-ImportError\t0\t1\t0',
'python-ImportError\t0\t1\t1',
)
p2 = self.expected_pydevd_request(
'python-BaseException\t3\t0\t0',
'python-BaseException\t1\t0\t1',
)
self.fix.send_request('setExceptionBreakpoints', dict(
filters=[],
@ -1745,8 +1750,8 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
]
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, removed + [
self.expected_pydevd_request('python-ImportError\t0\t0\t0'),
self.expected_pydevd_request('python-RuntimeError\t0\t1\t0'),
self.expected_pydevd_request('python-ImportError\t0\t0\t1'),
self.expected_pydevd_request('python-RuntimeError\t0\t1\t1'),
])
# TODO: As with the option modes, we've hard-coded the filters
@ -1767,7 +1772,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
self.expected_pydevd_request('python-BaseException\t3\t0\t0'),
self.expected_pydevd_request('python-BaseException\t1\t0\t1'),
])
def test_single_filter_uncaught(self):
@ -1784,7 +1789,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
self.expected_pydevd_request('python-BaseException\t0\t1\t0'),
self.expected_pydevd_request('python-BaseException\t0\t1\t1'),
])
def test_multiple_filters_all(self):
@ -1802,7 +1807,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
self.expected_pydevd_request('python-BaseException\t3\t1\t0'),
self.expected_pydevd_request('python-BaseException\t1\t1\t1'),
])
def test_multiple_filters_repeat(self):
@ -1820,7 +1825,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
self.expected_pydevd_request('python-BaseException\t3\t0\t0'),
self.expected_pydevd_request('python-BaseException\t1\t0\t1'),
])
def test_empty_filters(self):
@ -1840,7 +1845,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
with self.hidden():
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
p1 = self.expected_pydevd_request(
'python-BaseException\t0\t1\t0',
'python-BaseException\t0\t1\t1',
)
self.fix.send_request('setExceptionBreakpoints', dict(
filters=[
@ -1864,7 +1869,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
]
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, removed + [
self.expected_pydevd_request('python-BaseException\t3\t0\t0'),
self.expected_pydevd_request('python-BaseException\t1\t0\t1'),
])
def test_filters_with_existing_options(self):
@ -1872,10 +1877,10 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
with self.hidden():
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
p1 = self.expected_pydevd_request(
'python-ImportError\t0\t1\t0',
'python-ImportError\t0\t1\t1',
)
p2 = self.expected_pydevd_request(
'python-BaseException\t3\t0\t0',
'python-BaseException\t1\t0\t1',
)
self.fix.send_request('setExceptionBreakpoints', dict(
filters=[],
@ -1915,7 +1920,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
]
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, removed + [
self.expected_pydevd_request('python-BaseException\t3\t0\t0'),
self.expected_pydevd_request('python-BaseException\t1\t0\t1'),
])
def test_filters_with_empty_options(self):
@ -1933,7 +1938,7 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
self.expected_pydevd_request('python-BaseException\t3\t0\t0'),
self.expected_pydevd_request('python-BaseException\t1\t0\t1'),
])
# TODO: verify behavior
@ -1959,8 +1964,8 @@ class SetExceptionBreakpointsTests(NormalRequestTest, unittest.TestCase):
])
self.PYDEVD_CMD = CMD_ADD_EXCEPTION_BREAK
self.assert_received(self.debugger, [
'python-BaseException\t3\t0\t0',
'python-ImportError\t0\t1\t0',
'python-BaseException\t1\t0\t1',
'python-ImportError\t0\t1\t1',
])

View file

@ -3,7 +3,7 @@ import unittest
import ptvsd.untangle
from ptvsd.wrapper import InternalsFilter
from ptvsd.wrapper import filter_ptvsd_files
from ptvsd.wrapper import dont_trace_ptvsd_files
class InternalsFilterTests(unittest.TestCase):
@ -34,12 +34,15 @@ class InternalsFilterTests(unittest.TestCase):
class PtvsdFileTraceFilter(unittest.TestCase):
def test_basic(self):
internal_dir = os.path.dirname(
os.path.abspath(ptvsd.untangle.__file__))
test_paths = {
os.path.join('C:', 'ptvsd', 'wrapper.py'): True,
os.path.join('C:', 'abcd', 'ptvsd', 'wrapper.py'): True,
os.path.join('usr', 'ptvsd', 'wrapper.py'): True,
os.path.join('ptvsd', 'wrapper.py'): True,
os.path.join('usr', 'abcd', 'ptvsd', 'wrapper.py'): True,
os.path.join(internal_dir, 'wrapper.py'): True,
os.path.join(internal_dir, 'abcd', 'ptvsd', 'wrapper.py'): True,
os.path.join(internal_dir, 'ptvsd', 'wrapper.py'): True,
os.path.join(internal_dir, 'abcd', 'wrapper.py'): True,
os.path.join('usr', 'abcd', 'ptvsd', 'wrapper.py'): False,
os.path.join('C:', 'ptvsd', 'wrapper1.py'): False,
os.path.join('C:', 'abcd', 'ptvsd', 'ptvsd.py'): False,
os.path.join('usr', 'ptvsd', 'w.py'): False,
@ -48,4 +51,6 @@ class PtvsdFileTraceFilter(unittest.TestCase):
}
for path, val in test_paths.items():
self.assertTrue(val == filter_ptvsd_files(path))
self.assertTrue(val == dont_trace_ptvsd_files(path),
msg='Path : %s\nActual: %s' % (path,
internal_dir))