Repository: spyder-ide/spyder

Issue:
Conda Environment Status Shows Full Path
## Problem Description
@steff456 
Environment status shows full path to conda environment, rather than just environment name.
Pyenv environment status shows correctly.

<img width="528" alt="Screen Shot 2020-11-03 at 8 40 33 AM" src="https://user-images.githubusercontent.com/9618975/98029880-126f9f00-1dc5-11eb-9e03-16ab80b02792.png">
<img width="262" alt="Screen Shot 2020-11-03 at 8 40 51 AM" src="https://user-images.githubusercontent.com/9618975/98029893-16032600-1dc5-11eb-9645-644cf1814580.png">

## 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: 4.2.0.dev0 0dfbe8967
* Python version: 3.7.9 64-bit
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Darwin 19.6.0

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```

# Mandatory:
applaunchservices >=0.1.7      :  0.2.1 (OK)
atomicwrites >=1.2.0           :  1.4.0 (OK)
chardet >=2.0.0                :  3.0.4 (OK)
cloudpickle >=0.5.0            :  1.6.0 (OK)
diff_match_patch >=20181111    :  20200713 (OK)
intervaltree >=3.0.2           :  3.1.0 (OK)
IPython >=4.0                  :  7.18.1 (OK)
jedi =0.17.2                   :  0.17.2 (OK)
jsonschema >=3.2.0             :  3.2.0 (OK)
nbconvert >=4.0                :  6.0.7 (OK)
numpydoc >=0.6.0               :  1.1.0 (OK)
parso =0.7.0                   :  0.7.0 (OK)
pexpect >=4.4.0                :  4.8.0 (OK)
pickleshare >=0.4              :  0.7.5 (OK)
psutil >=5.3                   :  5.7.2 (OK)
pygments >=2.0                 :  2.7.2 (OK)
pylint >=1.0                   :  2.6.0 (OK)
pyls >=0.35.0;<1.0.0           :  test-selector-01+92.g0dfbe8967 (OK)
pyls_black >=0.4.6             :  0.4.6 (OK)
pyls_spyder >=0.1.1            :  0.1.1 (OK)
qdarkstyle >=2.8               :  2.8.1 (OK)
qtawesome >=0.5.7              :  1.0.1 (OK)
qtconsole >=4.7.7              :  4.7.7 (OK)
qtpy >=1.5.0                   :  1.9.0 (OK)
rtree >=0.8.3                  :  0.9.4 (OK)
setuptools >=39.0.0            :  50.3.0.post20201006 (OK)
sphinx >=0.6.6                 :  3.2.1 (OK)
spyder_kernels >=1.9.4;<1.10.0 :  1.10.0.dev0 (OK)
three_merge >=0.1.1            :  0.1.1 (OK)
watchdog >=0.10.3              :  0.10.3 (OK)
zmq >=17                       :  19.0.2 (OK)

# Optional:
cython >=0.21                  :  0.29.21 (OK)
matplotlib >=2.0.0             :  3.3.2 (OK)
numpy >=1.7                    :  1.19.2 (OK)
pandas >=1.1.1                 :  1.1.3 (OK)
scipy >=0.17.0                 :  1.5.2 (OK)
sympy >=0.7.3                  :  1.6.2 (OK)
```



Discussion:

Resolving patch:
diff --git a/spyder/utils/conda.py b/spyder/utils/conda.py
--- a/spyder/utils/conda.py
+++ b/spyder/utils/conda.py
@@ -14,7 +14,7 @@
 import sys
 
 from spyder.config.base import running_in_mac_app, get_home_dir
-from spyder.utils.programs import find_program
+from spyder.utils.programs import find_program, run_shell_command
 
 
 WINDOWS = os.name == 'nt'
@@ -105,37 +105,20 @@ def get_conda_env_path(pyexec, quote=False):
 
 def get_list_conda_envs():
     """Return the list of all conda envs found in the system."""
-    conda_list = ['conda', 'env', 'list', '--json']
-    if running_in_mac_app():
-        # set PATHs for finding conda
-        old_path = os.environ['PATH']
-        home = get_home_dir()
-        os.environ['PATH'] = os.pathsep.join([
-            old_path,
-            os.path.join(home, 'opt', 'anaconda3', 'condabin'),
-            # could have miniconda
-            os.path.join(home, 'opt', 'miniconda3', 'condabin'),
-            # could be installed for all users
-            os.path.join('/opt', 'anaconda3', 'condabin'),
-            os.path.join('/opt', 'miniconda3', 'condabin')
-        ])
-        conda_path = find_program('conda')
-        os.environ['PATH'] = old_path  # restore PATH
-        if conda_path:
-            conda_list = [conda_path, 'env', 'list', '--json']
+    env_list = {}
+    conda = find_program('conda')
+    if conda is None:
+        return env_list
+
+    cmdstr = ' '.join([conda, 'env', 'list', '--json'])
     try:
