Repository: capless/envs

Issue:
Incompatible with click>=8.0
Updating click to 8.0 and later breaks the tests, because raw_input isn't exposed via compats anymore.

```
======================================================================
ERROR: util (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: util
Traceback (most recent call last):
  File "/nix/store/2nhfiak8a30vw67mxksc2kdb69np2jcw-python3-3.8.9/lib/python3.8/unittest/loader.py", line 154, in loadTestsFromName
    module = __import__(module_name)
  File "/build/envs-1.3/envs/util.py", line 7, in <module>
    from click._compat import raw_input
ImportError: cannot import name 'raw_input' from 'click._compat' (/nix/store/s6a73ssai10wpz50nnk2cy3k48wydl05-python3.8-click-8.0.1/lib/python3.8/site-packages/click/_compat.py)


======================================================================
ERROR: cli (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: cli
Traceback (most recent call last):
  File "/nix/store/2nhfiak8a30vw67mxksc2kdb69np2jcw-python3-3.8.9/lib/python3.8/unittest/loader.py", line 154, in loadTestsFromName
    module = __import__(module_name)
  File "/build/envs-1.3/envs/cli.py", line 10, in <module>
    from .util import convert_module, import_mod, list_envs_module, raw_input
  File "/build/envs-1.3/envs/util.py", line 7, in <module>
    from click._compat import raw_input
ImportError: cannot import name 'raw_input' from 'click._compat' (/nix/store/s6a73ssai10wpz50nnk2cy3k48wydl05-python3.8-click-8.0.1/lib/python3.8/site-packages/click/_compat.py)


----------------------------------------------------------------------
Ran 20 tests in 0.005s

FAILED (errors=2)
```

Comments:

Patch:
diff --git a/envs/__init__.py b/envs/__init__.py
index 9d6bbce..4a0b860 100644
--- a/envs/__init__.py
+++ b/envs/__init__.py
@@ -48,12 +48,14 @@ class Env(object):
                 json.dump({'key': key, 'var_type': var_type, 'default': default, 'value': os.getenv(key)}, f)
                 f.write(',')
         value = os.getenv(key, default)
-        if not value and not allow_none:
-            raise EnvsValueException('{}: Environment Variable Not Set'.format(key))
         if not var_type in self.valid_types.keys():
             raise ValueError(
                 'The var_type argument should be one of the following {0}'.format(
                     ','.join(self.valid_types.keys())))
+        if value is None:
+            if not allow_none:
+                raise EnvsValueException('{}: Environment Variable Not Set'.format(key))
+            return value
         return self.validate_type(value, self.valid_types[var_type], key)
 
     def validate_type(self, value, klass, key):
diff --git a/envs/util.py b/envs/util.py
index ab0f58c..adabc60 100644
--- a/envs/util.py
+++ b/envs/util.py
@@ -4,12 +4,12 @@ import json
 import os
 import sys
 
-from click._compat import raw_input
-
 from . import Env, ENVS_RESULT_FILENAME
 
 VAR_TYPES = Env.valid_types.keys()
 
+if sys.version_info >= (3, 0):
+    raw_input = input
 
 def import_util(imp):
     """


Test patch:
diff --git a/envs/tests.py b/envs/tests.py
index 741ad43..1b066df 100644
--- a/envs/tests.py
+++ b/envs/tests.py
@@ -14,6 +14,7 @@ except ImportError:
 import sys
 
 from envs import env
+from envs.exceptions import EnvsValueException
 
 class EnvTestCase(unittest.TestCase):
     def setUp(self):
@@ -113,6 +114,40 @@ class EnvTestCase(unittest.TestCase):
         self.assertEqual(env('HELLO', 'true', var_type='boolean'), True)
         self.assertEqual(env('HELLO', Decimal('3.14'), var_type='decimal'), Decimal('3.14'))
 
+    def test_without_defaults_allow_none(self):
+        self.assertEqual(env('HELLO'), None)
+        self.assertEqual(env('HELLO', var_type='integer'), None)
+        self.assertEqual(env('HELLO', var_type='float'), None)
+        self.assertEqual(env('HELLO', var_type='list'), None)
+
+    def test_without_defaults_disallow_none(self):
+        with self.assertRaises(EnvsValueException):
+            env('HELLO', allow_none=False)
+        with self.assertRaises(EnvsValueException):
+            env('HELLO', var_type='integer', allow_none=False)
+        with self.assertRaises(EnvsValueException):
+            env('HELLO', var_type='float', allow_none=False)
+        with self.assertRaises(EnvsValueException):
+            env('HELLO', var_type='list', allow_none=False)
+
+    def test_empty_values(self):
+        os.environ.setdefault('EMPTY', '')
+        self.assertEqual(env('EMPTY'), '')
+        with self.assertRaises(SyntaxError):
+            env('EMPTY', var_type='integer')
+        with self.assertRaises(SyntaxError):
+            env('EMPTY', var_type='float')
+        with self.assertRaises(SyntaxError):
+            env('EMPTY', var_type='list')
+        with self.assertRaises(SyntaxError):
+            env('EMPTY', var_type='dict')
+        with self.assertRaises(SyntaxError):
+            env('EMPTY', var_type='tuple')
+        with self.assertRaises(ValueError):
+            env('EMPTY', var_type='boolean')
+        with self.assertRaises(ArithmeticError):
+            env('EMPTY', var_type='decimal')
+
 '''
 Each CLI Test must be run outside of test suites in isolation
 since Click CLI Runner alters the global context