Repository: spyder-ide/spyder
Pull request: PR: Centralize dependencies and declare the missing ones
<!--- Make sure to read the Contributing Guidelines:                   --->
<!--- https://github.com/spyder-ide/spyder/blob/master/CONTRIBUTING.md --->
<!--- and follow PEP 8, PEP 257 and Spyder's code style:               --->
<!--- https://github.com/spyder-ide/spyder/wiki/Dev:-Coding-Style      --->

## Description of Changes
* [ ] Wrote at least one-line docstrings (for any new functions)
* [ ] Added unit test(s) covering the changes (if testable)
<!--- Remember that an image/animation is worth a thousand words! --->
* [x] Included a screenshot or animation (if affecting the UI, see [Licecap](https://www.cockos.com/licecap/))


<!--- Explain what you've done and why --->

Centralized all dependencies in one place and declared all the ones missing that are present in setup
to solve issue #9796 

![Screen Shot 2019-08-07 at 12 00 33 AM](https://user-images.githubusercontent.com/18587879/62596225-07b71900-b8a7-11e9-8192-5f37038ac01b.png)


### Issue(s) Resolved

<!--- List the issue(s) below, in the form "Fixes #1234"; one per line --->

Fixes #9796 


### Affirmation

By submitting this Pull Request or typing my (user)name below,
I affirm the [Developer Certificate of Origin](https://developercertificate.org)
with respect to all commits and content included in this PR,
and understand I am releasing the same under Spyder's MIT (Expat) license.

<!--- TYPE YOUR USER/NAME AFTER THE FOLLOWING: --->
I certify the above statement is true and correct:
Juanis2112

<!--- Thanks for your help making Spyder better for everyone! --->


Problem statement:
Centralize all dependencies in one place and declare all the ones present in setup.py
@juanis2112, the idea is to move all calls of the form

```python
QDARKSTYLE_REQVER = '>=2.6.4'
dependencies.add("qdarkstyle", _("Dark style for the entire interface"),
                 required_version=QDARKSTYLE_REQVER)
```

to `spyder/dependencies.py`, inside a function called `declare_dependencies`. Then, please import that function in `spyder/app/mainwindow.py` and call it where the above code for qdarkstyle is placed right now.

Besides doing that, please go through our entire list of dependencies in our `setup.py` and declare the missing ones in `declare_dependencies` too.

Hints from issue discussion:

Commit message: Fixing required version for QTCONSOLE_REQVER

Patch to review:
diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py
index 9bddd61faad..24f6e8a0464 100644
--- a/spyder/app/mainwindow.py
+++ b/spyder/app/mainwindow.py
@@ -274,10 +274,7 @@ def qt_message_handler(msg_type, msg_log_context, msg_string):
 # =============================================================================
 # Dependencies
 # =============================================================================
-QDARKSTYLE_REQVER = '>=2.6.4'
-dependencies.add("qdarkstyle", "qdarkstyle",
-                 _("Dark style for the entire interface"),
-                 required_version=QDARKSTYLE_REQVER)
+dependencies.declare_dependencies()
 
 #==============================================================================
 # Main Window
diff --git a/spyder/dependencies.py b/spyder/dependencies.py
index 70ad22de05d..ae732dd09bd 100644
--- a/spyder/dependencies.py
+++ b/spyder/dependencies.py
@@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
+     'required_version': PYMPLER_REQVER}]
+
+if sys.platform == 'Linux':
+    DEPENDENCIES_BASE.append({'modname': "xdg", 'package_name': "pyxdg", 'features': _("Parse `.desktop` files on Linux"), 'required_version': PYXDG_REQVER})
+
+if sys.platform == 'Windows':
+    DEPENDENCIES_BASE.append({'modname': "paramiko", 'package_name': "paramiko", 'features': _("Connect to remote kernels through SSH."), 'required_version': PARAMIKO_REQVER})
 
 class Dependency(object):
     """Spyder's dependency
@@ -113,3 +231,9 @@ def missing_dependencies():
         return status(deps=missing_deps, linesep='<br>')
     else:
         return ""
+
+
+def declare_dependencies():
+    for dep in DEPENDENCIES_BASE:
+        add(dep['modname'], dep['package_name'],
+            dep['features'], dep['required_version'])
diff --git a/spyder/plugins/editor/plugin.py b/spyder/plugins/editor/plugin.py
index dd5efe67004..0b734419a72 100644
--- a/spyder/plugins/editor/plugin.py
+++ b/spyder/plugins/editor/plugin.py
@@ -68,11 +68,6 @@
                    "real-time code analysis"),
                  required_version=PYLS_REQVER)
 
-NBCONVERT_REQVER = ">=4.0"
-dependencies.add("nbconvert", "nbconvert",
-                 _("Manipulate Jupyter notebooks on the Editor"),
-                 required_version=NBCONVERT_REQVER)
-
 WINPDB_PATH = programs.find_program('winpdb')
 
 
diff --git a/spyder/plugins/help/plugin.py b/spyder/plugins/help/plugin.py
index 6ffd26d8991..97b80008f1e 100644
--- a/spyder/plugins/help/plugin.py
+++ b/spyder/plugins/help/plugin.py
@@ -34,13 +34,6 @@
 from spyder.plugins.help.utils.sphinxthread import SphinxThread
 from spyder.plugins.help.widgets import PlainText, RichText, ObjectComboBox
 
-# Sphinx dependency
-dependencies.add("sphinx", "sphinx",
-                 _("Show help for objects in the Editor and "
-                   "Consoles in a dedicated pane"),
-                 required_version='>=0.6.6')
-
-
 
 class Help(SpyderPluginWidget):
     """
diff --git a/spyder/plugins/ipythonconsole/plugin.py b/spyder/plugins/ipythonconsole/plugin.py
index 77fc6e62bd5..bc858db02d0 100644
--- a/spyder/plugins/ipythonconsole/plugin.py
+++ b/spyder/plugins/ipythonconsole/plugin.py
@@ -67,11 +67,6 @@
                  _("Run Cython files in the IPython Console"),
                  required_version=CYTHON_REQVER, optional=True)
 
-QTCONSOLE_REQVER = ">=4.5.5"
-dependencies.add("qtconsole", "qtconsole",
-                 _("Integrate the IPython console"),
-                 required_version=QTCONSOLE_REQVER)
-
 IPYTHON_REQVER = ">=4.0;<6.0" if PY2 else ">=4.0"
 dependencies.add("IPython", "IPython",
                  _("IPython interactive python environment"),
diff --git a/spyder/plugins/pylint/widgets/pylintgui.py b/spyder/plugins/pylint/widgets/pylintgui.py
index 149009e09f4..d46ff78e969 100644
--- a/spyder/plugins/pylint/widgets/pylintgui.py
+++ b/spyder/plugins/pylint/widgets/pylintgui.py
@@ -45,12 +45,7 @@
     import gettext
     _ = gettext.gettext
 
-PYLINT_REQVER = '>=0.25'
 PYLINT_VER = pylint.__version__
-dependencies.add("pylint", "pylint", _("Static code analysis"),
-                 required_version=PYLINT_REQVER, installed_version=PYLINT_VER)
-
-
 #TODO: display results on 3 columns instead of 1: msg_id, lineno, message
 class ResultsTree(OneColumnTree):
     sig_edit_goto = Signal(str, int, str)
diff --git a/spyder/plugins/variableexplorer/plugin.py b/spyder/plugins/variableexplorer/plugin.py
index ec5b6a997a3..a7df1f0e0f6 100644
--- a/spyder/plugins/variableexplorer/plugin.py
+++ b/spyder/plugins/variableexplorer/plugin.py
@@ -32,13 +32,6 @@
                    "in the Variable Explorer"),
                  required_version=NUMPY_REQVER, optional=True)
 
