Coverage for src/prosemark/adapters/logger_stdout.py: 100%
16 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
1# Copyright (c) 2024 Prosemark Contributors
2# This software is licensed under the MIT License
4"""Standard output logger implementation."""
6import sys
7from typing import TextIO
9from prosemark.ports.logger import Logger
12class LoggerStdout(Logger):
13 """Standard output logger implementation.
15 This implementation provides logging to stdout/stderr streams with:
16 - Standard log level formatting
17 - Configurable output streams (stdout for info/debug, stderr for warning/error)
18 - String formatting support compatible with Python's logging module
19 - Simple, dependency-free implementation for production use
21 The logger follows common conventions:
22 - info/debug messages go to stdout (can be redirected separately)
23 - warning/error messages go to stderr (for proper error handling)
24 - Consistent formatting with log level prefixes
25 """
27 def __init__(
28 self,
29 info_stream: TextIO = sys.stdout,
30 error_stream: TextIO = sys.stderr,
31 ) -> None:
32 """Initialize logger with specified output streams.
34 Args:
35 info_stream: Stream for info and debug messages (default: sys.stdout)
36 error_stream: Stream for warning and error messages (default: sys.stderr)
38 """
39 self.info_stream = info_stream
40 self.error_stream = error_stream
42 def debug(self, msg: object, *args: object, **_kwargs: object) -> None:
43 """Log detailed diagnostic information for troubleshooting.
45 Args:
46 msg: The log message or format string
47 *args: Positional arguments for string formatting
48 **kwargs: Keyword arguments (ignored in this implementation)
50 """
51 formatted_msg = str(msg) % args if args else str(msg) # pragma: no cover
52 print(f'[DEBUG] {formatted_msg}', file=self.info_stream)
54 def info(self, msg: object, *args: object, **_kwargs: object) -> None:
55 """Log general operational information.
57 Args:
58 msg: The log message or format string
59 *args: Positional arguments for string formatting
60 **kwargs: Keyword arguments (ignored in this implementation)
62 """
63 formatted_msg = str(msg) % args if args else str(msg) # pragma: no cover
64 print(f'[INFO] {formatted_msg}', file=self.info_stream)
66 def warning(self, msg: object, *args: object, **_kwargs: object) -> None:
67 """Log warning messages for important events that don't prevent operation.
69 Args:
70 msg: The log message or format string
71 *args: Positional arguments for string formatting
72 **kwargs: Keyword arguments (ignored in this implementation)
74 """
75 formatted_msg = str(msg) % args if args else str(msg) # pragma: no cover
76 print(f'[WARNING] {formatted_msg}', file=self.error_stream)
78 def error(self, msg: object, *args: object, **_kwargs: object) -> None:
79 """Log error conditions that prevent operations from completing.
81 Args:
82 msg: The log message or format string
83 *args: Positional arguments for string formatting
84 **kwargs: Keyword arguments (ignored in this implementation)
86 """
87 formatted_msg = str(msg) % args if args else str(msg) # pragma: no cover
88 print(f'[ERROR] {formatted_msg}', file=self.error_stream)
90 def exception(self, msg: object, *args: object, **_kwargs: object) -> None:
91 """Log exception information with error level and traceback.
93 Args:
94 msg: The log message or format string
95 *args: Positional arguments for string formatting
96 **kwargs: Keyword arguments (ignored in this implementation)
98 """
99 formatted_msg = str(msg) % args if args else str(msg) # pragma: no cover
100 print(f'[EXCEPTION] {formatted_msg}', file=self.error_stream) # pragma: no cover