Repository: conda/conda

Issue:
Empty sequences for configuration parameters cannot be expressed in environment variables 
<!--
Hi!

This is an issue tracker for conda -- the package manager.  File feature requests
for conda here, as well as bug reports about something conda has messed up.

If your issue is a bug report or feature request for:
  * a specific conda package from Anaconda ('defaults' channel):
      ==> file at https://github.com/ContinuumIO/anaconda-issues
  * a specific conda package from conda-forge:
      ==> file at the corresponding feedstock under https://github.com/conda-forge
  * repo.continuum.io access and service:
      ==> file at https://github.com/ContinuumIO/anaconda-issues
  * anaconda.org access and service:
      ==> file at https://anaconda.org/contact/report
  * commands under 'conda build':
      ==> file at https://github.com/conda/conda-build
  * commands under 'conda env':
      ==> please file it here!
  * all other conda commands that start with 'conda':
      ==> please file it here!

-->

**I'm submitting a...**
  - [ ] bug report
  - [x] feature request


### Current Behavior
<!-- What actually happens? -->
For a configuration parameter that accepts sequences, an empty value in the corresponding environment variable gets interpreted as an one-element sequence containing an empty string, i.e., `[""]`. Thus there is no way to specify an empty sequence via an environment variable.

### Steps to Reproduce
<!-- If the current behavior is a bug, please provide specific, minimal steps to independently reproduce.
     Include the exact conda commands that reproduce the issue. -->
```bash
$ export CONDA_CHANNELS=
$ conda config --show channels
channels:
  - 
$ export CONDA_CHANNELS=defaults,
$ conda config --show channels
channels:
  - defaults
  - 
$ export CONDA_CHANNELS=defaults,,
$ conda config --show channels
channels:
  - defaults
  - 
```

### Expected Behavior
<!-- What do you think should happen? -->
One possibility to allow empty sequences would be to allow and ignore trailing separator, i.e., interpret
  * `,` as `[]`,
  *  `,,` as `[""]`,
  * `,,,` as `["", ""]`,
  * `defaults,` as `["defaults"]`,
  * `defaults,,` as `["defaults", ""]`.

The commands given above would then yield:
```bash
$ export CONDA_CHANNELS=
$ conda config --show channels
channels: []
$ export CONDA_CHANNELS=defaults,
$ conda config --show channels
channels:
  - defaults
$ export CONDA_CHANNELS=defaults,,
$ conda config --show channels
channels:
  - defaults
  - 
```

##### `conda info`
<!-- between the ticks below, paste the output of 'conda info' -->
```
     active environment : base
    active env location : /home/maba/code/conda/conda-4.4
            shell level : 1
       user config file : /home/maba/.condarc
 populated config files : /home/maba/code/conda/conda-4.4/.condarc
          conda version : 4.4.7
    conda-build version : not installed
         python version : 3.6.4.final.0
       base environment : /home/maba/code/conda/conda-4.4  (writable)
           channel URLs : https://repo.continuum.io/pkgs/main/linux-64
                          https://repo.continuum.io/pkgs/main/noarch
                          https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/linux-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
          package cache : /home/maba/code/conda/conda-4.4/pkgs
                          /home/maba/.conda/pkgs
       envs directories : /home/maba/code/conda/conda-4.4/envs
                          /home/maba/.conda/envs
               platform : linux-64
             user-agent : conda/4.4.7 requests/2.18.4 CPython/3.6.4 Linux/4.14.12-1-MANJARO manjaro/17.1-dev glibc/2.26
                UID:GID : 1000:1000
             netrc file : None
           offline mode : False
```


##### `conda config --show-sources`
<!-- between the ticks below, paste the output of 'conda config --show-sources' -->
(not needed)


##### `conda list --show-channel-urls`
<!-- between the ticks below, paste the output of 'conda list --show-channel-urls' -->
(not needed)



Discussion:
I think this is the first template we’ve actually had filled out. Like, wow, this is awesome! 👍

Sent from my iPhone

