new: working logger
This commit is contained in:
@@ -23,6 +23,8 @@ dependencies = [
|
|||||||
"tomli_w",
|
"tomli_w",
|
||||||
"numba",
|
"numba",
|
||||||
"tqdm",
|
"tqdm",
|
||||||
|
"pydantic",
|
||||||
|
"pydantic-settings",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
from scgenerator import io, math, noise, operators, plotting
|
from scgenerator import io, math, noise, operators, plotting
|
||||||
from scgenerator.helpers import *
|
from scgenerator.helpers import *
|
||||||
from scgenerator.io import MemoryIOHandler, ZipFileIOHandler
|
from scgenerator.io import MemoryIOHandler, ZipFileIOHandler
|
||||||
|
from scgenerator.logger import get_logger
|
||||||
from scgenerator.math import abs2, argclosest, normalized, span, tspace, wspace
|
from scgenerator.math import abs2, argclosest, normalized, span, tspace, wspace
|
||||||
from scgenerator.parameter import Parameters
|
from scgenerator.parameter import Parameters
|
||||||
from scgenerator.physics import fiber, materials, plasma, pulse, units
|
from scgenerator.physics import fiber, materials, plasma, pulse, units
|
||||||
|
|||||||
@@ -1,91 +1,43 @@
|
|||||||
import os
|
import os
|
||||||
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Literal, Optional, Set
|
from typing import Any, Dict, Literal, Optional, Set
|
||||||
|
|
||||||
ENVIRON_KEY_BASE = "SCGENERATOR_"
|
from pydantic import ImportString, NonNegativeFloat, ValidationInfo, model_validator
|
||||||
TMP_FOLDER_KEY_BASE = ENVIRON_KEY_BASE + "SC_TMP_"
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
PREFIX_KEY_BASE = ENVIRON_KEY_BASE + "PREFIX_"
|
|
||||||
|
|
||||||
PBAR_POLICY = ENVIRON_KEY_BASE + "PBAR_POLICY"
|
|
||||||
LOG_FILE_LEVEL = ENVIRON_KEY_BASE + "LOG_FILE_LEVEL"
|
|
||||||
LOG_PRINT_LEVEL = ENVIRON_KEY_BASE + "LOG_PRINT_LEVEL"
|
|
||||||
START_RAY = ENVIRON_KEY_BASE + "START_RAY"
|
|
||||||
NO_RAY = ENVIRON_KEY_BASE + "NO_RAY"
|
|
||||||
OUTPUT_PATH = ENVIRON_KEY_BASE + "OUTPUT_PATH"
|
|
||||||
|
|
||||||
|
|
||||||
global_config: dict[str, dict[str, Any]] = {
|
class LogLevel(Enum):
|
||||||
LOG_FILE_LEVEL: dict(
|
DEBUG = "debug"
|
||||||
help="minimum lvl of message to be saved in the log file",
|
INFO = "info"
|
||||||
choices=["critical", "error", "warning", "info", "debug"],
|
WARNING = "warning"
|
||||||
default=None,
|
ERROR = "error"
|
||||||
type=str,
|
CRITICAL = "critical"
|
||||||
),
|
|
||||||
LOG_PRINT_LEVEL: dict(
|
|
||||||
help="minimum lvl of message to be printed to the standard output",
|
|
||||||
choices=["critical", "error", "warning", "info", "debug"],
|
|
||||||
default="error",
|
|
||||||
type=str,
|
|
||||||
),
|
|
||||||
PBAR_POLICY: dict(
|
|
||||||
help="what to do with progress pars (print them, make them a txt file or nothing), default is print",
|
|
||||||
choices=["print", "file", "both", "none"],
|
|
||||||
default=None,
|
|
||||||
type=str,
|
|
||||||
),
|
|
||||||
START_RAY: dict(action="store_true", help="initialize ray (ray must be installed)", type=bool),
|
|
||||||
NO_RAY: dict(action="store_true", help="force not to use ray", type=bool),
|
|
||||||
OUTPUT_PATH: dict(
|
|
||||||
short_name="-o", help="path to the final output folder", default=None, type=str
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def data_folder(task_id: int) -> Optional[str]:
|
class Config(BaseSettings):
|
||||||
idstr = str(int(task_id))
|
model_config = SettingsConfigDict(validate_default=True, env_prefix="SCG_")
|
||||||
tmp = os.getenv(TMP_FOLDER_KEY_BASE + idstr)
|
|
||||||
return tmp
|
@model_validator(mode="before")
|
||||||
|
@classmethod
|
||||||
|
def sort_log_stuff(
|
||||||
|
self, data: dict[str, Any], validation_info: ValidationInfo
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
if "log_file" in data and "log_output" not in data:
|
||||||
|
data["log_output"] = None
|
||||||
|
|
||||||
|
if "log_file" in data and "log_level" not in data:
|
||||||
|
data["log_level"] = LogLevel.INFO
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
progress_interval: NonNegativeFloat = 2.0
|
||||||
|
log_level: LogLevel = LogLevel.ERROR
|
||||||
|
log_output: ImportString | None = "sys.stderr"
|
||||||
|
log_file: Path | None = None
|
||||||
|
|
||||||
|
|
||||||
def get(key: str, default=None) -> Any:
|
def log_level() -> Set[Literal["critical", "error", "warning", "info", "debug"]]:
|
||||||
str_value = os.environ.get(key)
|
|
||||||
if isinstance(str_value, str):
|
|
||||||
try:
|
|
||||||
t = global_config[key]["type"]
|
|
||||||
if t == bool:
|
|
||||||
return str_value.lower() == "true"
|
|
||||||
return t(str_value)
|
|
||||||
except (ValueError, KeyError):
|
|
||||||
pass
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
def all_environ() -> Dict[str, str]:
|
|
||||||
"""returns a dictionary of all environment variables set by any instance of scgenerator"""
|
|
||||||
d = dict(filter(lambda el: el[0].startswith(ENVIRON_KEY_BASE), os.environ.items()))
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
def output_path() -> Path:
|
|
||||||
p = get(OUTPUT_PATH)
|
|
||||||
if p is not None:
|
|
||||||
return Path(p).resolve()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def pbar_policy() -> Set[Literal["print", "file"]]:
|
|
||||||
policy = get(PBAR_POLICY)
|
|
||||||
if policy == "print" or policy is None:
|
|
||||||
return {"print"}
|
|
||||||
elif policy == "file":
|
|
||||||
return {"file"}
|
|
||||||
elif policy == "both":
|
|
||||||
return {"file", "print"}
|
|
||||||
else:
|
|
||||||
return set()
|
|
||||||
|
|
||||||
|
|
||||||
def log_file_level() -> Set[Literal["critical", "error", "warning", "info", "debug"]]:
|
|
||||||
policy = get(LOG_FILE_LEVEL)
|
policy = get(LOG_FILE_LEVEL)
|
||||||
try:
|
try:
|
||||||
policy = policy.lower()
|
policy = policy.lower()
|
||||||
@@ -105,3 +57,6 @@ def log_print_level() -> Set[Literal["critical", "error", "warning", "info", "de
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG = Config()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from scgenerator.env import log_file_level, log_print_level
|
from scgenerator.env import CONFIG
|
||||||
|
|
||||||
lvl_map: dict[str, int] = dict(
|
lvl_map: dict[str, int] = dict(
|
||||||
debug=logging.DEBUG,
|
debug=logging.DEBUG,
|
||||||
@@ -27,7 +27,7 @@ def get_logger(name=None):
|
|||||||
logging.Logger obj
|
logging.Logger obj
|
||||||
logger
|
logger
|
||||||
"""
|
"""
|
||||||
name = __name__ if name is None else name
|
name = name or __name__
|
||||||
logger = logging.getLogger(name)
|
logger = logging.getLogger(name)
|
||||||
return configure_logger(logger)
|
return configure_logger(logger)
|
||||||
|
|
||||||
@@ -40,29 +40,26 @@ def configure_logger(logger: logging.Logger):
|
|||||||
----------
|
----------
|
||||||
logger : logging.Logger
|
logger : logging.Logger
|
||||||
logger to configure
|
logger to configure
|
||||||
logfile : str or None, optional
|
|
||||||
path to log file
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
logging.Logger obj
|
logging.Logger obj
|
||||||
updated logger
|
updated logger
|
||||||
"""
|
"""
|
||||||
if not hasattr(logger, "already_configured"):
|
if hasattr(logger, "already_configured"):
|
||||||
print_lvl = lvl_map.get(log_print_level(), logging.NOTSET)
|
return logger
|
||||||
file_lvl = lvl_map.get(log_file_level(), logging.NOTSET)
|
log_level = lvl_map.get(CONFIG.log_level.value, logging.NOTSET)
|
||||||
|
if CONFIG.log_file is not None:
|
||||||
if file_lvl > logging.NOTSET:
|
|
||||||
formatter = logging.Formatter("{levelname}: {name}: {message}", style="{")
|
formatter = logging.Formatter("{levelname}: {name}: {message}", style="{")
|
||||||
file_handler1 = logging.FileHandler("scgenerator.log", "a+")
|
file_handler1 = logging.FileHandler(CONFIG.log_file, "a+")
|
||||||
file_handler1.setFormatter(formatter)
|
file_handler1.setFormatter(formatter)
|
||||||
file_handler1.setLevel(file_lvl)
|
file_handler1.setLevel(log_level)
|
||||||
logger.addHandler(file_handler1)
|
logger.addHandler(file_handler1)
|
||||||
if print_lvl > logging.NOTSET:
|
if CONFIG.log_output is not None:
|
||||||
stream_handler = logging.StreamHandler()
|
stream_handler = logging.StreamHandler(CONFIG.log_output)
|
||||||
stream_handler.setLevel(print_lvl)
|
stream_handler.setLevel(log_level)
|
||||||
logger.addHandler(stream_handler)
|
logger.addHandler(stream_handler)
|
||||||
|
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(log_level)
|
||||||
logger.already_configured = True
|
logger.already_configured = True
|
||||||
return logger
|
return logger
|
||||||
|
|||||||
7
tests/test_logger.py
Normal file
7
tests/test_logger.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import scgenerator as sc
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_logger():
|
||||||
|
assert sc.get_logger() is sc.get_logger()
|
||||||
|
assert sc.get_logger("this_test") is sc.get_logger("this_test")
|
||||||
|
assert sc.get_logger("this_test") is not sc.get_logger()
|
||||||
Reference in New Issue
Block a user