beans-logging 7.1.0__tar.gz → 8.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {beans_logging-7.1.0/src/beans_logging.egg-info → beans_logging-8.0.1}/PKG-INFO +19 -51
  2. {beans_logging-7.1.0 → beans_logging-8.0.1}/README.md +17 -49
  3. {beans_logging-7.1.0 → beans_logging-8.0.1}/pyproject.toml +0 -5
  4. beans_logging-8.0.1/requirements/requirements.fastapi.txt +1 -0
  5. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/__init__.py +5 -1
  6. beans_logging-8.0.1/src/beans_logging/__version__.py +1 -0
  7. beans_logging-8.0.1/src/beans_logging/_builder.py +132 -0
  8. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/_core.py +8 -7
  9. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/config.py +65 -39
  10. beans_logging-8.0.1/src/beans_logging/constants.py +46 -0
  11. beans_logging-7.1.0/src/beans_logging/_intercept.py → beans_logging-8.0.1/src/beans_logging/intercepters.py +2 -2
  12. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/schemas.py +2 -6
  13. {beans_logging-7.1.0 → beans_logging-8.0.1/src/beans_logging.egg-info}/PKG-INFO +19 -51
  14. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging.egg-info/SOURCES.txt +2 -2
  15. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging.egg-info/requires.txt +1 -1
  16. beans_logging-7.1.0/requirements/requirements.fastapi.txt +0 -1
  17. beans_logging-7.1.0/src/beans_logging/__version__.py +0 -1
  18. beans_logging-7.1.0/src/beans_logging/_builder.py +0 -131
  19. beans_logging-7.1.0/src/beans_logging/_constants.py +0 -30
  20. {beans_logging-7.1.0 → beans_logging-8.0.1}/.python-version +0 -0
  21. {beans_logging-7.1.0 → beans_logging-8.0.1}/LICENSE.txt +0 -0
  22. {beans_logging-7.1.0 → beans_logging-8.0.1}/requirements/requirements.build.txt +0 -0
  23. {beans_logging-7.1.0 → beans_logging-8.0.1}/requirements/requirements.dev.txt +0 -0
  24. {beans_logging-7.1.0 → beans_logging-8.0.1}/requirements/requirements.docs.txt +0 -0
  25. {beans_logging-7.1.0 → beans_logging-8.0.1}/requirements/requirements.test.txt +0 -0
  26. {beans_logging-7.1.0 → beans_logging-8.0.1}/requirements.txt +0 -0
  27. {beans_logging-7.1.0 → beans_logging-8.0.1}/setup.cfg +0 -0
  28. {beans_logging-7.1.0 → beans_logging-8.0.1}/setup.py +0 -0
  29. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/auto.py +0 -0
  30. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/filters.py +0 -0
  31. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/formats.py +0 -0
  32. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/rotators.py +0 -0
  33. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging/sinks.py +0 -0
  34. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging.egg-info/dependency_links.txt +0 -0
  35. {beans_logging-7.1.0 → beans_logging-8.0.1}/src/beans_logging.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beans_logging
3
- Version: 7.1.0
3
+ Version: 8.0.1
4
4
  Summary: 'beans-logging' is a python package for simple logger and easily managing logs.
5
5
  Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/bybatkhuu/module-python-logging
@@ -25,7 +25,7 @@ Requires-Dist: pydantic[timezone]<3.0.0,>=2.5.3
25
25
  Requires-Dist: loguru<1.0.0,>=0.7.3
26
26
  Requires-Dist: potato_util<1.0.0,>=0.2.0
27
27
  Provides-Extra: fastapi
28
- Requires-Dist: beans-logging-fastapi<2.0.0,>=1.0.0; extra == "fastapi"
28
+ Requires-Dist: beans-logging-fastapi<4.0.0,>=3.0.0; extra == "fastapi"
29
29
  Provides-Extra: test
30
30
  Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
31
31
  Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
