Repository: microsoft/debugpy

Issue:
Module with __file__=None is not supported
<!-- Please search existing issues to avoid creating duplicates. -->

## Environment data


-   VS Code version: 1.51.1
-   Extension version (available under the Extensions sidebar): XXX
-   OS and version: Darwin x64 19.6.0
-   Python version (& distribution if applicable, e.g. Anaconda): python 3.7.3
-   Type of virtual environment used (N/A | venv | virtualenv | conda | ...): 8.3.110.13-electron.0
-   Relevant/affected Python packages and their versions: XXX
-   Relevant/affected Python-related VS Code extensions and their versions: XXX
-   Value of the `python.languageServer` setting:  `"python.languageServer": "Pylance",`

[**NOTE**: If you suspect that your issue is related to the Microsoft Python Language Server (`python.languageServer: 'Microsoft'`), please download our new language server [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) from the VS Code marketplace to see if that fixes your issue]

## Expected behaviour

XXX

## Actual behaviour

can't launch debug...
report 
```
 /usr/bin/env /usr/bin/python3 /Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/launcher 60731 -- odoo-bin -c odoo.conf 
~/git-repo/odoo(master ✗)  /usr/bin/env /usr/bin/python3 /Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/launcher 60731 -- odoo-bin -c odoo.conf 
Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/__main__.py", line 43, in <module>
    from debugpy.server import cli
  File "/Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/../debugpy/server/__init__.py", line 9, in <module>
    import debugpy._vendored.force_pydevd  # noqa
  File "/Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/../debugpy/_vendored/force_pydevd.py", line 15, in <module>
    prefix_matcher('pydev', '_pydev'))
  File "/Users/jeffery/.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/../debugpy/_vendored/__init__.py", line 106, in check_modules
    elif not mod.__file__.startswith(root):
AttributeError: 'NoneType' object has no attribute 'startswith'
```


## Steps to reproduce:

[**NOTE**: Self-contained, minimal reproducing code samples are **extremely** helpful and will expedite addressing your issue]

1.  clone Odoo code.
2.  open it in vscode, and create launch.json for it 
3.  launch debug. not success



<!--
Note: If you think a GIF of what is happening would be helpful, consider tools like https://www.cockos.com/licecap/, https://github.com/phw/peek or https://www.screentogif.com/ .
-->

## Logs

<details>

<summary>Output for <code>Python</code> in the <code>Output</code> panel (<code>View</code>→<code>Output</code>, change the drop-down the upper-right of the <code>Output</code> panel to <code>Python</code>)
</summary>

<p>

```
XXX
```

</p>
</details>


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=486&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=486&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&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=486&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=486&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&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=486&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=486&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=microsoft_debugpy&pullRequest=486&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=486&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=486&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=microsoft_debugpy&pullRequest=486&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=486&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=486&metric=duplicated_lines_density&view=list) No Duplication information



Patch:
diff --git a/cgmanifest.json b/cgmanifest.json
index 55a2f788..3d0c13a7 100644
--- a/cgmanifest.json
+++ b/cgmanifest.json
@@ -24,7 +24,7 @@
     {
       "Component": {
         "Type": "pip",
-        "pip": { "Name": "pydevd", "Version": "2.0.0" }
+        "pip": { "Name": "pydevd", "Version": "2.1.0" }
       },
       "DevelopmentDependency": false
     },
diff --git a/src/debugpy/_vendored/__init__.py b/src/debugpy/_vendored/__init__.py
index 0d6376ae..abde2e33 100644
--- a/src/debugpy/_vendored/__init__.py
+++ b/src/debugpy/_vendored/__init__.py
@@ -15,16 +15,14 @@ from . import _util
 VENDORED_ROOT = os.path.dirname(os.path.abspath(__file__))
 # TODO: Move the "pydevd" git submodule to the debugpy/_vendored directory
 # and then drop the following fallback.
-if 'pydevd' not in os.listdir(VENDORED_ROOT):
+if "pydevd" not in os.listdir(VENDORED_ROOT):
     VENDORED_ROOT = os.path.dirname(VENDORED_ROOT)
 
 
 def list_all(resolve=False):
     """Return the list of vendored projects."""
     # TODO: Derive from os.listdir(VENDORED_ROOT)?
-    projects = [
-        'pydevd',
-    ]
+    projects = ["pydevd"]
     if not resolve:
         return projects
     return [project_root(name) for name in projects]
