Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
greenlet_exceptions.hpp172 linesDownload Raw Back to greenlet
1#ifndef GREENLET_EXCEPTIONS_HPP
2#define GREENLET_EXCEPTIONS_HPP
3
4#define PY_SSIZE_T_CLEAN
5#include <Python.h>
6#include <stdexcept>
7#include <string>
8
9#ifdef __clang__
10#    pragma clang diagnostic push
11#    pragma clang diagnostic ignored "-Wunused-function"
12#endif
13
14namespace greenlet {
15
16    class PyErrOccurred : public std::runtime_error
17    {
18    public:
19
20        // CAUTION: In debug builds, may run arbitrary Python code.
21        static const PyErrOccurred
22        from_current()
23        {
24            assert(PyErr_Occurred());
25#ifndef NDEBUG
26            // This is not exception safe, and
27            // not necessarily safe in general (what if it switches?)
28            // But we only do this in debug mode, where we are in
29            // tight control of what exceptions are getting raised and
30            // can prevent those issues.
31
32            // You can't call PyObject_Str with a pending exception.
33            PyObject* typ;
34            PyObject* val;
35            PyObject* tb;
36
37            PyErr_Fetch(&typ, &val, &tb);
38            PyObject* typs = PyObject_Str(typ);
39            PyObject* vals = PyObject_Str(val ? val : typ);
40            const char* typ_msg = PyUnicode_AsUTF8(typs);
41            const char* val_msg = PyUnicode_AsUTF8(vals);
42            PyErr_Restore(typ, val, tb);
43
44            std::string msg(typ_msg);
45            msg += ": ";
46            msg += val_msg;
47            PyErrOccurred ex(msg);
48            Py_XDECREF(typs);
49            Py_XDECREF(vals);
50
51            return ex;
52#else
53            return PyErrOccurred();
54#endif
55        }
56
57        PyErrOccurred() : std::runtime_error("")
58        {
59            assert(PyErr_Occurred());
60        }
61
62        PyErrOccurred(const std::string& msg) : std::runtime_error(msg)
63        {
64            assert(PyErr_Occurred());
65        }
66
67        PyErrOccurred(PyObject* exc_kind, const char* const msg)
68            : std::runtime_error(msg)
69        {
70            PyErr_SetString(exc_kind, msg);
71        }
72
73        PyErrOccurred(PyObject* exc_kind, const std::string msg)
74            : std::runtime_error(msg)
75        {
76            // This copies the c_str, so we don't have any lifetime
77            // issues to worry about.
78            PyErr_SetString(exc_kind, msg.c_str());
79        }
80
81        PyErrOccurred(PyObject* exc_kind,
82                      const std::string msg, //This is the format
83                                             //string; that's not
84                                             //usually safe!
85
86                      PyObject* borrowed_obj_one, PyObject* borrowed_obj_two)
87            : std::runtime_error(msg)
88        {
89
90            //This is designed specifically for the
91            //``check_switch_allowed`` function.
92
93            // PyObject_Str and PyObject_Repr are safe to call with
94            // NULL pointers; they return the string "<NULL>" in that
95            // case.
96            // This function always returns null.
97            PyErr_Format(exc_kind,
98                         msg.c_str(),
99                         borrowed_obj_one, borrowed_obj_two);
100        }
101    };
102
103    class TypeError : public PyErrOccurred
104    {
105    public:
106        TypeError(const char* const what)
107            : PyErrOccurred(PyExc_TypeError, what)
108        {
109        }
110        TypeError(const std::string what)
111            : PyErrOccurred(PyExc_TypeError, what)
112        {
113        }
114    };
115
116    class ValueError : public PyErrOccurred
117    {
118    public:
119        ValueError(const char* const what)
120            : PyErrOccurred(PyExc_ValueError, what)
121        {
122        }
123    };
124
125    class AttributeError : public PyErrOccurred
126    {
127    public:
128        AttributeError(const char* const what)
129            : PyErrOccurred(PyExc_AttributeError, what)
130        {
131        }
132    };
133
134    /**
135     * Calls `Py_FatalError` when constructed, so you can't actually
136     * throw this. It just makes static analysis easier.
137     */
138    class PyFatalError : public std::runtime_error
139    {
140    public:
141        PyFatalError(const char* const msg)
142            : std::runtime_error(msg)
143        {
144            Py_FatalError(msg);
145        }
146    };
147
148    static inline PyObject*
149    Require(PyObject* p, const std::string& msg="")
150    {
151        if (!p) {
152            throw PyErrOccurred(msg);
153        }
154        return p;
155    };
156
157    static inline void
158    Require(const int retval)
159    {
160        if (retval < 0) {
161            throw PyErrOccurred();
162        }
163    };
164
165
166};
167#ifdef __clang__
168#    pragma clang diagnostic pop
169#endif
170
171#endif
172 
codekingpro/portable-devtools · Team Ai