Repository: microsoft/debugpy

Issue:
VS Code shows wrong order of dict
The issue has been closed, but the bug is still not resolved:
https://github.com/microsoft/vscode-python/issues/3236
https://github.com/microsoft/vscode-python/issues/7787

## Environment data

-   VS Code version: 1.54.3
-   Extension version (available under the Extensions sidebar): v2021.3.658691958
-   OS and version: Win 10 
-   Python version (& distribution if applicable, e.g. Anaconda): 3.6
-   Type of virtual environment used (N/A | venv | virtualenv | conda | ...): conda
-   Value of the `python.languageServer` setting: pylance v2021.3.2



## Expected behaviour

The debugger shows the dict element in the right order.

## Actual behaviour

The debugger shows the dict elements in a wrong order.

## Steps to reproduce:
Debug the code by inserting a breakpoint at the print statement:

```python
atoms = {"H": 0, "He": 1, "Li": 2, "Be": 3}
print(atoms)
```
The debugger will show an alphabetic order. The function print produces the right result though.

![Untitled-1](https://user-images.githubusercontent.com/6088393/111834794-0277d800-88ec-11eb-9567-2e48e0c10b31.png)



Discussion:
sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=coverage&view=list) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo.png' alt='No Duplication information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=duplicated_lines_density&view=list) No Duplication information


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=coverage&view=list) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo.png' alt='No Duplication information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=duplicated_lines_density&view=list) No Duplication information


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=570&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=570&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=coverage&view=list) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo.png' alt='No Duplication information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=microsoft_debugpy&pullRequest=570&metric=duplicated_lines_density&view=list) No Duplication information



Patch:
diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_safe_repr.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_safe_repr.py
index be1e61e9..56b384a6 100644
--- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_safe_repr.py
+++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_safe_repr.py
@@ -4,7 +4,7 @@
 
 # Gotten from ptvsd for supporting the format expected there.
 import sys
-from _pydevd_bundle.pydevd_constants import IS_PY2
+from _pydevd_bundle.pydevd_constants import IS_PY2, IS_PY36_OR_GREATER
 import locale
 from _pydev_bundle import pydev_log
 
@@ -248,10 +248,15 @@ class SafeRepr(object):
         count = self.maxcollection[level]
         yield_comma = False
 
-        try:
-            sorted_keys = sorted(obj)
-        except Exception:
+        if IS_PY36_OR_GREATER:
+            # On Python 3.6 (onwards) dictionaries now keep
+            # insertion order.
             sorted_keys = list(obj)
+        else:
+            try:
+                sorted_keys = sorted(obj)
+            except Exception:
+                sorted_keys = list(obj)
 
         for key in sorted_keys:
             if yield_comma:


Test patch:
diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_safe_repr.py b/src/debugpy/_vendored/pydevd/tests_python/test_safe_repr.py
index c03a07c1..95d4370e 100644
--- a/src/debugpy/_vendored/pydevd/tests_python/test_safe_repr.py
+++ b/src/debugpy/_vendored/pydevd/tests_python/test_safe_repr.py
@@ -5,7 +5,7 @@ import re
 import pytest
 from _pydevd_bundle.pydevd_safe_repr import SafeRepr
 import json
-from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY2
+from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY2, IS_PY36_OR_GREATER
 
 try:
     import numpy as np
@@ -400,7 +400,10 @@ class TestDicts(SafeReprTestBase):
         d1['c'] = None
         d1['b'] = None
         d1['a'] = None
-        self.assert_saferepr(d1, "{'a': None, 'b': None, 'c': None}")
+        if IS_PY36_OR_GREATER:
+            self.assert_saferepr(d1, "{'c': None, 'b': None, 'a': None}")
+        else:
+            self.assert_saferepr(d1, "{'a': None, 'b': None, 'c': None}")
 
     @pytest.mark.skipif(sys.version_info < (3, 0), reason='Py3 specific test')
     def test_unsortable_keys(self):