Skip to content

Commit 069764d

Browse files
committed
✨⬇️ Added pydantic_v1 support and downgraded dependency.
1 parent 14645c4 commit 069764d

File tree

14 files changed

+255
-75
lines changed

14 files changed

+255
-75
lines changed

README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ if logger_loader.config.extra.http_json_enabled:
290290
)
291291
```
292292

293-
[**`app.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/app.py):
293+
[**`main.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/main.py):
294294

295295
```python
296296
from typing import Union
@@ -338,28 +338,28 @@ cd ./examples/advanced
338338
# Install python dependencies for examples:
339339
pip install -r ./requirements.txt
340340
341-
uvicorn app:app --host=0.0.0.0 --port=8000
341+
uvicorn main:app --host=0.0.0.0 --port=8000
342342
```
343343

344344
**Output**:
345345

346346
```txt
347-
[2023-09-01 12:37:38.569 +09:00 | TRACE | beans_logging._base:499]: Intercepted modules: ['watchfiles.watcher', 'asyncio', 'watchfiles', 'concurrent', 'dotenv', 'concurrent.futures', 'fastapi', 'dotenv.main', 'uvicorn', 'watchfiles.main']; Muted modules: ['uvicorn.error', 'uvicorn.access'];
348-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.server:76]: Started server process [22599]
349-
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
350-
[2023-09-01 12:37:38.579 +09:00 | INFO | app:21]: Preparing to startup...
351-
[2023-09-01 12:37:38.580 +09:00 | OK | app:22]: Finished preparation to startup.
352-
[2023-09-01 12:37:38.580 +09:00 | INFO | app:23]: API version: 0.0.1-000000
353-
[2023-09-01 12:37:38.580 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
354-
[2023-09-01 12:37:38.582 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
355-
[2023-09-01 12:37:48.487 +09:00 | DEBUG | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1"
356-
[2023-09-01 12:37:48.488 +09:00 | OK | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.5ms
357-
^C[2023-09-01 12:37:51.845 +09:00 | INFO | uvicorn.server:264]: Shutting down
358-
[2023-09-01 12:37:51.949 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
359-
[2023-09-01 12:37:51.951 +09:00 | INFO | app:26]: Praparing to shutdown...
360-
[2023-09-01 12:37:51.952 +09:00 | OK | app:27]: Finished preparation to shutdown.
361-
[2023-09-01 12:37:51.952 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
362-
[2023-09-01 12:37:51.953 +09:00 | INFO | uvicorn.server:86]: Finished server process [22599]
347+
[2023-09-01 14:55:11.724 +09:00 | TRACE | beans_logging._base:576]: Intercepted modules: ['watchfiles.watcher', 'dotenv', 'asyncio', 'dotenv.main', 'watchfiles.main', 'concurrent.futures', 'uvicorn', 'fastapi', 'concurrent', 'watchfiles']; Muted modules: ['uvicorn.access', 'uvicorn.error'];
348+
[2023-09-01 14:55:11.740 +09:00 | INFO | uvicorn.server:76]: Started server process [17146]
349+
[2023-09-01 14:55:11.740 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
350+
[2023-09-01 14:55:11.741 +09:00 | INFO | main:21]: Preparing to startup...
351+
[2023-09-01 14:55:11.741 +09:00 | OK | main:22]: Finished preparation to startup.
352+
[2023-09-01 14:55:11.741 +09:00 | INFO | main:23]: API version: 0.0.1-000000
353+
[2023-09-01 14:55:11.741 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
354+
[2023-09-01 14:55:11.745 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
355+
[2023-09-01 14:55:17.417 +09:00 | DEBUG | anyio._backends._asyncio:833]: [f635ebbc3f2348db9dcff681be1bd52a] 127.0.0.1 - "GET / HTTP/1.1"
356+
[2023-09-01 14:55:17.418 +09:00 | OK | anyio._backends._asyncio:833]: [f635ebbc3f2348db9dcff681be1bd52a] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.7ms
357+
^C[2023-09-01 14:55:18.729 +09:00 | INFO | uvicorn.server:264]: Shutting down
358+
[2023-09-01 14:55:18.831 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
359+
[2023-09-01 14:55:18.834 +09:00 | INFO | main:26]: Praparing to shutdown...
360+
[2023-09-01 14:55:18.835 +09:00 | OK | main:27]: Finished preparation to shutdown.
361+
[2023-09-01 14:55:18.837 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
362+
[2023-09-01 14:55:18.837 +09:00 | INFO | uvicorn.server:86]: Finished server process [17146]
363363
```
364364

365365
---

beans_logging/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
from ._base import Logger, logger, LoggerLoader
44
from .schemas import LoggerConfigPM
5-
from ._const import WarnEnum
5+
from ._consts import WarnEnum
66
from .__version__ import __version__

beans_logging/_base.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
import yaml
1212
from loguru import logger
1313
from loguru._logger import Logger
14-
from pydantic import validate_call
14+
import pydantic
15+
16+
if "2.0.0" <= pydantic.__version__:
17+
from pydantic import validate_call
18+
else:
19+
from pydantic import validate_arguments as validate_call
1520

1621
## Internal modules
1722
from ._utils import create_dir, deep_merge
@@ -168,7 +173,11 @@ def update_config(self, config: Union[LoggerConfigPM, Dict[str, Any]]):
168173
"""
169174

170175
if isinstance(config, dict):
171-
_config_dict = self.config.model_dump()
176+
if "2.0.0" <= pydantic.__version__:
177+
_config_dict = self.config.model_dump()
178+
else:
179+
_config_dict = self.config.dict()
180+
172181
_merged_dict = deep_merge(_config_dict, config)
173182
try:
174183
self.config = LoggerConfigPM(**_merged_dict)
@@ -219,7 +228,11 @@ def _load_config_file(self):
219228
return
220229

221230
_new_config_dict = _new_config_dict["logger"]
222-
_config_dict = self.config.model_dump()
231+
if "2.0.0" <= pydantic.__version__:
232+
_config_dict = self.config.model_dump()
233+
else:
234+
_config_dict = self.config.dict()
235+
223236
_merged_dict = deep_merge(_config_dict, _new_config_dict)
224237
self.config = LoggerConfigPM(**_merged_dict)
225238
except Exception:
@@ -240,7 +253,11 @@ def _load_config_file(self):
240253
return
241254

242255
_new_config_dict = _new_config_dict["logger"]
243-
_config_dict = self.config.model_dump()
256+
if "2.0.0" <= pydantic.__version__:
257+
_config_dict = self.config.model_dump()
258+
else:
259+
_config_dict = self.config.dict()
260+
244261
_merged_dict = deep_merge(_config_dict, _new_config_dict)
245262
self.config = LoggerConfigPM(**_merged_dict)
246263
except Exception:
@@ -252,7 +269,9 @@ def _load_config_file(self):
252269
# try:
253270
# import toml
254271

255-
# with open(self.config_file_path, "r", encoding="utf-8") as _config_file:
272+
# with open(
273+
# self.config_file_path, "r", encoding="utf-8"
274+
# ) as _config_file:
256275
# _new_config_dict = toml.load(_config_file) or {}
257276
# if "logger" not in _new_config_dict:
258277
# logger.warning(
@@ -261,7 +280,11 @@ def _load_config_file(self):
261280
# return
262281

263282
# _new_config_dict = _new_config_dict["logger"]
264-
# _config_dict = self.config.model_dump()
283+
# if "2.0.0" <= pydantic.__version__:
284+
# _config_dict = self.config.model_dump()
285+
# else:
286+
# _config_dict = self.config.dict()
287+
265288
# _merged_dict = deep_merge(_config_dict, _new_config_dict)
266289
# self.config = LoggerConfigPM(**_merged_dict)
267290
# except Exception:

beans_logging/_const.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

beans_logging/_consts.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from enum import Enum
4+
5+
6+
class WarnEnum(str, Enum):
7+
ERROR = "ERROR"
8+
ALWAYS = "ALWAYS"
9+
DEBUG = "DEBUG"
10+
IGNORE = "IGNORE"
11+
12+
13+
class LogLevelEnum(str, Enum):
14+
TRACE = "TRACE"
15+
DEBUG = "DEBUG"
16+
INFO = "INFO"
17+
SUCCESS = "SUCCESS"
18+
WARNING = "WARNING"
19+
ERROR = "ERROR"
20+
CRITICAL = "CRITICAL"

beans_logging/_utils.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
# -*- coding: utf-8 -*-
22

33
import os
4+
import sys
45
import copy
56
import errno
67

78
from loguru import logger
8-
from pydantic import validate_call
9+
import pydantic
910

10-
from ._const import WarnEnum
11+
if "2.0.0" <= pydantic.__version__:
12+
from pydantic import validate_call
13+
else:
14+
from pydantic import validate_arguments as validate_call
15+
16+
from ._consts import WarnEnum
1117

1218

1319
@validate_call
@@ -16,13 +22,13 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):
1622
1723
Args:
1824
create_dir (str, required): Create directory path.
19-
warn_mode (str, optional): Warning message mode, for example: 'LOG', 'DEBUG', 'QUIET'. Defaults to "QUIET".
25+
warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'. Defaults to "DEBUG".
2026
"""
2127

2228
if not os.path.isdir(create_dir):
2329
try:
2430
_message = f"Creaing '{create_dir}' directory..."
25-
if warn_mode == WarnEnum.LOG:
31+
if warn_mode == WarnEnum.ALWAYS:
2632
logger.info(_message)
2733
elif warn_mode == WarnEnum.DEBUG:
2834
logger.debug(_message)
@@ -36,7 +42,7 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):
3642
raise
3743

3844
_message = f"Successfully created '{create_dir}' directory."
39-
if warn_mode == WarnEnum.LOG:
45+
if warn_mode == WarnEnum.ALWAYS:
4046
logger.success(_message)
4147
elif warn_mode == WarnEnum.DEBUG:
4248
logger.debug(_message)
@@ -67,3 +73,28 @@ def deep_merge(dict1: dict, dict2: dict) -> dict:
6773
_merged[_key] = copy.deepcopy(_val)
6874

6975
return _merged
76+
77+
78+
def get_default_logs_dir() -> str:
79+
"""Return default logs directory path (current working directory + 'logs').
80+
81+
Returns:
82+
str: Default logs directory path.
83+
"""
84+
85+
return os.path.join(os.getcwd(), "logs")
86+
87+
88+
def get_app_name() -> str:
89+
"""Return application name (sys.argv[0]).
90+
91+
Returns:
92+
str: Application name.
93+
"""
94+
95+
return (
96+
os.path.splitext(os.path.basename(sys.argv[0]))[0]
97+
.strip()
98+
.replace(" ", "-")
99+
.lower()
100+
)

beans_logging/fastapi/_handlers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
from typing import Union, Callable
44

5-
from pydantic import validate_call
5+
import pydantic
6+
7+
if "2.0.0" <= pydantic.__version__:
8+
from pydantic import validate_call
9+
else:
10+
from pydantic import validate_arguments as validate_call
611

712
from beans_logging import LoggerLoader
813

beans_logging/schemas/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import pydantic
4+
5+
if "2.0.0" <= pydantic.__version__:
6+
from .config import LoggerConfigPM
7+
else:
8+
from .config_v1 import LoggerConfigPM

beans_logging/schemas.py renamed to beans_logging/schemas/config.py

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
import os
4-
import sys
53
import datetime
6-
from enum import Enum
74
from typing import List
85

96
from pydantic import (
@@ -15,34 +12,14 @@
1512
ConfigDict,
1613
)
1714

18-
19-
def _get_logs_dir() -> str:
20-
return os.path.join(os.getcwd(), "logs")
21-
22-
23-
def _get_app_name() -> str:
24-
return (
25-
os.path.splitext(os.path.basename(sys.argv[0]))[0]
26-
.strip()
27-
.replace(" ", "-")
28-
.lower()
29-
)
15+
from .._consts import LogLevelEnum
16+
from .._utils import get_default_logs_dir, get_app_name
3017

3118

3219
class ExtraBaseModel(BaseModel):
3320
model_config = ConfigDict(extra="allow")
3421

3522

36-
class LevelEnum(str, Enum):
37-
TRACE = "TRACE"
38-
DEBUG = "DEBUG"
39-
INFO = "INFO"
40-
SUCCESS = "SUCCESS"
41-
WARNING = "WARNING"
42-
ERROR = "ERROR"
43-
CRITICAL = "CRITICAL"
44-
45-
4623
class StdHandlerPM(ExtraBaseModel):
4724
enabled: bool = Field(default=True)
4825

@@ -104,7 +81,7 @@ def _check_log_path(self) -> "JsonHandlersPM":
10481

10582
class FilePM(ExtraBaseModel):
10683
logs_dir: constr(strip_whitespace=True) = Field(
107-
default_factory=_get_logs_dir, min_length=2, max_length=1023
84+
default_factory=get_default_logs_dir, min_length=2, max_length=1023
10885
)
10986
rotate_size: int = Field(
11087
default=10_000_000, ge=1_000, lt=1_000_000_000 # 10MB = 10 * 1000 * 1000
@@ -143,11 +120,11 @@ class ExtraPM(ExtraBaseModel):
143120

144121
class LoggerConfigPM(ExtraBaseModel):
145122
app_name: constr(strip_whitespace=True) = Field(
146-
default_factory=_get_app_name,
123+
default_factory=get_app_name,
147124
min_length=1,
148125
max_length=127,
149126
)
150-
level: LevelEnum = Field(default=LevelEnum.INFO)
127+
level: LogLevelEnum = Field(default=LogLevelEnum.INFO)
151128
use_backtrace: bool = Field(default=True)
152129
use_diagnose: bool = Field(default=False)
153130
stream: StreamPM = Field(default_factory=StreamPM)

0 commit comments

Comments
 (0)