File: warnings.h

package info (click to toggle)
regina-normal 7.4.1-1.1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 154,244 kB
  • sloc: cpp: 295,026; xml: 9,992; sh: 1,344; python: 1,225; perl: 616; ansic: 138; makefile: 26
file content (75 lines) | stat: -rw-r--r-- 2,368 bytes parent folder | download | duplicates (2)
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
/*
    pybind11/warnings.h: Python warnings wrappers.

    Copyright (c) 2024 Jan Iwaszkiewicz <jiwaszkiewicz6@gmail.com>

    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 "pybind11.h"
#include "detail/common.h"

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

PYBIND11_NAMESPACE_BEGIN(detail)

inline bool PyWarning_Check(PyObject *obj) {
    int result = PyObject_IsSubclass(obj, PyExc_Warning);
    if (result == 1) {
        return true;
    }
    if (result == -1) {
        raise_from(PyExc_SystemError,
                   "pybind11::detail::PyWarning_Check(): PyObject_IsSubclass() call failed.");
        throw error_already_set();
    }
    return false;
}

PYBIND11_NAMESPACE_END(detail)

PYBIND11_NAMESPACE_BEGIN(warnings)

inline object
new_warning_type(handle scope, const char *name, handle base = PyExc_RuntimeWarning) {
    if (!detail::PyWarning_Check(base.ptr())) {
        pybind11_fail("pybind11::warnings::new_warning_type(): cannot create custom warning, base "
                      "must be a subclass of "
                      "PyExc_Warning!");
    }
    if (hasattr(scope, name)) {
        pybind11_fail("pybind11::warnings::new_warning_type(): an attribute with name \""
                      + std::string(name) + "\" exists already.");
    }
    std::string full_name = scope.attr("__name__").cast<std::string>() + std::string(".") + name;
    handle h(PyErr_NewException(full_name.c_str(), base.ptr(), nullptr));
    if (!h) {
        raise_from(PyExc_SystemError,
                   "pybind11::warnings::new_warning_type(): PyErr_NewException() call failed.");
        throw error_already_set();
    }
    auto obj = reinterpret_steal<object>(h);
    scope.attr(name) = obj;
    return obj;
}

// Similar to Python `warnings.warn()`
inline void
warn(const char *message, handle category = PyExc_RuntimeWarning, int stack_level = 2) {
    if (!detail::PyWarning_Check(category.ptr())) {
        pybind11_fail(
            "pybind11::warnings::warn(): cannot raise warning, category must be a subclass of "
            "PyExc_Warning!");
    }

    if (PyErr_WarnEx(category.ptr(), message, stack_level) == -1) {
        throw error_already_set();
    }
}

PYBIND11_NAMESPACE_END(warnings)

PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)