-PYMPLER_REQVER = '>=0.7'
-dependencies.add("pympler", "pympler",
-                 _("Development tool to measure, monitor and analyze the"
-                   " memory behavior of Python objects in a running Python"
-                   " application."),
-                 required_version=PYMPLER_REQVER, optional=True)
-
 
 class VariableExplorer(SpyderPluginWidget):
     """Variable Explorer plugin."""
diff --git a/spyder/utils/syntaxhighlighters.py b/spyder/utils/syntaxhighlighters.py
index e365bd55d87..a174abbe325 100644
--- a/spyder/utils/syntaxhighlighters.py
+++ b/spyder/utils/syntaxhighlighters.py
@@ -39,11 +39,6 @@
 from spyder.plugins.outlineexplorer.api import OutlineExplorerData
 from spyder.utils.qstringhelpers import qstring_length
 
-PYGMENTS_REQVER = '>=2.0'
-dependencies.add("pygments", "pygments",
-                 _("Syntax highlighting for Matlab, Julia and "
-                   "other file types"),
-                 required_version=PYGMENTS_REQVER)
 
 
 # =============================================================================
diff --git a/spyder/widgets/status.py b/spyder/widgets/status.py
index 23fc8175ed3..6fc58ee99bb 100644
--- a/spyder/widgets/status.py
+++ b/spyder/widgets/status.py
@@ -24,15 +24,6 @@
 from spyder.config import utils
 from spyder.py3compat import PY3
 
