diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py index 20a7351a..82a3cdab 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py @@ -238,9 +238,9 @@ def _does_obj_repr_evaluate_to_obj(obj): # ======================================================================================================================= -# DictResolver +# MappingResolver # ======================================================================================================================= -class DictResolver: +class MappingResolver: sort_keys = not IS_PY36_OR_GREATER def resolve(self, dct, key): @@ -452,7 +452,7 @@ def resolve(self, var, attribute): return var.resolve(attribute) -class TupleResolver: # to enumerate tuples and lists +class SequenceResolver: def resolve(self, var, attribute): """ :param var: that's the original object we're dealing with. @@ -657,7 +657,7 @@ def get_dictionary(self, obj): # ======================================================================================================================= # MultiValueDictResolver # ======================================================================================================================= -class MultiValueDictResolver(DictResolver): +class MultiValueDictResolver(MappingResolver): def resolve(self, dct, key): if key in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR): return None @@ -699,9 +699,9 @@ def get_dictionary(self, var, names=None): # ======================================================================================================================= # DequeResolver # ======================================================================================================================= -class DequeResolver(TupleResolver): +class DequeResolver(SequenceResolver): def get_dictionary(self, var): - d = TupleResolver.get_dictionary(self, var) + d = SequenceResolver.get_dictionary(self, var) d["maxlen"] = getattr(var, "maxlen", None) return d @@ -709,7 +709,7 @@ def get_dictionary(self, var): # ======================================================================================================================= # OrderedDictResolver # ======================================================================================================================= -class OrderedDictResolver(DictResolver): +class OrderedDictResolver(MappingResolver): sort_keys = False def init_dict(self): @@ -765,8 +765,8 @@ def get_frame_name(self, frame): defaultResolver = DefaultResolver() -dictResolver = DictResolver() -tupleResolver = TupleResolver() +mappingResolver = MappingResolver() +sequenceResolver = SequenceResolver() instanceResolver = InstanceResolver() jyArrayResolver = JyArrayResolver() setResolver = SetResolver() diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py index af8ad0fa..549707d5 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_xml.py @@ -1,7 +1,13 @@ +import sys + +from collections import deque, OrderedDict +from collections.abc import Mapping, Sequence, Set as AbstractSet +from types import FrameType +from typing import Optional + from _pydev_bundle import pydev_log from _pydevd_bundle import pydevd_extension_utils from _pydevd_bundle import pydevd_resolver -import sys from _pydevd_bundle.pydevd_constants import ( BUILTINS_MODULE_NAME, MAXIMUM_VARIABLE_REPRESENTATION_SIZE, @@ -13,14 +19,6 @@ from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, StrPresentationProvider from _pydevd_bundle.pydevd_utils import isinstance_checked, hasattr_checked, DAPGrouper from _pydevd_bundle.pydevd_resolver import get_var_scope, MoreItems, MoreItemsRange -from typing import Optional - -try: - import types - - frame_type = types.FrameType -except: - frame_type = None def make_valid_xml_value(s): @@ -40,97 +38,47 @@ def __init__(self, result, etype, tb): def _create_default_type_map(): 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), + # non-compound types + ((type(None), int, float, complex, str), None), + # collections + (Sequence, pydevd_resolver.sequenceResolver), + (deque, pydevd_resolver.dequeResolver), + (OrderedDict, pydevd_resolver.orderedDictResolver), + (Mapping, pydevd_resolver.mappingResolver), + (AbstractSet, pydevd_resolver.setResolver), + # other builtin types + (FrameType, pydevd_resolver.frameResolver), + # pydevd types + (DAPGrouper, pydevd_resolver.dapGrouperResolver), + ((MoreItems, MoreItemsRange), pydevd_resolver.forwardInternalResolverToObject), ] - try: - from collections import OrderedDict - - default_type_map.insert(0, (OrderedDict, pydevd_resolver.orderedDictResolver)) - # we should put it before dict - except: - pass - - try: - default_type_map.append((long, None)) # @UndefinedVariable - except: - pass # not available on all python versions - - default_type_map.append((DAPGrouper, pydevd_resolver.dapGrouperResolver)) - default_type_map.append((MoreItems, pydevd_resolver.forwardInternalResolverToObject)) - default_type_map.append((MoreItemsRange, pydevd_resolver.forwardInternalResolverToObject)) - - 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: from django.utils.datastructures import MultiValueDict - + from django.forms import BaseForm + except ImportError: + pass # django may not be installed + else: 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 collections import deque - - default_type_map.append((deque, pydevd_resolver.dequeResolver)) - except: - pass try: from ctypes import Array - - default_type_map.append((Array, pydevd_resolver.tupleResolver)) - except: - pass - - if frame_type is not None: - default_type_map.append((frame_type, pydevd_resolver.frameResolver)) + except ImportError: + pass # TODO: comment on reason why this might this not be available + else: + default_type_map.append((Array, pydevd_resolver.sequenceResolver)) if _IS_JYTHON: from org.python import core # @UnresolvedImport - 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)) + default_type_map += [ + ((core.PyNone, core.PyInteger, core.PyLong, core.PyFloat, core.PyComplex, core.PyString), None), + ((core.PyTuple, core.PyList), pydevd_resolver.sequenceResolver), + ((core.PyDictionary, core.PyStringMap), pydevd_resolver.mappingResolver), + ] return default_type_map diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_resolvers.py b/src/debugpy/_vendored/pydevd/tests_python/test_resolvers.py index 1266caf4..86186653 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/test_resolvers.py +++ b/src/debugpy/_vendored/pydevd/tests_python/test_resolvers.py @@ -1,7 +1,16 @@ +from __future__ import annotations + +import sys +from types import MappingProxyType +from typing import TYPE_CHECKING +from collections import UserDict, UserList + +import pytest from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER, GENERATED_LEN_ATTR_NAME from _pydevd_bundle import pydevd_constants, pydevd_frame_utils -import pytest -import sys + +if TYPE_CHECKING: + from collections.abc import Mapping, Sequence def check_len_entry(len_entry, first_2_params): @@ -10,12 +19,13 @@ def check_len_entry(len_entry, first_2_params): assert len_entry[2]("check") == "len(check)" -def test_dict_resolver(): - from _pydevd_bundle.pydevd_resolver import DictResolver +@pytest.mark.parametrize("map_cls", [dict, MappingProxyType, UserDict]) +def test_mapping_resolver(map_cls: type[Mapping]): + from _pydevd_bundle.pydevd_resolver import MappingResolver - dict_resolver = DictResolver() - dct = {(1, 2): 2, "22": 22} - contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(dict_resolver.get_contents_debug_adapter_protocol(dct)) + mapping_resolver = MappingResolver() + dct = map_cls({(1, 2): 2, "22": 22}) + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(mapping_resolver.get_contents_debug_adapter_protocol(dct)) len_entry = contents_debug_adapter_protocol.pop(-1) check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 2)) if IS_PY36_OR_GREATER: @@ -25,13 +35,13 @@ def test_dict_resolver(): assert contents_debug_adapter_protocol == [("'22'", 22, "['22']"), ("(1, 2)", 2, "[(1, 2)]")] -def test_dict_resolver_hex(): - from _pydevd_bundle.pydevd_resolver import DictResolver +def test_mapping_resolver_hex(): + from _pydevd_bundle.pydevd_resolver import MappingResolver - dict_resolver = DictResolver() + mapping_resolver = MappingResolver() dct = {(1, 10, 100): (10000, 100000, 100000)} contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol( - dict_resolver.get_contents_debug_adapter_protocol(dct, fmt={"hex": True}) + mapping_resolver.get_contents_debug_adapter_protocol(dct, fmt={"hex": True}) ) len_entry = contents_debug_adapter_protocol.pop(-1) check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 1)) @@ -164,13 +174,14 @@ def clear_contents_dictionary(dictionary): return dictionary -def test_tuple_resolver(): - from _pydevd_bundle.pydevd_resolver import TupleResolver +@pytest.mark.parametrize("seq_cls", [list, tuple, UserList]) +def test_sequence_resolver(seq_cls: type[Sequence]): + from _pydevd_bundle.pydevd_resolver import SequenceResolver - tuple_resolver = TupleResolver() + seq_resolver = SequenceResolver() fmt = {"hex": True} - lst = tuple(range(11)) - contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(tuple_resolver.get_contents_debug_adapter_protocol(lst)) + lst = seq_cls(range(11)) + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(seq_resolver.get_contents_debug_adapter_protocol(lst)) len_entry = contents_debug_adapter_protocol.pop(-1) assert contents_debug_adapter_protocol == [ ("00", 0, "[0]"), @@ -187,7 +198,7 @@ def test_tuple_resolver(): ] check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 11)) - assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst)) == { + assert clear_contents_dictionary(seq_resolver.get_dictionary(lst)) == { "00": 0, "01": 1, "02": 2, @@ -202,9 +213,9 @@ def test_tuple_resolver(): GENERATED_LEN_ATTR_NAME: 11, } - lst = tuple(range(17)) + lst = seq_cls(range(17)) contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol( - tuple_resolver.get_contents_debug_adapter_protocol(lst, fmt=fmt) + seq_resolver.get_contents_debug_adapter_protocol(lst, fmt=fmt) ) len_entry = contents_debug_adapter_protocol.pop(-1) assert contents_debug_adapter_protocol == [ @@ -228,7 +239,7 @@ def test_tuple_resolver(): ] check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 17)) - assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst, fmt=fmt)) == { + assert clear_contents_dictionary(seq_resolver.get_dictionary(lst, fmt=fmt)) == { "0x00": 0, "0x01": 1, "0x02": 2, @@ -249,8 +260,8 @@ def test_tuple_resolver(): GENERATED_LEN_ATTR_NAME: 17, } - lst = tuple(range(10)) - contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(tuple_resolver.get_contents_debug_adapter_protocol(lst)) + lst = seq_cls(range(10)) + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(seq_resolver.get_contents_debug_adapter_protocol(lst)) len_entry = contents_debug_adapter_protocol.pop(-1) assert contents_debug_adapter_protocol == [ ("0", 0, "[0]"), @@ -266,7 +277,7 @@ def test_tuple_resolver(): ] check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 10)) - assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst)) == { + assert clear_contents_dictionary(seq_resolver.get_dictionary(lst)) == { "0": 0, "1": 1, "2": 2, @@ -281,7 +292,7 @@ def test_tuple_resolver(): } contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol( - tuple_resolver.get_contents_debug_adapter_protocol(lst, fmt=fmt) + seq_resolver.get_contents_debug_adapter_protocol(lst, fmt=fmt) ) len_entry = contents_debug_adapter_protocol.pop(-1) assert contents_debug_adapter_protocol == [ @@ -298,7 +309,7 @@ def test_tuple_resolver(): ] check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 10)) - assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst, fmt=fmt)) == { + assert clear_contents_dictionary(seq_resolver.get_dictionary(lst, fmt=fmt)) == { "0x0": 0, "0x1": 1, "0x2": 2, @@ -313,17 +324,17 @@ def test_tuple_resolver(): } -def test_tuple_resolver_mixed(): - from _pydevd_bundle.pydevd_resolver import TupleResolver +def test_sequence_resolver_mixed(): + from _pydevd_bundle.pydevd_resolver import SequenceResolver - tuple_resolver = TupleResolver() + seq_resolver = SequenceResolver() class CustomTuple(tuple): pass my_tuple = CustomTuple([1, 2]) my_tuple.some_value = 10 - contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(tuple_resolver.get_contents_debug_adapter_protocol(my_tuple)) + contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(seq_resolver.get_contents_debug_adapter_protocol(my_tuple)) len_entry = contents_debug_adapter_protocol.pop(-1) check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 2)) assert contents_debug_adapter_protocol == [ @@ -333,7 +344,7 @@ class CustomTuple(tuple): ] -def test_tuple_resolver_ctypes(): +def test_sequence_resolver_ctypes(): import ctypes from _pydevd_bundle.pydevd_xml import get_type