Skip to content

Commit

Permalink
Fix #445 casting on dottet get. (#446)
Browse files Browse the repository at this point in the history
* Fix #445 casting on dottet get.

Fix the rebound of `cast` on dotted get.

Fix #445

* better handling of casting data
  • Loading branch information
rochacbruno committed Oct 9, 2020
1 parent 9a5fcd7 commit 2071842
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 3 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -106,6 +106,7 @@ test_examples:
cd example/issues/434_setenv;pwd;python app.py --config development dynaconf
cd example/issues/430_same_name;pwd;python app.py
cd example/issues/443_object_merge;pwd;python app.py
cd example/issues/445_casting;pwd;python app.py

test_vault:
# @cd example/vault;pwd;python write.py
Expand Down
16 changes: 13 additions & 3 deletions dynaconf/base.py
Expand Up @@ -351,7 +351,9 @@ def as_dict(self, env=None, internal=False):

to_dict = as_dict # backwards compatibility

def _dotted_get(self, dotted_key, default=None, parent=None, **kwargs):
def _dotted_get(
self, dotted_key, default=None, parent=None, cast=None, **kwargs
):
"""
Perform dotted key lookups and keep track of where we are.
:param key: The name of the setting value, will always be upper case
Expand All @@ -364,11 +366,15 @@ def _dotted_get(self, dotted_key, default=None, parent=None, **kwargs):

# If we've reached the end, or parent key not found, then return result
if not keys or result == default:
if cast and cast in converters:
return get_converter(cast, result, box_settings=self)
elif cast is True:
return parse_conf_data(result, tomlfy=True, box_settings=self)
return result

# If we've still got key elements to traverse, let's do that.
return self._dotted_get(
".".join(keys), default=default, parent=result, **kwargs
".".join(keys), default=default, parent=result, cast=cast, **kwargs
)

def get(
Expand All @@ -394,6 +400,10 @@ def get(
:param parent: Is there a pre-loaded parent in a nested data?
:return: The value if found, default or None
"""
nested_sep = self._store.get("NESTED_SEPARATOR_FOR_DYNACONF")
if nested_sep and nested_sep in key:
# turn FOO__bar__ZAZ in `FOO.bar.ZAZ`
key = key.replace(nested_sep, ".")

if "." in key and dotted_lookup:
return self._dotted_get(
Expand Down Expand Up @@ -458,7 +468,7 @@ def get_environ(self, key, default=None, cast=None):
if data:
if cast in converters:
data = get_converter(cast, data, box_settings=self)
if cast is True:
elif cast is True:
data = parse_conf_data(data, tomlfy=True, box_settings=self)
return data

Expand Down
2 changes: 2 additions & 0 deletions dynaconf/utils/__init__.py
Expand Up @@ -47,6 +47,8 @@ def object_merge(old, new, unique=False, full_path=None):
and key == full_path[-1]
and existing_value is value
):
# Here Be The Dragons
# This comparison needs to be smarter
continue

if key not in new:
Expand Down
1 change: 1 addition & 0 deletions example/issues/445_casting/.env
@@ -0,0 +1 @@
export DYNACONF_UPSTREAM_ROOK__BUILD_ROOK_FROM_GIT=TRUE
48 changes: 48 additions & 0 deletions example/issues/445_casting/README.md
@@ -0,0 +1,48 @@
# [bug] Casting does not work with Box'd settings (eg dicts)

* created by @jhesketh on 2020-10-08 12:01:21 +0000 UTC

**Describe the bug**
Using any of the cast or "as_bool" etc methods do not work with nested/boxed settings.

**To Reproduce**

<details>
<summary> Python interpreter </summary>

```python

>>> settings.UPSTREAM_ROOK
<Box: {'BUILD_ROOK_FROM_GIT': 'TRUE'}>
>>> settings.UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT
'TRUE'
>>> settings.as_bool('UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT')
False
>>> settings.get('UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT')
'TRUE'
>>> settings.get('UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT', cast="@bool")
False

```
</details>

2. Having the following config files:

<!-- Please adjust if you are using different files and formats! -->

<details>
<summary> Config files </summary>

```
[upstream_rook]
build_rook_from_git = true
```


</details>


**Expected behavior**

`settings.as_bool('UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT')` returns `True`.

11 changes: 11 additions & 0 deletions example/issues/445_casting/app.py
@@ -0,0 +1,11 @@
from dynaconf import Dynaconf

settings = Dynaconf(load_dotenv=True)

assert settings.get("UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT") == "TRUE"

assert (
settings.as_bool("UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT") is True
), settings.as_bool("UPSTREAM_ROOK.BUILD_ROOK_FROM_GIT")

assert settings.get("UPSTREAM_ROOK__BUILD_ROOK_FROM_GIT", cast="@bool") is True

0 comments on commit 2071842

Please sign in to comment.