Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse negative numbers from envvar Fix #799 and Fix #585 #802

Merged
merged 1 commit into from Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -133,6 +133,7 @@ test_examples:
cd example/issues/741_envvars_ignored;pwd;sh recreate.sh
cd example/issues/705_flask_dynaconf_init;pwd;make test;make clean
cd example/issues/794_includes;pwd;python app.py
cd example/issues/799_negative_numbers;pwd;DYNACONF_NUM="-1" python app.py

test_vault:
# @cd example/vault;pwd;python write.py
Expand Down
8 changes: 0 additions & 8 deletions dynaconf/utils/parse_conf.py
Expand Up @@ -356,7 +356,6 @@ def parse_conf_data(data, tomlfy=False, box_settings=None):
box_settings = box_settings or {}

if isinstance(data, (tuple, list)):

# recursively parse each sequence item
return [
parse_conf_data(item, tomlfy=tomlfy, box_settings=box_settings)
Expand All @@ -372,13 +371,6 @@ def parse_conf_data(data, tomlfy=False, box_settings=None):
)
return _parsed

if (
isinstance(data, str)
and data.startswith(("+", "-"))
and data[1:].isdigit()
):
return data

# return parsed string value
return _parse_conf_data(data, tomlfy=tomlfy, box_settings=box_settings)

Expand Down
17 changes: 17 additions & 0 deletions dynaconf/validator.py
Expand Up @@ -135,6 +135,9 @@ def __init__(
self.envs: Sequence[str] | None = None
self.apply_default_on_none = apply_default_on_none

# See #585
self.is_type_of = operations.get("is_type_of")

if isinstance(env, str):
self.envs = [env]
elif isinstance(env, (list, tuple)):
Expand Down Expand Up @@ -243,6 +246,20 @@ def _validate_items(
else:
default_value = empty

# THIS IS A FIX FOR #585 in contrast with #799
# toml considers signed strings "+-1" as integers
# however existing users are passing strings
# to default on validator (see #585)
# The solution we added on #667 introduced a new problem
# This fix here makes it to work for both cases.
if (
isinstance(default_value, str)
and default_value.startswith(("+", "-"))
and self.is_type_of is str
):
# avoid TOML from parsing "+-1" as integer
default_value = f"'{default_value}'"

value = self.cast(
settings.setdefault(
name,
Expand Down
11 changes: 11 additions & 0 deletions example/issues/799_negative_numbers/app.py
@@ -0,0 +1,11 @@
from __future__ import annotations

from dynaconf import Dynaconf

settings = Dynaconf(settings_files=["settings.toml"])

print(settings.num)
print(type(settings.num))

assert settings.num == -1, settings.num
assert isinstance(settings.num, int)
1 change: 1 addition & 0 deletions example/issues/799_negative_numbers/settings.toml
@@ -0,0 +1 @@
num = -1
14 changes: 14 additions & 0 deletions tests/test_env_loader.py
Expand Up @@ -206,6 +206,20 @@ def test_backwards_compat_using_env_argument():
assert settings.VALUE == "BLARG as prefix"


def test_load_signed_integer():
environ["799_SIGNED_NEG_INT"] = "-1"
environ["799_SIGNED_POS_INT"] = "+1"
load_from_env(
identifier="env_global",
key=None,
prefix="799",
obj=settings,
silent=True,
)
assert settings.SIGNED_NEG_INT == -1
assert settings.SIGNED_POS_INT == 1


def test_env_is_not_str_raises():
with pytest.raises(TypeError):
load_from_env(settings, prefix=int)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_validators.py
Expand Up @@ -739,6 +739,17 @@ def test_toml_should_not_change_validator_type_with_is_type_set():
assert settings.test == "+172800"


def test_toml_should_not_change_validator_type_with_is_type_not_set_int():
settings = Dynaconf(
validators=[Validator("TEST", default="+172800")]
# The ways to force a string is
# passing is_type_of=str
# or default="@str +172800" or default="'+172800'"
)

assert settings.test == +172800


def test_toml_should_not_change_validator_type_using_at_sign():
settings = Dynaconf(
validators=[Validator("TEST", is_type_of=str, default="@str +172800")]
Expand Down