warnings.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. /*
  3. pybind11/warnings.h: Python warnings wrappers.
  4. Copyright (c) 2024 Jan Iwaszkiewicz <jiwaszkiewicz6@gmail.com>
  5. All rights reserved. Use of this source code is governed by a
  6. BSD-style license that can be found in the LICENSE file.
  7. */
  8. #pragma once
  9. #include "pybind11.h"
  10. #include "detail/common.h"
  11. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  12. PYBIND11_NAMESPACE_BEGIN(detail)
  13. inline bool PyWarning_Check(PyObject *obj) {
  14. int result = PyObject_IsSubclass(obj, PyExc_Warning);
  15. if (result == 1) {
  16. return true;
  17. }
  18. if (result == -1) {
  19. raise_from(PyExc_SystemError,
  20. "pybind11::detail::PyWarning_Check(): PyObject_IsSubclass() call failed.");
  21. throw error_already_set();
  22. }
  23. return false;
  24. }
  25. PYBIND11_NAMESPACE_END(detail)
  26. PYBIND11_NAMESPACE_BEGIN(warnings)
  27. inline object
  28. new_warning_type(handle scope, const char *name, handle base = PyExc_RuntimeWarning) {
  29. if (!detail::PyWarning_Check(base.ptr())) {
  30. pybind11_fail("pybind11::warnings::new_warning_type(): cannot create custom warning, base "
  31. "must be a subclass of "
  32. "PyExc_Warning!");
  33. }
  34. if (hasattr(scope, name)) {
  35. pybind11_fail("pybind11::warnings::new_warning_type(): an attribute with name \""
  36. + std::string(name) + "\" exists already.");
  37. }
  38. std::string full_name = scope.attr("__name__").cast<std::string>() + std::string(".") + name;
  39. handle h(PyErr_NewException(full_name.c_str(), base.ptr(), nullptr));
  40. if (!h) {
  41. raise_from(PyExc_SystemError,
  42. "pybind11::warnings::new_warning_type(): PyErr_NewException() call failed.");
  43. throw error_already_set();
  44. }
  45. auto obj = reinterpret_steal<object>(h);
  46. scope.attr(name) = obj;
  47. return obj;
  48. }
  49. // Similar to Python `warnings.warn()`
  50. inline void
  51. warn(const char *message, handle category = PyExc_RuntimeWarning, int stack_level = 2) {
  52. if (!detail::PyWarning_Check(category.ptr())) {
  53. pybind11_fail(
  54. "pybind11::warnings::warn(): cannot raise warning, category must be a subclass of "
  55. "PyExc_Warning!");
  56. }
  57. if (PyErr_WarnEx(category.ptr(), message, stack_level) == -1) {
  58. throw error_already_set();
  59. }
  60. }
  61. PYBIND11_NAMESPACE_END(warnings)
  62. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
  63. #else
  64. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  65. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)