1
+ ### IMPORTS
2
+ ### ============================================================================
3
+ ## Future
4
+ from __future__ import annotations
5
+
6
+ ## Standard Library
7
+ from dataclasses import dataclass
8
+ import datetime
9
+ import enum
10
+ import io
11
+ import json
12
+ import logging
13
+ from logging .config import ConvertingDict
14
+ import sys
15
+ import traceback
16
+ from types import TracebackType
17
+ from typing import Any , Generator
18
+ import uuid
19
+
20
+ if sys .version_info >= (3 , 9 ):
21
+ import zoneinfo
22
+ else :
23
+ from backports import zoneinfo
24
+
25
+ ## Installed
26
+ import freezegun
27
+ import pytest
28
+
29
+ ## Application
30
+ import pythonjsonlogger
31
+ import pythonjsonlogger .defaults
32
+ from pythonjsonlogger .core import RESERVED_ATTRS , BaseJsonFormatter , merge_record_extra
33
+ from pythonjsonlogger .json import JsonFormatter
34
+
35
+ if pythonjsonlogger .ORJSON_AVAILABLE :
36
+ from pythonjsonlogger .orjson import OrjsonFormatter
37
+
38
+ if pythonjsonlogger .MSGSPEC_AVAILABLE :
39
+ from pythonjsonlogger .msgspec import MsgspecFormatter
40
+
41
+ ### SETUP
42
+ ### ============================================================================
43
+ ALL_FORMATTERS : list [type [BaseJsonFormatter ]] = [JsonFormatter ]
44
+ if pythonjsonlogger .ORJSON_AVAILABLE :
45
+ ALL_FORMATTERS .append (OrjsonFormatter )
46
+ if pythonjsonlogger .MSGSPEC_AVAILABLE :
47
+ ALL_FORMATTERS .append (MsgspecFormatter )
48
+
49
+ _LOGGER_COUNT = 0
50
+ EXT_VAL = 999
51
+
52
+ LOGGING_CONFIG = {
53
+ 'version' : 1 ,
54
+ 'disable_existing_loggers' : False ,
55
+ 'formatters' : {
56
+ 'default' : {
57
+ '()' : 'pythonjsonlogger.json.JsonFormatter' ,
58
+ 'static_fields' : {
59
+ 'ext-val' : 'ext://tests.test_dictconfig.EXT_VAL'
60
+ }
61
+ }
62
+ },
63
+ 'handlers' : {
64
+ 'default' : {
65
+ 'level' : 'DEBUG' ,
66
+ 'formatter' : 'default' ,
67
+ 'class' : 'logging.StreamHandler' ,
68
+ 'stream' : 'ext://sys.stdout' , # Default is stderr
69
+ },
70
+ },
71
+ 'loggers' : {
72
+ '' : { # root logger
73
+ 'handlers' : ['default' ],
74
+ 'level' : 'WARNING' ,
75
+ 'propagate' : False
76
+ },
77
+ }
78
+ }
79
+
80
+
81
+ @dataclass
82
+ class LoggingEnvironment :
83
+ logger : logging .Logger
84
+ buffer : io .StringIO
85
+
86
+ def load_json (self ) -> Any :
87
+ return json .loads (self .buffer .getvalue ())
88
+
89
+
90
+ @pytest .fixture
91
+ def env () -> Generator [LoggingEnvironment , None , None ]:
92
+ global _LOGGER_COUNT # pylint: disable=global-statement
93
+ _LOGGER_COUNT += 1
94
+ logging .config .dictConfig (LOGGING_CONFIG )
95
+ default_formatter = logging .root .handlers [0 ].formatter
96
+ logger = logging .getLogger (f"pythonjsonlogger.tests.{ _LOGGER_COUNT } " )
97
+ logger .setLevel (logging .DEBUG )
98
+ buffer = io .StringIO ()
99
+ handler = logging .StreamHandler (buffer )
100
+ handler .setFormatter (default_formatter )
101
+ logger .addHandler (handler )
102
+ yield LoggingEnvironment (logger = logger , buffer = buffer )
103
+ logger .removeHandler (handler )
104
+ logger .setLevel (logging .NOTSET )
105
+ buffer .close ()
106
+ return
107
+
108
+
109
+ ### TESTS
110
+ ### ============================================================================
111
+ def test_external_reference_support (env : LoggingEnvironment ):
112
+ env .logger .info ("hello" )
113
+ log_json = env .load_json ()
114
+
115
+ assert log_json ["ext-val" ] == EXT_VAL
116
+ return
0 commit comments