Coverage Report

Created: 2026-08-31 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pybind11/include/pybind11/detail/exception_translation.h
Line
Count
Source
1
/*
2
    pybind11/detail/exception_translation.h: means to translate C++ exceptions to Python exceptions
3
4
    Copyright (c) 2024 The Pybind Development Team.
5
6
    All rights reserved. Use of this source code is governed by a
7
    BSD-style license that can be found in the LICENSE file.
8
*/
9
10
#pragma once
11
12
#include "common.h"
13
#include "internals.h"
14
15
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
16
PYBIND11_NAMESPACE_BEGIN(detail)
17
18
// Apply all the extensions translators from a list
19
// Return true if one of the translators completed without raising an exception
20
// itself. Return of false indicates that if there are other translators
21
// available, they should be tried.
22
0
inline bool apply_exception_translators(std::forward_list<ExceptionTranslator> &translators) {
23
0
    auto last_exception = std::current_exception();
24
25
0
    for (auto &translator : translators) {
26
0
        try {
27
0
            translator(last_exception);
28
0
            return true;
29
0
        } catch (...) {
30
0
            last_exception = std::current_exception();
31
0
        }
32
0
    }
33
0
    return false;
34
0
}
35
36
0
inline void try_translate_exceptions() {
37
    /* When an exception is caught, give each registered exception
38
        translator a chance to translate it to a Python exception. First
39
        all module-local translators will be tried in reverse order of
40
        registration. If none of the module-locale translators handle
41
        the exception (or there are no module-locale translators) then
42
        the global translators will be tried, also in reverse order of
43
        registration.
44
45
        A translator may choose to do one of the following:
46
47
        - catch the exception and call py::set_error()
48
            to set a standard (or custom) Python exception, or
49
        - do nothing and let the exception fall through to the next translator, or
50
        - delegate translation to the next translator by throwing a new type of exception.
51
        */
52
53
0
    bool handled = with_exception_translators(
54
0
        [&](std::forward_list<ExceptionTranslator> &exception_translators,
55
0
            std::forward_list<ExceptionTranslator> &local_exception_translators) {
56
0
            if (detail::apply_exception_translators(local_exception_translators)) {
57
0
                return true;
58
0
            }
59
0
            if (detail::apply_exception_translators(exception_translators)) {
60
0
                return true;
61
0
            }
62
0
            return false;
63
0
        });
64
65
0
    if (!handled) {
66
0
        set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
67
0
    }
68
0
}
69
70
PYBIND11_NAMESPACE_END(detail)
71
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)