> On Jan 14, 2018, at 5:00 PM, Marcel Bargull <notifications@github.com> wrote:
> 
> I'm submitting a...
> 
>  bug report
>  feature request
> Current Behavior
> 
> For a configuration parameter that accepts sequences, an empty value in the corresponding environment variable gets interpreted as an one-element sequence containing an empty string, i.e., [""]. Thus there is no way to specify an empty sequence via an environment variable.
> 
> Steps to Reproduce
> 
> $ export CONDA_CHANNELS=
> $ conda config --show channels
> channels:
>   - 
> $ export CONDA_CHANNELS=defaults,
> $ conda config --show channels
> channels:
>   - defaults
>   - 
> $ export CONDA_CHANNELS=defaults,,
> $ conda config --show channels
> channels:
>   - defaults
>   - 
> Expected Behavior
> 
> One possibility to allow empty sequences would be to allow and ignore trailing separator, i.e., interpret
> 
> , as [],
> ,, as [""],
> ,,, as ["", ""],
> defaults, as ["defaults"],
> defaults,, as ["defaults", ""].
> The commands given above would then yield:
> 
> $ export CONDA_CHANNELS=
> $ conda config --show channels
> channels: []
> $ export CONDA_CHANNELS=defaults,
> $ conda config --show channels
> channels:
>   - defaults
> $ export CONDA_CHANNELS=defaults,,
> $ conda config --show channels
> channels:
>   - defaults
>   - 
> conda info
> 
>      active environment : base
>     active env location : /home/maba/code/conda/conda-4.4
>             shell level : 1
>        user config file : /home/maba/.condarc
>  populated config files : /home/maba/code/conda/conda-4.4/.condarc
>           conda version : 4.4.7
>     conda-build version : not installed
>          python version : 3.6.4.final.0
>        base environment : /home/maba/code/conda/conda-4.4  (writable)
>            channel URLs : https://repo.continuum.io/pkgs/main/linux-64
>                           https://repo.continuum.io/pkgs/main/noarch
>                           https://repo.continuum.io/pkgs/free/linux-64
>                           https://repo.continuum.io/pkgs/free/noarch
>                           https://repo.continuum.io/pkgs/r/linux-64
>                           https://repo.continuum.io/pkgs/r/noarch
>                           https://repo.continuum.io/pkgs/pro/linux-64
>                           https://repo.continuum.io/pkgs/pro/noarch
>           package cache : /home/maba/code/conda/conda-4.4/pkgs
>                           /home/maba/.conda/pkgs
>        envs directories : /home/maba/code/conda/conda-4.4/envs
>                           /home/maba/.conda/envs
>                platform : linux-64
>              user-agent : conda/4.4.7 requests/2.18.4 CPython/3.6.4 Linux/4.14.12-1-MANJARO manjaro/17.1-dev glibc/2.26
>                 UID:GID : 1000:1000
>              netrc file : None
>            offline mode : False
> conda config --show-sources
> 
> (not needed)
> 
> conda list --show-channel-urls
> 
> (not needed)
> 
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub, or mute the thread.
> 


Resolving patch:
diff --git a/conda/common/configuration.py b/conda/common/configuration.py
--- a/conda/common/configuration.py
+++ b/conda/common/configuration.py
@@ -206,14 +206,12 @@ class EnvRawParameter(RawParameter):
 
     def value(self, parameter_obj):
         if hasattr(parameter_obj, 'string_delimiter'):
+            assert isinstance(self._raw_value, string_types)
             string_delimiter = getattr(parameter_obj, 'string_delimiter')
             # TODO: add stripping of !important, !top, and !bottom
-            raw_value = self._raw_value
-            if string_delimiter in raw_value:
-                value = raw_value.split(string_delimiter)
-            else:
-                value = [raw_value]
-            return tuple(v.strip() for v in value)
+            return tuple(v for v in (
+                vv.strip() for vv in self._raw_value.split(string_delimiter)
+            ) if v)
         else:
             return self.__important_split_value[0].strip()
 


Test patch:
diff --git a/tests/common/test_configuration.py b/tests/common/test_configuration.py
--- a/tests/common/test_configuration.py
+++ b/tests/common/test_configuration.py
@@ -241,6 +241,21 @@ def make_key(appname, key):
         finally:
             [environ.pop(key) for key in test_dict]
 
+    def test_env_var_config_empty_sequence(self):
+        def make_key(appname, key):
+            return "{0}_{1}".format(appname.upper(), key.upper())
+        appname = "myapp"
+        test_dict = {}
+        test_dict[make_key(appname, 'channels')] = ''
+
+        try:
+            environ.update(test_dict)
+            assert 'MYAPP_CHANNELS' in environ
+            config = SampleConfiguration()._set_env_vars(appname)
+            assert config.channels == ()
+        finally:
+            [environ.pop(key) for key in test_dict]
+
     def test_load_raw_configs(self):
         try:
             tempdir = mkdtemp()