mirror of
https://github.com/dtomlinson91/panaetius.git
synced 2025-12-21 20:55:43 +00:00
adding latest tests
This commit is contained in:
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@@ -4,20 +4,5 @@
|
||||
"python.linting.enabled": true,
|
||||
"python.pythonPath": ".venv/bin/python",
|
||||
"restructuredtext.confPath": "${workspaceFolder}/docs/source",
|
||||
"workbench.colorCustomizations": {
|
||||
"editorGroup.border": "#3ea389",
|
||||
"panel.border": "#3ea389",
|
||||
"sash.hoverBorder": "#3ea389",
|
||||
"sideBar.border": "#3ea389",
|
||||
"statusBar.background": "#307e6a",
|
||||
"statusBar.foreground": "#e7e7e7",
|
||||
"statusBarItem.hoverBackground": "#3ea389",
|
||||
"statusBarItem.remoteBackground": "#307e6a",
|
||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||
"titleBar.activeBackground": "#307e6a",
|
||||
"titleBar.activeForeground": "#e7e7e7",
|
||||
"titleBar.inactiveBackground": "#307e6a99",
|
||||
"titleBar.inactiveForeground": "#e7e7e799"
|
||||
},
|
||||
"peacock.color": "#307E6A"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import os
|
||||
import pathlib
|
||||
from typing import Any
|
||||
|
||||
import toml
|
||||
|
||||
from panaetius.exceptions import KeyErrorTooDeepException
|
||||
|
||||
|
||||
class Config:
|
||||
"""docstring for Config()."""
|
||||
@@ -16,7 +20,7 @@ class Config:
|
||||
if config_path
|
||||
else pathlib.Path.home() / ".config"
|
||||
)
|
||||
self._missing_config = False
|
||||
self._missing_config = self._check_config_file_exists()
|
||||
|
||||
# default logging options
|
||||
self.logging_path: str | None = None
|
||||
@@ -24,42 +28,52 @@ class Config:
|
||||
self.logging_backup_count: int = 0
|
||||
|
||||
@property
|
||||
def config(self) -> dict[str, Any]:
|
||||
def config(self) -> dict:
|
||||
config_file_location = self.config_path / self.header_variable / "config.toml"
|
||||
try:
|
||||
with open(config_file_location, "r", encoding="utf-8") as config_file:
|
||||
return dict(toml.load(config_file))
|
||||
except FileNotFoundError:
|
||||
self._missing_config = True
|
||||
return {}
|
||||
|
||||
def get_value(self, key: str, default: Any, coerce: bool = False) -> Any:
|
||||
def get_value(self, key: str, default: Any) -> Any:
|
||||
env_key = f"{self.header_variable.upper()}_{key.upper().replace('.', '_')}"
|
||||
|
||||
if not self._missing_config:
|
||||
# look in the config file
|
||||
return self._get_config_value(env_key, key, default, coerce)
|
||||
return self._get_config_value(env_key, key, default)
|
||||
# no config file, look for env vars
|
||||
return self._get_env_value(env_key, default, coerce)
|
||||
return self._get_env_value(env_key, default)
|
||||
|
||||
def _get_config_value(
|
||||
self, env_key: str, key: str, default: Any, coerce: bool = False
|
||||
) -> Any:
|
||||
def _check_config_file_exists(self) -> bool:
|
||||
config_file_location = self.config_path / self.header_variable / "config.toml"
|
||||
try:
|
||||
with open(config_file_location, "r", encoding="utf-8"):
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
return True
|
||||
|
||||
def _get_config_value(self, env_key: str, key: str, default: Any) -> Any:
|
||||
try:
|
||||
# look under top header
|
||||
# REVIEW: could this be auto handled for a key of arbitrary length?
|
||||
if len(key.split(".")) > 2:
|
||||
raise KeyErrorTooDeepException(
|
||||
f"Your key of {key} can only be 2 levels deep maximum. "
|
||||
f"You have {len(key.split('.'))}"
|
||||
)
|
||||
if len(key.split(".")) == 1:
|
||||
return self.__get_config_value_key_split_once(key)
|
||||
if len(key.split(".")) == 2:
|
||||
return self.__get_config_value_key_split_twice(key)
|
||||
raise KeyError
|
||||
raise KeyError()
|
||||
|
||||
except (KeyError, TypeError):
|
||||
value = os.environ.get(env_key.replace("-", "_"))
|
||||
if value is None:
|
||||
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
|
||||
return self.__get_config_value_missing_key_value_is_not_none(value, coerce)
|
||||
return self.__get_config_value_missing_key_value_is_not_none(value)
|
||||
|
||||
def __get_config_value_key_split_once(self, key: str) -> Any:
|
||||
name = key.lower()
|
||||
@@ -72,33 +86,18 @@ class Config:
|
||||
def __get_config_value_missing_key_value_is_none(self, default: Any) -> Any:
|
||||
return self.__load_default_value(default)
|
||||
|
||||
def __get_config_value_missing_key_value_is_not_none(
|
||||
self, value: str, coerce: bool
|
||||
) -> Any:
|
||||
return self.__load_value(value, coerce)
|
||||
def __get_config_value_missing_key_value_is_not_none(self, value: str) -> Any:
|
||||
return self.__load_value(value)
|
||||
|
||||
def _get_env_value( # noqa
|
||||
self, env_key: str, default: Any, coerce: bool = False
|
||||
) -> Any:
|
||||
def _get_env_value(self, env_key: str, default: Any) -> Any: # noqa
|
||||
# look for an environment variable, fallback to default
|
||||
value = os.environ.get(env_key.replace("-", "_"))
|
||||
if value is None:
|
||||
return self.__load_default_value(default)
|
||||
return self.__load_value(value, coerce)
|
||||
return self.__load_value(value)
|
||||
|
||||
def __load_value(self, value: str, coerce: bool) -> Any: # noqa
|
||||
value = str(value).lower() if isinstance(value, bool) else value
|
||||
return (
|
||||
toml.loads(f"value = {value}")["value"]
|
||||
if coerce
|
||||
else toml.loads(f'value = "{value}"')["value"]
|
||||
)
|
||||
def __load_value(self, value: str) -> Any: # noqa
|
||||
return ast.literal_eval(value)
|
||||
|
||||
def __load_default_value(self, default: Any) -> Any: # noqa
|
||||
if isinstance(default, str):
|
||||
return toml.loads(f'value = "{default}"')["value"]
|
||||
# if default is bool convert to lower case toml syntax
|
||||
default = str(default).lower() if isinstance(default, bool) else default
|
||||
return (
|
||||
toml.loads(f"value = {default}")["value"] if default is not None else None
|
||||
)
|
||||
return default
|
||||
|
||||
6
panaetius/exceptions.py
Normal file
6
panaetius/exceptions.py
Normal file
@@ -0,0 +1,6 @@
|
||||
class KeyErrorTooDeepException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class LoggingDirectoryDoesNotExistException(Exception):
|
||||
pass
|
||||
@@ -9,7 +9,6 @@ def set_config(
|
||||
config_inst: Config,
|
||||
key: str,
|
||||
default: Any = None,
|
||||
coerce: bool = False,
|
||||
):
|
||||
config_var = key.lower().replace(".", "_")
|
||||
setattr(config_inst, config_var, config_inst.get_value(key, default, coerce))
|
||||
setattr(config_inst, config_var, config_inst.get_value(key, default))
|
||||
|
||||
@@ -8,6 +8,7 @@ import sys
|
||||
|
||||
from panaetius import Config
|
||||
from panaetius.library import set_config
|
||||
from panaetius.exceptions import LoggingDirectoryDoesNotExistException
|
||||
|
||||
|
||||
def set_logger(config_inst: Config, logging_format_inst: LoggingData) -> logging.Logger:
|
||||
@@ -22,6 +23,9 @@ def set_logger(config_inst: Config, logging_format_inst: LoggingData) -> logging
|
||||
/ f"{config_inst.header_variable}.log"
|
||||
).expanduser()
|
||||
|
||||
if not logging_file.parents[0].exists():
|
||||
raise LoggingDirectoryDoesNotExistException()
|
||||
|
||||
if config_inst.logging_rotate_bytes == 0:
|
||||
set_config(config_inst, "logging.rotate_bytes", 512000)
|
||||
if config_inst.logging_backup_count == 0:
|
||||
|
||||
48
poetry.lock
generated
48
poetry.lock
generated
@@ -57,6 +57,17 @@ category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "6.0.2"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "dodgy"
|
||||
version = "0.2.1"
|
||||
@@ -610,7 +621,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "bc75d0878aaf4033c2d9520333a559d29e81962a8a0138ed8861014d2fc77eac"
|
||||
content-hash = "468d1aa5e0c440262f6041ad859358a84ef32462941aa6f3ba71838a52cc1ced"
|
||||
|
||||
[metadata.files]
|
||||
astroid = [
|
||||
@@ -633,6 +644,41 @@ colorama = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||
]
|
||||
coverage = [
|
||||
{file = "coverage-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1549e1d08ce38259de2bc3e9a0d5f3642ff4a8f500ffc1b2df73fd621a6cdfc0"},
|
||||
{file = "coverage-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcae10fccb27ca2a5f456bf64d84110a5a74144be3136a5e598f9d9fb48c0caa"},
|
||||
{file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:53a294dc53cfb39c74758edaa6305193fb4258a30b1f6af24b360a6c8bd0ffa7"},
|
||||
{file = "coverage-6.0.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8251b37be1f2cd9c0e5ccd9ae0380909c24d2a5ed2162a41fcdbafaf59a85ebd"},
|
||||
{file = "coverage-6.0.2-cp310-cp310-win32.whl", hash = "sha256:db42baa892cba723326284490283a68d4de516bfb5aaba369b4e3b2787a778b7"},
|
||||
{file = "coverage-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:bbffde2a68398682623d9dd8c0ca3f46fda074709b26fcf08ae7a4c431a6ab2d"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:60e51a3dd55540bec686d7fff61b05048ca31e804c1f32cbb44533e6372d9cc3"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a6a9409223a27d5ef3cca57dd7cd4dfcb64aadf2fad5c3b787830ac9223e01a"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b34ae4f51bbfa5f96b758b55a163d502be3dcb24f505d0227858c2b3f94f5b9"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bbda1b550e70fa6ac40533d3f23acd4f4e9cb4e6e77251ce77fdf41b3309fb2"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-win32.whl", hash = "sha256:4e28d2a195c533b58fc94a12826f4431726d8eb029ac21d874345f943530c122"},
|
||||
{file = "coverage-6.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a82d79586a0a4f5fd1cf153e647464ced402938fbccb3ffc358c7babd4da1dd9"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3be1206dc09fb6298de3fce70593e27436862331a85daee36270b6d0e1c251c4"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cd3828bbe1a40070c11fe16a51df733fd2f0cb0d745fb83b7b5c1f05967df7"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d036dc1ed8e1388e995833c62325df3f996675779541f682677efc6af71e96cc"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04560539c19ec26995ecfb3d9307ff154fbb9a172cb57e3b3cfc4ced673103d1"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:e4fb7ced4d9dec77d6cf533acfbf8e1415fe799430366affb18d69ee8a3c6330"},
|
||||
{file = "coverage-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:77b1da5767ed2f44611bc9bc019bc93c03fa495728ec389759b6e9e5039ac6b1"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:61b598cbdbaae22d9e34e3f675997194342f866bb1d781da5d0be54783dce1ff"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36e9040a43d2017f2787b28d365a4bb33fcd792c7ff46a047a04094dc0e2a30d"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9f1627e162e3864a596486774876415a7410021f4b67fd2d9efdf93ade681afc"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7a0b42db2a47ecb488cde14e0f6c7679a2c5a9f44814393b162ff6397fcdfbb"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-win32.whl", hash = "sha256:a1b73c7c4d2a42b9d37dd43199c5711d91424ff3c6c22681bc132db4a4afec6f"},
|
||||
{file = "coverage-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:1db67c497688fd4ba85b373b37cc52c50d437fd7267520ecd77bddbd89ea22c9"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f184bf38e74f152eed7f87e345b51f3ab0b703842f447c22efe35e59942c24"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1cf1deb3d5544bd942356364a2fdc8959bad2b6cf6eb17f47d301ea34ae822"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad9b8c1206ae41d46ec7380b78ba735ebb77758a650643e841dd3894966c31d0"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:381d773d896cc7f8ba4ff3b92dee4ed740fb88dfe33b6e42efc5e8ab6dfa1cfe"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-win32.whl", hash = "sha256:424c44f65e8be58b54e2b0bd1515e434b940679624b1b72726147cfc6a9fc7ce"},
|
||||
{file = "coverage-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:abbff240f77347d17306d3201e14431519bf64495648ca5a49571f988f88dee9"},
|
||||
{file = "coverage-6.0.2-pp36-none-any.whl", hash = "sha256:7092eab374346121805fb637572483270324407bf150c30a3b161fc0c4ca5164"},
|
||||
{file = "coverage-6.0.2-pp37-none-any.whl", hash = "sha256:30922626ce6f7a5a30bdba984ad21021529d3d05a68b4f71ea3b16bda35b8895"},
|
||||
{file = "coverage-6.0.2.tar.gz", hash = "sha256:6807947a09510dc31fa86f43595bf3a14017cd60bf633cc746d52141bfa6b149"},
|
||||
]
|
||||
dodgy = [
|
||||
{file = "dodgy-0.2.1-py3-none-any.whl", hash = "sha256:51f54c0fd886fa3854387f354b19f429d38c04f984f38bc572558b703c0542a6"},
|
||||
{file = "dodgy-0.2.1.tar.gz", hash = "sha256:28323cbfc9352139fdd3d316fa17f325cc0e9ac74438cbba51d70f9b48f86c3a"},
|
||||
|
||||
@@ -103,9 +103,9 @@ dodgy:
|
||||
|
||||
bandit:
|
||||
run: true
|
||||
options:
|
||||
# options:
|
||||
# ignore assert warning
|
||||
B101
|
||||
# - B101
|
||||
|
||||
mypy:
|
||||
run: true
|
||||
|
||||
@@ -33,6 +33,7 @@ types-toml = "^0.10.1"
|
||||
pytest = "^6.2.5"
|
||||
pytest-datadir = "^1.3.1"
|
||||
pytest-xdist = "^2.4.0"
|
||||
coverage = "^6.0.2"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
; parallel tests with pytest-xdist
|
||||
[pytest]
|
||||
addopts=-n4
|
||||
; ; parallel tests with pytest-xdist
|
||||
; [pytest]
|
||||
; addopts=-n4
|
||||
|
||||
47
rewrite.todo
47
rewrite.todo
@@ -14,8 +14,9 @@ Coding:
|
||||
✔ Logging path should take by default the config path unless overwritten? @done(21-10-16 23:49)
|
||||
|
||||
Errors:
|
||||
☐ Check logging path + config path are valid, if not raise error.
|
||||
☐ Add tests for these.
|
||||
✔ Check logging path + config path are valid, if not raise error. @done(21-10-18 00:04)
|
||||
✔ Add tests for these. @done(21-10-18 00:04)
|
||||
✔ Check for a key > 2 levels, raise custom error, write test @done(21-10-17 23:30)
|
||||
|
||||
Linting:
|
||||
☐ Check all functions and annotations.
|
||||
@@ -23,21 +24,45 @@ Coding:
|
||||
Docstrings:
|
||||
☐ Write the docstrings for public functions/methods.
|
||||
|
||||
Functionality:
|
||||
☐ When both a config file and a env var is found, use the env var.
|
||||
|
||||
Documentation:
|
||||
☐ Rewrite documentation using `mkdocs` and using `.md`. @2h
|
||||
|
||||
Misc:
|
||||
☐ Use the python runner to build the docs & run the tests
|
||||
☐ document this in trilium
|
||||
|
||||
Tests:
|
||||
Config File:
|
||||
☐
|
||||
|
||||
Environment Variable:
|
||||
☐
|
||||
Bugfixes:
|
||||
✔ If loading from a default, don't covert to TOML @done(21-10-17 20:33)
|
||||
✔ Env Vars should be given as python objects @done(21-10-17 20:33)
|
||||
The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.
|
||||
use ast.literal_eval()
|
||||
https://docs.python.org/3/library/ast.html#ast.literal_eval
|
||||
|
||||
__init__:
|
||||
☐ Test default config path set to "~/.config"
|
||||
☐ Test config path is set when passed in
|
||||
✔ Test default config path set to "~/.config" @done(21-10-17 17:25)
|
||||
✔ Test config path is set when passed in @done(21-10-17 17:25)
|
||||
|
||||
config property:
|
||||
☐ Check testing config file is returned as dict
|
||||
☐ Check _self.missing_config and empty dict is returned
|
||||
✔ Check testing config file is returned as dict @done(21-10-17 17:25)
|
||||
✔ Check _self.missing_config and empty dict is returned @done(21-10-17 17:25)
|
||||
|
||||
get_value:
|
||||
config_file:
|
||||
✔ Arrays & tables loaded correctly from config file @done(21-10-17 20:34)
|
||||
✔ test when key length is 1 the value is returned @done(21-10-17 18:55)
|
||||
✔ test when key length is 2 the value is returned @done(21-10-17 18:55)
|
||||
✔ test when key not found and no env var default is loaded @done(21-10-17 19:01)
|
||||
✔ test bool's are properly converted @done(21-10-17 19:01)
|
||||
✔ test when key not found and env var is set value is loaded @done(21-10-17 20:43)
|
||||
|
||||
env_var:
|
||||
✔ 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)
|
||||
✔ parametrise a test to read in values form env vars and they're set correctly @done(21-10-17 22:24)
|
||||
|
||||
library:
|
||||
✔ test set_config works @done(21-10-17 23:29)
|
||||
|
||||
@@ -4,3 +4,20 @@ import pytest
|
||||
@pytest.fixture()
|
||||
def header():
|
||||
return "panaetius_testing"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def testing_config_contents():
|
||||
return {
|
||||
"panaetius_testing": {
|
||||
"some_top_string": "some_top_value",
|
||||
"second": {
|
||||
"some_second_string": "some_second_value",
|
||||
"some_second_int": 1,
|
||||
"some_second_float": 1.0,
|
||||
"some_second_list": ["some", "second", "value"],
|
||||
"some_second_table": {"first": ["some", "first", "value"]},
|
||||
"some_second_table_bools": {"bool": [True, False]},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,4 @@ some_second_int = 1
|
||||
some_second_float = 1.0
|
||||
some_second_list = ["some", "second", "value"]
|
||||
some_second_table = { "first" = ["some", "first", "value"] }
|
||||
|
||||
# [panaetius_testing.logging]
|
||||
# path = ""
|
||||
some_second_table_bools = { "bool" = [true, false] }
|
||||
@@ -1,54 +1,57 @@
|
||||
import os
|
||||
|
||||
from panaetius import Config, set_config, set_logger, SimpleLogger
|
||||
# from panaetius.logging import AdvancedLogger
|
||||
|
||||
from panaetius.logging import AdvancedLogger
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ["PANAETIUS_TEST_PATH"] = "/usr/local"
|
||||
os.environ["PANAETIUS_TEST_BOOL"] = "true"
|
||||
print(os.environ.get("PANAETIUS_TEST_PATH"))
|
||||
os.environ["PANAETIUS_TEST_PATH"] = '"/usr/local"'
|
||||
os.environ["PANAETIUS_TEST_BOOL"] = "True"
|
||||
# print(os.environ.get("PANAETIUS_TEST_PATH"))
|
||||
# os.environ[
|
||||
# "PANAETIUS_TEST_TOML_POINTS"
|
||||
# ] = "[ { x = 1, y = 2, z = 3 }, { x = 7, y = 8, z = 9 }, { x = 2, y = 4, z = 8 }]"
|
||||
|
||||
os.environ["PANAETIUS_TEST_NOC_PATH"] = "/usr/locals"
|
||||
os.environ["PANAETIUS_TEST_NOC_PATH"] = '"/usr/locals"'
|
||||
os.environ["PANAETIUS_TEST_NOC_FLOAT"] = "2.0"
|
||||
os.environ["PANAETIUS_TEST_NOC_BOOL"] = "true"
|
||||
os.environ["PANAETIUS_TEST_NOC_EMBEDDED_PATH"] = "/usr/local"
|
||||
os.environ["PANAETIUS_TEST_NOC_BOOL"] = "True"
|
||||
os.environ["PANAETIUS_TEST_NOC_EMBEDDED_PATH"] = '"/usr/local"'
|
||||
os.environ["PANAETIUS_TEST_NOC_EMBEDDED_FLOAT"] = "2.0"
|
||||
os.environ["PANAETIUS_TEST_NOC_EMBEDDED_BOOL"] = "true"
|
||||
os.environ["PANAETIUS_TEST_NOC_EMBEDDED_BOOL"] = "True"
|
||||
|
||||
# c = Config("panaetius_test")
|
||||
c = Config("panaetius_test_noc")
|
||||
c = Config("panaetius_test")
|
||||
# c = Config("panaetius_test_noc")
|
||||
|
||||
set_config(c, key="toml.points", coerce=True)
|
||||
set_config(c, key="toml.points")
|
||||
set_config(c, key="path", default="some path")
|
||||
set_config(c, key="top", default="some top")
|
||||
set_config(c, key="logging.path")
|
||||
set_config(c, key="nonexistent.item", default="some nonexistent item")
|
||||
set_config(c, key="nonexistent.item")
|
||||
set_config(c, key="toml.points_config")
|
||||
set_config(c, key="float", coerce=True)
|
||||
set_config(c, key="float")
|
||||
set_config(c, key="float_str", default="2.0")
|
||||
set_config(c, key="bool", coerce=True)
|
||||
set_config(c, key="bool")
|
||||
set_config(c, key="noexistbool", default=False)
|
||||
set_config(c, key="middle.middle")
|
||||
|
||||
# set_config(c, key="path")
|
||||
# set_config(c, key="float", coerce=True)
|
||||
# set_config(c, key="bool", coerce=True)
|
||||
# set_config(c, key="float")
|
||||
# set_config(c, key="bool")
|
||||
# set_config(c, key="noexiststr", default="2.0")
|
||||
# set_config(c, key="noexistfloat", default=2.0)
|
||||
# set_config(c, key="noexistbool", default=False)
|
||||
|
||||
set_config(c, key="embedded.path")
|
||||
set_config(c, key="embedded.float", coerce=True)
|
||||
set_config(c, key="embedded.bool", coerce=True)
|
||||
set_config(c, key="embedded.float")
|
||||
set_config(c, key="embedded.bool")
|
||||
set_config(c, key="embedded.noexiststr", default="2.0")
|
||||
set_config(c, key="embedded.noexistfloat", default=2.0)
|
||||
set_config(c, key="embedded.noexistbool", default=False)
|
||||
|
||||
logger = set_logger(c, SimpleLogger())
|
||||
# logger = set_logger(c, AdvancedLogger(logging_level="INFO"))
|
||||
# logger = set_logger(c, SimpleLogger())
|
||||
logger = set_logger(c, AdvancedLogger(logging_level="DEBUG"))
|
||||
logger.info("test logging message")
|
||||
logger.debug("debugging message")
|
||||
for i in dir(c):
|
||||
logger.debug(i + ": " + str(getattr(c, i)) + " - " + str(type(getattr(c, i))))
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import os
|
||||
import pathlib
|
||||
from uuid import uuid4
|
||||
|
||||
import toml
|
||||
import pytest
|
||||
|
||||
import panaetius
|
||||
from panaetius.exceptions import KeyErrorTooDeepException
|
||||
|
||||
# test config paths
|
||||
|
||||
|
||||
def test_default_config_path_set(header):
|
||||
@@ -13,9 +18,9 @@ def test_default_config_path_set(header):
|
||||
assert str(config.config_path) == str(pathlib.Path.home() / ".config")
|
||||
|
||||
|
||||
def test_user_config_path_set(header, datadir):
|
||||
def test_user_config_path_set(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(datadir / "without_logging")
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
@@ -24,13 +29,182 @@ def test_user_config_path_set(header, datadir):
|
||||
assert str(config.config_path) == config_path
|
||||
|
||||
|
||||
def test_config_file_exists(header, datadir):
|
||||
# test config files
|
||||
|
||||
|
||||
def test_config_file_exists(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(datadir / "without_logging")
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
_ = config.config
|
||||
|
||||
# assert
|
||||
assert config._missing_config is False
|
||||
|
||||
|
||||
def test_config_file_contents_read_success(header, shared_datadir, testing_config_contents):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
config_contents = config.config
|
||||
|
||||
# assert
|
||||
assert config._missing_config == False
|
||||
assert config_contents == testing_config_contents
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"set_config_key,get_config_key,expected_value",
|
||||
[
|
||||
("some_top_string", "some_top_string", "some_top_value"),
|
||||
("second.some_second_string", "second_some_second_string", "some_second_value"),
|
||||
(
|
||||
"second.some_second_list",
|
||||
"second_some_second_list",
|
||||
["some", "second", "value"],
|
||||
),
|
||||
(
|
||||
"second.some_second_table",
|
||||
"second_some_second_table",
|
||||
{"first": ["some", "first", "value"]},
|
||||
),
|
||||
(
|
||||
"second.some_second_table_bools",
|
||||
"second_some_second_table_bools",
|
||||
{"bool": [True, False]},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get_value_from_key(
|
||||
set_config_key, get_config_key, expected_value, header, shared_datadir
|
||||
):
|
||||
"""
|
||||
Test the following:
|
||||
|
||||
- keys are read from top level key
|
||||
- keys are read from two level key
|
||||
- inline arrays are read correctly
|
||||
- inline tables are read correctly
|
||||
- inline tables & arrays read bools correctly
|
||||
"""
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(config, set_config_key)
|
||||
|
||||
# act
|
||||
config_value = getattr(config, get_config_key)
|
||||
|
||||
# assert
|
||||
assert config_value == expected_value
|
||||
|
||||
|
||||
def test_key_level_too_deep(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
config = panaetius.Config(header, config_path)
|
||||
key = "a.key.too.deep"
|
||||
|
||||
# act
|
||||
with pytest.raises(KeyErrorTooDeepException) as key_error_too_deep:
|
||||
panaetius.set_config(config, key)
|
||||
|
||||
# assert
|
||||
assert (
|
||||
str(key_error_too_deep.value)
|
||||
== f"Your key of {key} can only be 2 levels deep maximum. "
|
||||
f"You have 4"
|
||||
)
|
||||
|
||||
|
||||
def test_get_value_missing_key_from_default(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(
|
||||
config,
|
||||
"missing.key_from_default",
|
||||
default=["some", "default", "value", 1.0, True],
|
||||
)
|
||||
|
||||
# act
|
||||
default_value = getattr(config, "missing_key_from_default")
|
||||
|
||||
# assert
|
||||
assert default_value == ["some", "default", "value", 1.0, True]
|
||||
|
||||
|
||||
def test_get_value_missing_key_from_env(header, shared_datadir):
|
||||
# arrange
|
||||
os.environ[f"{header.upper()}_MISSING_KEY"] = '"some missing key"'
|
||||
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(config, "missing_key")
|
||||
|
||||
# act
|
||||
value_from_key = getattr(config, "missing_key")
|
||||
|
||||
# assert
|
||||
assert value_from_key == "some missing key"
|
||||
|
||||
|
||||
# test env vars
|
||||
|
||||
|
||||
def test_config_file_does_not_exist(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "nonexistent_folder")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
config_contents = config.config
|
||||
|
||||
# assert
|
||||
assert config._missing_config is True
|
||||
assert config_contents == {}
|
||||
|
||||
|
||||
def test_missing_config_read_from_default(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "nonexistent_folder")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(config, "missing.key_read_from_default", default=True)
|
||||
|
||||
# assert
|
||||
assert getattr(config, "missing_key_read_from_default") is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"env_value,expected_value",
|
||||
[
|
||||
('"a missing string"', "a missing string"),
|
||||
("1", 1),
|
||||
("1.0", 1.0),
|
||||
("True", True),
|
||||
(
|
||||
'["an", "array", "of", "items", 1, True]',
|
||||
["an", "array", "of", "items", 1, True],
|
||||
),
|
||||
(
|
||||
'{"an": "array", "of": "items", "1": True}',
|
||||
{"an": "array", "of": "items", "1": True},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_missing_config_read_from_env_var(env_value, expected_value, header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / str(uuid4()))
|
||||
os.environ[f"{header.upper()}_MISSING_KEY_READ_FROM_ENV_VAR"] = env_value
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(config, "missing.key_read_from_env_var")
|
||||
|
||||
# assert
|
||||
assert getattr(config, "missing_key_read_from_env_var") == expected_value
|
||||
|
||||
13
tests/test_library.py
Normal file
13
tests/test_library.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import panaetius
|
||||
|
||||
|
||||
def test_set_config(header, shared_datadir):
|
||||
# arrange
|
||||
config_path = str(shared_datadir / "without_logging")
|
||||
|
||||
# act
|
||||
config = panaetius.Config(header, config_path)
|
||||
panaetius.set_config(config, "some_top_string")
|
||||
|
||||
# assert
|
||||
assert getattr(config, "some_top_string") == "some_top_value"
|
||||
34
tests/test_logging.py
Normal file
34
tests/test_logging.py
Normal file
@@ -0,0 +1,34 @@
|
||||
import logging
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from panaetius import set_logger, SimpleLogger, Config, set_config
|
||||
from panaetius.exceptions import LoggingDirectoryDoesNotExistException
|
||||
|
||||
|
||||
def test_logging_directory_does_not_exist(header, shared_datadir):
|
||||
# arrange
|
||||
config = Config(header)
|
||||
logging_path = str(shared_datadir / str(uuid4()))
|
||||
set_config(config, "logging.path", default=str(logging_path))
|
||||
|
||||
# act
|
||||
with pytest.raises(LoggingDirectoryDoesNotExistException) as logging_exception:
|
||||
_ = set_logger(config, SimpleLogger())
|
||||
|
||||
# assert
|
||||
assert str(logging_exception.value) == ""
|
||||
|
||||
|
||||
def test_logging_directory_does_exist(header, shared_datadir):
|
||||
# arrange
|
||||
config = Config(header)
|
||||
logging_path = str(shared_datadir / "without_logging")
|
||||
set_config(config, "logging.path", default=str(logging_path))
|
||||
|
||||
# act
|
||||
logger = set_logger(config, SimpleLogger())
|
||||
|
||||
# assert
|
||||
assert isinstance(logger, logging.Logger)
|
||||
Reference in New Issue
Block a user