mirror of
https://github.com/dtomlinson91/panaetius.git
synced 2025-12-22 04:55:44 +00:00
adding latest tests
This commit is contained in:
@@ -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
|
||||||
return ast.literal_eval(value)
|
try:
|
||||||
|
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
|
||||||
|
|||||||
@@ -4,3 +4,6 @@ class KeyErrorTooDeepException(Exception):
|
|||||||
|
|
||||||
class LoggingDirectoryDoesNotExistException(Exception):
|
class LoggingDirectoryDoesNotExistException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class InvalidPythonException(Exception):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
Reference in New Issue
Block a user