@@ -102,42 +102,7 @@ It is a `Loguru` based custom logging package for python projects.
102
102
  - Install [**git**](https://git-scm.com/downloads)
103
103
  - Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
104
104
 
105
- ### 2. 📥 Download or clone the repository
106
-
107
- [TIP] Skip this step, if you're going to install the package directly from **PyPi** or **GitHub** repository.
108
-
109
- **2.1.** Prepare projects directory (if not exists):
110
-
111
- ```sh
112
- # Create projects directory:
113
- mkdir -pv ~/workspaces/projects
114
-
115
- # Enter into projects directory:
116
- cd ~/workspaces/projects
117
- ```
118
-
119
- **2.2.** Follow one of the below options **[A]**, **[B]** or **[C]**:
120
-
121
- **OPTION A.** Clone the repository:
122
-
123
- ```sh
124
- git clone https://github.com/bybatkhuu/module-python-logging.git && \
125
- cd module-python-logging
126
- ```
127
-
128
- **OPTION B.** Clone the repository (for **DEVELOPMENT**: git + ssh key):
129
-
130
- ```sh
131
- git clone git@github.com:bybatkhuu/module-python-logging.git && \
132
- cd module-python-logging
133
- ```
134
-
135
- **OPTION C.** Download source code:
136
-
137
- 1. Download archived **zip** file from [**releases**](https://github.com/bybatkhuu/module-python-logging/releases).
138
- 2. Extract it into the projects directory.
139
-
140
- ### 3. 📦 Install the package
105
+ ### 2. 📦 Install the package
141
106
 
142
107
  [NOTE] Choose one of the following methods to install the package **[A ~ F]**:
143
108
 
@@ -156,6 +121,9 @@ pip install git+https://github.com/bybatkhuu/module-python-logging.git
156
121
  **OPTION C.** Install from the downloaded **source code**:
157
122
 
158
123
  ```sh
124
+ git clone https://github.com/bybatkhuu/module-python-logging.git && \
125
+ cd ./module-python-logging
126
+
159
127
  # Install directly from the source code:
160
128
  pip install .
161
129
 
@@ -339,30 +307,30 @@ logger:
339
307
  mute_modules: []
340
308
  handlers:
341
309
  default.all.std_handler:
342
- type: STD
310
+ enabled: true
311
+ h_type: STD
343
312
  format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
344
313
  colorize: true
345
- enabled: true
346
314
  default.all.file_handler:
347
- type: FILE
348
- sink: "{app_name}.all.log"
349
315
  enabled: false
316
+ h_type: FILE
317
+ sink: "{app_name}.all.log"
350
318
  default.err.file_handler:
351
- type: FILE
319
+ enabled: false
320
+ h_type: FILE
352
321
  sink: "{app_name}.err.log"
353
322
  error: true
354
- enabled: false
355
323
  default.all.json_handler:
356
- type: FILE
357
- sink: "json/{app_name}.json.all.log"
358
- serialize: true
359
324
  enabled: false
325
+ h_type: FILE
326
+ sink: "json/{app_name}.all.json.log"
327
+ serialize: true
360
328
  default.err.json_handler:
361
- type: FILE
362
- sink: "json/{app_name}.json.err.log"
329
+ enabled: false
330
+ h_type: FILE
331
+ sink: "json/{app_name}.err.json.log"
363
332
  serialize: true
364
333
  error: true
365
- enabled: false
366
334
  extra:
367
335
  ```
368
336
 
@@ -415,7 +383,7 @@ To build the documentation, run the following command:
415
383
  pip install -r ./requirements/requirements.docs.txt
416
384
 
417
385
  # Serve documentation locally (for development):
418
- mkdocs serve -a 0.0.0.0:8000
386
+ mkdocs serve -a 0.0.0.0:8000 --livereload
419
387
  # Or use the docs script:
420
388
  ./scripts/docs.sh
421
389
 
@@ -40,42 +40,7 @@ It is a `Loguru` based custom logging package for python projects.
40
40
  - Install [**git**](https://git-scm.com/downloads)
41
41
  - Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
42
42
 
43
- ### 2. 📥 Download or clone the repository
44
-
45
- [TIP] Skip this step, if you're going to install the package directly from **PyPi** or **GitHub** repository.
46
-
47
- **2.1.** Prepare projects directory (if not exists):
48
-
49
- ```sh
50
- # Create projects directory:
51
- mkdir -pv ~/workspaces/projects
52
-
53
- # Enter into projects directory:
54
- cd ~/workspaces/projects
55
- ```
56
-
57
- **2.2.** Follow one of the below options **[A]**, **[B]** or **[C]**:
58
-
59
- **OPTION A.** Clone the repository:
60
-
61
- ```sh
62
- git clone https://github.com/bybatkhuu/module-python-logging.git && \
63
- cd module-python-logging
64
- ```
65
-
66
- **OPTION B.** Clone the repository (for **DEVELOPMENT**: git + ssh key):
67
-
68
- ```sh
69
- git clone git@github.com:bybatkhuu/module-python-logging.git && \
70
- cd module-python-logging
71
- ```
72
-
73
- **OPTION C.** Download source code:
74
-
75
- 1. Download archived **zip** file from [**releases**](https://github.com/bybatkhuu/module-python-logging/releases).
76
- 2. Extract it into the projects directory.
77
-
78
- ### 3. 📦 Install the package
43
+ ### 2. 📦 Install the package
79
44
 
80
45
  [NOTE] Choose one of the following methods to install the package **[A ~ F]**:
81
46
 
@@ -94,6 +59,9 @@ pip install git+https://github.com/bybatkhuu/module-python-logging.git
94
59
  **OPTION C.** Install from the downloaded **source code**:
95
60
 
96
61
  ```sh
62
+ git clone https://github.com/bybatkhuu/module-python-logging.git && \
63
+ cd ./module-python-logging
64
+
97
65
  # Install directly from the source code:
98
66
  pip install .
99
67
 
@@ -277,30 +245,30 @@ logger:
277
245
  mute_modules: []
278
246
  handlers:
279
247
  default.all.std_handler:
280
- type: STD
248
+ enabled: true
249
+ h_type: STD
281
250
  format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
282
251
  colorize: true
283
- enabled: true
284
252
  default.all.file_handler:
285
- type: FILE
286
- sink: "{app_name}.all.log"
287
253
  enabled: false
254
+ h_type: FILE
255
+ sink: "{app_name}.all.log"
288
256
  default.err.file_handler:
289
- type: FILE
257
+ enabled: false
258
+ h_type: FILE
290
259
  sink: "{app_name}.err.log"
291
260
  error: true
292
- enabled: false
293
261
  default.all.json_handler:
294
- type: FILE
295
- sink: "json/{app_name}.json.all.log"
296
- serialize: true
297
262
  enabled: false
263
+ h_type: FILE
264
+ sink: "json/{app_name}.all.json.log"
265
+ serialize: true
298
266
  default.err.json_handler:
299
- type: FILE
300
- sink: "json/{app_name}.json.err.log"
267
+ enabled: false
268
+ h_type: FILE
269
+ sink: "json/{app_name}.err.json.log"
301
270
  serialize: true
302
271
  error: true
303
- enabled: false
304
272
  extra:
305
273
  ```
306
274
 
@@ -353,7 +321,7 @@ To build the documentation, run the following command:
353
321
  pip install -r ./requirements/requirements.docs.txt
354
322
 
355
323
  # Serve documentation locally (for development):
356
- mkdocs serve -a 0.0.0.0:8000
324
+ mkdocs serve -a 0.0.0.0:8000 --livereload
357
325
  # Or use the docs script:
358
326
  ./scripts/docs.sh
359
327
 
@@ -31,11 +31,6 @@ classifiers = [
31
31
  ]
32
32
  dynamic = ["version", "dependencies", "optional-dependencies"]
33
33
 
34
- # [tool.setuptools.packages.find]
35
- # where = ["src"]
36
- # include = ["beans_logging*"]
37
- # namespaces = false
38
-
39
34
  [tool.setuptools.dynamic]
40
35
  version = { attr = "beans_logging.__version__.__version__" }
41
36
  dependencies = { file = "./requirements.txt" }
@@ -0,0 +1 @@
1
+ beans-logging-fastapi>=3.0.0,<4.0.0
@@ -1,12 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from .__version__ import __version__
4
- from .config import LoggerConfigPM
4
+ from .schemas import LoguruHandlerPM, LogHandlerPM
5
+ from .config import get_default_handlers, LoggerConfigPM
5
6
  from ._core import Logger, logger, LoggerLoader
6
7
 
7
8
 
8
9
  __all__ = [
9
10
  "__version__",
11
+ "LoguruHandlerPM",
12
+ "LogHandlerPM",
13
+ "get_default_handlers",
10
14
  "LoggerConfigPM",
11
15
  "Logger",
12
16
  "logger",
@@ -0,0 +1 @@
1
+ __version__ = "8.0.1"
@@ -0,0 +1,132 @@
1
+ import os
2
+ from typing import Any
3
+ from pathlib import Path
4
+
5
+ from pydantic import validate_call
6
+
7
+ from .constants import LogHandlerTypeEnum, LogLevelEnum
8
+ from .schemas import LogHandlerPM
9
+ from .config import LoggerConfigPM
10
+ from .sinks import std_sink
11
+ from .formats import json_formatter
12
+ from .filters import (
13
+ use_all_filter,
14
+ use_std_filter,
15
+ use_file_filter,
16
+ use_file_err_filter,
17
+ use_file_json_filter,
18
+ use_file_json_err_filter,
19
+ )
20
+ from .rotators import Rotator
21
+
22
+
23
+ @validate_call
24
+ def build_handler(handler: LogHandlerPM, config: LoggerConfigPM) -> dict[str, Any]:
25
+ """Build handler config as dictionary for Loguru logger to add new handler.
26
+
27
+ Args:
28
+ handler (LogHandlerPM , required): Target log handler model.
29
+ config (LoggerConfigPM, required): Default main config model to fill missing values.
30
+
31
+ Raises:
32
+ ValueError: 'sink' attribute is empty, required for any log handler except std and file handlers!
33
+
34
+ Returns:
35
+ dict[str, Any]: Loguru handler config as dictionary.
36
+ """
37
+
38
+ if handler.sink is None:
39
+ if handler.h_type == LogHandlerTypeEnum.STD:
40
+ handler.sink = std_sink
41
+ else:
42
+ raise ValueError(
43
+ "'sink' attribute is empty, required for any log handler except std handler!"
44
+ )
45
+
46
+ _sink = handler.sink
47
+ if isinstance(_sink, (str, Path)):
48
+ if not os.path.isabs(_sink):
49
+ _sink = os.path.join(config.default.file.logs_dir, _sink)
50
+
51
+ if isinstance(_sink, Path):
52
+ _sink = str(_sink)
53
+
54
+ if "{app_name}" in _sink:
55
+ _sink = _sink.format(app_name=config.app_name)
56
+
57
+ handler.sink = _sink
58
+
59
+ if handler.level is None:
60
+ if handler.error:
61
+ handler.level = config.default.level.err
62
+ else:
63
+ handler.level = config.default.level.base
64
+
65
+ if (handler.custom_serialize is None) and handler.serialize:
66
+ handler.custom_serialize = config.default.custom_serialize
67
+
68
+ if handler.custom_serialize:
69
+ handler.serialize = False
70
+ handler.format_ = json_formatter
71
+
72
+ if (handler.format_ is None) and (not handler.serialize):
73
+ handler.format_ = config.default.format_str
74
+
75
+ if handler.filter_ is None:
76
+ if handler.h_type == LogHandlerTypeEnum.STD:
77
+ handler.filter_ = use_std_filter
78
+ elif handler.h_type == LogHandlerTypeEnum.FILE:
79
+ if handler.serialize or handler.custom_serialize:
80
+ if handler.error:
81
+ handler.filter_ = use_file_json_err_filter
82
+ else:
83
+ handler.filter_ = use_file_json_filter
84
+ else:
85
+ if handler.error:
86
+ handler.filter_ = use_file_err_filter
87
+ else:
88
+ handler.filter_ = use_file_filter
89
+ else:
90
+ handler.filter_ = use_all_filter
91
+
92
+ if handler.backtrace is None:
93
+ handler.backtrace = True
94
+
95
+ if (handler.diagnose is None) and (
96
+ (handler.level == LogLevelEnum.TRACE) or (handler.level == 5)
97
+ ):
98
+ handler.diagnose = True
99
+
100
+ if handler.h_type == LogHandlerTypeEnum.FILE:
101
+ if handler.enqueue is None:
102
+ handler.enqueue = True
103
+
104
+ if handler.rotation is None:
105
+ handler.rotation = Rotator(
106
+ rotate_size=config.default.file.rotate_size,
107
+ rotate_time=config.default.file.rotate_time,
108
+ ).should_rotate
109
+
110
+ if handler.retention is None:
111
+ handler.retention = config.default.file.retention
112
+
113
+ if handler.encoding is None:
114
+ handler.encoding = config.default.file.encoding
115
+
116
+ _handler_dict = handler.model_dump(
117
+ by_alias=True,
118
+ exclude_none=True,
119
+ exclude={
120
+ "enabled",
121
+ "h_type",
122
+ "error",
123
+ "custom_serialize",
124
+ },
125
+ )
126
+
127
+ return _handler_dict
128
+
129
+
130
+ __all__ = [
131
+ "build_handler",
132
+ ]
@@ -17,10 +17,11 @@ from pydantic import validate_call
17
17
  from potato_util import io as io_utils
18
18
 
19
19
  # Internal modules
20
+ from .constants import DEFAULT_LOGURU_HANDLER_NAME, DEFAULT_NO_HANDLER_NAME_PREFIX
20
21
  from .schemas import LogHandlerPM, LoguruHandlerPM
21
22
  from .config import LoggerConfigPM
22
23
  from ._builder import build_handler
23
- from ._intercept import init_intercepter
24
+ from .intercepters import add_intercepter
24
25
 
25
26
 
26
27
  class LoggerLoader:
@@ -52,7 +53,7 @@ class LoggerLoader:
52
53
  **kwargs,
53
54
  ) -> None:
54
55
 
55
- self.handlers_map = {"default.loguru_handler": 0}
56
+ self.handlers_map = {DEFAULT_LOGURU_HANDLER_NAME: 0}
56
57
  if not config:
57
58
  config = LoggerConfigPM()
58
59
 
@@ -63,15 +64,15 @@ class LoggerLoader:
63
64
  self.config_path = config_path
64
65
 
65
66
  if auto_load:
66
- self.load()
67
+ self.load(load_config_file=True)
67
68
 
68
69
  @validate_call
69
- def load(self, load_config_file: bool = True) -> "Logger":
70
+ def load(self, load_config_file: bool = False) -> "Logger":
70
71
  """Load logger handlers based on logger config.
71
72
 
72
73
  Args:
73
74
  load_config_file (bool, optional): Whether to load config from file before loading handlers.
74
- Default is True.
75
+ Default is False.
75
76
 
76
77
  Returns:
77
78
  Logger: Main loguru logger instance.
@@ -84,7 +85,7 @@ class LoggerLoader:
84
85
  for _key, _handler in self.config.handlers.items():
85
86
  self.add_handler(name=_key, handler=_handler)
86
87
 
87
- init_intercepter(config=self.config)
88
+ add_intercepter(config=self.config)
88
89
  return logger
89
90
 
90
91
  def _load_config_file(self) -> None:
@@ -195,7 +196,7 @@ class LoggerLoader:
195
196
 
196
197
  _handler_id = logger.add(**_handler_dict)
197
198
  if not name:
198
- name = f"log_handler.{uuid.uuid4().hex}"
199
+ name = f"{DEFAULT_NO_HANDLER_NAME_PREFIX}{uuid.uuid4().hex}"
199
200
 
200
201
  self.handlers_map[name] = _handler_id
201
202
 
@@ -5,11 +5,19 @@ from typing import Any
5
5
  import potato_util as utils
6
6
  from pydantic import Field, field_validator
7
7
 
8
- from ._constants import LogHandlerTypeEnum, LogLevelEnum
9
- from .schemas import ExtraBaseModel, LogHandlerPM, LoguruHandlerPM
10
-
11
-
12
- def _get_handlers() -> dict[str, LogHandlerPM]:
8
+ from .constants import (
9
+ LogLevelEnum,
10
+ LogHandlerTypeEnum,
11
+ DEFAULT_ALL_STD_HANDLER_NAME,
12
+ DEFAULT_ALL_FILE_HANDLER_NAME,
13
+ DEFAULT_ERR_FILE_HANDLER_NAME,
14
+ DEFAULT_ALL_JSON_HANDLER_NAME,
15
+ DEFAULT_ERR_JSON_HANDLER_NAME,
16
+ )
17
+ from .schemas import ExtraBaseModel, LogHandlerPM
18
+
19
+
20
+ def get_default_handlers() -> dict[str, LogHandlerPM]:
13
21
  """Get default log handlers.
14
22
 
15
23
  Returns:
@@ -17,37 +25,37 @@ def _get_handlers() -> dict[str, LogHandlerPM]:
17
25
  """
18
26
 
19
27
  _log_handlers: dict[str, LogHandlerPM] = {
20
- "default.all.std_handler": LogHandlerPM(
21
- type_=LogHandlerTypeEnum.STD,
28
+ DEFAULT_ALL_STD_HANDLER_NAME: LogHandlerPM(
29
+ h_type=LogHandlerTypeEnum.STD,
22
30
  format_=(
23
31
  "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
24
32
  "<w>{name}:{line}</w>]: <level>{message}</level>"
25
33
  ),
26
34
  colorize=True,
27
35
  ),
28
- "default.all.file_handler": LogHandlerPM(
29
- type_=LogHandlerTypeEnum.FILE,
30
- sink="{app_name}.all.log",
36
+ DEFAULT_ALL_FILE_HANDLER_NAME: LogHandlerPM(
31
37
  enabled=False,
38
+ h_type=LogHandlerTypeEnum.FILE,
39
+ sink="{app_name}.all.log",
32
40
  ),
33
- "default.err.file_handler": LogHandlerPM(
34
- type_=LogHandlerTypeEnum.FILE,
41
+ DEFAULT_ERR_FILE_HANDLER_NAME: LogHandlerPM(
42
+ enabled=False,
43
+ h_type=LogHandlerTypeEnum.FILE,
35
44
  sink="{app_name}.err.log",
36
45
  error=True,
37
- enabled=False,
38
46
  ),
39
- "default.all.json_handler": LogHandlerPM(
40
- type_=LogHandlerTypeEnum.FILE,
41
- sink="json/{app_name}.json.all.log",
42
- serialize=True,
47
+ DEFAULT_ALL_JSON_HANDLER_NAME: LogHandlerPM(
43
48
  enabled=False,
49
+ h_type=LogHandlerTypeEnum.FILE,
50
+ sink="json/{app_name}.all.json.log",
51
+ serialize=True,
44
52
  ),
45
- "default.err.json_handler": LogHandlerPM(
46
- type_=LogHandlerTypeEnum.FILE,
47
- sink="json/{app_name}.json.err.log",
53
+ DEFAULT_ERR_JSON_HANDLER_NAME: LogHandlerPM(
54
+ enabled=False,
55
+ h_type=LogHandlerTypeEnum.FILE,
56
+ sink="json/{app_name}.err.json.log",
48
57
  serialize=True,
49
58
  error=True,
50
- enabled=False,
51
59
  ),
52
60
  }
53
61
 
@@ -131,36 +139,54 @@ class LoggerConfigPM(ExtraBaseModel):
131
139
  )
132
140
  default: DefaultConfigPM = Field(default_factory=DefaultConfigPM)
133
141
  intercept: InterceptConfigPM = Field(default_factory=InterceptConfigPM)
134
- handlers: dict[str, LogHandlerPM] = Field(default_factory=_get_handlers)
142
+ handlers: dict[str, LogHandlerPM] = Field(default_factory=get_default_handlers)
135
143
  extra: ExtraConfigPM | None = Field(default_factory=ExtraConfigPM)
136
144
 
137
145
  @field_validator("handlers", mode="before")
138
146
  @classmethod
139
- def _check_handlers(cls, val: Any) -> Any:
140
- if val:
141
- if not isinstance(val, dict):
147
+ def _check_handlers(cls, val: Any) -> dict[str, LogHandlerPM]:
148
+
149
+ _default_handlers = get_default_handlers()
150
+
151
+ if not val:
152
+ val = _default_handlers
153
+ return val
154
+
155
+ if not isinstance(val, dict):
156
+ raise TypeError(
157
+ f"'handlers' attribute type {type(val).__name__} is invalid, must be a dict of <LogHandlerPM> or dict!"
158
+ )
159
+
160
+ for _key, _handler in val.items():
161
+ if not isinstance(_handler, (LogHandlerPM, dict)):
142
162
  raise TypeError(
143
- f"'handlers' attribute type {type(val).__name__} is invalid, must be a dict of <LogHandlerPM>, "
144
- f"<LoguruHandlerPM> or dict!"
163
+ f"'handlers' attribute's '{_key}' key -> value type {type(_handler).__name__} is invalid, must be "
164
+ f"<LogHandlerPM> or dict!"
165
+ )
166
+
167
+ if isinstance(_handler, LogHandlerPM):
168
+ val[_key] = _handler.model_dump(
169
+ by_alias=True, exclude_unset=True, exclude_none=True
145
170
  )
146
171
 
147
- for _i, _handler in val.items():
148
- if not isinstance(_handler, (LogHandlerPM, LoguruHandlerPM, dict)):
149
- raise TypeError(
150
- f"'handlers' attribute index {_i} type {type(_handler).__name__} is invalid, must be "
151
- f"<LogHandlerPM>, <LoguruHandlerPM> or dict!"
152
- )
172
+ _default_dict = {
173
+ _key: _handler.model_dump(
174
+ by_alias=True, exclude_unset=True, exclude_none=True
175
+ )
176
+ for _key, _handler in _default_handlers.items()
177
+ }
178
+
179
+ if _default_dict != val:
180
+ val = utils.deep_merge(_default_dict, val)
153
181
 
154
- if isinstance(_handler, LoguruHandlerPM):
155
- val[_i] = LogHandlerPM(
156
- **_handler.model_dump(exclude_none=True, exclude_unset=True)
157
- )
158
- elif isinstance(_handler, dict):
159
- val[_i] = LogHandlerPM(**_handler)
182
+ for _key, _handler in val.items():
183
+ val[_key] = LogHandlerPM(**_handler)
160
184
 
161
185
  return val
162
186
 
163
187
 
164
188
  __all__ = [
165
189
  "LoggerConfigPM",
190
+ "InterceptConfigPM",
191
+ "get_default_handlers",
166
192
  ]
@@ -0,0 +1,46 @@
1
+ from enum import Enum
2
+
3
+
4
+ class LogHandlerTypeEnum(str, Enum):
5
+ STD = "STD"
6
+ FILE = "FILE"
7
+ SOCKET = "SOCKET"
8
+ HTTP = "HTTP"
9
+ SYSLOG = "SYSLOG"
10
+ QUEUE = "QUEUE"
11
+ MEMORY = "MEMORY"
12
+ NULL = "NULL"
13
+ CUSTOM = "CUSTOM"
14
+ UNKNOWN = "UNKNOWN"
15
+
16
+
17
+ class LogLevelEnum(str, Enum):
18
+ TRACE = "TRACE"
19
+ DEBUG = "DEBUG"
20
+ INFO = "INFO"
21
+ SUCCESS = "SUCCESS"
22
+ WARNING = "WARNING"
23
+ ERROR = "ERROR"
24
+ CRITICAL = "CRITICAL"
25
+
26
+
27
+ DEFAULT_LOGURU_HANDLER_NAME = "default.loguru.std_handler"
28
+ DEFAULT_ALL_STD_HANDLER_NAME = "default.all.std_handler"
29
+ DEFAULT_ALL_FILE_HANDLER_NAME = "default.all.file_handler"
30
+ DEFAULT_ERR_FILE_HANDLER_NAME = "default.err.file_handler"
31
+ DEFAULT_ALL_JSON_HANDLER_NAME = "default.all.json_handler"
32
+ DEFAULT_ERR_JSON_HANDLER_NAME = "default.err.json_handler"
33
+ DEFAULT_NO_HANDLER_NAME_PREFIX = "log_handler."
34
+
35
+
36
+ __all__ = [
37
+ "LogHandlerTypeEnum",
38
+ "LogLevelEnum",
39
+ "DEFAULT_LOGURU_HANDLER_NAME",
40
+ "DEFAULT_ALL_STD_HANDLER_NAME",
41
+ "DEFAULT_ALL_FILE_HANDLER_NAME",
42
+ "DEFAULT_ERR_FILE_HANDLER_NAME",
43
+ "DEFAULT_ALL_JSON_HANDLER_NAME",
44
+ "DEFAULT_ERR_JSON_HANDLER_NAME",
45
+ "DEFAULT_NO_HANDLER_NAME_PREFIX",
46
+ ]
@@ -45,7 +45,7 @@ class InterceptHandler(Handler):
45
45
 
46
46
 
47
47
  @validate_call
48
- def init_intercepter(config: LoggerConfigPM) -> None:
48
+ def add_intercepter(config: LoggerConfigPM) -> None:
49
49
  """Initialize log interceptor based on provided config.
50
50
 
51
51
  Args:
@@ -102,5 +102,5 @@ def init_intercepter(config: LoggerConfigPM) -> None:
102
102
 
103
103
  __all__ = [
104
104
  "InterceptHandler",
105
- "init_intercepter",
105
+ "add_intercepter",
106
106
  ]
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
19
19
  from loguru import Record, Message
20
20
  from pydantic import BaseModel, Field, ConfigDict, model_validator
21
21
 
22
- from ._constants import LogHandlerTypeEnum, LogLevelEnum
22
+ from .constants import LogHandlerTypeEnum, LogLevelEnum
23
23
 
24
24
 
25
25
  class ExtraBaseModel(BaseModel):
@@ -94,11 +94,7 @@ class LoguruHandlerPM(ExtraBaseModel):
94
94
 
95
95
 
96
96
  class LogHandlerPM(LoguruHandlerPM):
97
- type_: LogHandlerTypeEnum = Field(
98
- default=LogHandlerTypeEnum.UNKNOWN,
99
- validation_alias="type",
100
- serialization_alias="type",
101
- )
97
+ h_type: LogHandlerTypeEnum = Field(default=LogHandlerTypeEnum.UNKNOWN)
102
98
  sink: _SinkType | None = Field(default=None)
103
99
  level: str | int | LogLevelEnum | None = Field(default=None)
104
100
  custom_serialize: bool | None = Field(default=None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beans_logging
3
- Version: 7.1.0
3
+ Version: 8.0.1
4
4
  Summary: 'beans-logging' is a python package for simple logger and easily managing logs.
5
5
  Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/bybatkhuu/module-python-logging
@@ -25,7 +25,7 @@ Requires-Dist: pydantic[timezone]<3.0.0,>=2.5.3
25
25
  Requires-Dist: loguru<1.0.0,>=0.7.3
26
26
  Requires-Dist: potato_util<1.0.0,>=0.2.0
27
27
  Provides-Extra: fastapi
28
- Requires-Dist: beans-logging-fastapi<2.0.0,>=1.0.0; extra == "fastapi"
28
+ Requires-Dist: beans-logging-fastapi<4.0.0,>=3.0.0; extra == "fastapi"
29
29
  Provides-Extra: test
30
30
  Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
31
31
  Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
@@ -102,42 +102,7 @@ It is a `Loguru` based custom logging package for python projects.
102
102
  - Install [**git**](https://git-scm.com/downloads)
103
103
  - Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
104
104
 
105
- ### 2. 📥 Download or clone the repository
106
-
107
- [TIP] Skip this step, if you're going to install the package directly from **PyPi** or **GitHub** repository.
108
-
109
- **2.1.** Prepare projects directory (if not exists):
110
-
111
- ```sh
112
- # Create projects directory:
113
- mkdir -pv ~/workspaces/projects
114
-
115
- # Enter into projects directory:
116
- cd ~/workspaces/projects
117
- ```
118
-
119
- **2.2.** Follow one of the below options **[A]**, **[B]** or **[C]**:
120
-
121
- **OPTION A.** Clone the repository:
122
-
123
- ```sh
124
- git clone https://github.com/bybatkhuu/module-python-logging.git && \
125
- cd module-python-logging
126
- ```
127
-
128
- **OPTION B.** Clone the repository (for **DEVELOPMENT**: git + ssh key):
129
-
130
- ```sh
131
- git clone git@github.com:bybatkhuu/module-python-logging.git && \
132
- cd module-python-logging
133
- ```
134
-
135
- **OPTION C.** Download source code:
136
-
137
- 1. Download archived **zip** file from [**releases**](https://github.com/bybatkhuu/module-python-logging/releases).
138
- 2. Extract it into the projects directory.
139
-
140
- ### 3. 📦 Install the package
105
+ ### 2. 📦 Install the package
141
106
 
142
107
  [NOTE] Choose one of the following methods to install the package **[A ~ F]**:
143
108
 
@@ -156,6 +121,9 @@ pip install git+https://github.com/bybatkhuu/module-python-logging.git
156
121
  **OPTION C.** Install from the downloaded **source code**:
157
122
 
158
123
  ```sh
124
+ git clone https://github.com/bybatkhuu/module-python-logging.git && \
125
+ cd ./module-python-logging
126
+
159
127
  # Install directly from the source code:
160
128
  pip install .
161
129
 
@@ -339,30 +307,30 @@ logger:
339
307
  mute_modules: []
340
308
  handlers:
341
309
  default.all.std_handler:
342
- type: STD
310
+ enabled: true
311
+ h_type: STD
343
312
  format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
344
313
  colorize: true
345
- enabled: true
346
314
  default.all.file_handler:
347
- type: FILE
348
- sink: "{app_name}.all.log"
349
315
  enabled: false
316
+ h_type: FILE
317
+ sink: "{app_name}.all.log"
350
318
  default.err.file_handler:
351
- type: FILE
319
+ enabled: false
320
+ h_type: FILE
352
321
  sink: "{app_name}.err.log"
353
322
  error: true
354
- enabled: false
355
323
  default.all.json_handler:
356
- type: FILE
357
- sink: "json/{app_name}.json.all.log"
358
- serialize: true
359
324
  enabled: false
325
+ h_type: FILE
326
+ sink: "json/{app_name}.all.json.log"
327
+ serialize: true
360
328
  default.err.json_handler:
361
- type: FILE
362
- sink: "json/{app_name}.json.err.log"
329
+ enabled: false
330
+ h_type: FILE
331
+ sink: "json/{app_name}.err.json.log"
363
332
  serialize: true
364
333
  error: true
365
- enabled: false
366
334
  extra:
367
335
  ```
368
336
 
@@ -415,7 +383,7 @@ To build the documentation, run the following command:
415
383
  pip install -r ./requirements/requirements.docs.txt
416
384
 
417
385
  # Serve documentation locally (for development):
418
- mkdocs serve -a 0.0.0.0:8000
386
+ mkdocs serve -a 0.0.0.0:8000 --livereload
419
387
  # Or use the docs script:
420
388
  ./scripts/docs.sh
421
389
 
@@ -19,13 +19,13 @@ requirements/requirements.test.txt
19
19
  src/beans_logging/__init__.py
20
20
  src/beans_logging/__version__.py
21
21
  src/beans_logging/_builder.py
22
- src/beans_logging/_constants.py
23
22
  src/beans_logging/_core.py
24
- src/beans_logging/_intercept.py
25
23
  src/beans_logging/auto.py
26
24
  src/beans_logging/config.py
25
+ src/beans_logging/constants.py
27
26
  src/beans_logging/filters.py
28
27
  src/beans_logging/formats.py
28
+ src/beans_logging/intercepters.py
29
29
  src/beans_logging/rotators.py
30
30
  src/beans_logging/schemas.py
31
31
  src/beans_logging/sinks.py
@@ -33,7 +33,7 @@ mkdocstrings[python]<2.0.0,>=0.24.3
33
33
  mike<3.0.0,>=2.1.3
34
34
 
35
35
  [fastapi]
36
- beans-logging-fastapi<2.0.0,>=1.0.0
36
+ beans-logging-fastapi<4.0.0,>=3.0.0
37
37
 
38
38
  [test]
39
39
  pytest<10.0.0,>=8.0.2
@@ -1 +0,0 @@
1
- beans-logging-fastapi>=1.0.0,<2.0.0
@@ -1 +0,0 @@
1
- __version__ = "7.1.0"
@@ -1,131 +0,0 @@
1
- import os
2
- from typing import Any
3
- from pathlib import Path
4
-
5
- from pydantic import validate_call
6
-
7
- from ._constants import LogHandlerTypeEnum, LogLevelEnum
8
- from .schemas import LogHandlerPM
9
- from .config import LoggerConfigPM
10
- from .sinks import std_sink
11
- from .formats import json_formatter
12
- from .filters import (
13
- use_all_filter,
14
- use_std_filter,
15
- use_file_filter,
16
- use_file_err_filter,
17
- use_file_json_filter,
18
- use_file_json_err_filter,
19
- )
20
- from .rotators import Rotator
21
-
22
-
23
- @validate_call
24
- def build_handler(handler: LogHandlerPM, config: LoggerConfigPM) -> dict[str, Any]:
25
- """Build handler config as dictionary for Loguru logger to add new handler.
26
-
27
- Args:
28
- handler (LogHandlerPM , required): Target log handler model.
29
- config (LoggerConfigPM, required): Default main config model to fill missing values.
30
-
31
- Raises:
32
- ValueError: 'sink' attribute is empty, required for any log handler except std and file handlers!
33
-
34
- Returns:
35
- dict[str, Any]: Loguru handler config as dictionary.
36
- """
37
-
38
- _handler_dict = handler.model_dump(by_alias=True, exclude_none=True)
39
-
40
- if _handler_dict.get("sink") is None:
41
- if _handler_dict.get("type") == LogHandlerTypeEnum.STD:
42
- _handler_dict["sink"] = std_sink
43
- else:
44
- raise ValueError(
45
- "'sink' attribute is empty, required for any log handler except std handler!"
46
- )
47
-
48
- _sink = _handler_dict.get("sink")
49
- if isinstance(_sink, (str, Path)):
50
- if not os.path.isabs(_sink):
51
- _sink = os.path.join(config.default.file.logs_dir, _sink)
52
-
53
- if isinstance(_sink, Path):
54
- _sink = str(_sink)
55
-
56
- if "{app_name}" in _sink:
57
- _sink = _sink.format(app_name=config.app_name)
58
-
59
- _handler_dict["sink"] = _sink
60
-
61
- if _handler_dict.get("level") is None:
62
- if _handler_dict.get("error"):
63
- _handler_dict["level"] = config.default.level.err
64
- else:
65
- _handler_dict["level"] = config.default.level.base
66
-
67
- if (_handler_dict.get("custom_serialize") is None) and _handler_dict.get(
68
- "serialize"
69
- ):
70
- _handler_dict["custom_serialize"] = config.default.custom_serialize
71
-
72
- if _handler_dict.get("custom_serialize"):
73
- _handler_dict["serialize"] = False
74
- _handler_dict["format"] = json_formatter
75
-
76
- if (_handler_dict.get("format") is None) and (not _handler_dict.get("serialize")):
77
- _handler_dict["format"] = config.default.format_str
78
-
79
- if _handler_dict.get("filter") is None:
80
- if _handler_dict.get("type") == LogHandlerTypeEnum.STD:
81
- _handler_dict["filter"] = use_std_filter
82
- elif _handler_dict.get("type") == LogHandlerTypeEnum.FILE:
83
- if _handler_dict.get("serialize") or _handler_dict.get("custom_serialize"):
84
- if _handler_dict.get("error"):
85
- _handler_dict["filter"] = use_file_json_err_filter
86
- else:
87
- _handler_dict["filter"] = use_file_json_filter
88
- else:
89
- if _handler_dict.get("error"):
90
- _handler_dict["filter"] = use_file_err_filter
91
- else:
92
- _handler_dict["filter"] = use_file_filter
93
- else:
94
- _handler_dict["filter"] = use_all_filter
95
-
96
- if _handler_dict.get("backtrace") is None:
97
- _handler_dict["backtrace"] = True
98
-
99
- if (_handler_dict.get("diagnose") is None) and (
100
- (_handler_dict.get("level") == LogLevelEnum.TRACE)
101
- or (_handler_dict.get("level") == 5)
102
- ):
103
- _handler_dict["diagnose"] = True
104
-
105
- if _handler_dict.get("type") == LogHandlerTypeEnum.FILE:
106
- if _handler_dict.get("enqueue") is None:
107
- _handler_dict["enqueue"] = True
108
-
109
- if _handler_dict.get("rotation") is None:
110
- _handler_dict["rotation"] = Rotator(
111
- rotate_size=config.default.file.rotate_size,
112
- rotate_time=config.default.file.rotate_time,
113
- ).should_rotate
114
-
115
- if _handler_dict.get("retention") is None:
116
- _handler_dict["retention"] = config.default.file.retention
117
-
118
- if _handler_dict.get("encoding") is None:
119
- _handler_dict["encoding"] = config.default.file.encoding
120
-
121
- _handler_dict.pop("type", None)
122
- _handler_dict.pop("error", None)
123
- _handler_dict.pop("custom_serialize", None)
124
- _handler_dict.pop("enabled", None)
125
-
126
- return _handler_dict
127
-
128
-
129
- __all__ = [
130
- "build_handler",
131
- ]
@@ -1,30 +0,0 @@
1
- from enum import Enum
2
-
3
-
4
- class LogHandlerTypeEnum(str, Enum):
5
- STD = "STD"
6
- FILE = "FILE"
7
- SOCKET = "SOCKET"
8
- HTTP = "HTTP"
9
- SYSLOG = "SYSLOG"
10
- QUEUE = "QUEUE"
11
- MEMORY = "MEMORY"
12
- NULL = "NULL"
13
- CUSTOM = "CUSTOM"
14
- UNKNOWN = "UNKNOWN"
15
-
16
-
17
- class LogLevelEnum(str, Enum):
18
- TRACE = "TRACE"
19
- DEBUG = "DEBUG"
20
- INFO = "INFO"
21
- SUCCESS = "SUCCESS"
22
- WARNING = "WARNING"
23
- ERROR = "ERROR"
24
- CRITICAL = "CRITICAL"
25
-
26
-
27
- __all__ = [
28
- "LogHandlerTypeEnum",
29
- "LogLevelEnum",
30
- ]
File without changes
File without changes
File without changes