Repository: microsoft/ptvsd

Issue:
pydevd_resolver.py: "unsupported operand type(s) for +: 'dict' and 'list'" in TupleResolver.get_contents_debug_adapter_protocol throws 
## Environment data

- PTVSD version: python-2019.3.6139
- OS and version: Windows10
- Python version (& distribution if applicable, e.g. Anaconda): 3.7.2.64 standard python
- Using VS Code or Visual Studio: VSCode

## Actual behavior

When trying to inspect a collection during debug, the variable inspector hangs and throws a message

## Expected  behavior
Inspection working


## Steps to reproduce:
1. Start debugging a program that uses collections module.
2. Trying to inspect a collections variable throws "unsupported operand type(s) for +: 'dict' and 'list'":

```
Traceback (most recent call last):  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_frame.py", line 695, in trace_dispatch
    self.do_wait_suspend(thread, frame, event, arg)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_frame.py", line 78, in do_wait_suspend
    self._args[0].do_wait_suspend(*args, **kwargs)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1285, in do_wait_suspend
    keep_suspended = self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread, frames_tracker)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1307, in _do_wait_suspend
    self.process_internal_commands()
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1024, in process_internal_commands
    int_cmd.do_it(self)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 485, in do_it
    self.method(dbg, *self.args, **self.kwargs)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 655, in internal_get_variable_json
    for child_var in variable.get_children_variables(fmt=fmt):
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_suspended_frames.py", line 97, in get_children_variables
    lst = resolver.get_contents_debug_adapter_protocol(self.value, fmt=fmt)
  File "c:\Users\adolgano\.vscode\extensions\ms-python.python-2019.3.6139\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_resolver.py", line 374, in get_contents_debug_adapter_protocol
    ret = from_default_resolver + ret
TypeError: unsupported operand type(s) for +: 'dict' and 'list'
```

The code tries indeed to add a list to a dict with a '+'
```
if from_default_resolver:
    ret = from_default_resolver + ret
return ret
```


Discussion:

Resolving patch:
diff --git a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py
--- a/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py
+++ b/src/ptvsd/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py
@@ -369,7 +369,7 @@ def get_contents_debug_adapter_protocol(self, lst, fmt=None):
 
         ret.append(('__len__', len(lst), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
         # Needed in case the class extends the built-in type and has some additional fields.
-        from_default_resolver = defaultResolver.get_dictionary(lst)
+        from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(lst, fmt=fmt)
         if from_default_resolver:
             ret = from_default_resolver + ret
         return ret


Test patch:
diff --git a/src/ptvsd/_vendored/pydevd/tests_python/test_resolvers.py b/src/ptvsd/_vendored/pydevd/tests_python/test_resolvers.py
--- a/src/ptvsd/_vendored/pydevd/tests_python/test_resolvers.py
+++ b/src/ptvsd/_vendored/pydevd/tests_python/test_resolvers.py
@@ -21,6 +21,7 @@ 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
     dict_resolver = DictResolver()
@@ -140,7 +141,7 @@ def __init__(self):
 def test_tuple_resolver():
     from _pydevd_bundle.pydevd_resolver import TupleResolver
     tuple_resolver = TupleResolver()
-    fmt={'hex': True}
+    fmt = {'hex': True}
     lst = tuple(range(11))
     contents_debug_adapter_protocol = tuple_resolver.get_contents_debug_adapter_protocol(lst)
     len_entry = contents_debug_adapter_protocol.pop(-1)
@@ -278,4 +279,20 @@ def test_tuple_resolver():
         '0x8': 8,
         '0x9': 9,
         '__len__': 10
-    }
\ No newline at end of file
+    }
+
+
+def test_tuple_resolver_mixed():
+    from _pydevd_bundle.pydevd_resolver import TupleResolver
+    tuple_resolver = TupleResolver()
+
+    class CustomTuple(tuple):
+        pass
+
+    my_tuple = CustomTuple([1, 2])
+    my_tuple.some_value = 10
+    contents_debug_adapter_protocol = tuple_resolver.get_contents_debug_adapter_protocol(my_tuple)
+    len_entry = contents_debug_adapter_protocol.pop(-1)
+    check_len_entry(len_entry, ('__len__', 2))
+    assert contents_debug_adapter_protocol == [
+        ('some_value', 10, '.some_value'), ('0', 1, '[0]'), ('1', 2, '[1]'), ]