Coverage for src/irorun/logger_setup.py: 66%

32 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-02 16:59 -0500

1# Copyright 2025 Faith O. Oyedemi 

2# SPDX-License-Identifier: Apache-2.0 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); 

5# you may not use this file except in compliance with the License. 

6# You may obtain a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, 

12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

13# See the License for the specific language governing permissions and 

14# limitations under the License. 

15# 

16# For more details, see the full text of the Apache License at: 

17# http://www.apache.org/licenses/LICENSE-2.0 

18 

19import logging 

20import logging.config 

21import os 

22 

23import typer 

24 

25 

26class TyperLoggerHandler(logging.Handler): 

27 """ 

28 A custom logging handler that uses Typer's secho to produce elegant, color-coded log messages. 

29 """ 

30 

31 def emit(self, record: logging.LogRecord) -> None: 

32 fg = None 

33 bg = None 

34 

35 # Map log levels to Typer colors. 

36 match record.levelno: 

37 case logging.DEBUG: 

38 fg = typer.colors.BLACK 

39 case logging.INFO: 

40 fg = typer.colors.BRIGHT_BLUE 

41 case logging.WARNING: 

42 fg = typer.colors.BRIGHT_MAGENTA 

43 case logging.ERROR: 

44 fg = typer.colors.BRIGHT_WHITE 

45 bg = typer.colors.RED 

46 case logging.CRITICAL: 

47 fg = typer.colors.BRIGHT_RED 

48 

49 message = self.format(record) 

50 typer.secho(message, fg=fg, bg=bg) 

51 

52 

53def setup_logging(config_path: str = 'logging.conf') -> logging.Logger: 

54 """ 

55 Loads logging configuration from the specified configuration file. 

56 Falls back to a basic configuration using TyperLoggerHandler if the config file is not found. 

57 """ 

58 if os.path.exists(config_path): 

59 logging.config.fileConfig(config_path, disable_existing_loggers=False) 

60 else: 

61 # Fallback configuration: use TyperLoggerHandler directly. 

62 handler = TyperLoggerHandler() 

63 formatter = logging.Formatter( 

64 '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', 

65 datefmt='%Y-%m-%d %H:%M:%S', 

66 ) 

67 handler.setFormatter(formatter) 

68 logging.basicConfig(level=logging.INFO, handlers=[handler]) 

69 return logging.getLogger('irorun') 

70 

71 

72# Initialize and export the logger. 

73def get_logger() -> logging.Logger: 

74 """ 

75 Returns the configured logger. 

76 """ 

77 return setup_logging()