-if not os.name == 'nt':
-    PSUTIL_REQVER = '>=0.3'
-    dependencies.add(
-        "psutil",
-        "psutil",
-        _("CPU and memory usage info in the status bar"),
-        required_version=PSUTIL_REQVER)
-
-
 class StatusBarWidget(QWidget):
     """Status bar widget base."""
     # Signals


Code review comments:
diff_hunk: @@ -274,10 +274,7 @@ def qt_message_handler(msg_type, msg_log_context, msg_string):
 # =============================================================================
 # Dependencies
 # =============================================================================
-QDARKSTYLE_REQVER = '>=2.6.4'
-dependencies.add("qdarkstyle", "qdarkstyle",
-                 _("Dark style for the entire interface"),
-                 required_version=QDARKSTYLE_REQVER)
+dependencies.declare_dependencies()
path: spyder/app/mainwindow.py
text: @user1:
Let's move this to the method called `report_missing_dependencies`, present also here in the main window, like this:

```python
def report_missing_dependencies(self):
    """Show a QMessageBox with a list of missing hard dependencies"""
    dependencies.declare_dependencies()
    missing_deps = dependencies.missing_dependencies()
    ...
```

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
+     'required_version': PYMPLER_REQVER}]
+
+if sys.platform == 'Linux':
+    DEPENDENCIES_BASE.append({'modname': "xdg", 'package_name': "pyxdg", 'features': _("Parse `.desktop` files on Linux"), 'required_version': PYXDG_REQVER})
path: spyder/dependencies.py
text: @user1:
Please change this to

```
DEPENDENCIES_BASE.append(
    {'modname': "xdg",
     'package_name': "pyxdg",
     'features': _("Parse `.desktop` files on Linux"),
     'required_version': PYXDG_REQVER}
)
```

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
+     'required_version': PYMPLER_REQVER}]
+
+if sys.platform == 'Linux':
+    DEPENDENCIES_BASE.append({'modname': "xdg", 'package_name': "pyxdg", 'features': _("Parse `.desktop` files on Linux"), 'required_version': PYXDG_REQVER})
+
+if sys.platform == 'Windows':
path: spyder/dependencies.py
text: @user1:
This needs to be

    if os.name == 'nt':

which is the way we test for Windows.

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
path: spyder/dependencies.py
text: @user1:
Let's change this description to

    Abstraction layer for Python Qt bindings.

diff_hunk: @@ -274,10 +274,7 @@ def qt_message_handler(msg_type, msg_log_context, msg_string):
 # =============================================================================
 # Dependencies
 # =============================================================================
path: spyder/app/mainwindow.py
text: @user1:
Please remove these three lines above this comment because they are not needed anymore.

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
+     'required_version': PYMPLER_REQVER}]
+
+if sys.platform == 'Linux':
+    DEPENDENCIES_BASE.append({'modname': "xdg", 'package_name': "pyxdg", 'features': _("Parse `.desktop` files on Linux"), 'required_version': PYXDG_REQVER})
+
+if sys.platform == 'Windows':
+    DEPENDENCIES_BASE.append({'modname': "paramiko", 'package_name': "paramiko", 'features': _("Connect to remote kernels through SSH."), 'required_version': PARAMIKO_REQVER})
path: spyder/dependencies.py
text: @user1:
Please change this to

```
DEPENDENCIES_BASE.append(
    {'modname': "paramiko",
     'package_name': "paramiko",
     'features': _("Connect to remote kernels through SSH."),
     'required_version': PARAMIKO_REQVER}
)
```

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
path: spyder/dependencies.py
text: @user1:
Let's change this to

    Tool to measure the memory behavior of Python objects.

diff_hunk: @@ -8,10 +8,128 @@
 
 
 import os
+import sys
 
 # Local imports
 from spyder.utils import programs
