test_exceptions.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 import sys
3 
4 import pytest
5 
6 from pybind11_tests import exceptions as m
7 import pybind11_cross_module_tests as cm
8 
9 
11  with pytest.raises(RuntimeError) as excinfo:
12  m.throw_std_exception()
13  assert msg(excinfo.value) == "This exception was intentionally thrown."
14 
15 
17  with pytest.raises(RuntimeError) as excinfo:
18  m.throw_already_set(False)
19  assert msg(excinfo.value) == "Unknown internal error occurred"
20 
21  with pytest.raises(ValueError) as excinfo:
22  m.throw_already_set(True)
23  assert msg(excinfo.value) == "foo"
24 
25 
27  with pytest.raises(RuntimeError) as excinfo:
28  cm.raise_runtime_error()
29  assert str(excinfo.value) == "My runtime error"
30 
31  with pytest.raises(ValueError) as excinfo:
32  cm.raise_value_error()
33  assert str(excinfo.value) == "My value error"
34 
35  with pytest.raises(ValueError) as excinfo:
36  cm.throw_pybind_value_error()
37  assert str(excinfo.value) == "pybind11 value error"
38 
39  with pytest.raises(TypeError) as excinfo:
40  cm.throw_pybind_type_error()
41  assert str(excinfo.value) == "pybind11 type error"
42 
43  with pytest.raises(StopIteration) as excinfo:
44  cm.throw_stop_iteration()
45 
46 
48  d = {}
49  assert m.python_call_in_destructor(d) is True
50  assert d["good"] is True
51 
52 
53 def test_python_alreadyset_in_destructor(monkeypatch, capsys):
54  hooked = False
55  triggered = [False] # mutable, so Python 2.7 closure can modify it
56 
57  if hasattr(sys, 'unraisablehook'): # Python 3.8+
58  hooked = True
59  default_hook = sys.unraisablehook
60 
61  def hook(unraisable_hook_args):
62  exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
63  if obj == 'already_set demo':
64  triggered[0] = True
65  default_hook(unraisable_hook_args)
66  return
67 
68  # Use monkeypatch so pytest can apply and remove the patch as appropriate
69  monkeypatch.setattr(sys, 'unraisablehook', hook)
70 
71  assert m.python_alreadyset_in_destructor('already_set demo') is True
72  if hooked:
73  assert triggered[0] is True
74 
75  _, captured_stderr = capsys.readouterr()
76  # Error message is different in Python 2 and 3, check for words that appear in both
77  assert 'ignored' in captured_stderr and 'already_set demo' in captured_stderr
78 
79 
81  assert m.exception_matches()
82  assert m.exception_matches_base()
83  assert m.modulenotfound_exception_matches_base()
84 
85 
86 def test_custom(msg):
87  # Can we catch a MyException?
88  with pytest.raises(m.MyException) as excinfo:
89  m.throws1()
90  assert msg(excinfo.value) == "this error should go to a custom type"
91 
92  # Can we translate to standard Python exceptions?
93  with pytest.raises(RuntimeError) as excinfo:
94  m.throws2()
95  assert msg(excinfo.value) == "this error should go to a standard Python exception"
96 
97  # Can we handle unknown exceptions?
98  with pytest.raises(RuntimeError) as excinfo:
99  m.throws3()
100  assert msg(excinfo.value) == "Caught an unknown exception!"
101 
102  # Can we delegate to another handler by rethrowing?
103  with pytest.raises(m.MyException) as excinfo:
104  m.throws4()
105  assert msg(excinfo.value) == "this error is rethrown"
106 
107  # Can we fall-through to the default handler?
108  with pytest.raises(RuntimeError) as excinfo:
109  m.throws_logic_error()
110  assert msg(excinfo.value) == "this error should fall through to the standard handler"
111 
112  # OverFlow error translation.
113  with pytest.raises(OverflowError) as excinfo:
114  m.throws_overflow_error()
115 
116  # Can we handle a helper-declared exception?
117  with pytest.raises(m.MyException5) as excinfo:
118  m.throws5()
119  assert msg(excinfo.value) == "this is a helper-defined translated exception"
120 
121  # Exception subclassing:
122  with pytest.raises(m.MyException5) as excinfo:
123  m.throws5_1()
124  assert msg(excinfo.value) == "MyException5 subclass"
125  assert isinstance(excinfo.value, m.MyException5_1)
126 
127  with pytest.raises(m.MyException5_1) as excinfo:
128  m.throws5_1()
129  assert msg(excinfo.value) == "MyException5 subclass"
130 
131  with pytest.raises(m.MyException5) as excinfo:
132  try:
133  m.throws5()
134  except m.MyException5_1:
135  raise RuntimeError("Exception error: caught child from parent")
136  assert msg(excinfo.value) == "this is a helper-defined translated exception"
137 
138 
139 def test_nested_throws(capture):
140  """Tests nested (e.g. C++ -> Python -> C++) exception handling"""
141 
142  def throw_myex():
143  raise m.MyException("nested error")
144 
145  def throw_myex5():
146  raise m.MyException5("nested error 5")
147 
148  # In the comments below, the exception is caught in the first step, thrown in the last step
149 
150  # C++ -> Python
151  with capture:
152  m.try_catch(m.MyException5, throw_myex5)
153  assert str(capture).startswith("MyException5: nested error 5")
154 
155  # Python -> C++ -> Python
156  with pytest.raises(m.MyException) as excinfo:
157  m.try_catch(m.MyException5, throw_myex)
158  assert str(excinfo.value) == "nested error"
159 
160  def pycatch(exctype, f, *args):
161  try:
162  f(*args)
163  except m.MyException as e:
164  print(e)
165 
166  # C++ -> Python -> C++ -> Python
167  with capture:
168  m.try_catch(
169  m.MyException5, pycatch, m.MyException, m.try_catch, m.MyException, throw_myex5)
170  assert str(capture).startswith("MyException5: nested error 5")
171 
172  # C++ -> Python -> C++
173  with capture:
174  m.try_catch(m.MyException, pycatch, m.MyException5, m.throws4)
175  assert capture == "this error is rethrown"
176 
177  # Python -> C++ -> Python -> C++
178  with pytest.raises(m.MyException5) as excinfo:
179  m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
180  assert str(excinfo.value) == "this is a helper-defined translated exception"
181 
182 
183 # This can often happen if you wrap a pybind11 class in a Python wrapper
185 
186  class MyRepr(object):
187  def __repr__(self):
188  raise AttributeError("Example error")
189 
190  with pytest.raises(TypeError):
191  m.simple_bool_passthrough(MyRepr())
void print(const Matrix &A, const string &s, ostream &stream)
Definition: Matrix.cpp:155
def test_custom(msg)
def test_std_exception(msg)
bool hasattr(handle obj, handle name)
Definition: pytypes.h:403
def test_exception_matches()
def test_cross_module_exceptions()
def test_error_already_set(msg)
bool isinstance(handle obj)
Definition: pytypes.h:384
def test_python_alreadyset_in_destructor(monkeypatch, capsys)
Definition: pytypes.h:928
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
def test_python_call_in_catch()
def test_nested_throws(capture)


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:46:03