Skip to content

Commit 48c46b2

Browse files
committed
ruff
1 parent 1044c35 commit 48c46b2

1 file changed

Lines changed: 79 additions & 69 deletions

File tree

tests/logging/test_handlers.py

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,3 @@
1-
2-
3-
4-
5-
#! What do we want to test here?
6-
7-
#! The processing of the environment variables, partiuclarly the protobuf, the random one, and also what happens when you try to initialise it without the right environment
8-
9-
# this should test _convert_str_to_handlertype with throttle, protobufstream, and random
10-
# throttle should return handlertype.throttle, none , protobufstream should return handlertype.protobufstream, and a valid protobufconf with the same values as expected
11-
12-
# See if its possible to test _make_ers_handler_conf
13-
# This should just take a default string comma and then return the correct features
14-
15-
# Definitely test the creation of the full thing, with the four environments
16-
17-
18-
#! Also test the from string in HandlerTypes
19-
# Should get this testesd for the enums but also the error itself
20-
21-
22-
#! We need to test the filters..
23-
# Figure out how to test logging filters..
24-
25-
26-
# Need tests for the throttling for sure
27-
28-
# Need a test for the base handlerfilter:
29-
# using one handlertype
30-
# using multiple handler types
31-
32-
33-
###########
34-
35-
361
"""Comprehensive tests for the logging filters in handlers.py.
372
383
Tests cover:
@@ -47,7 +12,7 @@
4712
import logging
4813
import time
4914
from threading import Thread
50-
from unittest.mock import MagicMock, patch
15+
from unittest.mock import MagicMock
5116

5217
import pytest
5318

@@ -79,9 +44,9 @@ def clean_logger():
7944

8045

8146
@pytest.fixture
82-
def log_record():
47+
def log_record() -> logging.LogRecord:
8348
"""Provide a basic log record for testing."""
84-
record = logging.LogRecord(
49+
return logging.LogRecord(
8550
name="test.module",
8651
level=logging.ERROR,
8752
pathname="/path/to/test.py",
@@ -90,7 +55,6 @@ def log_record():
9055
args=(),
9156
exc_info=None,
9257
)
93-
return record
9458

9559

9660
@pytest.fixture
@@ -130,7 +94,9 @@ def mock_ers_handlers():
13094
class TestBaseHandlerFilter:
13195
"""Tests for BaseHandlerFilter.get_allowed() logic."""
13296

133-
def test_non_ers_uses_record_handlers_attribute(self, log_record):
97+
def test_non_ers_uses_record_handlers_attribute(
98+
self, log_record: logging.LogRecord
99+
):
134100
"""Test get_allowed() uses 'handlers' attribute from record for non-ERS."""
135101
log_record.handlers = [HandlerType.Rich, HandlerType.File]
136102
filter_obj = BaseHandlerFilter()
@@ -139,7 +105,9 @@ def test_non_ers_uses_record_handlers_attribute(self, log_record):
139105

140106
assert allowed == [HandlerType.Rich, HandlerType.File]
141107

142-
def test_non_ers_defaults_to_base_handlers(self, log_record):
108+
def test_non_ers_defaults_to_base_handlers(
109+
self, log_record: logging.LogRecord
110+
):
143111
"""Test get_allowed() falls back to default handlers when attribute missing."""
144112
# log_record has no 'handlers' attribute
145113
filter_obj = BaseHandlerFilter()
@@ -151,7 +119,9 @@ def test_non_ers_defaults_to_base_handlers(self, log_record):
151119
expected_handlers = {HandlerType.Stream, HandlerType.Rich, HandlerType.File}
152120
assert expected_handlers.issubset(set(allowed))
153121

154-
def test_ers_path_valid_configuration(self, ers_log_record, mock_ers_handlers):
122+
def test_ers_path_valid_configuration(
123+
self, ers_log_record: logging.LogRecord, mock_ers_handlers: dict
124+
):
155125
"""Test get_allowed() extracts ERS handlers correctly with valid config."""
156126
ers_log_record.ers_handlers = mock_ers_handlers
157127
filter_obj = BaseHandlerFilter()
@@ -160,7 +130,9 @@ def test_ers_path_valid_configuration(self, ers_log_record, mock_ers_handlers):
160130

161131
assert allowed == [HandlerType.Throttle, HandlerType.Protobufstream]
162132

163-
def test_ers_path_no_matching_level_variable(self, ers_log_record, mock_ers_handlers):
133+
def test_ers_path_no_matching_level_variable(
134+
self, ers_log_record: logging.LogRecord, mock_ers_handlers: dict
135+
):
164136
"""Test get_allowed() returns None when log level has no ERS mapping."""
165137
# Set a log level that does not have an ERS equivalent
166138
ers_log_record.levelno = 25 # Between INFO and WARNING
@@ -194,7 +166,9 @@ def test_list_handler_ids_converted_to_set(self):
194166
assert isinstance(filter_obj.handler_ids, set)
195167
assert filter_obj.handler_ids == {HandlerType.Rich, HandlerType.File}
196168

197-
def test_filter_returns_true_when_handler_in_allowed(self, log_record):
169+
def test_filter_returns_true_when_handler_in_allowed(
170+
self, log_record: logging.LogRecord
171+
):
198172
"""Test filter() returns True when handler_id is in allowed list."""
199173
log_record.handlers = [HandlerType.Rich, HandlerType.File, HandlerType.Stream]
200174
filter_obj = HandleIDFilter(HandlerType.Rich)
@@ -203,7 +177,9 @@ def test_filter_returns_true_when_handler_in_allowed(self, log_record):
203177

204178
assert result is True
205179

206-
def test_filter_returns_false_when_handler_not_in_allowed(self, log_record):
180+
def test_filter_returns_false_when_handler_not_in_allowed(
181+
self, log_record: logging.LogRecord
182+
):
207183
"""Test filter() returns False when handler_id not in allowed."""
208184
log_record.handlers = [HandlerType.File, HandlerType.Stream]
209185
filter_obj = HandleIDFilter(HandlerType.Rich)
@@ -212,7 +188,9 @@ def test_filter_returns_false_when_handler_not_in_allowed(self, log_record):
212188

213189
assert result is False
214190

215-
def test_filter_returns_false_when_get_allowed_returns_none(self, log_record):
191+
def test_filter_returns_false_when_get_allowed_returns_none(
192+
self, log_record: logging.LogRecord
193+
):
216194
"""Test filter() returns False when get_allowed() returns None."""
217195
filter_obj = HandleIDFilter(HandlerType.Rich)
218196
filter_obj.get_allowed = MagicMock(return_value=None)
@@ -221,7 +199,9 @@ def test_filter_returns_false_when_get_allowed_returns_none(self, log_record):
221199

222200
assert result is False
223201

224-
def test_filter_with_multiple_handler_ids(self, log_record):
202+
def test_filter_with_multiple_handler_ids(
203+
self, log_record: logging.LogRecord
204+
):
225205
"""Test filter() with multiple handler_ids checks intersection."""
226206
log_record.handlers = [HandlerType.Rich, HandlerType.File]
227207
filter_obj = HandleIDFilter([HandlerType.Rich, HandlerType.Stream])
@@ -231,7 +211,9 @@ def test_filter_with_multiple_handler_ids(self, log_record):
231211
# Should return True because Rich is in both sets
232212
assert result is True
233213

234-
def test_filter_no_intersection_with_multiple_ids(self, log_record):
214+
def test_filter_no_intersection_with_multiple_ids(
215+
self, log_record: logging.LogRecord
216+
):
235217
"""Test filter() returns False when no intersection with multiple ids."""
236218
log_record.handlers = [HandlerType.File]
237219
filter_obj = HandleIDFilter([HandlerType.Rich, HandlerType.Stream])
@@ -249,7 +231,9 @@ def test_filter_no_intersection_with_multiple_ids(self, log_record):
249231
class TestThrottleFilter:
250232
"""Tests for ThrottleFilter throttling and suppression logic."""
251233

252-
def test_initial_phase_lets_through_first_n_messages(self, log_record):
234+
def test_initial_phase_lets_through_first_n_messages(
235+
self, log_record: logging.LogRecord
236+
):
253237
"""Test that first N messages pass through without suppression."""
254238
log_record.handlers = [HandlerType.Throttle]
255239
filter_obj = ThrottleFilter(initial_threshold=3, time_limit=10)
@@ -259,7 +243,9 @@ def test_initial_phase_lets_through_first_n_messages(self, log_record):
259243
assert filter_obj.filter(log_record) is True
260244
assert filter_obj.filter(log_record) is True
261245

262-
def test_after_initial_threshold_suppresses(self, log_record):
246+
def test_after_initial_threshold_suppresses(
247+
self, log_record: logging.LogRecord
248+
):
263249
"""Test that messages are suppressed after initial_threshold."""
264250
log_record.handlers = [HandlerType.Throttle]
265251
filter_obj = ThrottleFilter(initial_threshold=2, time_limit=10)
@@ -271,7 +257,9 @@ def test_after_initial_threshold_suppresses(self, log_record):
271257
# 3rd should be suppressed
272258
assert filter_obj.filter(log_record) is False
273259

274-
def test_escalating_threshold_doubles_on_report(self, log_record):
260+
def test_escalating_threshold_doubles_on_report(
261+
self, log_record: logging.LogRecord
262+
):
275263
"""Test that threshold escalates (10->100->1000) when reporting."""
276264
log_record.handlers = [HandlerType.Throttle]
277265
filter_obj = ThrottleFilter(initial_threshold=1, time_limit=100)
@@ -288,7 +276,9 @@ def test_escalating_threshold_doubles_on_report(self, log_record):
288276

289277
assert issue_record.threshold == 100 # Escalated from 10
290278

291-
def test_time_window_reset_resets_counters(self, log_record, monkeypatch):
279+
def test_time_window_reset_resets_counters(
280+
self, log_record: logging.LogRecord, monkeypatch: pytest.MonkeyPatch
281+
):
292282
"""Test that state resets after time_limit expires."""
293283
log_record.handlers = [HandlerType.Throttle]
294284
filter_obj = ThrottleFilter(initial_threshold=1, time_limit=1)
@@ -302,7 +292,9 @@ def test_time_window_reset_resets_counters(self, log_record, monkeypatch):
302292
# Time advances beyond time_limit with no suppression, reset should allow pass
303293
assert filter_obj.filter(log_record) is True
304294

305-
def test_suppressed_counter_increments(self, log_record):
295+
def test_suppressed_counter_increments(
296+
self, log_record: logging.LogRecord
297+
):
306298
"""Test that suppressed_counter increments for each suppressed message."""
307299
log_record.handlers = [HandlerType.Throttle]
308300
filter_obj = ThrottleFilter(initial_threshold=0, time_limit=100)
@@ -317,7 +309,9 @@ def test_suppressed_counter_increments(self, log_record):
317309
if i > 0:
318310
assert issue_record.suppressed_counter >= 0
319311

320-
def test_throttle_suppression_flag_bypasses_filter(self, log_record):
312+
def test_throttle_suppression_flag_bypasses_filter(
313+
self, log_record: logging.LogRecord
314+
):
321315
"""Test that _throttle_suppression flag allows suppression messages through."""
322316
log_record.handlers = [HandlerType.Throttle]
323317
filter_obj = ThrottleFilter(initial_threshold=0, time_limit=100)
@@ -329,7 +323,9 @@ def test_throttle_suppression_flag_bypasses_filter(self, log_record):
329323
log_record._throttle_suppression = True
330324
assert filter_obj.filter(log_record) is True
331325

332-
def test_get_allowed_returns_none_skips_throttle(self, log_record):
326+
def test_get_allowed_returns_none_skips_throttle(
327+
self, log_record: logging.LogRecord
328+
):
333329
"""Test filter() returns True if get_allowed() returns None."""
334330
filter_obj = ThrottleFilter()
335331
filter_obj.get_allowed = MagicMock(return_value=None)
@@ -338,7 +334,9 @@ def test_get_allowed_returns_none_skips_throttle(self, log_record):
338334
result = filter_obj.filter(log_record)
339335
assert result is False
340336

341-
def test_throttle_not_in_allowed_returns_true(self, log_record):
337+
def test_throttle_not_in_allowed_returns_true(
338+
self, log_record: logging.LogRecord
339+
):
342340
"""Test filter() returns True if Throttle not in allowed handlers."""
343341
log_record.handlers = [HandlerType.Rich, HandlerType.File]
344342
filter_obj = ThrottleFilter(initial_threshold=0, time_limit=10)
@@ -358,7 +356,9 @@ def test_timestamp_formatting(self):
358356
assert formatted.count("-") == 2 # Two dashes for date
359357
assert formatted.count(":") == 2 # Two colons for time
360358

361-
def test_different_issues_tracked_separately(self, log_record):
359+
def test_different_issues_tracked_separately(
360+
self, log_record: logging.LogRecord
361+
):
362362
"""Test that different file:line combinations track state separately."""
363363
filter_obj = ThrottleFilter(initial_threshold=2, time_limit=10)
364364

@@ -390,13 +390,15 @@ def test_different_issues_tracked_separately(self, log_record):
390390
# Issue 2: suppressed (independent)
391391
assert filter_obj.filter(record2) is False
392392

393-
def test_thread_safety_concurrent_issues(self, log_record):
393+
def test_thread_safety_concurrent_issues(
394+
self, log_record: logging.LogRecord
395+
):
394396
"""Test ThrottleFilter is thread-safe with concurrent logging."""
395397
filter_obj = ThrottleFilter(initial_threshold=5, time_limit=10)
396398
log_record.handlers = [HandlerType.Throttle]
397399
results = []
398400

399-
def log_messages(record, num_messages):
401+
def log_messages(record: logging.LogRecord, num_messages: int) -> None:
400402
"""Log from a thread."""
401403
for _ in range(num_messages):
402404
result = filter_obj.filter(record)
@@ -465,7 +467,7 @@ def test_reset_clears_all_state(self):
465467
class TestFiltersIntegration:
466468
"""Integration tests with real logger setup."""
467469

468-
def test_logger_with_handle_id_filter(self, clean_logger):
470+
def test_logger_with_handle_id_filter(self, clean_logger: logging.Logger):
469471
"""Test logger with HandleIDFilter allows only specific handlers."""
470472
stream = io.StringIO()
471473
handler = logging.StreamHandler(stream)
@@ -490,7 +492,7 @@ def test_logger_with_handle_id_filter(self, clean_logger):
490492
# Message should appear because Stream is in allowed
491493
assert "Test message" in stream.getvalue()
492494

493-
def test_logger_with_throttle_filter(self, clean_logger):
495+
def test_logger_with_throttle_filter(self, clean_logger: logging.Logger):
494496
"""Test logger correctly suppresses messages with ThrottleFilter."""
495497
stream = io.StringIO()
496498
handler = logging.StreamHandler(stream)
@@ -521,7 +523,7 @@ def test_logger_with_throttle_filter(self, clean_logger):
521523
# First 2 should appear, then suppression message
522524
assert output.count("Repeated message") >= 2
523525

524-
def test_chained_filters(self, clean_logger):
526+
def test_chained_filters(self, clean_logger: logging.Logger):
525527
"""Test stacking HandleIDFilter and ThrottleFilter."""
526528
stream = io.StringIO()
527529
handler = logging.StreamHandler(stream)
@@ -561,7 +563,7 @@ def test_chained_filters(self, clean_logger):
561563
class TestEdgeCases:
562564
"""Tests for edge cases and boundary conditions."""
563565

564-
def test_empty_handlers_list(self, log_record):
566+
def test_empty_handlers_list(self, log_record: logging.LogRecord):
565567
"""Test filter behavior with empty handlers list."""
566568
log_record.handlers = []
567569
filter_obj = HandleIDFilter(HandlerType.Rich)
@@ -570,7 +572,7 @@ def test_empty_handlers_list(self, log_record):
570572

571573
assert result is False
572574

573-
def test_none_handlers_attribute(self, log_record):
575+
def test_none_handlers_attribute(self, log_record: logging.LogRecord):
574576
"""Test filter when record.handlers is None."""
575577
log_record.handlers = None
576578
filter_obj = HandleIDFilter(HandlerType.Rich)
@@ -579,15 +581,17 @@ def test_none_handlers_attribute(self, log_record):
579581
result = filter_obj.filter(log_record)
580582
assert result is False
581583

582-
def test_throttle_with_zero_initial_threshold(self, log_record):
584+
def test_throttle_with_zero_initial_threshold(
585+
self, log_record: logging.LogRecord
586+
):
583587
"""Test ThrottleFilter with initial_threshold=0."""
584588
log_record.handlers = [HandlerType.Throttle]
585589
filter_obj = ThrottleFilter(initial_threshold=0, time_limit=10)
586590

587591
# All messages should be suppressed after first
588592
assert filter_obj.filter(log_record) is False
589593

590-
def test_issue_record_key_format(self, log_record):
594+
def test_issue_record_key_format(self, log_record: logging.LogRecord):
591595
"""Test that issue_record key is formatted correctly."""
592596
filter_obj = ThrottleFilter()
593597

@@ -596,7 +600,9 @@ def test_issue_record_key_format(self, log_record):
596600

597601
assert isinstance(record, IssueRecord)
598602

599-
def test_multiple_handler_types_intersection(self, log_record):
603+
def test_multiple_handler_types_intersection(
604+
self, log_record: logging.LogRecord
605+
):
600606
"""Test set intersection with multiple handler types."""
601607
log_record.handlers = [
602608
HandlerType.Rich,
@@ -609,7 +615,9 @@ def test_multiple_handler_types_intersection(self, log_record):
609615
result = filter_obj.filter(log_record)
610616
assert result is True
611617

612-
def test_protobuf_conf_in_ers_handlers(self, ers_log_record, mock_ers_handlers):
618+
def test_protobuf_conf_in_ers_handlers(
619+
self, ers_log_record: logging.LogRecord, mock_ers_handlers: dict
620+
):
613621
"""Test that ProtobufConf is properly included in ERS configuration."""
614622
ers_log_record.ers_handlers = mock_ers_handlers
615623
filter_obj = BaseHandlerFilter()
@@ -618,7 +626,9 @@ def test_protobuf_conf_in_ers_handlers(self, ers_log_record, mock_ers_handlers):
618626

619627
assert HandlerType.Protobufstream in allowed
620628

621-
def test_suppression_message_includes_count(self, log_record, clean_logger):
629+
def test_suppression_message_includes_count(
630+
self, clean_logger: logging.Logger
631+
):
622632
"""Test that suppression message includes suppressed count."""
623633
stream = io.StringIO()
624634
handler = logging.StreamHandler(stream)

0 commit comments

Comments
 (0)