|
1 | 1 | """Logging mixin for pdfbaker classes.""" |
2 | 2 |
|
3 | 3 | import logging |
| 4 | +import sys |
4 | 5 | from typing import Any |
5 | 6 |
|
6 | 7 | TRACE = 5 |
7 | 8 | logging.addLevelName(TRACE, "TRACE") |
8 | 9 |
|
| 10 | +__all__ = ["LoggingMixin", "setup_logging", "truncate_strings"] |
| 11 | + |
9 | 12 |
|
10 | 13 | class LoggingMixin: |
11 | 14 | """Mixin providing consistent logging functionality across pdfbaker classes.""" |
@@ -71,6 +74,37 @@ def log_critical(self, msg: str, *args: Any, **kwargs: Any) -> None: |
71 | 74 | self.logger.critical(msg, *args, **kwargs) |
72 | 75 |
|
73 | 76 |
|
| 77 | +def setup_logging(quiet=False, trace=False, verbose=False) -> None: |
| 78 | + """Set up logging for the application.""" |
| 79 | + logger = logging.getLogger() |
| 80 | + logger.setLevel(logging.INFO) |
| 81 | + formatter = logging.Formatter("%(levelname)s: %(message)s") |
| 82 | + |
| 83 | + # stdout handler for TRACE/DEBUG/INFO |
| 84 | + stdout_handler = logging.StreamHandler(sys.stdout) |
| 85 | + stdout_handler.setFormatter(formatter) |
| 86 | + stdout_handler.setLevel(TRACE) |
| 87 | + stdout_handler.addFilter(lambda record: record.levelno < logging.WARNING) |
| 88 | + |
| 89 | + # stderr handler for WARNING and above |
| 90 | + stderr_handler = logging.StreamHandler(sys.stderr) |
| 91 | + stderr_handler.setFormatter(formatter) |
| 92 | + stderr_handler.setLevel(logging.WARNING) |
| 93 | + |
| 94 | + logger.handlers.clear() |
| 95 | + logger.addHandler(stdout_handler) |
| 96 | + logger.addHandler(stderr_handler) |
| 97 | + |
| 98 | + if quiet: |
| 99 | + logger.setLevel(logging.ERROR) |
| 100 | + elif trace: |
| 101 | + logger.setLevel(TRACE) |
| 102 | + elif verbose: |
| 103 | + logger.setLevel(logging.DEBUG) |
| 104 | + else: |
| 105 | + logger.setLevel(logging.INFO) |
| 106 | + |
| 107 | + |
74 | 108 | def truncate_strings(obj, max_chars: int) -> Any: |
75 | 109 | """Recursively truncate strings in nested structures.""" |
76 | 110 | if isinstance(obj, str): |
|
0 commit comments