From 7327ded6a4fbebd7e4b6658e76f53b17ccc5ba32 Mon Sep 17 00:00:00 2001 From: Guillermo Narvaja Date: Fri, 28 Feb 2020 13:51:48 -0300 Subject: [PATCH 1/4] Fix to log_level handler, now accepts lowercase ("info") And validates the attribute from logging module is int. Previously, sending "info" as value was returning the "info" function. --- environs/__init__.py | 3 ++- tests/test_environs.py | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/environs/__init__.py b/environs/__init__.py index ecede98..1546522 100644 --- a/environs/__init__.py +++ b/environs/__init__.py @@ -210,7 +210,8 @@ def _format_num(self, value) -> int: try: return super()._format_num(value) except (TypeError, ValueError) as error: - if hasattr(logging, value): + value = value.upper() + if hasattr(logging, value) and isinstance(int, getattr(logging, value)): return getattr(logging, value) else: raise ma.ValidationError("Not a valid log level.") from error diff --git a/tests/test_environs.py b/tests/test_environs.py index 10e3787..7a9c929 100644 --- a/tests/test_environs.py +++ b/tests/test_environs.py @@ -160,9 +160,14 @@ def test_path_cast(self, set_env, env): assert isinstance(res, pathlib.Path) def test_log_level_cast(self, set_env, env): - set_env({"LOG_LEVEL": "WARNING", "LOG_LEVEL_INT": str(logging.WARNING)}) + set_env({ + "LOG_LEVEL": "WARNING", + "LOG_LEVEL_INT": str(logging.WARNING), + "LOG_LEVEL_LOWER": "info", + }) assert env.log_level("LOG_LEVEL_INT") == logging.WARNING assert env.log_level("LOG_LEVEL") == logging.WARNING + assert env.log_level("LOG_LEVEL_LOWER") == logging.INFO def test_invalid_log_level(self, set_env, env): set_env({"LOG_LEVEL": "INVALID"}) From 240d4667c108995d15ea3beb0e5c724e18a15f22 Mon Sep 17 00:00:00 2001 From: Guillermo Narvaja Date: Fri, 28 Feb 2020 15:26:44 -0300 Subject: [PATCH 2/4] Fix inverted isinstance in the code and new test to verify int validation. --- environs/__init__.py | 2 +- tests/test_environs.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/environs/__init__.py b/environs/__init__.py index 1546522..5be124e 100644 --- a/environs/__init__.py +++ b/environs/__init__.py @@ -211,7 +211,7 @@ def _format_num(self, value) -> int: return super()._format_num(value) except (TypeError, ValueError) as error: value = value.upper() - if hasattr(logging, value) and isinstance(int, getattr(logging, value)): + if hasattr(logging, value) and isinstance(getattr(logging, value), int): return getattr(logging, value) else: raise ma.ValidationError("Not a valid log level.") from error diff --git a/tests/test_environs.py b/tests/test_environs.py index 7a9c929..4f6a139 100644 --- a/tests/test_environs.py +++ b/tests/test_environs.py @@ -170,10 +170,13 @@ def test_log_level_cast(self, set_env, env): assert env.log_level("LOG_LEVEL_LOWER") == logging.INFO def test_invalid_log_level(self, set_env, env): - set_env({"LOG_LEVEL": "INVALID"}) + set_env({"LOG_LEVEL": "INVALID", "LOG_LEVEL_BAD": "getLogger"}) with pytest.raises(environs.EnvError) as excinfo: env.log_level("LOG_LEVEL") assert "Not a valid log level" in excinfo.value.args[0] + with pytest.raises(environs.EnvError) as excinfo: + env.log_level("LOG_LEVEL_BAD") + assert "Not a valid log level" in excinfo.value.args[0] @pytest.mark.parametrize("url", ["foo", "42", "foo@bar"]) def test_invalid_url(self, url, set_env, env): From 1f9b61bc1a04000bec84c45347d5cffc64ec19e8 Mon Sep 17 00:00:00 2001 From: Guillermo Narvaja Date: Fri, 28 Feb 2020 17:18:28 -0300 Subject: [PATCH 3/4] Fix lint errors. --- tests/test_environs.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/test_environs.py b/tests/test_environs.py index 4f6a139..5e525eb 100644 --- a/tests/test_environs.py +++ b/tests/test_environs.py @@ -160,11 +160,7 @@ def test_path_cast(self, set_env, env): assert isinstance(res, pathlib.Path) def test_log_level_cast(self, set_env, env): - set_env({ - "LOG_LEVEL": "WARNING", - "LOG_LEVEL_INT": str(logging.WARNING), - "LOG_LEVEL_LOWER": "info", - }) + set_env({"LOG_LEVEL": "WARNING", "LOG_LEVEL_INT": str(logging.WARNING), "LOG_LEVEL_LOWER": "info"}) assert env.log_level("LOG_LEVEL_INT") == logging.WARNING assert env.log_level("LOG_LEVEL") == logging.WARNING assert env.log_level("LOG_LEVEL_LOWER") == logging.INFO From e4260269d3da6276b42c390a87c2efbc3b3fc384 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Sun, 1 Mar 2020 12:34:07 -0500 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 6 ++++++ environs/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17dd1c0..2271076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 7.3.0 (unreleased) + +- `log_level` accepts lower-cased log level names and rejects invalid + names ([#138](https://github.com/sloria/environs/pull/138)). + Thanks [gnarvaja](https://github.com/gnarvaja) for the PR. + ## 7.2.0 (2020-02-09) - Add `dj_cache_url` for caching Django cache URLs (requires installing with `[django]`) diff --git a/environs/__init__.py b/environs/__init__.py index 5be124e..95ad1d2 100644 --- a/environs/__init__.py +++ b/environs/__init__.py @@ -14,7 +14,7 @@ import marshmallow as ma from dotenv.main import load_dotenv, _walk_to_root -__version__ = "7.2.0" +__version__ = "7.3.0" __all__ = ["EnvError", "Env"] MARSHMALLOW_VERSION_INFO = tuple(int(part) for part in ma.__version__.split(".") if part.isdigit())