diff --git a/pyproject.toml b/pyproject.toml index 31bc993..633113b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "delta-barth" -version = "0.4.0dev0" +version = "0.4.1" description = "workflows and pipelines for the Python-based Plugin of Delta Barth's ERP system" authors = [ {name = "Florian Förster", email = "f.foerster@d-opt.com"}, @@ -73,7 +73,7 @@ directory = "reports/coverage" [tool.bumpversion] -current_version = "0.4.0dev0" +current_version = "0.4.1" parse = """(?x) (?P0|[1-9]\\d*)\\. (?P0|[1-9]\\d*)\\. diff --git a/src/delta_barth/api/common.py b/src/delta_barth/api/common.py index 2a05f82..688a35a 100644 --- a/src/delta_barth/api/common.py +++ b/src/delta_barth/api/common.py @@ -8,10 +8,12 @@ from dopt_basics.io import combine_route from pydantic import BaseModel from requests import Response +import delta_barth.logging from delta_barth.errors import ( STATUS_HANDLER, UnspecifiedRequestType, ) +from delta_barth.logging import logger_session as logger from delta_barth.types import ( ApiCredentials, DelBarApiError, @@ -26,19 +28,40 @@ class Session: def __init__( self, base_headers: HttpContentHeaders, + logging_folder: str = "logs", ) -> None: self._data_path: Path | None = None + self._logging_dir: Path | None = None + self._logging_folder = logging_folder self._creds: ApiCredentials | None = None self._base_url: str | None = None self._headers = base_headers self._session_token: str | None = None self._logged_in: bool = False + def setup(self) -> None: + self.setup_logging() + @property def data_path(self) -> Path: assert self._data_path is not None, "accessed data path not set" return self._data_path + @property + def logging_dir(self) -> Path: + if self._logging_dir is not None: + return self._logging_dir + + logging_dir = self.data_path / self._logging_folder + if not logging_dir.exists(): + logging_dir.mkdir(parents=False) + self._logging_dir = logging_dir + return self._logging_dir + + def setup_logging(self) -> None: + delta_barth.logging.setup_logging(self.logging_dir) + logger.info("[SESSION] Successfully setup logging") + @property def creds(self) -> ApiCredentials: assert self._creds is not None, "accessed credentials not set" diff --git a/src/delta_barth/constants.py b/src/delta_barth/constants.py index b613d9d..4a85a6f 100644 --- a/src/delta_barth/constants.py +++ b/src/delta_barth/constants.py @@ -18,6 +18,7 @@ DUMMY_DATA_PATH: Final[Path] = dummy_data_pth ENABLE_LOGGING: Final[bool] = False LOGGING_TO_FILE: Final[bool] = True LOGGING_TO_STDERR: Final[bool] = True +LOG_FILENAME: Final[str] = "dopt-delbar.log" # ** error handling diff --git a/src/delta_barth/logging.py b/src/delta_barth/logging.py index 871971f..adeb308 100644 --- a/src/delta_barth/logging.py +++ b/src/delta_barth/logging.py @@ -6,50 +6,66 @@ from pathlib import Path from time import gmtime from typing import Final -from delta_barth.constants import ENABLE_LOGGING, LIB_PATH, LOGGING_TO_FILE, LOGGING_TO_STDERR +from delta_barth.constants import ( + ENABLE_LOGGING, + LOG_FILENAME, + LOGGING_TO_FILE, + LOGGING_TO_STDERR, +) # ** config logging.Formatter.converter = gmtime LOG_FMT: Final[str] = "%(asctime)s | lang_main:%(module)s:%(levelname)s | %(message)s" LOG_DATE_FMT: Final[str] = "%Y-%m-%d %H:%M:%S +0000" -LOG_FILE_FOLDER: Final[Path] = LIB_PATH / "logs" -if not LOG_FILE_FOLDER.exists(): - LOG_FILE_FOLDER.mkdir(parents=True) +# LOG_FILE_FOLDER: Final[Path] = LIB_PATH / "logs" # !! configured in SESSION +# if not LOG_FILE_FOLDER.exists(): +# LOG_FILE_FOLDER.mkdir(parents=True) + -LOG_FILE_PATH: Final[Path] = LOG_FILE_FOLDER / "lang-main.log" LOGGING_LEVEL_STDERR: Final[int] = logging.INFO LOGGING_LEVEL_FILE: Final[int] = logging.DEBUG -# ** formatters -logger_all_formater = logging.Formatter(fmt=LOG_FMT, datefmt=LOG_DATE_FMT) - -# ** handlers -null_handler = logging.NullHandler() -if ENABLE_LOGGING and LOGGING_TO_STDERR: - logger_all_handler_stderr = logging.StreamHandler() - logger_all_handler_stderr.setLevel(LOGGING_LEVEL_STDERR) - logger_all_handler_stderr.setFormatter(logger_all_formater) -else: # pragma: no cover - logger_all_handler_stderr = null_handler - -if ENABLE_LOGGING and LOGGING_TO_FILE: - logger_all_handler_file = logging.handlers.RotatingFileHandler( - LOG_FILE_PATH, - encoding="utf-8", - maxBytes=5_242_880, - backupCount=1, - ) - logger_all_handler_file.setLevel(LOGGING_LEVEL_FILE) - logger_all_handler_file.setFormatter(logger_all_formater) -else: # pragma: no cover - logger_all_handler_file = null_handler # ** loggers and configuration logger_all = logging.getLogger("delta_barth") -logger_all.addHandler(logger_all_handler_stderr) -logger_all.addHandler(logger_all_handler_file) - +# logger_all.addHandler(logger_all_handler_stderr) +# logger_all.addHandler(logger_all_handler_file) +logger_session = logging.getLogger("delta_barth.session") +logger_session.setLevel(logging.DEBUG) logger_wrapped_results = logging.getLogger("delta_barth.wrapped_results") logger_wrapped_results.setLevel(logging.DEBUG) logger_pipelines = logging.getLogger("delta_barth.logger_pipelines") logger_pipelines.setLevel(logging.DEBUG) + + +def setup_logging( + logging_dir: Path, +) -> None: + # ** formatters + logger_all_formater = logging.Formatter(fmt=LOG_FMT, datefmt=LOG_DATE_FMT) + + # ** handlers + LOG_FILE_PATH: Final[Path] = logging_dir / LOG_FILENAME + null_handler = logging.NullHandler() + if ENABLE_LOGGING and LOGGING_TO_STDERR: + logger_all_handler_stderr = logging.StreamHandler() + logger_all_handler_stderr.setLevel(LOGGING_LEVEL_STDERR) + logger_all_handler_stderr.setFormatter(logger_all_formater) + else: # pragma: no cover + logger_all_handler_stderr = null_handler + + if ENABLE_LOGGING and LOGGING_TO_FILE: + logger_all_handler_file = logging.handlers.RotatingFileHandler( + LOG_FILE_PATH, + encoding="utf-8", + maxBytes=5_242_880, + backupCount=1, + delay=True, + ) + logger_all_handler_file.setLevel(LOGGING_LEVEL_FILE) + logger_all_handler_file.setFormatter(logger_all_formater) + else: # pragma: no cover + logger_all_handler_file = null_handler + + logger_all.addHandler(logger_all_handler_stderr) + logger_all.addHandler(logger_all_handler_file) diff --git a/src/delta_barth/management.py b/src/delta_barth/management.py index a7177bc..77a1ffc 100644 --- a/src/delta_barth/management.py +++ b/src/delta_barth/management.py @@ -13,7 +13,7 @@ SESSION: Final[Session] = Session(HTTP_BASE_CONTENT_HEADERS) def set_data_path( path: str, -) -> None: +) -> None: # pragma: no cover SESSION.set_data_path(path) diff --git a/tests/api/test_common.py b/tests/api/test_common.py index 30440a4..f48f3cb 100644 --- a/tests/api/test_common.py +++ b/tests/api/test_common.py @@ -1,10 +1,15 @@ from pathlib import Path +from unittest.mock import patch import pytest from pydantic import ValidationError from delta_barth.api import common -from delta_barth.constants import DEFAULT_API_ERR_CODE, HTTP_BASE_CONTENT_HEADERS +from delta_barth.constants import ( + DEFAULT_API_ERR_CODE, + HTTP_BASE_CONTENT_HEADERS, + LOG_FILENAME, +) from delta_barth.errors import ( UnspecifiedRequestType, ) @@ -43,6 +48,25 @@ def test_session_set_DataPath(tmp_path): assert isinstance(session.data_path, Path) +@patch("delta_barth.logging.ENABLE_LOGGING", True) +@patch("delta_barth.logging.LOGGING_TO_FILE", True) +def test_session_setup_logging(tmp_path): + str_path = str(tmp_path) + foldername: str = "logging_test" + target_log_dir = tmp_path / foldername + + session = common.Session(HTTP_BASE_CONTENT_HEADERS, logging_folder=foldername) + session.set_data_path(str_path) + log_dir = session.logging_dir + assert log_dir.exists() + assert log_dir == target_log_dir + # write file + target_file = target_log_dir / LOG_FILENAME + assert not target_file.exists() + session.setup() # calls setup code for logging + assert target_file.exists() + + def test_validate_creds(credentials): creds = common.validate_credentials( username=credentials["user"],