Repository: joke2k/django-environ

Issue:
Attach cause to ImproperlyConfigured exception raised for missing environment variables
I'd like to propose to add the original exception as the cause of the `ImproperlyConfigured` exception that's raised when an environment variable is missing using `raise ... from ...`:

```py
        try:
            value = self.ENVIRON[var]
        except KeyError as exc:
            if default is self.NOTSET:
                error_msg = "Set the {} environment variable".format(var)
                raise ImproperlyConfigured(error_msg) from exc
```

The original:

https://github.com/joke2k/django-environ/blob/509cf7737363a56e4464962dbae4ab72b801c7b3/environ/environ.py#L366-L371

Note: Since it's a two-line change, I've opened #361 to introduce this change. I know that the proposal hasn't been discussed yet, but I figured not a lot of work is lost if it's rejected.

## Background
The main difference is that this will mark the original `KeyError` as the explicit cause of the `ImproperlyConfigered`, instead of marking the `ImproperlyConfigured` as another exception that "happened to happen" during the handling of the `KeyError`. (A better explanation is given by Martijn Pieters [here](https://stackoverflow.com/questions/24752395/python-raise-from-usage/24752607#24752607)).


## Differences for end-users
The most notable difference is the output. The proposed change would change the traceback output to:

```python-traceback
Traceback (most recent call last):
  (...)
KeyError: 'missing_key'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  (...)
environ.compat.ImproperlyConfigured: Set the missing_key environment variable
```

instead of 

```python-traceback
Traceback (most recent call last):
  (...)
KeyError: 'missing_key'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  (...)
environ.compat.ImproperlyConfigured: Set the missing_key environment variable
```

Notice that the middle line that indicates the relationship between the two exceptions has changed.

Additionally, the original exception will now be attached to the `ImproperlyConfigured` exception under the `__cause__` attribute instead of the `__context__` attribute.

Discussion:

Patch:
diff --git a/environ/environ.py b/environ/environ.py
index acdfb15..5eb6b78 100644
--- a/environ/environ.py
+++ b/environ/environ.py
@@ -365,10 +365,10 @@ class Env:
 
         try:
             value = self.ENVIRON[var]
-        except KeyError:
+        except KeyError as exc:
             if default is self.NOTSET:
                 error_msg = "Set the {} environment variable".format(var)
-                raise ImproperlyConfigured(error_msg)
+                raise ImproperlyConfigured(error_msg) from exc
 
             value = default
 


Test patch:
diff --git a/tests/test_env.py b/tests/test_env.py
index 59110e3..d154708 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -45,6 +45,7 @@ class TestEnv:
         with pytest.raises(ImproperlyConfigured) as excinfo:
             self.env('not_present')
         assert str(excinfo.value) == 'Set the not_present environment variable'
+        assert excinfo.value.__cause__ is not None
 
     def test_contains(self):
         assert 'STR_VAR' in self.env