File size: 2,671 Bytes
568f19a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*

    pybind11/detail/exception_translation.h: means to translate C++ exceptions to Python exceptions



    Copyright (c) 2024 The Pybind Development Team.



    All rights reserved. Use of this source code is governed by a

    BSD-style license that can be found in the LICENSE file.

*/

#pragma once

#include "common.h"
#include "internals.h"

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail)

// Apply all the extensions translators from a list
// Return true if one of the translators completed without raising an exception
// itself. Return of false indicates that if there are other translators
// available, they should be tried.
inline bool apply_exception_translators(std::forward_list<ExceptionTranslator> &translators) {
    auto last_exception = std::current_exception();

    for (auto &translator : translators) {
        try {
            translator(last_exception);
            return true;
        } catch (...) {
            last_exception = std::current_exception();
        }
    }
    return false;
}

inline void try_translate_exceptions() {
    /* When an exception is caught, give each registered exception

        translator a chance to translate it to a Python exception. First

        all module-local translators will be tried in reverse order of

        registration. If none of the module-locale translators handle

        the exception (or there are no module-locale translators) then

        the global translators will be tried, also in reverse order of

        registration.



        A translator may choose to do one of the following:



        - catch the exception and call py::set_error()

            to set a standard (or custom) Python exception, or

        - do nothing and let the exception fall through to the next translator, or

        - delegate translation to the next translator by throwing a new type of exception.

        */

    bool handled = with_internals([&](internals &internals) {
        auto &local_exception_translators = get_local_internals().registered_exception_translators;
        if (detail::apply_exception_translators(local_exception_translators)) {
            return true;
        }
        auto &exception_translators = internals.registered_exception_translators;
        if (detail::apply_exception_translators(exception_translators)) {
            return true;
        }
        return false;
    });

    if (!handled) {
        set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
    }
}

PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)