Skip to content

Commit

Permalink
fix(inspect): Fixed an error that would raise when using get_history(…
Browse files Browse the repository at this point in the history
…) with lazy values (#1184)

This fixes the error by avoiding the attempt to evaluate altogheter.

get_history() should provide the original representation, so the user
can reliably inspect its data. The evaluted value might be hard to track
and potentially confusing to inspect.

Closes #1180
  • Loading branch information
pedro-psb authored Oct 4, 2024
1 parent 285c4f9 commit b23dac4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/flask.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ FlaskDynaconf(app)

Dynaconf transform nested data structures to a new DynaBox instance, this is an
object that allows dot notation access such as `app.config.key.value.other`.
However this feature is imcompatible with some Flask extensions, for example:
However this feature is incompatible with some Flask extensions, for example:
`Flask-Alembic`.

So in case you see a `BoxKeyError` when running your app with you can run it on
Expand Down
11 changes: 9 additions & 2 deletions dynaconf/utils/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from dynaconf.loaders.base import SourceMetadata
from dynaconf.utils.boxing import DynaBox
from dynaconf.utils.functional import empty
from dynaconf.utils.parse_conf import Lazy
from dynaconf.vendor.box.box_list import BoxList
from dynaconf.vendor.ruamel.yaml import YAML

Expand Down Expand Up @@ -322,13 +323,19 @@ def _get_data_by_key(
if sep in key_dotted_path:
key_dotted_path = key_dotted_path.replace(sep, ".")

def handle_repr(value):
# lazy values shouldnt be evaluated for inspecting
if isinstance(value, Lazy):
return value._dynaconf_encode()
return value

def traverse_data(data, path):
# transform `a.b.c` in successive calls to `data['a']['b']['c']`
path = path.split(".")
root_key, nested_keys = path[0], path[1:]
result = data[root_key]
result = data._safe_get(root_key)
for key in nested_keys:
result = result[key]
result = handle_repr(result._safe_get(key))
return result

try:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,37 @@ def test_get_history_env_and_key_filter(tmp_path):
assert history[1]["value"] == "from_prod_b"


def tests_get_history_with_variable_interpolation():
"""Variable interpolation is not evaluated.
https://github.com/dynaconf/dynaconf/issues/1180
The original issue was about an exception being raised when there was
variable interpolation involved. But in the end, the get_history shouldnt
evaluate the interpolations:
- History should accurately inform the order and content of what the user loaded.
- For a key with a interpolation value, the accurate representation is not the evaluated
value, but the original template string.
- The evaluated depends on other keys, so for
history inspecting it is more reliable to show what variables were used so the user
can verify if everything happened as expected.
"""
data = {
"a": {
"b": "foo",
"c": "bar",
"d": "@format {this.a.b} {this.a.c}",
}
}

settings = Dynaconf(**data)

assert settings.a.d == "foo bar"
history = get_history(settings, "a.d")
# shows the not-evaluated (raw) value
assert history[0]["value"] == "@format {this.a.b} {this.a.c}"


def test_caveat__get_history_env_true(tmp_path):
"""
Given environments=True and sources=file
Expand Down

0 comments on commit b23dac4

Please sign in to comment.