python3-commons 0.16.1__py3-none-any.whl → 0.16.2__py3-none-any.whl

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.
@@ -5,7 +5,7 @@ from datetime import UTC, datetime, date
5
5
  from decimal import Decimal
6
6
  from typing import Any, Final, Callable
7
7
 
8
- import orjson
8
+ import msgspec
9
9
 
10
10
  correlation_id: ContextVar[str | None] = ContextVar('correlation_id', default=None)
11
11
 
@@ -36,7 +36,7 @@ _STD_LOG_FIELDS: Final[frozenset[str]] = frozenset(
36
36
  )
37
37
 
38
38
 
39
- # Keep normalization minimal and branch-based (faster than dict dispatch)
39
+ # Keep normalization minimal and branch-based (unchanged)
40
40
  def _normalize(v: Any) -> Any:
41
41
  if isinstance(v, datetime | date):
42
42
  return v.isoformat()
@@ -54,29 +54,38 @@ def _normalize(v: Any) -> Any:
54
54
 
55
55
 
56
56
  class JSONFormatter(logging.Formatter):
57
- __slots__ = ('_get_correlation_id', '_max_tb_chars')
57
+ __slots__ = ('_get_correlation_id', '_max_tb_chars', '_encoder')
58
58
 
59
59
  def __init__(
60
- self,
61
- *,
62
- get_correlation_id: Callable[[], str | None] = lambda: correlation_id.get(),
63
- max_exc_tb_chars: int = _DEFAULT_MAX_TB_CHARS,
64
- **kwargs: Any,
60
+ self,
61
+ *,
62
+ get_correlation_id: Callable[[], str | None] = lambda: correlation_id.get(),
63
+ max_exc_tb_chars: int = _DEFAULT_MAX_TB_CHARS,
64
+ **kwargs: Any,
65
65
  ) -> None:
66
66
  super().__init__(**kwargs)
67
+
67
68
  self._get_correlation_id = get_correlation_id
68
69
  self._max_tb_chars = max_exc_tb_chars
70
+ self._encoder = msgspec.json.Encoder()
69
71
 
70
72
  def format(self, record: logging.LogRecord) -> str:
71
- # --- message (fast path, avoid Formatter.formatMessage) ---
73
+ # -------------------------
74
+ # message (fast path)
75
+ # -------------------------
72
76
  try:
73
77
  message = record.getMessage()
74
78
  except Exception:
75
79
  message = str(record.msg)
76
80
 
77
- # --- timestamp (no Formatter.formatTime overhead) ---
81
+ # -------------------------
82
+ # timestamp (no Formatter overhead)
83
+ # -------------------------
78
84
  timestamp = datetime.fromtimestamp(record.created, UTC).isoformat().replace('+00:00', 'Z')
79
85
 
