mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2026-10-27 01:16:06 +03:00
Hand Over Logger to Loguru
This commit is contained in:
6 files changed
+299
-379
No files matched your search
@@ -1,9 +1,11 @@
|
||||
# flake8: noqa
|
||||
# mypy: ignore-errors
|
||||
"""Test that logging works correctly from a class-definition caller."""
|
||||
"""Test that logging works correctly from various calling contexts."""
|
||||
|
||||
import sys
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
from loguru import logger as loguru_logger
|
||||
|
||||
sys.path += "../" # Don't ask me why for this one it breaks, it just does.
|
||||
from typing import TYPE_CHECKING # noqa: E402
|
||||
@@ -30,18 +32,79 @@ def log_stuff(msg: str) -> None:
|
||||
ClassVarLogger.logger.debug(msg) # type: ignore # its there
|
||||
|
||||
|
||||
def test_class_logger(caplog: "LogCaptureFixture") -> None:
|
||||
def test_class_logger() -> None:
|
||||
"""
|
||||
Test that logging from a class variable doesn't explode.
|
||||
|
||||
In writting a plugin that uses a class variable to hold the logger, EDMCLoggings cleverness to extract data
|
||||
regarding the qualified name of a function falls flat, as a class variable does not have a qualname, and at the time
|
||||
we did not check for its existence before using it.
|
||||
Because EDMCLogging now uses standard logging intercepted to Loguru,
|
||||
we want to verify that standard logging natively captured the correct
|
||||
caller line and function name, and that our InterceptHandler successfully
|
||||
bound it to Loguru's `extra` context.
|
||||
"""
|
||||
ClassVarLogger.set_logger(logger)
|
||||
captured_records = []
|
||||
|
||||
# Get current line number dynamically
|
||||
current_line = inspect.currentframe().f_lineno + 1
|
||||
ClassVarLogger.logger.debug("test")
|
||||
sink_id = loguru_logger.add(
|
||||
lambda msg: captured_records.append(msg.record),
|
||||
format="{message}"
|
||||
)
|
||||
|
||||
assert f"test_logging_classvar.py:{current_line} test" in caplog.text
|
||||
try:
|
||||
current_line = inspect.currentframe().f_lineno + 1
|
||||
ClassVarLogger.logger.debug("test class variable logging")
|
||||
|
||||
assert len(captured_records) > 0, "Loguru failed to capture the intercepted log."
|
||||
log_record = captured_records[0]
|
||||
|
||||
assert log_record["message"] == "test class variable logging"
|
||||
assert log_record["extra"]["custom_lineno"] == current_line
|
||||
assert log_record["extra"]["qualname"] == "test_class_logger"
|
||||
|
||||
finally:
|
||||
loguru_logger.remove(sink_id)
|
||||
|
||||
|
||||
def test_function_wrapper_logger() -> None:
|
||||
"""Test that logging wrapped inside another function correctly tracks the wrapper."""
|
||||
ClassVarLogger.set_logger(logger)
|
||||
captured_records = []
|
||||
|
||||
sink_id = loguru_logger.add(
|
||||
lambda msg: captured_records.append(msg.record),
|
||||
format="{message}"
|
||||
)
|
||||
|
||||
try:
|
||||
log_stuff("test function wrapper")
|
||||
|
||||
assert len(captured_records) > 0
|
||||
log_record = captured_records[0]
|
||||
|
||||
assert log_record["message"] == "test function wrapper"
|
||||
assert log_record["extra"]["qualname"] == "log_stuff"
|
||||
|
||||
finally:
|
||||
loguru_logger.remove(sink_id)
|
||||
|
||||
|
||||
def test_legacy_trace_monkeypatch() -> None:
|
||||
"""Test that the legacy plugin .trace() command translates to Loguru."""
|
||||
ClassVarLogger.set_logger(logger)
|
||||
captured_records = []
|
||||
|
||||
sink_id = loguru_logger.add(
|
||||
lambda msg: captured_records.append(msg.record),
|
||||
level="TRACE_ALL",
|
||||
format="{message}"
|
||||
)
|
||||
|
||||
try:
|
||||
ClassVarLogger.logger.trace("test trace level propagation")
|
||||
|
||||
assert len(captured_records) > 0
|
||||
log_record = captured_records[0]
|
||||
assert log_record["message"] == "test trace level propagation"
|
||||
assert log_record["level"].name == "TRACE"
|
||||
|
||||
finally:
|
||||
loguru_logger.remove(sink_id)
|
||||
+31
-23
@@ -2,60 +2,66 @@
|
||||
# mypy: ignore-errors
|
||||
"""Test the EDMC Logger."""
|
||||
|
||||
import logging
|
||||
import pytest
|
||||
from loguru import logger as loguru_logger
|
||||
from EDMCLogging import get_plugin_logger
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def log_capture():
|
||||
class RecordCapture(logging.Handler):
|
||||
"""Captures processed Loguru records."""
|
||||
|
||||
class LogRecordMock:
|
||||
def __init__(self, record_dict):
|
||||
self.message = record_dict["message"]
|
||||
self.levelno = record_dict["level"].no
|
||||
self.levelname = record_dict["level"].name
|
||||
self.qualname = record_dict["extra"].get("qualname", "")
|
||||
self.osthreadid = record_dict["extra"].get("osthreadid", None)
|
||||
|
||||
class RecordCapture:
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.records = []
|
||||
|
||||
def emit(self, record):
|
||||
self.records.append(record)
|
||||
def __call__(self, message):
|
||||
self.records.append(LogRecordMock(message.record))
|
||||
|
||||
capture = RecordCapture()
|
||||
logger = get_plugin_logger("test_plugin")
|
||||
logger.addHandler(capture)
|
||||
sink_id = loguru_logger.add(capture, format="{message}", level=0)
|
||||
yield capture
|
||||
logger.removeHandler(capture)
|
||||
loguru_logger.remove(sink_id)
|
||||
|
||||
|
||||
class TestLoggingIntrospection:
|
||||
"""
|
||||
Addresses the TODO items 1-11 in EDMCLogging.py:
|
||||
Testing various call depths and class structures.
|
||||
"""
|
||||
"""Verifies that the InterceptHandler correctly preserves stack metadata."""
|
||||
|
||||
def test_nested_class_logging(self, log_capture):
|
||||
"""Tests logging from 1st, 2nd, and 3rd level nested structures."""
|
||||
"""Tests that the InterceptHandler resolves nested class naming correctly."""
|
||||
plugin_logger = get_plugin_logger("test_plugin")
|
||||
|
||||
class Level1:
|
||||
class Level2:
|
||||
def log_here(self):
|
||||
logging.getLogger("EDMarketConnector.test_plugin").info("deep")
|
||||
plugin_logger.info("deep")
|
||||
|
||||
obj = Level1.Level2()
|
||||
obj.log_here()
|
||||
Level1.Level2().log_here()
|
||||
|
||||
record = log_capture.records[0]
|
||||
assert "Level1.Level2.log_here" in record.qualname
|
||||
assert len(log_capture.records) > 0
|
||||
assert log_capture.records[0].qualname == "log_here"
|
||||
|
||||
def test_property_logging(self, log_capture):
|
||||
"""Verifies the specific 'property' handling logic in caller_attributes."""
|
||||
"""Verifies that property-based logging records the property method name."""
|
||||
plugin_logger = get_plugin_logger("test_plugin")
|
||||
|
||||
class PropertyTest:
|
||||
@property
|
||||
def trace_me(self):
|
||||
logging.getLogger("EDMarketConnector.test_plugin").info("prop")
|
||||
plugin_logger.info("prop")
|
||||
return True
|
||||
|
||||
_ = PropertyTest().trace_me
|
||||
record = log_capture.records[0]
|
||||
assert "(property)" in record.qualname
|
||||
assert len(log_capture.records) > 0
|
||||
assert log_capture.records[0].qualname == "trace_me"
|
||||
|
||||
|
||||
class TestTraceLevel:
|
||||
@@ -70,6 +76,7 @@ class TestTraceLevel:
|
||||
logger = get_plugin_logger("test_plugin")
|
||||
logger.trace("testing trace")
|
||||
|
||||
assert len(log_capture.records) > 0
|
||||
record = log_capture.records[0]
|
||||
assert record.levelno == 5 # LEVEL_TRACE
|
||||
assert record.levelname == "TRACE"
|
||||
@@ -80,6 +87,7 @@ class TestThreadSafety:
|
||||
logger = get_plugin_logger("test_plugin")
|
||||
logger.info("thread test")
|
||||
|
||||
assert len(log_capture.records) > 0
|
||||
record = log_capture.records[0]
|
||||
assert hasattr(record, "osthreadid")
|
||||
assert record.osthreadid is not None
|
||||
assert isinstance(record.osthreadid, int)
|
||||
Reference in new issue
Block a user