Repository: rochacbruno/dynaconf
Pull request #192 (2019-05-07 13:16:44)

Catch BoxKeyError when contents are TOML-parsable but not keyable
I discovered what I would consider a bug, but @rochacbruno, you may correct me here, maybe this is expected behavior:

When an env var contains contents that are technically TOML-parsable but can not be retrieved from the (Dyna)Box, that raises a BoxKeyError, and causes the entire env_loader to drop out and parse none of the env vars at all.

To reproduce:

```bash
export DYNACONF_SOME_VAR="something=42"
python -c 'from dynaconf import settings; print(settings.SOME_VAR)'
```
Throws:

```
2019-05-07:15:13:29,634 ERROR    [env_loader.py:55 - load_from_env] "'DynaBox' object has no attribute 'KEY'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/jan/Library/Caches/pypoetry/virtualenvs/protagonist-py3.7/lib/python3.7/site-packages/dynaconf/base.py", line 107, in __getattr__
    return getattr(self._wrapped, name)
AttributeError: 'Settings' object has no attribute 'SOME_VAR'
```

This PR catches the occurring BoxKeyError in `dynaconf.utils.parse_conf.parse_with_toml()`, which passes the unmodified value of the env var (`something=42` in the example above) into the settings (which I'd consider expected behavior).

codecov[bot]: # [Codecov](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=h1) Report
> Merging [#192](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=desc) into [master](https://codecov.io/gh/rochacbruno/dynaconf/commit/5a7cc8f8252251cbdf4f4112965801f9dfe2831d?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/rochacbruno/dynaconf/pull/192/graphs/tree.svg?width=650&token=GXszVzJcqW&height=150&src=pr)](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master   #192   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          18     18           
  Lines         736    737    +1     
=====================================
+ Hits          736    737    +1
```


| [Impacted Files](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [dynaconf/utils/parse\_conf.py](https://codecov.io/gh/rochacbruno/dynaconf/pull/192/diff?src=pr&el=tree#diff-ZHluYWNvbmYvdXRpbHMvcGFyc2VfY29uZi5weQ==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=footer). Last update [5a7cc8f...7dc7e01](https://codecov.io/gh/rochacbruno/dynaconf/pull/192?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/dynaconf/utils/parse_conf.py b/dynaconf/utils/parse_conf.py
index dddd7ce..bce36e1 100644
--- a/dynaconf/utils/parse_conf.py
+++ b/dynaconf/utils/parse_conf.py
@@ -2,10 +2,10 @@ import json
 import os
 
 import toml
+from box import BoxKeyError
 
 from dynaconf.utils.boxing import DynaBox
 
-
 true_values = ("t", "true", "enabled", "1", "on", "yes", "True")
 false_values = ("f", "false", "disabled", "0", "off", "no", "False", "")
 
@@ -29,7 +29,7 @@ def parse_with_toml(data):
     """Uses TOML syntax to parse data"""
     try:
         return toml.loads("key={}".format(data), DynaBox).key
-    except toml.TomlDecodeError:
+    except (toml.TomlDecodeError, BoxKeyError):
         return data
 
 


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
index e5c0bf5..0a11069 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,6 +1,8 @@
 import io
 import os
 
+import pytest
+
 from dynaconf import default_settings
 from dynaconf.utils import ensure_a_list
 from dynaconf.utils import Missing
@@ -94,6 +96,11 @@ def test_tomlfy():
     }
 
 
+@pytest.mark.parametrize("test_input", ["something=42"])
+def test_tomlfy_unparseable(test_input):
+    assert parse_conf_data(test_input, tomlfy=True) == test_input
+
+
 def test_missing_sentinel():
 
     # The missing singleton should always compare truthfully to itself