86
+ # -------------------------
87
+ # base log object (plain dict)
88
+ # -------------------------
80
89
  log: dict[str, Any] = {
81
90
  'message': message,
82
91
  'level': record.levelname,
@@ -94,7 +103,6 @@ class JSONFormatter(logging.Formatter):
94
103
  log['exc_value'] = str(exc_value)
95
104
 
96
105
  tb = ''.join(traceback.format_exception(exc_type, exc_value, exc_tb)).rstrip()
97
-
98
106
  cap = self._max_tb_chars
99
107
 
100
108
  if cap and len(tb) > cap:
@@ -112,7 +120,6 @@ class JSONFormatter(logging.Formatter):
112
120
  for k, v in record_dict.items():
113
121
  if k[0] == '_' or k in std_log_fields:
114
122
  continue
115
-
116
123
  out_set(k, normalize(v))
117
124
 
118
- return orjson.dumps(log).decode('utf-8')
125
+ return self._encoder.encode(log).decode('utf-8')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.16.1
3
+ Version: 0.16.2
4
4
  Summary: Re-usable Python3 code
5
5
  Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -19,7 +19,6 @@ Requires-Dist: lxml~=6.1.0
19
19
  Requires-Dist: msgpack~=1.1.2
20
20
  Requires-Dist: msgspec==0.21.1
21
21
  Requires-Dist: object-storage-client==0.0.22
22
- Requires-Dist: orjson==3.11.8
23
22
  Requires-Dist: pydantic-settings~=2.14.0
24
23
  Requires-Dist: SQLAlchemy[asyncio]~=2.0.49
25
24
  Requires-Dist: valkey[libvalkey]~=6.1.1
@@ -20,15 +20,15 @@ python3_commons/db/models/rbac.py,sha256=ARRQ1tn_GThxiBiIs_6IKkGnIIv37SmVgSi90cb
20
20
  python3_commons/db/models/users.py,sha256=zNN3bNWl3cVE6dJtTPzmPSo_5d1SsBZwwkvIs-WzUBA,644
21
21
  python3_commons/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  python3_commons/log/filters.py,sha256=fuyjXZAUm-i2MNrxvFYag8F8Rr27x8W8MdV3ke6miSs,175
23
- python3_commons/log/formatters.py,sha256=RVqN2rkNwurgyGX3jTtDs8-8iwr9QHQy4dw62pb4MIo,3268
23
+ python3_commons/log/formatters.py,sha256=uFZit5Xl7k2_hAVjqVG8-6nwFR3C7fKoeuW2jiz2S8M,3496
24
24
  python3_commons/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  python3_commons/serializers/common.py,sha256=VkA7C6wODvHk0QBXVX_x2JieDstihx3U__UFbTYf654,120
26
26
  python3_commons/serializers/json.py,sha256=UPkC3ps13x2C_NxwVV-K7Ewp4VjkVHSSUkJVw5k7Wiw,712
27
27
  python3_commons/serializers/msgpack.py,sha256=zESFBX34GsZ8rDu6Zk5V6CLT6P0mPilU0r04Ka6TblI,1474
28
28
  python3_commons/serializers/msgspec.py,sha256=upy5CBmK66-8hYnK5bAM_sZvZY5CAqZmzCw9GIF346I,2988
29
- python3_commons-0.16.1.dist-info/licenses/AUTHORS.rst,sha256=3R9JnfjfjH5RoPWOeqKFJgxVShSSfzQPIrEr1nxIo9Q,90
30
- python3_commons-0.16.1.dist-info/licenses/LICENSE,sha256=xxILuojHm4fKQOrMHPSslbyy6WuKAN2RiG74HbrYfzM,34575
31
- python3_commons-0.16.1.dist-info/METADATA,sha256=YVAEZkhgPWs2KNmv6MVRHrUxU6tUzyos9LX_cbSRFh4,1051
32
- python3_commons-0.16.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
33
- python3_commons-0.16.1.dist-info/top_level.txt,sha256=lJI6sCBf68eUHzupCnn2dzG10lH3jJKTWM_hrN1cQ7M,16
34
- python3_commons-0.16.1.dist-info/RECORD,,
29
+ python3_commons-0.16.2.dist-info/licenses/AUTHORS.rst,sha256=3R9JnfjfjH5RoPWOeqKFJgxVShSSfzQPIrEr1nxIo9Q,90
30
+ python3_commons-0.16.2.dist-info/licenses/LICENSE,sha256=xxILuojHm4fKQOrMHPSslbyy6WuKAN2RiG74HbrYfzM,34575
31
+ python3_commons-0.16.2.dist-info/METADATA,sha256=VHzo-ZDsPUIiAdIK3N2CHiOkc6EvdUgsSUjB6yAHBTc,1021
32
+ python3_commons-0.16.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
33
+ python3_commons-0.16.2.dist-info/top_level.txt,sha256=lJI6sCBf68eUHzupCnn2dzG10lH3jJKTWM_hrN1cQ7M,16
34
+ python3_commons-0.16.2.dist-info/RECORD,,