@@ -37,7 +35,7 @@ def project_root(project):
     projects (e.g. "debugpy/_vendored/") will be returned.
     """
     if not project:
-        project = ''
+        project = ""
     return os.path.join(VENDORED_ROOT, project)
 
 
@@ -63,17 +61,14 @@ def iter_packaging_files(project):
     prune_dir = None
     exclude_file = None
     try:
-        mod = import_module('._{}_packaging'.format(project), __name__)
+        mod = import_module("._{}_packaging".format(project), __name__)
     except ImportError:
         pass
     else:
-        prune_dir = getattr(mod, 'prune_dir', prune_dir)
-        exclude_file = getattr(mod, 'exclude_file', exclude_file)
+        prune_dir = getattr(mod, "prune_dir", prune_dir)
+        exclude_file = getattr(mod, "exclude_file", exclude_file)
     results = iter_project_files(
-        project,
-        relative=True,
-        prune_dir=prune_dir,
-        exclude_file=exclude_file,
+        project, relative=True, prune_dir=prune_dir, exclude_file=exclude_file
     )
     for _, _, filename in results:
         yield filename
@@ -89,6 +84,7 @@ def prefix_matcher(*prefixes):
                 return True
         else:
             return False
+
     return match
 
 
@@ -101,10 +97,14 @@ def check_modules(project, match, root=None):
     for modname, mod in list(sys.modules.items()):
         if not match(modname, mod):
             continue
-        if not hasattr(mod, '__file__'):  # extension module
+        try:
+            filename = getattr(mod, "__file__", None)
+        except:  # In theory it's possible that any error is raised when accessing __file__
+            filename = None
+        if not filename:  # extension module
             extensions.append(modname)
-        elif not mod.__file__.startswith(root):
-            unvendored[modname] = mod.__file__
+        elif not filename.startswith(root):
+            unvendored[modname] = filename
     return unvendored, extensions
 
 
diff --git a/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_imports_tipper.py b/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_imports_tipper.py
index 510fc820..7ba858d9 100644
--- a/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_imports_tipper.py
+++ b/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_imports_tipper.py
@@ -86,12 +86,14 @@ def get_file(mod):
     try:
         f = inspect.getsourcefile(mod) or inspect.getfile(mod)
     except:
-        if hasattr_checked(mod, '__file__'):
-            f = mod.__file__
-            if f.lower(f[-4:]) in ['.pyc', '.pyo']:
-                filename = f[:-4] + '.py'
-                if os.path.exists(filename):
-                    f = filename
+        try:
+            f = getattr(mod, '__file__', None)
+        except:
+            f = None
+        if f and f.lower(f[-4:]) in ['.pyc', '.pyo']:
+            filename = f[:-4] + '.py'
+            if os.path.exists(filename):
+                f = filename
 
     return f
 
diff --git a/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_jy_imports_tipper.py b/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_jy_imports_tipper.py
index 28d5f6b1..558d5632 100644
--- a/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_jy_imports_tipper.py
+++ b/src/debugpy/_vendored/pydevd/_pydev_bundle/_pydev_jy_imports_tipper.py
@@ -56,8 +56,10 @@ def Find(name):
     parent = mod
     foundAs = ''
 
-    if hasattr(mod, '__file__'):
-        f = mod.__file__
+    try:
+        f = getattr(mod, '__file__', None)
+    except:
+        f = None
 
 
     components = name.split('.')
diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_json.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_json.py
index 2ee825e1..a9e8fe29 100644
--- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_json.py
+++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_json.py
@@ -405,7 +405,7 @@ class NetCommandFactoryJson(NetCommandFactory):
 
     @overrides(NetCommandFactory.make_evaluation_timeout_msg)
     def make_evaluation_timeout_msg(self, py_db, expression, curr_thread):
-        msg = '''Evaluating: %s did not finish after %.2fs seconds.
+        msg = '''Evaluating: %s did not finish after %.2f seconds.
 This may mean a number of things:
 - This evaluation is really slow and this is expected.
     In this case it's possible to silence this error by raising the timeout, setting the
diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_xml.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_xml.py
index a8b65d9d..3feec307 100644
--- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_xml.py
+++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_xml.py
@@ -460,7 +460,7 @@ class NetCommandFactory(object):
         return NULL_NET_COMMAND  # Not a part of the xml protocol
 
     def make_evaluation_timeout_msg(self, py_db, expression, thread):
-        msg = '''pydevd: Evaluating: %s did not finish after %.2fs seconds.
+        msg = '''pydevd: Evaluating: %s did not finish after %.2f seconds.
 This may mean a number of things:
 - This evaluation is really slow and this is expected.
     In this case it's possible to silence this error by raising the timeout, setting the
diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/release_mem.h b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/release_mem.h
index 256e6443..cc6e3d92 100644
--- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/release_mem.h
+++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/release_mem.h
@@ -1,5 +1,5 @@
 #include "Python.h"
 
 void release_co_extra(void *obj) {
-    Py_DECREF(obj);
-}
\ No newline at end of file
+    Py_XDECREF(obj);
+}
diff --git a/src/debugpy/_vendored/pydevd/build_tools/pydevd_release_process.txt b/src/debugpy/_vendored/pydevd/build_tools/pydevd_release_process.txt
index 828817ec..8e57f7c0 100644
--- a/src/debugpy/_vendored/pydevd/build_tools/pydevd_release_process.txt
+++ b/src/debugpy/_vendored/pydevd/build_tools/pydevd_release_process.txt
@@ -211,6 +211,6 @@ dir dist
 # Note: uploading with twine gives an error in the end, but apparently it works (check final result in pypi).
 twine upload dist/pydevd*
 
-git tag pydev_debugger_2_0_0 -a -m "PyDev.Debugger 2.0.0"
+git tag pydev_debugger_2_1_0 -a -m "PyDev.Debugger 2.1.0"
 git push --tags
 
diff --git a/src/debugpy/_vendored/pydevd/pydevd.py b/src/debugpy/_vendored/pydevd/pydevd.py
index 48c487fb..0625dcdc 100644
--- a/src/debugpy/_vendored/pydevd/pydevd.py
+++ b/src/debugpy/_vendored/pydevd/pydevd.py
@@ -84,7 +84,7 @@ from _pydevd_bundle.pydevd_thread_lifecycle import suspend_all_threads, mark_thr
 if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
     from _pydevd_bundle.pydevd_constants import constructed_tid_to_last_frame
 
-__version_info__ = (2, 0, 0)
+__version_info__ = (2, 1, 0)
 __version_info_str__ = []
 for v in __version_info__:
     __version_info_str__.append(str(v))
diff --git a/src/debugpy/_vendored/pydevd/stubs/_get_tips.py b/src/debugpy/_vendored/pydevd/stubs/_get_tips.py
index b98e1c53..79dffaaa 100644
--- a/src/debugpy/_vendored/pydevd/stubs/_get_tips.py
+++ b/src/debugpy/_vendored/pydevd/stubs/_get_tips.py
@@ -62,9 +62,12 @@ def GetFile(mod):
     try:
         f = inspect.getsourcefile(mod) or inspect.getfile(mod)
     except:
-        if hasattr(mod, '__file__'):
-            f = mod.__file__
-            if f.lower(f[-4:]) in ['.pyc', '.pyo']:
+        try:
+            f = getattr(mod, '__file__', None)
+        except:
+            pass
+        else:
+            if f and f.lower(f[-4:]) in ['.pyc', '.pyo']:
                 filename = f[:-4] + '.py'
                 if os.path.exists(filename):
                     f = filename


Test patch:
diff --git a/src/debugpy/_vendored/pydevd/conftest.py b/src/debugpy/_vendored/pydevd/conftest.py
index f41ca5f6..b4edce10 100644
--- a/src/debugpy/_vendored/pydevd/conftest.py
+++ b/src/debugpy/_vendored/pydevd/conftest.py
@@ -106,34 +106,6 @@ def check_no_threads():
     _start_monitoring_threads()
 
 
-from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread
-import threading
-
-
-@pytest.yield_fixture(autouse=True)
-def check_main_thread(request):
-    was_main = is_current_thread_main_thread()
-
-    yield
-
-    is_main = is_current_thread_main_thread()
-    if not is_main:
-        error_msg = 'Current thread does not seem to be a main thread. Details:\n'
-        current_thread = threading.current_thread()
-        error_msg += 'Current thread: %s\n' % (current_thread,)
-
-        if hasattr(threading, 'main_thread'):
-            error_msg += 'Main thread found: %s\n' % (threading.main_thread(),)
-        else:
-            error_msg += 'Current main thread not instance of: %s (%s)\n' % (
-                threading._MainThread, current_thread.__class__.__mro__,)
-
-        error_msg += 'Was main: %s\n' % (was_main,)
-        error_msg += 'Function: %s\n' % (request.node.nodeid,)
-
-        raise AssertionError(error_msg)
-
-
 # see: http://goo.gl/kTQMs
 SYMBOLS = {
     'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'),
diff --git a/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py b/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py
index 3914b232..a533c594 100644
--- a/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py
+++ b/src/debugpy/_vendored/pydevd/tests_python/debugger_unittest.py
@@ -558,7 +558,7 @@ class DebuggerRunner(object):
                             continue
 
                         if not shown_intermediate and (time.time() - initial_time > (TIMEOUT / 3.)):  # 1/3 of timeout
-                            print('Warning: writer thread exited and process still did not (%.2fs seconds elapsed).' % (time.time() - initial_time,))
+                            print('Warning: writer thread exited and process still did not (%.2f seconds elapsed).' % (time.time() - initial_time,))
                             shown_intermediate = True
 
                         if time.time() - initial_time > ((TIMEOUT / 3.) * 2.):  # 2/3 of timeout
@@ -575,7 +575,7 @@ class DebuggerRunner(object):
                             process.kill()
                             time.sleep(.2)
                             self.fail_with_message(
-                                "The other process should've exited but still didn't (%.2fs seconds timeout for process to exit)." % (time.time() - initial_time,),
+                                "The other process should've exited but still didn't (%.2f seconds timeout for process to exit)." % (time.time() - initial_time,),
                                 stdout, stderr, writer
                             )
                 time.sleep(.2)
diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_debugger.py b/src/debugpy/_vendored/pydevd/tests_python/test_debugger.py
index c10424d4..4212bb35 100644
--- a/src/debugpy/_vendored/pydevd/tests_python/test_debugger.py
+++ b/src/debugpy/_vendored/pydevd/tests_python/test_debugger.py
@@ -2752,7 +2752,7 @@ def test_attach_to_pid_no_threads(case_setup_remote, reattach):
         writer.finished_ok = True
 
 
-@pytest.mark.skipif(not IS_CPYTHON, reason='CPython only test.')
+@pytest.mark.skipif(not IS_CPYTHON or IS_MAC, reason='CPython only test (brittle on Mac).')
 def test_attach_to_pid_halted(case_setup_remote):
     with case_setup_remote.test_file('_debugger_case_attach_to_pid_multiple_threads.py', wait_for_port=False) as writer:
         time.sleep(1)  # Give it some time to initialize and get to the proper halting condition
diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py b/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py
index 70ad9496..4d9b24e1 100644
--- a/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py
+++ b/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py
@@ -17,7 +17,7 @@ from _pydevd_bundle._debug_adapter.pydevd_schema import (ThreadEvent, ModuleEven
 from _pydevd_bundle.pydevd_comm_constants import file_system_encoding
 from _pydevd_bundle.pydevd_constants import (int_types, IS_64BIT_PROCESS,
     PY_VERSION_STR, PY_IMPL_VERSION_STR, PY_IMPL_NAME, IS_PY36_OR_GREATER,
-    IS_PYPY, GENERATED_LEN_ATTR_NAME, IS_WINDOWS, IS_LINUX)
+    IS_PYPY, GENERATED_LEN_ATTR_NAME, IS_WINDOWS, IS_LINUX, IS_MAC)
 from tests_python import debugger_unittest
 from tests_python.debug_constants import TEST_CHERRYPY, IS_PY2, TEST_DJANGO, TEST_FLASK, IS_PY26, \
     IS_PY27, IS_CPYTHON, TEST_GEVENT, TEST_CYTHON
@@ -3958,7 +3958,7 @@ def _attach_to_writer_pid(writer):
 
 
 @pytest.mark.parametrize('reattach', [True, False])
-@pytest.mark.skipif(not IS_CPYTHON, reason='Attach to pid only available in CPython.')
+@pytest.mark.skipif(not IS_CPYTHON or IS_MAC, reason='Attach to pid only available in CPython (brittle on Mac).')
 def test_attach_to_pid(case_setup_remote, reattach):
     import threading
 
diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_utilities.py b/src/debugpy/_vendored/pydevd/tests_python/test_utilities.py
index c7af82fa..0e193089 100644
--- a/src/debugpy/_vendored/pydevd/tests_python/test_utilities.py
+++ b/src/debugpy/_vendored/pydevd/tests_python/test_utilities.py
@@ -26,7 +26,55 @@ def test_expression_to_evaluate():
         assert _expression_to_evaluate(u'  for a in expr:\n  pass') == u'for a in expr:\npass'
 
 
+@pytest.mark.skipif(IS_WINDOWS, reason='Brittle on Windows.')
 def test_is_main_thread():
+    '''
+    This is now skipped due to it failing sometimes (only on Windows).
+
+    I (fabioz) am not 100% sure on why this happens, but when this happens the initial thread for
+    the tests seems to be a non main thread.
+
+    i.e.: With an autouse fixture with a scope='session' with the code and error message below, it's
+    possible to see that at even at the `conftest` import (where indent_at_import is assigned) the
+    current thread is already not the main thread.
+
+    As far as I know this seems to be an issue in how pytest-xdist is running the tests (i.e.:
+    I couldn't reproduce this without running with `python -m pytest -n 0 ...`).
+
+    -------- Code to check error / error output ----------
+
+    from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread
+    import threading
+    indent_at_import = threading.get_ident()
+
+    @pytest.yield_fixture(autouse=True, scope='session')
+    def check_main_thread_session(request):
+        if not is_current_thread_main_thread():
+            error_msg = 'Current thread does not seem to be a main thread at the start of the session. Details:\n'
+            current_thread = threading.current_thread()
+            error_msg += 'Current thread: %s\n' % (current_thread,)
+            error_msg += 'Current thread ident: %s\n' % (current_thread.ident,)
+            error_msg += 'ident at import: %s\n' % (indent_at_import,)
+            error_msg += 'curr ident: %s\n' % (threading.get_ident(),)
+
+            if hasattr(threading, 'main_thread'):
+                error_msg += 'Main thread found: %s\n' % (threading.main_thread(),)
+                error_msg += 'Main thread id: %s\n' % (threading.main_thread().ident,)
+            else:
+                error_msg += 'Current main thread not instance of: %s (%s)\n' % (
+                    threading._MainThread, current_thread.__class__.__mro__,)
+
+>           raise AssertionError(error_msg)
+E           AssertionError: Current thread does not seem to be a main thread at the start of the session. Details:
+E           Current thread: <_DummyThread(Dummy-2, started daemon 7072)>
+E           Current thread ident: 7072
+E           ident at import: 7072
+E           curr ident: 7072
+E           Main thread found: <_MainThread(MainThread, started 5924)>
+E           Main thread id: 5924
+
+conftest.py:67: AssertionError
+    '''
     from _pydevd_bundle.pydevd_utils import is_current_thread_main_thread
     from _pydevd_bundle.pydevd_utils import dump_threads
     if not is_current_thread_main_thread():
diff --git a/tests/tests/test_vendoring.py b/tests/tests/test_vendoring.py
new file mode 100644
index 00000000..dd6c4269
--- /dev/null
+++ b/tests/tests/test_vendoring.py
@@ -0,0 +1,34 @@
+def test_vendoring(pyfile):
+    @pyfile
+    def import_debugpy():
+        import sys
+
+        class Dummy(object):
+            __file__ = None
+
+        class Dummy2(object):
+            pass
+        
+        class Dummy3(object):
+            def __getattribute__(self, *args, **kwargs):
+                raise AssertionError('Error')
+
+        sys.modules["pydev_dummy"] = Dummy()
+        sys.modules["pydev_dummy2"] = Dummy2()
+        sys.modules["pydev_dummy3"] = Dummy3()
+        
+        sys.modules["_pydev_dummy"] = Dummy()
+        sys.modules["_pydev_dummy2"] = Dummy2()
+        sys.modules["_pydev_dummy3"] = Dummy3()
+
+        from debugpy._vendored import force_pydevd  # noqa
+
+        print("Properly applied pydevd vendoring.")
+
+    import subprocess
+    import sys
+
+    output = subprocess.check_output([sys.executable, "-u", import_debugpy.strpath])
+    output = output.decode("utf-8")
+    if "Properly applied pydevd vendoring." not in output:
+        raise AssertionError(output)