aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/libshiboken/sbkerrors.cpp
blob: 1832624d5dbc26966fa77215ce3449e7e86ddea5 (plain)
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "sbkerrors.h"
#include "sbkstring.h"
#include "helper.h"
#include "gilstate.h"

namespace Shiboken
{

// PYSIDE-2335: Track down if we can reach a Python error handler.
//              _pythonContextStack has always the current state of handler status
//              in its lowest bit.
//              Blocking calls like exec or run need to use `setBlocking`.
static thread_local std::size_t _pythonContextStack{};

PythonContextMarker::PythonContextMarker()
{
    // Shift history up and set lowest bit.
    _pythonContextStack = (_pythonContextStack * 2) + 1;
}

PythonContextMarker::~PythonContextMarker()
{
    // Shift history down.
    _pythonContextStack /= 2;
}

void PythonContextMarker::setBlocking()
{
    // Clear lowest bit.
    _pythonContextStack = _pythonContextStack / 2 * 2;
}

namespace Errors
{

void setInstantiateAbstractClass(const char *name)
{
    PyErr_Format(PyExc_NotImplementedError,
                 "'%s' represents a C++ abstract class and cannot be instantiated", name);
}

void setInstantiateAbstractClassDisabledWrapper(const char *name)
{
    PyErr_Format(PyExc_NotImplementedError,
                 "Abstract class '%s' cannot be instantiated since the wrapper has been disabled.",
                 name);
}

void setInvalidTypeDeletion(const char *name)
{
    PyErr_Format(PyExc_TypeError, "'%s' may not be deleted", name);
}

void setOperatorNotImplemented()
{
    PyErr_SetString(PyExc_NotImplementedError, "operator not implemented.");
}

void setPureVirtualMethodError(const char *name)
{
    PyErr_Format(PyExc_NotImplementedError, "pure virtual method '%s' not implemented.", name);
}

void setPrivateMethod(const char *name)
{
    PyErr_Format(PyExc_TypeError, "%s is a private method.\", ", name);
}

void setReverseOperatorNotImplemented()
{
    PyErr_SetString(PyExc_NotImplementedError, "reverse operator not implemented.");
}

void setSequenceTypeError(const char *expectedType)
{
    PyErr_Format(PyExc_TypeError,
                 "attributed value with wrong type, '%s' or other convertible type expected",
                 expectedType);
}

void setSetterTypeError(const char *name, const char *expectedType)
{
    PyErr_Format(PyExc_TypeError,
                 "wrong type attributed to '%s', '%s' or convertible type expected",
                 name, expectedType);
}

void setWrongContainerType()
{
    PyErr_SetString(PyExc_TypeError, "Wrong type passed to container conversion.");
}

struct ErrorStore {
    PyObject *type;
    PyObject *exc;
    PyObject *traceback;
};

static thread_local ErrorStore savedError{};

void storeErrorOrPrint()
{
    // This error happened in a function with no way to return an error state.
    // Therefore, we handle the error when we are error checking, anyway.
    // But we do that only when we know that an error handler can pick it up.
    if (_pythonContextStack & 1)
        PyErr_Fetch(&savedError.type, &savedError.exc, &savedError.traceback);
    else
        PyErr_Print();
}

PyObject *occurred()
{
    if (savedError.type) {
        PyErr_Restore(savedError.type, savedError.exc, savedError.traceback);
        savedError.type = nullptr;
    }
    return PyErr_Occurred();
}

} // namespace Errors

namespace Warnings
{
void warnInvalidReturnValue(const char *className, const char *functionName,
                            const char *expectedType, const char *actualType)
{
    Shiboken::warning(PyExc_RuntimeWarning, 2,
                      "Invalid return value in function '%s.%s', expected %s, got %s.",
                      className, functionName, expectedType, actualType);
}

void warnDeprecated(const char *functionName)
{
    Shiboken::warning(PyExc_DeprecationWarning, 1,
                      "Function: '%s' is marked as deprecated, please check "
                      "the documentation for more information.",
                      functionName);
}

void warnDeprecated(const char *className, const char *functionName)
{
    Shiboken::warning(PyExc_DeprecationWarning, 1,
                      "Function: '%s.%s' is marked as deprecated, please check "
                      "the documentation for more information.",
                      className, functionName);
}

void warnDeprecatedEnum(const char *enumName)
{
    Shiboken::warning(PyExc_DeprecationWarning, 1,
                      "Enum: '%s' is marked as deprecated, please check "
                      "the documentation for more information.",
                      enumName);
}

void warnDeprecatedEnumValue(const char *enumName, const char *valueName)
{
    Shiboken::warning(PyExc_DeprecationWarning, 1,
                      "Enum value '%s.%s' is marked as deprecated, please check "
                      "the documentation for more information.",
                      enumName, valueName);

}

} // namespace Warnings
} // namespace Shiboken