-
+from spyder.config.base import _
+
+
+CLOUDPICKLE_REQVER = '>=0.5.0'
+PYGMENTS_REQVER = '>=2.0'
+QTCONSOLE_REQVER = '>=4.5.5'
+NBCONVERT_REQVER = '>=4.0'
+SPHINX_REQVER = '>=0.6.6'
+PYLINT_REQVER = '>=0.25'
+PSUTIL_REQVER = '>=0.3'
+QTAWESOME_REQVER = '>=0.5.7'
+QTPY_REQVER = '>=1.5.0'
+PICKLESHARE_REQVER = '>=0.4'
+PYZMQ_REQVER = '>=17'
+CHARDET_REQVER = '>=2.0.0'
+NUMPYDOC_REQVER = '>=0.6.0'
+SPYDER_KERNELS_REQVER = '>=1.4.0'
+QDARKSTYLE_REQVER = '>=2.7'
+ATOMICWRITES_REQVER = '>=1.2.0'
+DIFF_MATCH_PATCH_REQVER = '>=20181111'
+WATCHDOG_REQVER = None
+KEYRING_REQVER = None
+PEXPECT_REQVER = '>=4.4.0'
+PARAMIKO_REQVER = '>=2.4.0'
+PYXDG_REQVER = '>=0.26'
+PYMPLER_REQVER = None
+
+DEPENDENCIES_BASE = [
+    {'modname': "cloudpickle",
+     'package_name': "cloudpickle",
+     'features': _("Serialize variables in the IPython kernel to send to Spyder."),
+     'required_version': CLOUDPICKLE_REQVER},
+    {'modname': "pygments",
+     'package_name': "pygments",
+     'features': _("Syntax highlighting for Matlab, Julia and other file types"),
+     'required_version': PYGMENTS_REQVER},
+    {'modname': "qtconsole",
+     'package_name': "qtconsole",
+     'features': _("Integrate the IPython console"),
+     'required_version': QTCONSOLE_REQVER},
+    {'modname': "nbconvert",
+     'package_name': "nbconvert",
+     'features': _("Manipulate Jupyter notebooks on the Editor"),
+     'required_version': NBCONVERT_REQVER},
+    {'modname': "sphinx",
+     'package_name': "sphinx",
+     'features': _("Show help for objects in the Editor and Consoles in a dedicated pane"),
+     'required_version': SPHINX_REQVER},
+    {'modname': "pylint",
+     'package_name': "pylint",
+     'features': _("Static code analysis"),
+     'required_version': PYLINT_REQVER},
+    {'modname': "psutil",
+     'package_name': "psutil",
+     'features': _("CPU and memory usage info in the status bar"),
+     'required_version': PSUTIL_REQVER},
+    {'modname': "qtawesome",
+     'package_name': "qtawesome",
+     'features': _("To have an icon theme based on FontAwesome."),
+     'required_version': QTAWESOME_REQVER},
+    {'modname': "qtpy",
+     'package_name': "qtpy",
+     'features': _("Abstraction layer for Python Qt bindings so that Spyder can run on multiple Qt bindings and versions."),
+     'required_version': QTPY_REQVER},
+    {'modname': "pickleshare",
+     'package_name': "pickleshare",
+     'features': _("Show import completions on the Python consoles."),
+     'required_version': PICKLESHARE_REQVER},
+    {'modname': "zmq",
+     'package_name': "pyzmq",
+     'features': _("Client for the language server protocol (LSP)."),
+     'required_version': PYZMQ_REQVER},
+    {'modname': "chardet",
+     'package_name': "chardet",
+     'features': _("Character encoding auto-detection in Python."),
+     'required_version': CHARDET_REQVER},
+    {'modname': "numpydoc",
+     'package_name': "numpydoc",
+     'features': _("Used by Jedi to get function return types from Numpydocstrings."),
+     'required_version': NUMPYDOC_REQVER},
+    {'modname': "spyder_kernels",
+     'package_name': "spyder-kernels",
+     'features': _("Jupyter kernels for the Spyder console."),
+     'required_version': SPYDER_KERNELS_REQVER},
+    {'modname': "qdarkstyle",
+     'package_name': "qdarkstyle",
+     'features': _("Dark style for the entire interface"),
+     'required_version': QDARKSTYLE_REQVER},
+    {'modname': "atomicwrites",
+     'package_name': "atomicwrites",
+     'features': _("Atomic file writes."),
+     'required_version': ATOMICWRITES_REQVER},
+    {'modname': "diff_match_patch",
+     'package_name': "diff_match_patch",
+     'features': _("Compute text file diff changes during edition."),
+     'required_version': DIFF_MATCH_PATCH_REQVER},
+    {'modname': "watchdog",
+     'package_name': "watchdog",
+     'features': _("Watch file changes on project directories."),
+     'required_version': WATCHDOG_REQVER},
+    {'modname': "keyring",
+     'package_name': "keyring",
+     'features': _("Save Github credentials to report errors securely."),
+     'required_version': KEYRING_REQVER},
+    {'modname': "pexpect",
+     'package_name': "pexpect",
+     'features': _("Connect to remote kernels through SSH."),
+     'required_version': PEXPECT_REQVER},
+    {'modname': "pympler",
+     'package_name': "pympler",
+     'features': _("Development tool to measure, monitor and analyze the memory behavior of Python objects in a running Python application."),
+     'required_version': PYMPLER_REQVER}]
+
+if sys.platform == 'Linux':
path: spyder/dependencies.py
text: @user1:
Please change this to

    if sys.platform.startswith('linux'):

That's the way we check for Linux in our codebase.