Skip to content

Commit bc2645b

Browse files
authored
Merge pull request #31 from bybatkhuu/dev
Simplify Pydantic version checks and reorganize schemas
2 parents 0dd3bb0 + 3921b4a commit bc2645b

File tree

6 files changed

+173
-224
lines changed

6 files changed

+173
-224
lines changed

src/beans_logging/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from ._base import Logger, logger, LoggerLoader
2-
from .schemas import LoggerConfigPM
3-
from ._consts import WarnEnum
2+
from .config import LoggerConfigPM
3+
from ._constants import WarnEnum
44
from .__version__ import __version__
55

66

src/beans_logging/_base.py

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,13 @@
99
import yaml
1010
from loguru import logger
1111
from loguru._logger import Logger
12-
import pydantic
13-
14-
if "2.0.0" <= pydantic.__version__:
15-
from pydantic import validate_call
16-
else:
17-
from pydantic import validate_arguments as validate_call
12+
from pydantic import validate_call
1813

1914
# Internal modules
2015
from ._utils import create_dir, deep_merge
2116
from ._handlers import InterceptHandler
2217
from .rotation import RotationChecker
23-
from .schemas import LoggerConfigPM
18+
from .config import LoggerConfigPM
2419
from .sinks import std_sink
2520
from .formats import json_format
2621
from .filters import (
@@ -73,13 +68,13 @@ def __init__(
7368
"""LoggerLoader constructor method.
7469
7570
Args:
76-
config (LoggerConfigPM | dict | None], optional): New logger config to update loaded config.
71+
config (LoggerConfigPM | dict | None, optional): New logger config to update loaded config.
7772
Defaults to None.
78-
config_file_path (str , optional): Logger config file path. Defaults to
73+
config_file_path (str , optional): Logger config file path. Defaults to
7974
`LoggerLoader._CONFIG_FILE_PATH`.
80-
auto_config_file (bool , optional): Indicates whether to load logger config
75+
auto_config_file (bool , optional): Indicates whether to load logger config
8176
file or not. Defaults to True.
82-
auto_load (bool , optional): Indicates whether to load logger
77+
auto_load (bool , optional): Indicates whether to load logger
8378
handlers or not. Defaults to False.
8479
"""
8580

@@ -171,11 +166,7 @@ def update_config(self, config: LoggerConfigPM | dict[str, Any]):
171166
"""
172167

173168
if isinstance(config, dict):
174-
if "2.0.0" <= pydantic.__version__:
175-
_config_dict = self.config.model_dump()
176-
else:
177-
_config_dict = self.config.dict()
178-
169+
_config_dict = self.config.model_dump()
179170
_merged_dict = deep_merge(_config_dict, config)
180171
try:
181172
self.config = LoggerConfigPM(**_merged_dict)
@@ -224,10 +215,7 @@ def _load_config_file(self):
224215
return
225216

226217
_new_config_dict = _new_config_dict["logger"]
227-
if "2.0.0" <= pydantic.__version__:
228-
_config_dict = self.config.model_dump()
229-
else:
230-
_config_dict = self.config.dict()
218+
_config_dict = self.config.model_dump()
231219

232220
_merged_dict = deep_merge(_config_dict, _new_config_dict)
233221
self.config = LoggerConfigPM(**_merged_dict)
@@ -247,10 +235,7 @@ def _load_config_file(self):
247235
return
248236

249237
_new_config_dict = _new_config_dict["logger"]
250-
if "2.0.0" <= pydantic.__version__:
251-
_config_dict = self.config.model_dump()
252-
else:
253-
_config_dict = self.config.dict()
238+
_config_dict = self.config.model_dump()
254239

255240
_merged_dict = deep_merge(_config_dict, _new_config_dict)
256241
self.config = LoggerConfigPM(**_merged_dict)
@@ -274,10 +259,7 @@ def _load_config_file(self):
274259
# return
275260

276261
# _new_config_dict = _new_config_dict["logger"]
277-
# if "2.0.0" <= pydantic.__version__:
278-
# _config_dict = self.config.model_dump()
279-
# else:
280-
# _config_dict = self.config.dict()
262+
# _config_dict = self.config.model_dump()
281263

282264
# _merged_dict = deep_merge(_config_dict, _new_config_dict)
283265
# self.config = LoggerConfigPM(**_merged_dict)
File renamed without changes.

src/beans_logging/_utils.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@
44
import errno
55

66
from loguru import logger
7-
import pydantic
7+
from pydantic import validate_call
88

9-
if "2.0.0" <= pydantic.__version__:
10-
from pydantic import validate_call
11-
else:
12-
from pydantic import validate_arguments as validate_call
13-
14-
from ._consts import WarnEnum
9+
from ._constants import WarnEnum
1510

1611

1712
@validate_call
@@ -74,26 +69,33 @@ def deep_merge(dict1: dict, dict2: dict) -> dict:
7469
return _merged
7570

7671

77-
def get_default_logs_dir() -> str:
78-
"""Return default logs directory path (current working directory + 'logs').
79-
80-
Returns:
81-
str: Default logs directory path.
82-
"""
83-
84-
return os.path.join(os.getcwd(), "logs")
85-
72+
@validate_call
73+
def get_slug_name(file_path: str | None = None) -> str:
74+
"""Slugify the file name from the given file path or the current script's file path.
8675
87-
def get_app_name() -> str:
88-
"""Return application name (sys.argv[0]).
76+
Args:
77+
file_path (str | None, optional): The file path to slugify. If None, uses the current script's file path.
78+
Defaults to None.
8979
9080
Returns:
91-
str: Application name.
81+
str: The slugified file name.
9282
"""
9383

94-
return (
95-
os.path.splitext(os.path.basename(sys.argv[0]))[0]
84+
if not file_path:
85+
file_path = sys.argv[0]
86+
87+
_slug_name = (
88+
os.path.splitext(os.path.basename(file_path))[0]
9689
.strip()
9790
.replace(" ", "-")
91+
.replace("_", "-")
9892
.lower()
9993
)
94+
return _slug_name
95+
96+
97+
__all__ = [
98+
"create_dir",
99+
"deep_merge",
100+
"get_slug_name",
101+
]

src/beans_logging/config.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import os
2+
import datetime
3+
from typing import Any
4+
from typing_extensions import Self
5+
6+
from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
7+
8+
from ._constants import LogLevelEnum
9+
from ._utils import get_slug_name
10+
11+
12+
class ExtraBaseModel(BaseModel):
13+
model_config = ConfigDict(extra="allow")
14+
15+
16+
class StdHandlerConfigPM(ExtraBaseModel):
17+
enabled: bool = Field(default=True)
18+
19+
20+
class StreamConfigPM(ExtraBaseModel):
21+
use_color: bool = Field(default=True)
22+
use_icon: bool = Field(default=False)
23+
format_str: str = Field(
24+
default=(
25+
"[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{level_short:<5}</level> | <w>{name}:{line}</w>]: "
26+
"<level>{message}</level>"
27+
),
28+
min_length=8,
29+
max_length=512,
30+
)
31+
std_handler: StdHandlerConfigPM = Field(default_factory=StdHandlerConfigPM)
32+
33+
34+
class LogHandlersConfigPM(ExtraBaseModel):
35+
enabled: bool = Field(default=False)
36+
format_str: str = Field(
37+
default="[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {level_short:<5} | {name}:{line}]: {message}",
38+
min_length=8,
39+
max_length=512,
40+
)
41+
log_path: str = Field(
42+
default="{app_name}.std.all.log", min_length=4, max_length=1024
43+
)
44+
err_path: str = Field(
45+
default="{app_name}.std.err.log", min_length=4, max_length=1024
46+
)
47+
48+
@model_validator(mode="after")
49+
def _check_log_path(self) -> Self:
50+
if self.log_path == self.err_path:
51+
raise ValueError(
52+
f"`log_path` and `err_path` attributes have same value: '{self.log_path}', must be different!"
53+
)
54+
55+
return self
56+
57+
58+
class JsonHandlersConfigPM(ExtraBaseModel):
59+
enabled: bool = Field(default=False)
60+
use_custom: bool = Field(default=False)
61+
log_path: str = Field(
62+
default="{app_name}.json.all.log", min_length=4, max_length=1024
63+
)
64+
err_path: str = Field(
65+
default="{app_name}.json.err.log", min_length=4, max_length=1024
66+
)
67+
68+
@model_validator(mode="after")
69+
def _check_log_path(self) -> Self:
70+
if self.log_path == self.err_path:
71+
raise ValueError(
72+
f"`log_path` and `err_path` attributes have same value: '{self.log_path}', must be different!"
73+
)
74+
75+
return self
76+
77+
78+
class FileConfigPM(ExtraBaseModel):
79+
logs_dir: str = Field(
80+
default_factory=lambda: os.path.join(os.getcwd(), "logs"),
81+
min_length=2,
82+
max_length=1024,
83+
)
84+
rotate_size: int = Field(
85+
default=10_000_000, ge=1_000, lt=1_000_000_000 # 10MB = 10 * 1000 * 1000
86+
)
87+
rotate_time: datetime.time = Field(default_factory=lambda: datetime.time(0, 0, 0))
88+
backup_count: int = Field(default=90, ge=1)
89+
encoding: str = Field(default="utf8", min_length=2, max_length=31)
90+
log_handlers: LogHandlersConfigPM = Field(default_factory=LogHandlersConfigPM)
91+
json_handlers: JsonHandlersConfigPM = Field(default_factory=JsonHandlersConfigPM)
92+
93+
@field_validator("rotate_time", mode="before")
94+
@classmethod
95+
def _check_rotate_time(cls, val: Any) -> Any:
96+
if isinstance(val, str):
97+
val = datetime.time.fromisoformat(val)
98+
99+
return val
100+
101+
102+
class AutoLoadConfigPM(ExtraBaseModel):
103+
enabled: bool = Field(default=True)
104+
only_base: bool = Field(default=False)
105+
ignore_modules: list[str] = Field(default=[])
106+
107+
108+
class InterceptConfigPM(ExtraBaseModel):
109+
auto_load: AutoLoadConfigPM = Field(default_factory=AutoLoadConfigPM)
110+
include_modules: list[str] = Field(default=[])
111+
mute_modules: list[str] = Field(default=[])
112+
113+
114+
class ExtraConfigPM(ExtraBaseModel):
115+
pass
116+
117+
118+
class LoggerConfigPM(ExtraBaseModel):
119+
app_name: str = Field(default_factory=get_slug_name, min_length=1, max_length=128)
120+
level: LogLevelEnum = Field(default=LogLevelEnum.INFO)
121+
use_backtrace: bool = Field(default=True)
122+
use_diagnose: bool = Field(default=False)
123+
stream: StreamConfigPM = Field(default_factory=StreamConfigPM)
124+
file: FileConfigPM = Field(default_factory=FileConfigPM)
125+
intercept: InterceptConfigPM = Field(default_factory=InterceptConfigPM)
126+
extra: ExtraConfigPM | None = Field(default_factory=ExtraConfigPM)
127+
128+
129+
__all__ = [
130+
"StdHandlerConfigPM",
131+
"StreamConfigPM",
132+
"LogHandlersConfigPM",
133+
"JsonHandlersConfigPM",
134+
"FileConfigPM",
135+
"AutoLoadConfigPM",
136+
"InterceptConfigPM",
137+
"LoggerConfigPM",
138+
]

0 commit comments

Comments
 (0)