Repository: spyder-ide/spyder

Issue:
Mambaforge environment not automatically detected
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist

* [x] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [ ] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [ ] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [ ] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [ ] Tried basic troubleshooting (if a bug/error)
    * [ ] Restarted Spyder
    * [ ] Reset preferences with ``spyder --reset``
    * [ ] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [ ] Tried the other applicable steps from the Troubleshooting Guide
* [ ] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below


## Problem Description

A minor issue, on Windows 10 the environments created using `mambaforge` (and possibly `miniforge` ?) are not automatically detected under the Python interpreter page in the Spyder preferences. By default, the environments are created under `C:\Users\username\AppData\Local\mambaforge\envs`.

Note: I also have `miniconda` environments, these are automatically detected.


## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: 5.4.2  (standalone)
* Python version: 3.8.10 64-bit
* Qt version: 5.15.2
* PyQt5 version: 5.15.7
* Operating System: Windows 10


### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->
<details>
```
atomicwrites >=1.2.0                 :  1.4.1 (OK)
chardet >=2.0.0                      :  5.1.0 (OK)
cloudpickle >=0.5.0                  :  2.2.0 (OK)
cookiecutter >=1.6.0                 :  2.1.1 (OK)
diff_match_patch >=20181111          :  20200713 (OK)
intervaltree                         :  None (OK)
IPython >=7.31.1;<9.0.0              :  8.8.0 (OK)
jedi >=0.17.2;<0.19.0                :  0.18.2 (OK)
jellyfish >=0.7                      :  0.9.0 (OK)
jsonschema >=3.2.0                   :  4.17.3 (OK)
keyring >=17.0.0                     :  23.13.1 (OK)
nbconvert >=4.0                      :  7.2.8 (OK)
numpydoc >=0.6.0                     :  1.5.0 (OK)
paramiko >=2.4.0                     :  2.12.0 (OK)
parso >=0.7.0;<0.9.0                 :  0.8.3 (OK)
pexpect >=4.4.0                      :  4.8.0 (OK)
pickleshare >=0.4                    :  0.7.5 (OK)
psutil >=5.3                         :  5.9.4 (OK)
pygments >=2.0                       :  2.14.0 (OK)
pylint >=2.5.0;<3.0                  :  2.15.10 (OK)
pylint_venv >=2.1.1                  :  2.3.0 (OK)
pyls_spyder >=0.4.0                  :  0.4.0 (OK)
pylsp >=1.7.1;<1.8.0                 :  1.7.1 (OK)
pylsp_black >=1.2.0                  :  1.2.1 (OK)
qdarkstyle >=3.0.2;<3.1.0            :  3.0.3 (OK)
qstylizer >=0.2.2                    :  0.2.2 (OK)
qtawesome >=1.2.1                    :  1.2.2 (OK)
qtconsole >=5.4.0;<5.5.0             :  5.4.0 (OK)
qtpy >=2.1.0                         :  2.3.0 (OK)
rtree >=0.9.7                        :  1.0.1 (OK)
setuptools >=49.6.0                  :  66.0.0 (OK)
sphinx >=0.6.6                       :  6.1.3 (OK)
spyder_kernels >=2.4.2;<2.5.0        :  2.4.2 (OK)
textdistance >=4.2.0                 :  4.5.0 (OK)
three_merge >=0.1.1                  :  0.1.1 (OK)
watchdog                             :  2.2.1 (OK)
zmq >=22.1.0                         :  24.0.1 (OK)

# Optional:
cython >=0.21                        :  0.29.33 (OK)
matplotlib >=3.0.0                   :  3.6.3 (OK)
numpy >=1.7                          :  1.24.1 (OK)
pandas >=1.1.1                       :  1.5.2 (OK)
scipy >=0.17.0                       :  1.10.0 (OK)
sympy >=0.7.3                        :  1.11.1 (OK)

# Spyder plugins:
spyder_terminal.terminalplugin 1.2.2 :  1.2.2 (OK)

```
</details>


Discussion:

Resolving patch:
diff --git a/spyder/utils/programs.py b/spyder/utils/programs.py
--- a/spyder/utils/programs.py
+++ b/spyder/utils/programs.py
@@ -82,42 +82,32 @@ def is_program_installed(basename):
     """
     home = get_home_dir()
     req_paths = []
-    if sys.platform == 'darwin':
-        if basename.endswith('.app') and osp.exists(basename):
-            return basename
-
+    if (
+        sys.platform == 'darwin'
+        and basename.endswith('.app')
+        and osp.exists(basename)
+    ):
+        return basename
+
+    if os.name == 'posix':
         pyenv = [
+            osp.join(home, '.pyenv', 'bin'),
             osp.join('/usr', 'local', 'bin'),
-            osp.join(home, '.pyenv', 'bin')
         ]
 
-        # Prioritize Anaconda before Miniconda; local before global.
-        a = [osp.join(home, 'opt'), '/opt']
-        b = ['anaconda', 'miniconda', 'anaconda3', 'miniconda3']
-        conda = [osp.join(*p, 'condabin') for p in itertools.product(a, b)]
-
-        req_paths.extend(pyenv + conda)
-
-    elif sys.platform.startswith('linux'):
-        pyenv = [
-            osp.join('/usr', 'local', 'bin'),
-            osp.join(home, '.pyenv', 'bin')
-        ]
-
-        a = [home, '/opt']
-        b = ['anaconda', 'miniconda', 'anaconda3', 'miniconda3']
-        conda = [osp.join(*p, 'condabin') for p in itertools.product(a, b)]
-
-        req_paths.extend(pyenv + conda)
-
-    elif os.name == 'nt':
+        a = [home, osp.join(home, 'opt'), '/opt']
+        b = ['mambaforge', 'miniforge3', 'miniforge',
+             'miniconda3', 'anaconda3', 'miniconda', 'anaconda']
+    else:
         pyenv = [osp.join(home, '.pyenv', 'pyenv-win', 'bin')]
 
-        a = [home, 'C:\\', osp.join('C:\\', 'ProgramData')]
-        b = ['Anaconda', 'Miniconda', 'Anaconda3', 'Miniconda3']
-        conda = [osp.join(*p, 'condabin') for p in itertools.product(a, b)]
+        a = [home, osp.join(home, 'AppData', 'Local'),
+             'C:\\', osp.join('C:\\', 'ProgramData')]
+        b = ['Mambaforge', 'Miniforge3', 'Miniforge',
+             'Miniconda3', 'Anaconda3', 'Miniconda', 'Anaconda']
 
-        req_paths.extend(pyenv + conda)
+    conda = [osp.join(*p, 'condabin') for p in itertools.product(a, b)]
+    req_paths.extend(pyenv + conda)
 
     for path in os.environ['PATH'].split(os.pathsep) + req_paths:
         abspath = osp.join(path, basename)


Test patch: