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
« 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/>.
27"""Declares a functions to log exceptions and to caught unhandled exceptions"""
29import logging
30import traceback
31from collections.abc import Callable
32from logging import Logger
33from types import TracebackType
34from typing import TypeAlias
36ExceptionHandlerFunction: TypeAlias = Callable[
37 [type[BaseException], BaseException, TracebackType | None], None
38]
39"""Type alias for exception handler signature"""
42def create_uncaught_exception_logger_handler(
43 logger: Logger,
44) -> ExceptionHandlerFunction:
45 """create_uncaught_exception_logger_handler(logger: Logger) -> ExceptionHandlerFunction
47 Create an handler that log an uncaught exception.
49 :param logger: the logger to use to log the exception
50 :type logger: Logger
52 :return: the exception handler
53 :rtype: Callable
55 Example
56 ^^^^^^^
58 .. code:: python
60 # get a logger
61 SIMULATION_LOG_FORMATER = logging.Formatter(logging.BASIC_FORMAT)
62 _root_logger = logging.getLogger()
63 _root_logger.setLevel(logging.DEBUG)
65 # register a hook to log uncaught exceptions to the logger
66 sys.excepthook = create_uncaught_exception_logger_handler(_root_logger)
68 """ # noqa: E501
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)
77 return log_handler
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.
90 .. note:: Type and message of the exception are logged with the provided
91 ``loglevel``, while the traceback informations are logged as ``DEBUG``.
93 :param logger: the logger used to log
94 :type logger: Logger
96 :param exc_type: the exception type
97 :type exception: type[BaseException]
99 :param exception: the exception to log
100 :type exception: Exception
102 :param tb: the traceback
103 :type exception: TracebackType
105 :param loglevel: The loglevel, default is error
106 :type loglevel: int
107 """
109 logger.log(loglevel, str.format("{0}: {1}", exc_type.__name__, exception))
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)