Repository: omegaml/omegaml

Issue:
env variables can end up having 'None' instead of not being set
*Currently*

* a variable in os.environ can end up having "None" set as a value
* `AuthenticationEnv.prepare_env` is used to prepared a runtime process's os.environ
* it uses values from om.defaults, cleaning the environ from parent process inherited
  envs. in doing so, a value of (Python) None is set as "None" instead of '' (blank)

*Expected*

1. set None-valued variables to '' (blank)

Discussion:

Solution patch:
diff --git a/omegaml/client/auth.py b/omegaml/client/auth.py
index 53b796398..5bbe97529 100644
--- a/omegaml/client/auth.py
+++ b/omegaml/client/auth.py
@@ -1,9 +1,7 @@
 import os
-
-from requests.auth import AuthBase
-
 from omegaml import session_cache
 from omegaml.util import load_class, settings, DefaultsContext
+from requests.auth import AuthBase
 
 
 class OmegaRestApiAuth(AuthBase):
@@ -165,8 +163,14 @@ class AuthenticationEnv(object):
         for k in defaults or cls.env_keys:
             if not k.isupper():
                 continue
+            # if k in cls.env_keys and not clear:
             if k in cls.env_keys and not clear:
-                envstr = lambda v: str(int(v) if isinstance(v, bool) else v)
+                # prepare a valid env value
+                # -- boolean => 0/1
+                # -- None => '' (empty string), avoid setting as 'None' (#414)
+                # -- any False value => '' (empty string)
+                # -- otherwise str(v)
+                envstr = lambda v: str(int(v) if isinstance(v, bool) else (v or ''))
                 os.environ[k] = envstr(defaults[k])
             else:
                 os.environ.pop(k, None)


Test patch:
diff --git a/omegaml/tests/core/test_configs.py b/omegaml/tests/core/test_configs.py
index d190ca2d7..94f490f1f 100644
--- a/omegaml/tests/core/test_configs.py
+++ b/omegaml/tests/core/test_configs.py
@@ -1,10 +1,11 @@
-from io import StringIO
 from unittest import TestCase
-from unittest.mock import patch
 
+import os
+from io import StringIO
 from omegaml import Omega
 from omegaml.client.auth import AuthenticationEnv
 from omegaml.defaults import update_from_config, update_from_obj, update_from_dict
+from unittest.mock import patch
 
 
 class BareObj(object):
@@ -185,3 +186,25 @@ class ConfigurationTests(TestCase):
         else:
             not_raised = True
         self.assertTrue(not_raised)
+
+    def test_auth_env_setup(self):
+        # setup a new Omega instance
+        # -- test fix #414
+        # -- we set OMEGA_BROKER to None to ensure it is cleared
+        om = Omega()
+        om.defaults.OMEGA_BROKER = None
+        self.assertTrue(om.runtime.omega.defaults.OMEGA_BROKER is None)
+        auth_env = AuthenticationEnv.active()
+        env = dict(os.environ)
+        # check prepare_env() clears OMEGA_BROKER
+        # -- start with $OMEGA_BROKER set to a value
+        # -- prepare_env() should clear it to be '' (blank)
+        # -- prepare_env(clear=True) should pop it
+        # -- finally the original env is unchanged
+        with patch('os.environ', new=dict(OMEGA_BROKER='foo')):
+            self.assertEqual(os.environ['OMEGA_BROKER'], 'foo')
+            auth_env.prepare_env(om.defaults)
+            self.assertEqual(os.environ['OMEGA_BROKER'], '')
+            auth_env.prepare_env(om.defaults, clear=True)
+            self.assertNotIn('OMEGA_BROKER', os.environ)
+        self.assertEqual(env, os.environ)