-        out, err = subprocess.Popen(
-            conda_list,
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE
-        ).communicate()
+        out, err = run_shell_command(cmdstr, env={}).communicate()
         out = out.decode()
         err = err.decode()
         out = json.loads(out)
     except Exception:
         out = {'envs': []}
         err = ''
-    env_list = {}
     for env in out['envs']:
         name = env.split('/')[-1]
         try:
diff --git a/spyder/utils/programs.py b/spyder/utils/programs.py
--- a/spyder/utils/programs.py
+++ b/spyder/utils/programs.py
@@ -71,17 +71,49 @@ def get_temp_dir(suffix=None):
 def is_program_installed(basename):
     """
     Return program absolute path if installed in PATH.
+    Otherwise, return None.
 
-    Otherwise, return None
+    Also searches specific platform dependent paths that are not already in
+    PATH. This permits general use without assuming user profiles are
+    sourced (e.g. .bash_Profile), such as when login shells are not used to
+    launch Spyder.
 
-    On macOS systems, a .app is considered installed if
-    it exists.
+    On macOS systems, a .app is considered installed if it exists.
     """
-    if (sys.platform == 'darwin' and basename.endswith('.app') and
-            osp.exists(basename)):
-        return basename
+    home = get_home_dir()
+    req_paths = []
+    if sys.platform == 'darwin':
+        if basename.endswith('.app') and osp.exists(basename):
+            return basename
+
+        pyenv = [osp.join('/usr', 'local', 'bin')]
+
+        # prioritize anaconda before miniconda; local before global
+        a = [osp.join(home, 'opt'), '/opt']
+        b = ['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')]
+
+        a = [home, '/opt']
+        b = ['anacona3', 'miniconda3']
+        conda = [osp.join(*p, 'condabin') for p in itertools.product(a, b)]
+
+        req_paths.extend(pyenv + conda)
+
+    elif WINDOWS:
+        pyenv = [osp.join(home, '.pyenv', 'pyenv-win', 'bin')]
 
-    for path in os.environ["PATH"].split(os.pathsep):
+        a = [home, 'C:', osp.join('C:', 'ProgramData')]
+        b = ['Anaconda3', 'Miniconda3']
+        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)
         if osp.isfile(abspath):
             return abspath
@@ -156,6 +188,11 @@ def alter_subprocess_kwargs_by_platform(**kwargs):
                         break  # don't risk multiple values
                 if sys_root_key is not None:
                     kwargs['env'].update({sys_root_key: os.environ[sys_root_key]})
+    else:
+        # linux and macOS
+        if kwargs.get('env') is not None:
+            if 'HOME' not in kwargs['env']:
+                kwargs['env'].update({'HOME': get_home_dir()})
 
     return kwargs
 
@@ -1026,27 +1063,20 @@ def get_pyenv_path(name):
 
 def get_list_pyenv_envs():
     """Return the list of all pyenv envs found in the system."""
-    pyenv = 'pyenv'
-    if running_in_mac_app():
-        old_path = os.environ['PATH']
-        os.environ['PATH'] = os.pathsep.join([old_path, '/usr/local/bin'])
-        pyenv_path = find_program('pyenv')
-        os.environ['PATH'] = old_path  # restore PATH
-        if pyenv_path:
-            pyenv = pyenv_path
+    env_list = {}
+    pyenv = find_program('pyenv')
+    if pyenv is None:
+        return env_list
+
+    cmdstr = ' '.join([pyenv, 'versions', '--bare', '--skip-aliases'])
     try:
-        out, err = subprocess.Popen(
-            [pyenv, 'versions', '--bare', '--skip-aliases'],
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE
-        ).communicate()
+        out, err = run_shell_command(cmdstr, env={}).communicate()
         out = out.decode()
         err = err.decode()
     except Exception:
         out = ''
         err = ''
     out = out.split('\n')
-    env_list = {}
     for env in out:
         data = env.split('/')
         path = get_pyenv_path(data[-1])


Test patch: