@@ -43,16 +43,24 @@ def __call__(self, *args: str) -> t.Sequence[t.Any]:
43
43
44
44
45
45
@pytest .fixture
46
- def logger_mocker (mocker ) -> _TSetupMockProtocol :
46
+ def logger_mocker (mocker ) -> t .Generator [_TSetupMockProtocol , None , None ]:
47
+ original_levels = {}
48
+
47
49
def setup_mock (* logger_names ):
50
+ nonlocal original_levels
51
+
48
52
loggers = [logging .getLogger (name ) for name in logger_names ]
49
53
for logger in loggers :
50
- logger .addHandler = mocker .Mock ()
51
- logger .removeHandler = mocker .Mock ()
52
- logger .setLevel = mocker .Mock ()
54
+ original_levels [logger ] = logger .level
55
+ mocker .patch .object (logger , "addHandler" )
56
+ mocker .patch .object (logger , "removeHandler" )
57
+ mocker .spy (logger , "setLevel" )
53
58
return loggers
54
59
55
- return setup_mock
60
+ yield setup_mock
61
+
62
+ for logger , level in original_levels .items ():
63
+ logger .setLevel (level )
56
64
57
65
58
66
def test_watch_returns_watcher (logger_mocker ) -> None :
@@ -106,22 +114,21 @@ def test_watcher_context_manager(mocker) -> None:
106
114
watcher .stop .assert_called_once ()
107
115
108
116
109
- @pytest .mark .parametrize (
110
- ("default_level" , "level" , "expected_level" ),
111
- (
112
- (None , None , logging .DEBUG ),
113
- (logging .WARNING , None , logging .WARNING ),
114
- (logging .WARNING , logging .DEBUG , logging .DEBUG ),
115
- (logging .DEBUG , logging .WARNING , logging .WARNING ),
116
- (1 , None , 1 ),
117
- (None , 1 , 1 ),
118
- )
117
+ WATCH_ARGS = (
118
+ #default_level, level, expected_level
119
+ (None , None , logging .DEBUG ),
120
+ (logging .WARNING , None , logging .WARNING ),
121
+ (logging .WARNING , logging .DEBUG , logging .DEBUG ),
122
+ (logging .DEBUG , logging .WARNING , logging .WARNING ),
123
+ (logging .INFO , None , logging .INFO ),
124
+ (logging .INFO , logging .DEBUG , logging .DEBUG ),
125
+ (logging .DEBUG , logging .INFO , logging .INFO ),
126
+ (1 , None , 1 ),
127
+ (None , 1 , 1 ),
119
128
)
120
- def test_watcher_level (
121
- logger_mocker , default_level , level , expected_level
122
- ) -> None :
123
- logger_name = "neo4j"
124
- logger = logger_mocker (logger_name )[0 ]
129
+
130
+
131
+ def _setup_watch (logger_name , default_level , level ):
125
132
kwargs = {}
126
133
if default_level is not None :
127
134
kwargs ["default_level" ] = default_level
@@ -131,9 +138,73 @@ def test_watcher_level(
131
138
kwargs ["level" ] = level
132
139
watcher .watch (** kwargs )
133
140
141
+
142
+ @pytest .mark .parametrize (
143
+ ("default_level" , "level" , "expected_level" ),
144
+ WATCH_ARGS
145
+ )
146
+ @pytest .mark .parametrize (
147
+ "effective_level" ,
148
+ (logging .DEBUG , logging .WARNING , logging .INFO , logging .ERROR )
149
+ )
150
+ def test_watcher_level (
151
+ logger_mocker , default_level , level , expected_level , effective_level ,
152
+ ) -> None :
153
+ logger_name = "neo4j"
154
+ logger = logger_mocker (logger_name )[0 ]
155
+ logger .setLevel (effective_level )
156
+ logger .setLevel .reset_mock ()
157
+ _setup_watch (logger_name , default_level , level )
158
+
134
159
(handler ,), _ = logger .addHandler .call_args
135
- assert handler .level == logging .NOTSET
136
- logger .setLevel .assert_called_once_with (expected_level )
160
+ assert handler .level == expected_level
161
+ if effective_level <= expected_level :
162
+ logger .setLevel .assert_not_called ()
163
+ else :
164
+ logger .setLevel .assert_called_once_with (expected_level )
165
+
166
+
167
+ @pytest .mark .parametrize (
168
+ ("default_level1" , "level1" , "expected_level1" ),
169
+ WATCH_ARGS
170
+ )
171
+ @pytest .mark .parametrize (
172
+ ("default_level2" , "level2" , "expected_level2" ),
173
+ WATCH_ARGS
174
+ )
175
+ @pytest .mark .parametrize (
176
+ "effective_level" ,
177
+ (logging .DEBUG , logging .WARNING , logging .INFO , logging .ERROR )
178
+ )
179
+ def test_watcher_level_multiple_watchers (
180
+ logger_mocker , default_level1 , level1 , expected_level1 ,
181
+ default_level2 , level2 , expected_level2 ,
182
+ effective_level ,
183
+ ) -> None :
184
+ logger_name = "neo4j"
185
+ logger = logger_mocker (logger_name )[0 ]
186
+ logger .setLevel (effective_level )
187
+ logger .setLevel .reset_mock ()
188
+ _setup_watch (logger_name , default_level1 , level1 )
189
+ _setup_watch (logger_name , default_level2 , level2 )
190
+
191
+ assert logger .addHandler .call_count == 2
192
+ (handler1 ,), _ = logger .addHandler .call_args_list [0 ]
193
+ (handler2 ,), _ = logger .addHandler .call_args_list [1 ]
194
+
195
+ assert handler1 .level == expected_level1
196
+ assert handler2 .level == expected_level2
197
+
198
+ expected_logger_level = min (expected_level1 , expected_level2 )
199
+ if effective_level <= expected_logger_level :
200
+ logger .setLevel .assert_not_called ()
201
+ else :
202
+ if effective_level > expected_level1 > expected_level2 :
203
+ assert logger .setLevel .call_count == 2
204
+ else :
205
+ assert logger .setLevel .call_count == 1
206
+ (level ,), _ = logger .setLevel .call_args_list [- 1 ]
207
+ assert level == expected_logger_level
137
208
138
209
139
210
custom_log_out = io .StringIO ()
@@ -220,6 +291,7 @@ def _assert_task_injection(
220
291
handler_cls_mock = mocker .patch ("neo4j.debug.StreamHandler" , autospec = True )
221
292
handler_mock = handler_cls_mock .return_value
222
293
logger_name = "neo4j"
294
+ logger_mocker (logger_name )[0 ]
223
295
watcher = neo4j_debug .Watcher (logger_name , colour = colour ,
224
296
thread_info = thread , task_info = task )
225
297
record_mock = mocker .Mock (spec = logging .LogRecord )
0 commit comments