prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Error when trying to load third-party plugins
  ## Description
  
  **What steps will reproduce the problem?**
  
  1. Start sypder.
  2. 
  3. 
  
  **What is the expected output? What do you see instead?**
  It shows right away after starting Spyder.
  
  **Please provide any additional information below**
  A message box show this:
      module = _import_module_from_path(module_name, plugin_path)
      module = spec.loader.load_module(module_name)
  AttributeError: 'NoneType' object has no attribute 'load_module'
  ![image](https://user-images.githubusercontent.com/9072983/28740752-f2f86f42-7432-11e7-84e5-539b3cf0e641.png)
  
  Spyder functions fine, no problem after close the message box.
  ## Version and main components
  
  * Spyder Version: 3.2.0 
  * Python Version: 3.5.3
  * Qt Versions: 5.6.2, PyQt5 5.6 on Darwin
  
  ## Dependencies
  ```
  pyflakes >=0.6.0 :  1.5.0 (OK)
  pycodestyle >=2.3:  2.3.1 (OK)
  pygments >=2.0   :  2.2.0 (OK)
  pandas >=0.13.1  :  0.19.2 (OK)
  numpy >=1.7      :  1.12.1 (OK)
  sphinx >=0.6.6   :  1.5.4 (OK)
  rope >=0.9.4     :  0.10.5 (OK)
  jedi >=0.9.0     :  0.10.2 (OK)
  psutil >=0.3     :  5.2.1 (OK)
  nbconvert >=4.0  :  5.1.1 (OK)
  sympy >=0.7.3    :  None (NOK)
  cython >=0.21    :  None (NOK)
  qtconsole >=4.2.0:  4.3.0 (OK)
  IPython >=4.0    :  6.1.0 (OK)
  pylint >=0.25    :  1.6.4 (OK)
  
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `spyder/otherplugins.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 #
  3 # Copyright © Spyder Project Contributors
  4 # Licensed under the terms of the MIT License
  5 # (see spyder/__init__.py for details)
  6 
  7 """
  8 Spyder third-party plugins configuration management
  9 """
  10 
  11 import os
  12 import os.path as osp
  13 import sys
  14 import traceback
  15 
  16 # Local imports
  17 from spyder.config.base import get_conf_path
  18 from spyder.py3compat import PY2
  19 
  20 if PY2:
  21     import imp
  22 else:
  23     import importlib
  24 
  25 
  26 USER_PLUGIN_DIR = "plugins"
  27 PLUGIN_PREFIX = "spyder_"
  28 IO_PREFIX = PLUGIN_PREFIX + "io_"
  29 
  30 
  31 def get_spyderplugins_mods(io=False):
  32     """Import modules from plugins package and return the list"""
  33     # Create user directory
  34     user_plugin_path = osp.join(get_conf_path(), USER_PLUGIN_DIR)
  35     if not osp.isdir(user_plugin_path):
  36         os.makedirs(user_plugin_path)
  37 
  38     modlist, modnames = [], []
  39 
  40     # The user plugins directory is given the priority when looking for modules
  41     for plugin_path in [user_plugin_path] + sys.path:
  42         _get_spyderplugins(plugin_path, io, modnames, modlist)
  43     return modlist
  44 
  45 
  46 def _get_spyderplugins(plugin_path, is_io, modnames, modlist):
  47     """Scan the directory `plugin_path` for plugin packages and loads them."""
  48     if not osp.isdir(plugin_path):
  49         return
  50 
  51     for name in os.listdir(plugin_path):
  52         # This is needed in order to register the spyder_io_hdf5 plugin.
  53         # See issue 4487
  54         # Is this a Spyder plugin?
  55         if not name.startswith(PLUGIN_PREFIX):
  56             continue
  57         # Ensure right type of plugin
  58         if is_io != name.startswith(IO_PREFIX):
  59             continue
  60 
  61         # Import the plugin
  62         _import_plugin(name, plugin_path, modnames, modlist)
  63 
  64 
  65 def _import_plugin(module_name, plugin_path, modnames, modlist):
  66     """Import the plugin `module_name` from `plugin_path`, add it to `modlist`
  67     and adds its name to `modnames`.
  68     """
  69     if module_name in modnames:
  70         return
  71     try:
  72         # First add a mock module with the LOCALEPATH attribute so that the
  73         # helper method can find the locale on import
  74         mock = _ModuleMock()
  75         mock.LOCALEPATH = osp.join(plugin_path, module_name, 'locale')
  76         sys.modules[module_name] = mock
  77 
  78         if osp.isdir(osp.join(plugin_path, module_name)):
  79             module = _import_module_from_path(module_name, plugin_path)
  80         else:
  81             module = None
  82 
  83         # Then restore the actual loaded module instead of the mock
  84         if module:
  85             sys.modules[module_name] = module
  86             modlist.append(module)
  87             modnames.append(module_name)
  88     except Exception:
  89         sys.stderr.write("ERROR: 3rd party plugin import failed for "
  90                          "`{0}`\n".format(module_name))
  91         traceback.print_exc(file=sys.stderr)
  92 
  93 
  94 def _import_module_from_path(module_name, plugin_path):
  95     """Imports `module_name` from `plugin_path`.
  96 
  97     Return None if no module is found.
  98     """
  99     module = None
  100     if PY2:
  101         info = imp.find_module(module_name, [plugin_path])
  102         if info:
  103             module = imp.load_module(module_name, *info)
  104     elif sys.version_info[0:2] <= (3, 3):
  105         loader = importlib.machinery.PathFinder.find_module(
  106             module_name,
  107             [plugin_path])
  108         if loader:
  109             module = loader.load_module(module_name)
  110     else:  # Python 3.4+
  111         spec = importlib.machinery.PathFinder.find_spec(
  112             module_name,
  113             [plugin_path])
  114         if spec:
  115             module = spec.loader.load_module(module_name)
  116     return module
  117 
  118 
  119 class _ModuleMock():
  120     """This mock module is added to sys.modules on plugin load to add the
  121     location of the LOCALEDATA so that the module loads succesfully.
  122     Once loaded the module is replaced by the actual loaded module object.
  123     """
  124     pass
  125
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/spyder/otherplugins.py b/spyder/otherplugins.py
  --- a/spyder/otherplugins.py
  +++ b/spyder/otherplugins.py
  @@ -54,10 +54,16 @@
           # Is this a Spyder plugin?
           if not name.startswith(PLUGIN_PREFIX):
               continue
  +
           # Ensure right type of plugin
           if is_io != name.startswith(IO_PREFIX):
               continue
   
  +        # Skip names that end in certain suffixes
  +        forbidden_suffixes = ['dist-info', 'egg.info', 'egg-link']
  +        if any([name.endswith(s) for s in forbidden_suffixes]):
  +            continue
  +
           # Import the plugin
           _import_plugin(name, plugin_path, modnames, modlist)
  
verification_info: {"golden_diff": "diff --git a/spyder/otherplugins.py b/spyder/otherplugins.py\n--- a/spyder/otherplugins.py\n+++ b/spyder/otherplugins.py\n@@ -54,10 +54,16 @@\n         # Is this a Spyder plugin?\r\n         if not name.startswith(PLUGIN_PREFIX):\r\n             continue\r\n+\r\n         # Ensure right type of plugin\r\n         if is_io != name.startswith(IO_PREFIX):\r\n             continue\r\n \r\n+        # Skip names that end in certain suffixes\r\n+        forbidden_suffixes = ['dist-info', 'egg.info', 'egg-link']\r\n+        if any([name.endswith(s) for s in forbidden_suffixes]):\r\n+            continue\r\n+\r\n         # Import the plugin\r\n         _import_plugin(name, plugin_path, modnames, modlist)\n", "issue": "Error when trying to load third-party plugins\n## Description\r\n\r\n**What steps will reproduce the problem?**\r\n\r\n1. Start sypder.\r\n2. \r\n3. \r\n\r\n**What is the expected output? What do you see instead?**\r\nIt shows right away after starting Spyder.\r\n\r\n**Please provide any additional information below**\r\nA message box show this:\r\n    module = _import_module_from_path(module_name, plugin_path)\r\n    module = spec.loader.load_module(module_name)\r\nAttributeError: 'NoneType' object has no attribute 'load_module'\r\n![image](https://user-images.githubusercontent.com/9072983/28740752-f2f86f42-7432-11e7-84e5-539b3cf0e641.png)\r\n\r\nSpyder functions fine, no problem after close the message box.\r\n## Version and main components\r\n\r\n* Spyder Version: 3.2.0 \r\n* Python Version: 3.5.3\r\n* Qt Versions: 5.6.2, PyQt5 5.6 on Darwin\r\n\r\n## Dependencies\r\n```\r\npyflakes >=0.6.0 :  1.5.0 (OK)\r\npycodestyle >=2.3:  2.3.1 (OK)\r\npygments >=2.0   :  2.2.0 (OK)\r\npandas >=0.13.1  :  0.19.2 (OK)\r\nnumpy >=1.7      :  1.12.1 (OK)\r\nsphinx >=0.6.6   :  1.5.4 (OK)\r\nrope >=0.9.4     :  0.10.5 (OK)\r\njedi >=0.9.0     :  0.10.2 (OK)\r\npsutil >=0.3     :  5.2.1 (OK)\r\nnbconvert >=4.0  :  5.1.1 (OK)\r\nsympy >=0.7.3    :  None (NOK)\r\ncython >=0.21    :  None (NOK)\r\nqtconsole >=4.2.0:  4.3.0 (OK)\r\nIPython >=4.0    :  6.1.0 (OK)\r\npylint >=0.25    :  1.6.4 (OK)\r\n\r\n```\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\r\n#\r\n# Copyright \u00a9 Spyder Project Contributors\r\n# Licensed under the terms of the MIT License\r\n# (see spyder/__init__.py for details)\r\n\r\n\"\"\"\r\nSpyder third-party plugins configuration management\r\n\"\"\"\r\n\r\nimport os\r\nimport os.path as osp\r\nimport sys\r\nimport traceback\r\n\r\n# Local imports\r\nfrom spyder.config.base import get_conf_path\r\nfrom spyder.py3compat import PY2\r\n\r\nif PY2:\r\n    import imp\r\nelse:\r\n    import importlib\r\n\r\n\r\nUSER_PLUGIN_DIR = \"plugins\"\r\nPLUGIN_PREFIX = \"spyder_\"\r\nIO_PREFIX = PLUGIN_PREFIX + \"io_\"\r\n\r\n\r\ndef get_spyderplugins_mods(io=False):\r\n    \"\"\"Import modules from plugins package and return the list\"\"\"\r\n    # Create user directory\r\n    user_plugin_path = osp.join(get_conf_path(), USER_PLUGIN_DIR)\r\n    if not osp.isdir(user_plugin_path):\r\n        os.makedirs(user_plugin_path)\r\n\r\n    modlist, modnames = [], []\r\n\r\n    # The user plugins directory is given the priority when looking for modules\r\n    for plugin_path in [user_plugin_path] + sys.path:\r\n        _get_spyderplugins(plugin_path, io, modnames, modlist)\r\n    return modlist\r\n\r\n\r\ndef _get_spyderplugins(plugin_path, is_io, modnames, modlist):\r\n    \"\"\"Scan the directory `plugin_path` for plugin packages and loads them.\"\"\"\r\n    if not osp.isdir(plugin_path):\r\n        return\r\n\r\n    for name in os.listdir(plugin_path):\r\n        # This is needed in order to register the spyder_io_hdf5 plugin.\r\n        # See issue 4487\r\n        # Is this a Spyder plugin?\r\n        if not name.startswith(PLUGIN_PREFIX):\r\n            continue\r\n        # Ensure right type of plugin\r\n        if is_io != name.startswith(IO_PREFIX):\r\n            continue\r\n\r\n        # Import the plugin\r\n        _import_plugin(name, plugin_path, modnames, modlist)\r\n\r\n\r\ndef _import_plugin(module_name, plugin_path, modnames, modlist):\r\n    \"\"\"Import the plugin `module_name` from `plugin_path`, add it to `modlist`\r\n    and adds its name to `modnames`.\r\n    \"\"\"\r\n    if module_name in modnames:\r\n        return\r\n    try:\r\n        # First add a mock module with the LOCALEPATH attribute so that the\r\n        # helper method can find the locale on import\r\n        mock = _ModuleMock()\r\n        mock.LOCALEPATH = osp.join(plugin_path, module_name, 'locale')\r\n        sys.modules[module_name] = mock\r\n\r\n        if osp.isdir(osp.join(plugin_path, module_name)):\r\n            module = _import_module_from_path(module_name, plugin_path)\r\n        else:\r\n            module = None\r\n\r\n        # Then restore the actual loaded module instead of the mock\r\n        if module:\r\n            sys.modules[module_name] = module\r\n            modlist.append(module)\r\n            modnames.append(module_name)\r\n    except Exception:\r\n        sys.stderr.write(\"ERROR: 3rd party plugin import failed for \"\r\n                         \"`{0}`\\n\".format(module_name))\r\n        traceback.print_exc(file=sys.stderr)\r\n\r\n\r\ndef _import_module_from_path(module_name, plugin_path):\r\n    \"\"\"Imports `module_name` from `plugin_path`.\r\n\r\n    Return None if no module is found.\r\n    \"\"\"\r\n    module = None\r\n    if PY2:\r\n        info = imp.find_module(module_name, [plugin_path])\r\n        if info:\r\n            module = imp.load_module(module_name, *info)\r\n    elif sys.version_info[0:2] <= (3, 3):\r\n        loader = importlib.machinery.PathFinder.find_module(\r\n            module_name,\r\n            [plugin_path])\r\n        if loader:\r\n            module = loader.load_module(module_name)\r\n    else:  # Python 3.4+\r\n        spec = importlib.machinery.PathFinder.find_spec(\r\n            module_name,\r\n            [plugin_path])\r\n        if spec:\r\n            module = spec.loader.load_module(module_name)\r\n    return module\r\n\r\n\r\nclass _ModuleMock():\r\n    \"\"\"This mock module is added to sys.modules on plugin load to add the\r\n    location of the LOCALEDATA so that the module loads succesfully.\r\n    Once loaded the module is replaced by the actual loaded module object.\r\n    \"\"\"\r\n    pass\r\n", "path": "spyder/otherplugins.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\r\n#\r\n# Copyright \u00a9 Spyder Project Contributors\r\n# Licensed under the terms of the MIT License\r\n# (see spyder/__init__.py for details)\r\n\r\n\"\"\"\r\nSpyder third-party plugins configuration management\r\n\"\"\"\r\n\r\nimport os\r\nimport os.path as osp\r\nimport sys\r\nimport traceback\r\n\r\n# Local imports\r\nfrom spyder.config.base import get_conf_path\r\nfrom spyder.py3compat import PY2\r\n\r\nif PY2:\r\n    import imp\r\nelse:\r\n    import importlib\r\n\r\n\r\nUSER_PLUGIN_DIR = \"plugins\"\r\nPLUGIN_PREFIX = \"spyder_\"\r\nIO_PREFIX = PLUGIN_PREFIX + \"io_\"\r\n\r\n\r\ndef get_spyderplugins_mods(io=False):\r\n    \"\"\"Import modules from plugins package and return the list\"\"\"\r\n    # Create user directory\r\n    user_plugin_path = osp.join(get_conf_path(), USER_PLUGIN_DIR)\r\n    if not osp.isdir(user_plugin_path):\r\n        os.makedirs(user_plugin_path)\r\n\r\n    modlist, modnames = [], []\r\n\r\n    # The user plugins directory is given the priority when looking for modules\r\n    for plugin_path in [user_plugin_path] + sys.path:\r\n        _get_spyderplugins(plugin_path, io, modnames, modlist)\r\n    return modlist\r\n\r\n\r\ndef _get_spyderplugins(plugin_path, is_io, modnames, modlist):\r\n    \"\"\"Scan the directory `plugin_path` for plugin packages and loads them.\"\"\"\r\n    if not osp.isdir(plugin_path):\r\n        return\r\n\r\n    for name in os.listdir(plugin_path):\r\n        # This is needed in order to register the spyder_io_hdf5 plugin.\r\n        # See issue 4487\r\n        # Is this a Spyder plugin?\r\n        if not name.startswith(PLUGIN_PREFIX):\r\n            continue\r\n\r\n        # Ensure right type of plugin\r\n        if is_io != name.startswith(IO_PREFIX):\r\n            continue\r\n\r\n        # Skip names that end in certain suffixes\r\n        forbidden_suffixes = ['dist-info', 'egg.info', 'egg-link']\r\n        if any([name.endswith(s) for s in forbidden_suffixes]):\r\n            continue\r\n\r\n        # Import the plugin\r\n        _import_plugin(name, plugin_path, modnames, modlist)\r\n\r\n\r\ndef _import_plugin(module_name, plugin_path, modnames, modlist):\r\n    \"\"\"Import the plugin `module_name` from `plugin_path`, add it to `modlist`\r\n    and adds its name to `modnames`.\r\n    \"\"\"\r\n    if module_name in modnames:\r\n        return\r\n    try:\r\n        # First add a mock module with the LOCALEPATH attribute so that the\r\n        # helper method can find the locale on import\r\n        mock = _ModuleMock()\r\n        mock.LOCALEPATH = osp.join(plugin_path, module_name, 'locale')\r\n        sys.modules[module_name] = mock\r\n\r\n        if osp.isdir(osp.join(plugin_path, module_name)):\r\n            module = _import_module_from_path(module_name, plugin_path)\r\n        else:\r\n            module = None\r\n\r\n        # Then restore the actual loaded module instead of the mock\r\n        if module:\r\n            sys.modules[module_name] = module\r\n            modlist.append(module)\r\n            modnames.append(module_name)\r\n    except Exception:\r\n        sys.stderr.write(\"ERROR: 3rd party plugin import failed for \"\r\n                         \"`{0}`\\n\".format(module_name))\r\n        traceback.print_exc(file=sys.stderr)\r\n\r\n\r\ndef _import_module_from_path(module_name, plugin_path):\r\n    \"\"\"Imports `module_name` from `plugin_path`.\r\n\r\n    Return None if no module is found.\r\n    \"\"\"\r\n    module = None\r\n    if PY2:\r\n        info = imp.find_module(module_name, [plugin_path])\r\n        if info:\r\n            module = imp.load_module(module_name, *info)\r\n    elif sys.version_info[0:2] <= (3, 3):\r\n        loader = importlib.machinery.PathFinder.find_module(\r\n            module_name,\r\n            [plugin_path])\r\n        if loader:\r\n            module = loader.load_module(module_name)\r\n    else:  # Python 3.4+\r\n        spec = importlib.machinery.PathFinder.find_spec(\r\n            module_name,\r\n            [plugin_path])\r\n        if spec:\r\n            module = spec.loader.load_module(module_name)\r\n    return module\r\n\r\n\r\nclass _ModuleMock():\r\n    \"\"\"This mock module is added to sys.modules on plugin load to add the\r\n    location of the LOCALEDATA so that the module loads succesfully.\r\n    Once loaded the module is replaced by the actual loaded module object.\r\n    \"\"\"\r\n    pass\r\n", "path": "spyder/otherplugins.py"}]}