diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py index cf7bd6c80..c249a5f84 100644 --- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py +++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py @@ -918,7 +918,7 @@ def internal_evaluate_expression_json(py_db, request, thread_id): body = pydevd_schema.EvaluateResponseBody( result=var_data['value'], - variablesReference=var_data.get('variableReference', 0), + variablesReference=var_data.get('variablesReference', 0), type=var_data.get('type'), presentationHint=var_data.get('presentationHint'), namedVariables=var_data.get('namedVariables'), @@ -1004,7 +1004,7 @@ def internal_set_expression_json(py_db, request, thread_id): body = pydevd_schema.SetExpressionResponseBody( value=var_data['value'], - variablesReference=var_data.get('variableReference', 0), + variablesReference=var_data.get('variablesReference', 0), type=var_data.get('type'), presentationHint=var_data.get('presentationHint'), namedVariables=var_data.get('namedVariables'), @@ -1111,11 +1111,11 @@ def internal_get_exception_details_json(dbg, request, thread_id, set_additional_ if trace_obj is not None: for frame_id, frame, method_name, filename_in_utf8, lineno in iter_visible_frames_info( dbg, trace_obj.tb_frame, frame_id_to_lineno): - + line_text = linecache.getline(filename_in_utf8, lineno) # Never filter out plugin frames! - if not getattr(frame, 'IS_PLUGIN_FRAME', False): + if not getattr(frame, 'IS_PLUGIN_FRAME', False): if not dbg.in_project_scope(filename_in_utf8): if not dbg.get_use_libraries_filter(): continue @@ -1132,7 +1132,7 @@ def internal_get_exception_details_json(dbg, request, thread_id, set_additional_ stack_str = ''.join(traceback.format_list(frames)) - # This is an extra bit of data used by Visual Studio + # This is an extra bit of data used by Visual Studio source_path = frames[0][0] if frames else '' # TODO: breakMode is set to always. This should be retrieved from exception diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py index fce451649..4c5973291 100644 --- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py +++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py @@ -80,6 +80,7 @@ def _convert_rules_to_exclude_filters(rules, filename_to_server, on_error): class IDMap(object): + def __init__(self): self._value_to_key = {} self._key_to_value = {} @@ -541,7 +542,7 @@ def on_gototargets_request(self, py_db, request): target_id = self._goto_targets_map.obtain_key((path, line)) target = { 'id': target_id, - 'label': '{}:{}'.format(path, line), + 'label': '%s:%s' % (path, line), 'line': line } body = GotoTargetsResponseBody(targets=[target]) @@ -567,4 +568,5 @@ def on_goto_request(self, py_db, request): 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 diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py index 81af7f7f9..5713144e2 100644 --- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py +++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py @@ -32,77 +32,75 @@ def __init__(self, result): def _create_default_type_map(): - if not _IS_JYTHON: - default_type_map = [ - # None means that it should not be treated as a compound variable - - # isintance does not accept a tuple on some versions of python, so, we must declare it expanded - (type(None), None,), - (int, None), - (float, None), - (complex, None), - (str, None), - (tuple, pydevd_resolver.tupleResolver), - (list, pydevd_resolver.tupleResolver), - (dict, pydevd_resolver.dictResolver), - ] - try: - default_type_map.append((long, None)) # @UndefinedVariable - except: - pass # not available on all python versions + default_type_map = [ + # None means that it should not be treated as a compound variable + + # isintance does not accept a tuple on some versions of python, so, we must declare it expanded + (type(None), None,), + (int, None), + (float, None), + (complex, None), + (str, None), + (tuple, pydevd_resolver.tupleResolver), + (list, pydevd_resolver.tupleResolver), + (dict, pydevd_resolver.dictResolver), + ] + try: + default_type_map.append((long, None)) # @UndefinedVariable + except: + pass # not available on all python versions - try: - default_type_map.append((unicode, None)) # @UndefinedVariable - except: - pass # not available on all python versions + try: + default_type_map.append((unicode, None)) # @UndefinedVariable + except: + pass # not available on all python versions - try: - default_type_map.append((set, pydevd_resolver.setResolver)) - except: - pass # not available on all python versions + try: + default_type_map.append((set, pydevd_resolver.setResolver)) + except: + pass # not available on all python versions - try: - default_type_map.append((frozenset, pydevd_resolver.setResolver)) - except: - pass # not available on all python versions + try: + default_type_map.append((frozenset, pydevd_resolver.setResolver)) + except: + pass # not available on all python versions - try: - from django.utils.datastructures import MultiValueDict - default_type_map.insert(0, (MultiValueDict, pydevd_resolver.multiValueDictResolver)) - # we should put it before dict - except: - pass # django may not be installed + try: + from django.utils.datastructures import MultiValueDict + default_type_map.insert(0, (MultiValueDict, pydevd_resolver.multiValueDictResolver)) + # we should put it before dict + except: + pass # django may not be installed - try: - from django.forms import BaseForm - default_type_map.insert(0, (BaseForm, pydevd_resolver.djangoFormResolver)) - # we should put it before instance resolver - except: - pass # django may not be installed + try: + from django.forms import BaseForm + default_type_map.insert(0, (BaseForm, pydevd_resolver.djangoFormResolver)) + # we should put it before instance resolver + except: + pass # django may not be installed - try: - from collections import deque - default_type_map.append((deque, pydevd_resolver.dequeResolver)) - except: - pass + try: + from collections import deque + default_type_map.append((deque, pydevd_resolver.dequeResolver)) + except: + pass - if frame_type is not None: - default_type_map.append((frame_type, pydevd_resolver.frameResolver)) + if frame_type is not None: + default_type_map.append((frame_type, pydevd_resolver.frameResolver)) - else: + if _IS_JYTHON: from org.python import core # @UnresolvedImport - default_type_map = [ - (core.PyNone, None), - (core.PyInteger, None), - (core.PyLong, None), - (core.PyFloat, None), - (core.PyComplex, None), - (core.PyString, None), - (core.PyTuple, pydevd_resolver.tupleResolver), - (core.PyList, pydevd_resolver.tupleResolver), - (core.PyDictionary, pydevd_resolver.dictResolver), - (core.PyStringMap, pydevd_resolver.dictResolver), - ] + default_type_map.append((core.PyNone, None)) + default_type_map.append((core.PyInteger, None)) + default_type_map.append((core.PyLong, None)) + default_type_map.append((core.PyFloat, None)) + default_type_map.append((core.PyComplex, None)) + default_type_map.append((core.PyString, None)) + default_type_map.append((core.PyTuple, pydevd_resolver.tupleResolver)) + default_type_map.append((core.PyList, pydevd_resolver.tupleResolver)) + default_type_map.append((core.PyDictionary, pydevd_resolver.dictResolver)) + default_type_map.append((core.PyStringMap, pydevd_resolver.dictResolver)) + if hasattr(core, 'PyJavaInstance'): # Jython 2.5b3 removed it. default_type_map.append((core.PyJavaInstance, pydevd_resolver.instanceResolver)) @@ -181,7 +179,7 @@ def _get_type(self, o, type_object, type_name): if type_name == 'org.python.core.PyArray': return type_object, type_name, pydevd_resolver.jyArrayResolver - return self._base_get_type(o, type_name, type_name) + return self._base_get_type(o, type_object, type_name) def str_from_providers(self, o, type_object, type_name): provider = self._type_to_str_provider_cache.get(type_object) diff --git a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py index 687cfeadb..669f43977 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger_json.py @@ -575,15 +575,34 @@ def test_evaluate_unicode(case_setup): evaluate_response = json_facade.wait_for_response( json_facade.write_request(EvaluateRequest(EvaluateArguments(u'\u16A0', json_hit.frameId)))) + evaluate_response_body = evaluate_response.body.to_dict() + if IS_PY2: - assert evaluate_response.body.to_dict() == { + # The error can be referenced. + variables_reference = json_facade.pop_variables_reference([evaluate_response_body]) + + assert evaluate_response_body == { 'result': u"SyntaxError('invalid syntax', ('', 1, 1, '\\xe1\\x9a\\xa0'))", 'type': u'SyntaxError', - 'variablesReference': 0, 'presentationHint': {}, } + + assert len(variables_reference) == 1 + reference = variables_reference[0] + assert reference > 0 + variables_response = json_facade.get_variables_response(reference) + child_variables = variables_response.to_dict()['body']['variables'] + assert len(child_variables) == 1 + assert json_facade.pop_variables_reference(child_variables)[0] > 0 + assert child_variables == [{ + u'type': u'SyntaxError', + u'evaluateName': u'\u16a0.result', + u'name': u'result', + u'value': u"SyntaxError('invalid syntax', ('', 1, 1, '\\xe1\\x9a\\xa0'))" + }] + else: - assert evaluate_response.body.to_dict() == { + assert evaluate_response_body == { 'result': "'\u16a1'", 'type': 'str', 'variablesReference': 0, @@ -594,6 +613,58 @@ def test_evaluate_unicode(case_setup): writer.finished_ok = True +def test_evaluate_variable_references(case_setup): + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateRequest + from _pydevd_bundle._debug_adapter.pydevd_schema import EvaluateArguments + with case_setup.test_file('_debugger_case_local_variables2.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')) + json_facade.write_make_initial_run() + + hit = writer.wait_for_breakpoint_hit() + json_hit = json_facade.get_stack_as_json_hit(hit.thread_id) + + evaluate_response = json_facade.wait_for_response( + json_facade.write_request(EvaluateRequest(EvaluateArguments('variable_for_test_2', json_hit.frameId)))) + + evaluate_response_body = evaluate_response.body.to_dict() + + variables_reference = json_facade.pop_variables_reference([evaluate_response_body]) + + assert evaluate_response_body == { + 'type': 'set', + 'result': "set(['a'])" if IS_PY2 else "{'a'}", + 'presentationHint': {}, + } + assert len(variables_reference) == 1 + reference = variables_reference[0] + assert reference > 0 + variables_response = json_facade.get_variables_response(reference) + child_variables = variables_response.to_dict()['body']['variables'] + + # The name for a reference in a set is the id() of the variable and can change at each run. + del child_variables[0]['name'] + + assert child_variables == [ + { + 'type': 'str', + 'value': "'a'", + 'presentationHint': {'attributes': ['rawString']}, + }, + { + 'name': '__len__', + 'type': 'int', + 'value': '1' + } + ] + + writer.write_run_thread(hit.thread_id) + writer.finished_ok = True + + def test_set_expression(case_setup): from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionRequest from _pydevd_bundle._debug_adapter.pydevd_schema import SetExpressionArguments @@ -1022,6 +1093,7 @@ def test_exception_details(case_setup): writer.finished_ok = True +@pytest.mark.skipif(IS_JYTHON, reason='No goto on Jython.') def test_goto(case_setup): with case_setup.test_file('_debugger_case_set_next_statement.py') as writer: json_facade = JsonFacade(writer)