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

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

19 import logging

20 import logging.config

21 import os

22

23 import typer

24

25

26 class 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

53 def 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.

73 def get_logger() -> logging.Logger:

74 """

75 Returns the configured logger.

76 """

77 return setup_logging()