adding latest tests

This commit is contained in:
2021-10-18 01:03:49 +01:00
parent f73a6d2441
commit 9299a12eb6
4 changed files with 71 additions and 9 deletions

View File

@@ -7,7 +7,7 @@ from typing import Any
import toml import toml
from panaetius.exceptions import KeyErrorTooDeepException from panaetius.exceptions import KeyErrorTooDeepException, InvalidPythonException
class Config: class Config:
@@ -57,6 +57,12 @@ class Config:
try: try:
# look under top header # look under top header
# REVIEW: could this be auto handled for a key of arbitrary length? # REVIEW: could this be auto handled for a key of arbitrary length?
# check for env variable and have it take priority
value = os.environ.get(env_key.replace("-", "_"))
if value is not None:
return self.__get_config_value_env_var_override(value)
if len(key.split(".")) > 2: if len(key.split(".")) > 2:
raise KeyErrorTooDeepException( raise KeyErrorTooDeepException(
f"Your key of {key} can only be 2 levels deep maximum. " f"Your key of {key} can only be 2 levels deep maximum. "
@@ -69,10 +75,9 @@ class Config:
raise KeyError() raise KeyError()
except (KeyError, TypeError): except (KeyError, TypeError):
value = os.environ.get(env_key.replace("-", "_"))
if value is None: if value is None:
return self.__get_config_value_missing_key_value_is_none(default) return self.__get_config_value_missing_key_value_is_none(default)
# if env var, coerce value if flag is set, else return a TOML string # if env var is present, load it
return self.__get_config_value_missing_key_value_is_not_none(value) return self.__get_config_value_missing_key_value_is_not_none(value)
def __get_config_value_key_split_once(self, key: str) -> Any: def __get_config_value_key_split_once(self, key: str) -> Any:
@@ -89,6 +94,9 @@ class Config:
def __get_config_value_missing_key_value_is_not_none(self, value: str) -> Any: def __get_config_value_missing_key_value_is_not_none(self, value: str) -> Any:
return self.__load_value(value) return self.__load_value(value)
def __get_config_value_env_var_override(self, value: str) -> Any:
return self.__load_value(value)
def _get_env_value(self, env_key: str, default: Any) -> Any: # noqa def _get_env_value(self, env_key: str, default: Any) -> Any: # noqa
# look for an environment variable, fallback to default # look for an environment variable, fallback to default
value = os.environ.get(env_key.replace("-", "_")) value = os.environ.get(env_key.replace("-", "_"))
@@ -97,7 +105,10 @@ class Config:
return self.__load_value(value) return self.__load_value(value)
def __load_value(self, value: str) -> Any: # noqa def __load_value(self, value: str) -> Any: # noqa
try:
return ast.literal_eval(value) return ast.literal_eval(value)
except (ValueError, SyntaxError):
raise InvalidPythonException(f"{value} is not valid Python.") # noqa
def __load_default_value(self, default: Any) -> Any: # noqa def __load_default_value(self, default: Any) -> Any: # noqa
return default return default

View File

@@ -4,3 +4,6 @@ class KeyErrorTooDeepException(Exception):
class LoggingDirectoryDoesNotExistException(Exception): class LoggingDirectoryDoesNotExistException(Exception):
pass pass
class InvalidPythonException(Exception):
pass

View File

@@ -25,13 +25,14 @@ Coding:
☐ Write the docstrings for public functions/methods. ☐ Write the docstrings for public functions/methods.
Functionality: Functionality:
When both a config file and a env var is found, use the env var. When both a config file and a env var is found, use the env var. @done(21-10-18 00:38)
Documentation: Documentation:
☐ Rewrite documentation using `mkdocs` and using `.md`. @2h ☐ Rewrite documentation using `mkdocs` and using `.md`. @2h
Misc: Misc:
☐ Use the python runner to build the docs & run the tests ☐ Use the python runner to build the docs & run the tests (including coverage html)
coverage run -m pytest && coverage report && coverage html
☐ document this in trilium ☐ document this in trilium
Tests: Tests:
@@ -63,6 +64,7 @@ Tests:
✔ check if env key is missing the default is read in @done(21-10-17 20:55) ✔ check if env key is missing the default is read in @done(21-10-17 20:55)
✔ check if env key is present the values are read in @done(21-10-17 22:24) ✔ check if env key is present the values are read in @done(21-10-17 22:24)
✔ parametrise a test to read in values form env vars and they're set correctly @done(21-10-17 22:24) ✔ parametrise a test to read in values form env vars and they're set correctly @done(21-10-17 22:24)
✔ test that the env var is valid python @done(21-10-18 01:03)
library: library:
✔ test set_config works @done(21-10-17 23:29) ✔ test set_config works @done(21-10-17 23:29)

View File

@@ -5,7 +5,7 @@ from uuid import uuid4
import pytest import pytest
import panaetius import panaetius
from panaetius.exceptions import KeyErrorTooDeepException from panaetius.exceptions import InvalidPythonException, KeyErrorTooDeepException
# test config paths # test config paths
@@ -44,7 +44,9 @@ def test_config_file_exists(header, shared_datadir):
assert config._missing_config is False assert config._missing_config is False
def test_config_file_contents_read_success(header, shared_datadir, testing_config_contents): def test_config_file_contents_read_success(
header, shared_datadir, testing_config_contents
):
# arrange # arrange
config_path = str(shared_datadir / "without_logging") config_path = str(shared_datadir / "without_logging")
@@ -102,6 +104,23 @@ def test_get_value_from_key(
assert config_value == expected_value assert config_value == expected_value
def test_get_value_environment_var_override(header, shared_datadir):
# arrange
os.environ[f"{header.upper()}_SOME_TOP_STRING"] = '"some_overridden_value"'
config_path = str(shared_datadir / "without_logging")
config = panaetius.Config(header, config_path)
panaetius.set_config(config, "some_top_string")
# act
config_value = getattr(config, "some_top_string")
# assert
assert config_value == "some_overridden_value"
# cleanup
del os.environ[f"{header.upper()}_SOME_TOP_STRING"]
def test_key_level_too_deep(header, shared_datadir): def test_key_level_too_deep(header, shared_datadir):
# arrange # arrange
config_path = str(shared_datadir / "without_logging") config_path = str(shared_datadir / "without_logging")
@@ -151,6 +170,9 @@ def test_get_value_missing_key_from_env(header, shared_datadir):
# assert # assert
assert value_from_key == "some missing key" assert value_from_key == "some missing key"
# cleanup
del os.environ[f"{header.upper()}_MISSING_KEY"]
# test env vars # test env vars
@@ -197,7 +219,9 @@ def test_missing_config_read_from_default(header, shared_datadir):
), ),
], ],
) )
def test_missing_config_read_from_env_var(env_value, expected_value, header, shared_datadir): def test_missing_config_read_from_env_var(
env_value, expected_value, header, shared_datadir
):
# arrange # arrange
config_path = str(shared_datadir / str(uuid4())) config_path = str(shared_datadir / str(uuid4()))
os.environ[f"{header.upper()}_MISSING_KEY_READ_FROM_ENV_VAR"] = env_value os.environ[f"{header.upper()}_MISSING_KEY_READ_FROM_ENV_VAR"] = env_value
@@ -208,3 +232,25 @@ def test_missing_config_read_from_env_var(env_value, expected_value, header, sha
# assert # assert
assert getattr(config, "missing_key_read_from_env_var") == expected_value assert getattr(config, "missing_key_read_from_env_var") == expected_value
# cleanup
del os.environ[f"{header.upper()}_MISSING_KEY_READ_FROM_ENV_VAR"]
def test_missing_config_read_from_env_var_invalid_python(header):
# arrange
os.environ[f"{header.upper()}_INVALID_PYTHON"] = "a string without quotes"
config = panaetius.Config(header)
# act
with pytest.raises(InvalidPythonException) as invalid_python_exception:
panaetius.set_config(config, "invalid_python")
# assert
assert (
str(invalid_python_exception.value)
== "a string without quotes is not valid Python."
)
# cleanup
del os.environ[f"{header.upper()}_INVALID_PYTHON"]