mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
* Set dont trace ptvsd files via json message. * Tests for set dont trace * Cleanup and fixes * Use custom json to generate DAP schema extensions * Address comments * Address more comments * Try fix the breakpoint() issue * Always true * Try this * Address comments.
This commit is contained in:
parent
66deeb108e
commit
b26bcd0778
11 changed files with 417 additions and 48 deletions
|
|
@ -87,6 +87,17 @@ def load_schema_data():
|
|||
return json_schema_data
|
||||
|
||||
|
||||
def load_custom_schema_data():
|
||||
import os.path
|
||||
import json
|
||||
|
||||
json_file = os.path.join(os.path.dirname(__file__), 'debugProtocolCustom.json')
|
||||
|
||||
with open(json_file, 'rb') as json_contents:
|
||||
json_schema_data = json.loads(json_contents.read())
|
||||
return json_schema_data
|
||||
|
||||
|
||||
def create_classes_to_generate_structure(json_schema_data):
|
||||
definitions = json_schema_data['definitions']
|
||||
|
||||
|
|
@ -490,6 +501,7 @@ def gen_debugger_protocol():
|
|||
raise AssertionError('Must be run with Python 3.6 onwards (to keep dict order).')
|
||||
|
||||
classes_to_generate = create_classes_to_generate_structure(load_schema_data())
|
||||
classes_to_generate.update(create_classes_to_generate_structure(load_custom_schema_data()))
|
||||
|
||||
class_to_generate = fill_properties_and_required_from_base(classes_to_generate)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Custom Debug Adapter Protocol",
|
||||
"description": "Extension to the DAP to support additional features.",
|
||||
"type": "object",
|
||||
|
||||
|
||||
"definitions": {
|
||||
|
||||
"SetDebuggerPropertyRequest": {
|
||||
"allOf": [ { "$ref": "#/definitions/Request" }, {
|
||||
"type": "object",
|
||||
"description": "The request can be used to enable or disable debugger features.",
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": "string",
|
||||
"enum": [ "setDebuggerProperty" ]
|
||||
},
|
||||
"arguments": {
|
||||
"$ref": "#/definitions/SetDebuggerPropertyArguments"
|
||||
}
|
||||
},
|
||||
"required": [ "command", "arguments" ]
|
||||
}]
|
||||
},
|
||||
"SetDebuggerPropertyArguments": {
|
||||
"type": "object",
|
||||
"description": "Arguments for 'setDebuggerProperty' request.",
|
||||
"properties": { }
|
||||
},
|
||||
"SetDebuggerPropertyResponse": {
|
||||
"allOf": [ { "$ref": "#/definitions/Response" }, {
|
||||
"type": "object",
|
||||
"description": "Response to 'setDebuggerProperty' request. This is just an acknowledgement, so no body field is required."
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -11478,6 +11478,197 @@ class ExceptionDetails(BaseSchema):
|
|||
return dct
|
||||
|
||||
|
||||
@register_request('setDebuggerProperty')
|
||||
@register
|
||||
class SetDebuggerPropertyRequest(BaseSchema):
|
||||
"""
|
||||
The request can be used to enable or disable debugger features.
|
||||
|
||||
Note: automatically generated code. Do not edit manually.
|
||||
"""
|
||||
|
||||
__props__ = {
|
||||
"seq": {
|
||||
"type": "integer",
|
||||
"description": "Sequence number."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"request"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"setDebuggerProperty"
|
||||
]
|
||||
},
|
||||
"arguments": {
|
||||
"type": "SetDebuggerPropertyArguments"
|
||||
}
|
||||
}
|
||||
__refs__ = set(['arguments'])
|
||||
|
||||
__slots__ = list(__props__.keys()) + ['kwargs']
|
||||
|
||||
def __init__(self, arguments, seq=-1, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused)
|
||||
"""
|
||||
:param string type:
|
||||
:param string command:
|
||||
:param SetDebuggerPropertyArguments arguments:
|
||||
:param integer seq: Sequence number.
|
||||
"""
|
||||
self.type = 'request'
|
||||
self.command = 'setDebuggerProperty'
|
||||
if arguments is None:
|
||||
self.arguments = SetDebuggerPropertyArguments()
|
||||
else:
|
||||
self.arguments = SetDebuggerPropertyArguments(update_ids_from_dap=update_ids_from_dap, **arguments) if arguments.__class__ != SetDebuggerPropertyArguments else arguments
|
||||
self.seq = seq
|
||||
self.kwargs = kwargs
|
||||
|
||||
|
||||
def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused)
|
||||
type = self.type # noqa (assign to builtin)
|
||||
command = self.command
|
||||
arguments = self.arguments
|
||||
seq = self.seq
|
||||
dct = {
|
||||
'type': type,
|
||||
'command': command,
|
||||
'arguments': arguments.to_dict(update_ids_to_dap=update_ids_to_dap),
|
||||
'seq': seq,
|
||||
}
|
||||
dct.update(self.kwargs)
|
||||
return dct
|
||||
|
||||
|
||||
@register
|
||||
class SetDebuggerPropertyArguments(BaseSchema):
|
||||
"""
|
||||
Arguments for 'setDebuggerProperty' request.
|
||||
|
||||
Note: automatically generated code. Do not edit manually.
|
||||
"""
|
||||
|
||||
__props__ = {}
|
||||
__refs__ = set()
|
||||
|
||||
__slots__ = list(__props__.keys()) + ['kwargs']
|
||||
|
||||
def __init__(self, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused)
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
self.kwargs = kwargs
|
||||
|
||||
|
||||
def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused)
|
||||
dct = {
|
||||
}
|
||||
dct.update(self.kwargs)
|
||||
return dct
|
||||
|
||||
|
||||
@register_response('setDebuggerProperty')
|
||||
@register
|
||||
class SetDebuggerPropertyResponse(BaseSchema):
|
||||
"""
|
||||
Response to 'setDebuggerProperty' request. This is just an acknowledgement, so no body field is
|
||||
required.
|
||||
|
||||
Note: automatically generated code. Do not edit manually.
|
||||
"""
|
||||
|
||||
__props__ = {
|
||||
"seq": {
|
||||
"type": "integer",
|
||||
"description": "Sequence number."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"response"
|
||||
]
|
||||
},
|
||||
"request_seq": {
|
||||
"type": "integer",
|
||||
"description": "Sequence number of the corresponding request."
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean",
|
||||
"description": "Outcome of the request."
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "The command requested."
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "Contains error message if success == false."
|
||||
},
|
||||
"body": {
|
||||
"type": [
|
||||
"array",
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"number",
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"description": "Contains request result if success is true and optional error details if success is false."
|
||||
}
|
||||
}
|
||||
__refs__ = set()
|
||||
|
||||
__slots__ = list(__props__.keys()) + ['kwargs']
|
||||
|
||||
def __init__(self, request_seq, success, command, seq=-1, message=None, body=None, update_ids_from_dap=False, **kwargs): # noqa (update_ids_from_dap may be unused)
|
||||
"""
|
||||
:param string type:
|
||||
:param integer request_seq: Sequence number of the corresponding request.
|
||||
:param boolean success: Outcome of the request.
|
||||
:param string command: The command requested.
|
||||
:param integer seq: Sequence number.
|
||||
:param string message: Contains error message if success == false.
|
||||
:param ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'] body: Contains request result if success is true and optional error details if success is false.
|
||||
"""
|
||||
self.type = 'response'
|
||||
self.request_seq = request_seq
|
||||
self.success = success
|
||||
self.command = command
|
||||
self.seq = seq
|
||||
self.message = message
|
||||
self.body = body
|
||||
self.kwargs = kwargs
|
||||
|
||||
|
||||
def to_dict(self, update_ids_to_dap=False): # noqa (update_ids_to_dap may be unused)
|
||||
type = self.type # noqa (assign to builtin)
|
||||
request_seq = self.request_seq
|
||||
success = self.success
|
||||
command = self.command
|
||||
seq = self.seq
|
||||
message = self.message
|
||||
body = self.body
|
||||
dct = {
|
||||
'type': type,
|
||||
'request_seq': request_seq,
|
||||
'success': success,
|
||||
'command': command,
|
||||
'seq': seq,
|
||||
}
|
||||
if message is not None:
|
||||
dct['message'] = message
|
||||
if body is not None:
|
||||
dct['body'] = body
|
||||
dct.update(self.kwargs)
|
||||
return dct
|
||||
|
||||
|
||||
@register
|
||||
class ErrorResponseBody(BaseSchema):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from _pydevd_bundle._debug_adapter.pydevd_schema import (SourceBreakpoint, Scope
|
|||
VariablesResponseBody, SetVariableResponseBody, ModulesResponseBody, SourceResponseBody,
|
||||
GotoTargetsResponseBody, ExceptionOptions)
|
||||
from _pydevd_bundle.pydevd_api import PyDevdAPI
|
||||
from _pydevd_bundle.pydevd_comm import pydevd_log
|
||||
from _pydevd_bundle.pydevd_comm_constants import (
|
||||
CMD_RETURN, CMD_STEP_OVER_MY_CODE, CMD_STEP_OVER, CMD_STEP_INTO_MY_CODE,
|
||||
CMD_STEP_INTO, CMD_STEP_RETURN_MY_CODE, CMD_STEP_RETURN, CMD_SET_NEXT_STATEMENT)
|
||||
|
|
@ -695,5 +696,49 @@ class _PyDevJsonCommandProcessor(object):
|
|||
response = pydevd_base_schema.build_response(request, kwargs={'body': {}})
|
||||
return NetCommand(CMD_RETURN, 0, response, is_json=True)
|
||||
|
||||
def _can_set_dont_trace_pattern(self, py_db, start_patterns, end_patterns):
|
||||
if py_db.is_cache_file_type_empty():
|
||||
return True
|
||||
|
||||
if py_db.dont_trace_external_files.__name__ == 'dont_trace_files_property_request':
|
||||
return py_db.dont_trace_external_files.start_patterns == start_patterns and \
|
||||
py_db.dont_trace_external_files.end_patterns == end_patterns
|
||||
|
||||
return False
|
||||
|
||||
def on_setdebuggerproperty_request(self, py_db, request):
|
||||
args = request.arguments.kwargs
|
||||
if 'dontTraceStartPatterns' in args and 'dontTraceEndPatterns' in args:
|
||||
start_patterns = tuple(args['dontTraceStartPatterns'])
|
||||
end_patterns = tuple(args['dontTraceEndPatterns'])
|
||||
if self._can_set_dont_trace_pattern(py_db, start_patterns, end_patterns):
|
||||
def dont_trace_files_property_request(abs_path):
|
||||
result = abs_path.startswith(start_patterns) or \
|
||||
abs_path.endswith(end_patterns)
|
||||
return result
|
||||
dont_trace_files_property_request.start_patterns = start_patterns
|
||||
dont_trace_files_property_request.end_patterns = end_patterns
|
||||
py_db.dont_trace_external_files = dont_trace_files_property_request
|
||||
else:
|
||||
# Don't trace pattern cannot be changed after it is set once. There are caches
|
||||
# throughout the debugger which rely on always having the same file type.
|
||||
message = ("Calls to set or change don't trace patterns (via setDebuggerProperty) are not "
|
||||
"allowed since debugging has already started or don't trace patterns are already set.")
|
||||
pydevd_log(0, message)
|
||||
response_args = {'success':False, 'body': {}, 'message': message}
|
||||
response = pydevd_base_schema.build_response(request, kwargs=response_args)
|
||||
return NetCommand(CMD_RETURN, 0, response, is_json=True)
|
||||
|
||||
# TODO: Support other common settings. Note that not all of these might be relevant to python.
|
||||
# JustMyCodeStepping: 0 or 1
|
||||
# AllowOutOfProcessSymbols: 0 or 1
|
||||
# DisableJITOptimization: 0 or 1
|
||||
# InterpreterOptions: 0 or 1
|
||||
# StopOnExceptionCrossingManagedBoundary: 0 or 1
|
||||
# WarnIfNoUserCodeOnLaunch: 0 or 1
|
||||
# EnableStepFiltering: true of false
|
||||
|
||||
response = pydevd_base_schema.build_response(request, kwargs={'body': {}})
|
||||
return NetCommand(CMD_RETURN, 0, response, is_json=True)
|
||||
|
||||
process_net_command_json = _PyDevJsonCommandProcessor(pydevd_base_schema.from_json).process_net_command_json
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ forked = False
|
|||
|
||||
file_system_encoding = getfilesystemencoding()
|
||||
|
||||
_CACHE_FILE_TYPE = {}
|
||||
|
||||
#=======================================================================================================================
|
||||
# PyDBCommandThread
|
||||
|
|
@ -546,7 +547,31 @@ class PyDB(object):
|
|||
if val is not None:
|
||||
info.pydev_message = str(val)
|
||||
|
||||
def get_file_type(self, abs_real_path_and_basename):
|
||||
def _internal_get_file_type(self, abs_real_path_and_basename):
|
||||
basename = abs_real_path_and_basename[-1]
|
||||
if basename.startswith('<frozen '):
|
||||
# In Python 3.7 "<frozen ..." appear multiple times during import and should be
|
||||
# ignored for the user.
|
||||
return self.PYDEV_FILE
|
||||
return self._dont_trace_get_file_type(basename)
|
||||
|
||||
def dont_trace_external_files(self, abs_path):
|
||||
'''
|
||||
:param abs_path:
|
||||
The result from get_abs_path_real_path_and_base_from_file or
|
||||
get_abs_path_real_path_and_base_from_frame.
|
||||
|
||||
:return
|
||||
True :
|
||||
If files should NOT be traced.
|
||||
|
||||
False:
|
||||
If files should be traced.
|
||||
'''
|
||||
# By default all external files are traced.
|
||||
return False
|
||||
|
||||
def get_file_type(self, abs_real_path_and_basename, _cache_file_type=_CACHE_FILE_TYPE):
|
||||
'''
|
||||
:param abs_real_path_and_basename:
|
||||
The result from get_abs_path_real_path_and_base_from_file or
|
||||
|
|
@ -563,12 +588,17 @@ class PyDB(object):
|
|||
None:
|
||||
If it's a regular user file which should be traced.
|
||||
'''
|
||||
basename = abs_real_path_and_basename[-1]
|
||||
if basename.startswith('<frozen '):
|
||||
# In Python 3.7 "<frozen ..." appear multiple times during import and should be
|
||||
# ignored for the user.
|
||||
return self.PYDEV_FILE
|
||||
return self._dont_trace_get_file_type(basename)
|
||||
try:
|
||||
return _cache_file_type[abs_real_path_and_basename[0]]
|
||||
except:
|
||||
file_type = self._internal_get_file_type(abs_real_path_and_basename)
|
||||
if file_type is None:
|
||||
file_type = PYDEV_FILE if self.dont_trace_external_files(abs_real_path_and_basename[0]) else None
|
||||
_cache_file_type[abs_real_path_and_basename[0]] = file_type
|
||||
return file_type
|
||||
|
||||
def is_cache_file_type_empty(self):
|
||||
return bool(_CACHE_FILE_TYPE)
|
||||
|
||||
def get_thread_local_trace_func(self):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
def call_me_back(callback):
|
||||
if callable(callback):
|
||||
callback()
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
from _debugger_case_dont_trace import call_me_back
|
||||
def my_callback():
|
||||
print('trace me') # Break here
|
||||
|
||||
if __name__ == '__main__':
|
||||
call_me_back(my_callback)
|
||||
print('TEST SUCEEDED!')
|
||||
|
|
@ -1302,6 +1302,66 @@ def test_goto(case_setup):
|
|||
|
||||
writer.finished_ok = True
|
||||
|
||||
@pytest.mark.parametrize('dbg_property', ['dont_trace', 'trace', 'change_pattern', 'dont_trace_after_start'])
|
||||
def test_set_debugger_property(case_setup, dbg_property):
|
||||
with case_setup.test_file('_debugger_case_dont_trace_test.py') as writer:
|
||||
json_facade = JsonFacade(writer)
|
||||
|
||||
writer.write_set_protocol('http_json')
|
||||
writer.write_add_breakpoint(writer.get_line_index_with_content('Break here'))
|
||||
|
||||
if dbg_property in ('dont_trace', 'change_pattern', 'dont_trace_after_start'):
|
||||
dbg_request = json_facade.write_request(
|
||||
pydevd_schema.SetDebuggerPropertyRequest(pydevd_schema.SetDebuggerPropertyArguments(
|
||||
dontTraceStartPatterns=[],
|
||||
dontTraceEndPatterns=['dont_trace.py'])))
|
||||
dbg_response = json_facade.wait_for_response(dbg_request)
|
||||
assert dbg_response.success
|
||||
|
||||
if dbg_property == 'change_pattern':
|
||||
# Attempting to change pattern after it is set but before start should succeed
|
||||
dbg_request = json_facade.write_request(
|
||||
pydevd_schema.SetDebuggerPropertyRequest(pydevd_schema.SetDebuggerPropertyArguments(
|
||||
dontTraceStartPatterns=[],
|
||||
dontTraceEndPatterns=['something_else.py'])))
|
||||
dbg_response = json_facade.wait_for_response(dbg_request)
|
||||
assert dbg_response.success
|
||||
|
||||
json_facade.write_make_initial_run()
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit()
|
||||
|
||||
stack_trace_request = json_facade.write_request(
|
||||
pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=hit.thread_id)))
|
||||
stack_trace_response = json_facade.wait_for_response(stack_trace_request)
|
||||
|
||||
if dbg_property == 'dont_trace_after_start':
|
||||
# Attempting to set don't trace after start should fail.
|
||||
# This has the same effect of not setting the trace.
|
||||
dbg_request = json_facade.write_request(
|
||||
pydevd_schema.SetDebuggerPropertyRequest(pydevd_schema.SetDebuggerPropertyArguments(
|
||||
dontTraceStartPatterns=[],
|
||||
dontTraceEndPatterns=['something_else.py'])))
|
||||
dbg_response = json_facade.wait_for_response(dbg_request)
|
||||
assert not dbg_response.success
|
||||
|
||||
stack_trace_request = json_facade.write_request(
|
||||
pydevd_schema.StackTraceRequest(pydevd_schema.StackTraceArguments(threadId=hit.thread_id)))
|
||||
stack_trace_response = json_facade.wait_for_response(stack_trace_request)
|
||||
dont_trace_frames = list(frame for frame in stack_trace_response.body.stackFrames
|
||||
if frame['source']['path'].endswith('dont_trace.py'))
|
||||
|
||||
if dbg_property in ('dont_trace', 'dont_trace_after_start'):
|
||||
# Since don't trace after start is expected to fail,
|
||||
# the original pattern still holds.
|
||||
assert dont_trace_frames == []
|
||||
else:
|
||||
assert len(dont_trace_frames) == 1
|
||||
|
||||
writer.write_run_thread(hit.thread_id)
|
||||
|
||||
writer.finished_ok = True
|
||||
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Flaky on Jython.')
|
||||
def test_path_translation_and_source_reference(case_setup):
|
||||
|
|
|
|||
|
|
@ -80,33 +80,13 @@ def path_to_unicode(s):
|
|||
PTVSD_DIR_PATH = os.path.dirname(os.path.abspath(get_abs_path_real_path_and_base_from_file(__file__)[0])) + os.path.sep
|
||||
NORM_PTVSD_DIR_PATH = os.path.normcase(PTVSD_DIR_PATH)
|
||||
|
||||
|
||||
def dont_trace_ptvsd_files(file_path):
|
||||
def dont_trace_ptvsd_files(py_db, file_path):
|
||||
"""
|
||||
Returns true if the file should not be traced.
|
||||
"""
|
||||
return file_path.startswith(PTVSD_DIR_PATH) or file_path.endswith('ptvsd_launcher.py')
|
||||
|
||||
|
||||
original_get_file_type = pydevd.PyDB.get_file_type
|
||||
|
||||
|
||||
def _get_file_type(py_db, abs_real_path_and_basename, _cache_file_type={}):
|
||||
abs_path = abs_real_path_and_basename[0]
|
||||
try:
|
||||
return _cache_file_type[abs_path]
|
||||
except KeyError:
|
||||
file_type = original_get_file_type(py_db, abs_real_path_and_basename)
|
||||
if file_type is not None:
|
||||
_cache_file_type[abs_path] = file_type
|
||||
elif dont_trace_ptvsd_files(abs_path):
|
||||
_cache_file_type[abs_path] = PYDEV_FILE
|
||||
else:
|
||||
_cache_file_type[abs_path] = None
|
||||
return _cache_file_type[abs_path]
|
||||
|
||||
|
||||
pydevd.PyDB.get_file_type = _get_file_type
|
||||
pydevd.PyDB.dont_trace_external_files = dont_trace_ptvsd_files
|
||||
|
||||
# NOTE: Previously this included sys.prefix, sys.base_prefix and sys.real_prefix
|
||||
# On some systems those resolve to '/usr'. That means any user code will
|
||||
|
|
@ -1338,6 +1318,14 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
msg = '1.1\t{}\tID'.format(self._client_os_type)
|
||||
return self.pydevd_request(cmd, msg)
|
||||
|
||||
def _get_new_setDebuggerProperty_request(self, **kwargs):
|
||||
return {
|
||||
"command": "setDebuggerProperty",
|
||||
"arguments": kwargs,
|
||||
"type": "request",
|
||||
# "seq": seq_id, # A new seq should be created for pydevd.
|
||||
}
|
||||
|
||||
@async_handler
|
||||
def _handle_launch_or_attach(self, request, args):
|
||||
self._path_mappings_received = True
|
||||
|
|
@ -1378,6 +1366,14 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
default_success_exitcodes += [3]
|
||||
self._success_exitcodes = args.get('successExitCodes', default_success_exitcodes)
|
||||
|
||||
# Don't trace files under ptvsd, and ptvsd_launcher.py files
|
||||
# TODO: un-comment this code after fixing https://github.com/Microsoft/ptvsd/issues/1355
|
||||
#dont_trace_request = self._get_new_setDebuggerProperty_request(
|
||||
# dontTraceStartPatterns=[PTVSD_DIR_PATH],
|
||||
# dontTraceEndPatterns=['ptvsd_launcher.py']
|
||||
#)
|
||||
#yield self.pydevd_request(-1, dont_trace_request, is_json=True)
|
||||
|
||||
def _handle_detach(self):
|
||||
ptvsd.log.info('Detaching ...')
|
||||
# TODO: Skip if already detached?
|
||||
|
|
@ -1723,12 +1719,14 @@ 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
|
||||
|
||||
# TODO: Replace the line below with _forward_request_to_pydevd
|
||||
# after fixing https://github.com/Microsoft/ptvsd/issues/1355
|
||||
self.send_response(request)
|
||||
|
||||
# PyDevd protocol event handlers
|
||||
|
|
|
|||
|
|
@ -361,12 +361,12 @@ def test_exception_stack(pyfile, run_as, start_method, max_frames):
|
|||
if max_frames == 'all':
|
||||
# trace back compresses repeated text
|
||||
min_expected_lines = 100
|
||||
max_expected_lines = 220
|
||||
max_expected_lines = 221
|
||||
args = {'maxExceptionStackFrames': 0}
|
||||
elif max_frames == 'default':
|
||||
# default is all frames
|
||||
min_expected_lines = 100
|
||||
max_expected_lines = 220
|
||||
max_expected_lines = 221
|
||||
args = {}
|
||||
else:
|
||||
min_expected_lines = 10
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import pytest
|
|||
import ptvsd
|
||||
|
||||
from ptvsd.wrapper import InternalsFilter
|
||||
from ptvsd.wrapper import dont_trace_ptvsd_files
|
||||
|
||||
INTERNAL_DIR = os.path.dirname(os.path.abspath(ptvsd.__file__))
|
||||
@pytest.mark.parametrize('path', [
|
||||
|
|
@ -28,18 +27,3 @@ def test_internal_paths(path):
|
|||
def test_user_file_paths(path):
|
||||
int_filter = InternalsFilter()
|
||||
assert not int_filter.is_internal_path(path)
|
||||
|
||||
@pytest.mark.parametrize('path, val', [
|
||||
(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),
|
||||
(os.path.join('ptvsd', 'w.py'), False),
|
||||
(os.path.join('usr', 'abcd', 'ptvsd', 'tangle.py'), False),
|
||||
])
|
||||
def test_ptvsd_paths(path, val):
|
||||
assert val == dont_trace_ptvsd_files(os.path.normcase(path))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue