Coverage for physioblocks / utils / exceptions_utils.py: 82%

17 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-09 16:40 +0100

1# SPDX-FileCopyrightText: Copyright INRIA 

2# 

3# SPDX-License-Identifier: LGPL-3.0-only 

4# 

5# Copyright INRIA 

6# 

7# This file is part of PhysioBlocks, a library mostly developed by the 

8# [Ananke project-team](https://team.inria.fr/ananke) at INRIA. 

9# 

10# Authors: 

11# - Colin Drieu 

12# - Dominique Chapelle 

13# - François Kimmig 

14# - Philippe Moireau 

15# 

16# PhysioBlocks is free software: you can redistribute it and/or modify it under the 

17# terms of the GNU Lesser General Public License as published by the Free Software 

18# Foundation, version 3 of the License. 

19# 

20# PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY 

21# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 

22# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 

23# 

24# You should have received a copy of the GNU Lesser General Public License along with 

25# PhysioBlocks. If not, see <https://www.gnu.org/licenses/>. 

26 

27"""Declares a functions to log exceptions and to caught unhandled exceptions""" 

28 

29import logging 

30import traceback 

31from collections.abc import Callable 

32from logging import Logger 

33from types import TracebackType 

34from typing import TypeAlias 

35 

36ExceptionHandlerFunction: TypeAlias = Callable[ 

37 [type[BaseException], BaseException, TracebackType | None], None 

38] 

39"""Type alias for exception handler signature""" 

40 

41 

42def create_uncaught_exception_logger_handler( 

43 logger: Logger, 

44) -> ExceptionHandlerFunction: 

45 """create_uncaught_exception_logger_handler(logger: Logger) -> ExceptionHandlerFunction 

46 

47 Create an handler that log an uncaught exception. 

48 

49 :param logger: the logger to use to log the exception 

50 :type logger: Logger 

51 

52 :return: the exception handler 

53 :rtype: Callable 

54 

55 Example 

56 ^^^^^^^ 

57 

58 .. code:: python 

59 

60 # get a logger 

61 SIMULATION_LOG_FORMATER = logging.Formatter(logging.BASIC_FORMAT) 

62 _root_logger = logging.getLogger() 

63 _root_logger.setLevel(logging.DEBUG) 

64 

65 # register a hook to log uncaught exceptions to the logger 

66 sys.excepthook = create_uncaught_exception_logger_handler(_root_logger) 

67 

68 """ # noqa: E501 

69 

70 def log_handler( 

71 exception_type: type[BaseException], 

72 exception_value: BaseException, 

73 tb: TracebackType | None = None, 

74 ) -> None: 

75 log_exception(logger, exception_type, exception_value, tb, logger.level) 

76 

77 return log_handler 

78 

79 

80def log_exception( 

81 logger: Logger, 

82 exc_type: type[BaseException], 

83 exception: BaseException, 

84 tb: TracebackType | None, 

85 loglevel: int = logging.ERROR, 

86) -> None: 

87 """ 

88 Log the provided exception. 

89 

90 .. note:: Type and message of the exception are logged with the provided 

91 ``loglevel``, while the traceback informations are logged as ``DEBUG``. 

92 

93 :param logger: the logger used to log 

94 :type logger: Logger 

95 

96 :param exc_type: the exception type 

97 :type exception: type[BaseException] 

98 

99 :param exception: the exception to log 

100 :type exception: Exception 

101 

102 :param tb: the traceback 

103 :type exception: TracebackType 

104 

105 :param loglevel: The loglevel, default is error 

106 :type loglevel: int 

107 """ 

108 

109 logger.log(loglevel, str.format("{0}: {1}", exc_type.__name__, exception)) 

110 

111 if tb is not None: 

112 exception_tb = str.join( 

113 "", traceback.format_exception(exc_type, value=exception, tb=tb) 

114 ) 

115 logger.debug(exception_tb)