conftest.py
Go to the documentation of this file.
1 """pytest configuration
2 
3 Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
4 Adds docstring and exceptions message sanitizers.
5 """
6 
7 import contextlib
8 import difflib
9 import gc
10 import re
11 import textwrap
12 
13 import pytest
14 
15 # Early diagnostic for failed imports
16 import pybind11_tests
17 
18 _long_marker = re.compile(r"([0-9])L")
19 _hexadecimal = re.compile(r"0x[0-9a-fA-F]+")
20 
21 # Avoid collecting Python3 only files
22 collect_ignore = []
23 
24 
26  """For triple-quote strings"""
27  return textwrap.dedent(s.lstrip("\n").rstrip())
28 
29 
31  """For output which does not require specific line order"""
32  return sorted(_strip_and_dedent(s).splitlines())
33 
34 
36  """Explanation for a failed assert -- the a and b arguments are List[str]"""
37  return ["--- actual / +++ expected"] + [
38  line.strip("\n") for line in difflib.ndiff(a, b)
39  ]
40 
41 
42 class Output:
43  """Basic output post-processing and comparison"""
44 
45  def __init__(self, string):
46  self.string = string
47  self.explanation = []
48 
49  def __str__(self):
50  return self.string
51 
52  def __eq__(self, other):
53  # Ignore constructor/destructor output which is prefixed with "###"
54  a = [
55  line
56  for line in self.string.strip().splitlines()
57  if not line.startswith("###")
58  ]
59  b = _strip_and_dedent(other).splitlines()
60  if a == b:
61  return True
62  else:
63  self.explanation = _make_explanation(a, b)
64  return False
65 
66 
68  """Custom comparison for output without strict line ordering"""
69 
70  def __eq__(self, other):
71  a = _split_and_sort(self.string)
72  b = _split_and_sort(other)
73  if a == b:
74  return True
75  else:
77  return False
78 
79 
80 class Capture:
81  def __init__(self, capfd):
82  self.capfd = capfd
83  self.out = ""
84  self.err = ""
85 
86  def __enter__(self):
87  self.capfd.readouterr()
88  return self
89 
90  def __exit__(self, *args):
91  self.out, self.err = self.capfd.readouterr()
92 
93  def __eq__(self, other):
94  a = Output(self.out)
95  b = other
96  if a == b:
97  return True
98  else:
99  self.explanation = a.explanation
100  return False
101 
102  def __str__(self):
103  return self.out
104 
105  def __contains__(self, item):
106  return item in self.out
107 
108  @property
109  def unordered(self):
110  return Unordered(self.out)
111 
112  @property
113  def stderr(self):
114  return Output(self.err)
115 
116 
117 @pytest.fixture
118 def capture(capsys):
119  """Extended `capsys` with context manager and custom equality operators"""
120  return Capture(capsys)
121 
122 
124  def __init__(self, sanitizer):
125  self.sanitizer = sanitizer
126  self.string = ""
127  self.explanation = []
128 
129  def __call__(self, thing):
130  self.string = self.sanitizer(thing)
131  return self
132 
133  def __eq__(self, other):
134  a = self.string
135  b = _strip_and_dedent(other)
136  if a == b:
137  return True
138  else:
139  self.explanation = _make_explanation(a.splitlines(), b.splitlines())
140  return False
141 
142 
144  s = s.strip()
145  s = s.replace("pybind11_tests.", "m.")
146  s = _long_marker.sub(r"\1", s)
147  return s
148 
149 
151  s = thing.__doc__
152  s = _sanitize_general(s)
153  return s
154 
155 
156 @pytest.fixture
157 def doc():
158  """Sanitize docstrings and add custom failure explanation"""
159  return SanitizedString(_sanitize_docstring)
160 
161 
162 def _sanitize_message(thing):
163  s = str(thing)
164  s = _sanitize_general(s)
165  s = _hexadecimal.sub("0", s)
166  return s
167 
168 
169 @pytest.fixture
170 def msg():
171  """Sanitize messages and add custom failure explanation"""
172  return SanitizedString(_sanitize_message)
173 
174 
175 # noinspection PyUnusedLocal
176 def pytest_assertrepr_compare(op, left, right):
177  """Hook to insert custom failure explanation"""
178  if hasattr(left, "explanation"):
179  return left.explanation
180 
181 
182 @contextlib.contextmanager
183 def suppress(exception):
184  """Suppress the desired exception"""
185  try:
186  yield
187  except exception:
188  pass
189 
190 
192  """Run the garbage collector twice (needed when running
193  reference counting tests with PyPy)"""
194  gc.collect()
195  gc.collect()
196 
197 
199  pytest.suppress = suppress
200  pytest.gc_collect = gc_collect
201 
202 
204  del config # Unused.
205  assert (
206  pybind11_tests.compiler_info is not None
207  ), "Please update pybind11_tests.cpp if this assert fails."
208  return (
209  "C++ Info:"
210  f" {pybind11_tests.compiler_info}"
211  f" {pybind11_tests.cpp_std}"
212  f" {pybind11_tests.PYBIND11_INTERNALS_ID}"
213  )
def _split_and_sort(s)
Definition: conftest.py:30
def pytest_configure()
Definition: conftest.py:198
bool hasattr(handle obj, handle name)
Definition: pytypes.h:728
def __contains__(self, item)
Definition: conftest.py:105
def gc_collect()
Definition: conftest.py:191
def msg()
Definition: conftest.py:170
def suppress(exception)
Definition: conftest.py:183
def __str__(self)
Definition: conftest.py:102
def pytest_assertrepr_compare(op, left, right)
Definition: conftest.py:176
def __eq__(self, other)
Definition: conftest.py:93
def unordered(self)
Definition: conftest.py:109
def _make_explanation(a, b)
Definition: conftest.py:35
def pytest_report_header(config)
Definition: conftest.py:203
Definition: pytypes.h:1403
def _strip_and_dedent(s)
Definition: conftest.py:25
def __call__(self, thing)
Definition: conftest.py:129
def __eq__(self, other)
Definition: conftest.py:133
def __exit__(self, args)
Definition: conftest.py:90
def _sanitize_docstring(thing)
Definition: conftest.py:150
def _sanitize_message(thing)
Definition: conftest.py:162
def __eq__(self, other)
Definition: conftest.py:70
def __init__(self, capfd)
Definition: conftest.py:81
def doc()
Definition: conftest.py:157
def __init__(self, sanitizer)
Definition: conftest.py:124
def _sanitize_general(s)
Definition: conftest.py:143
def __init__(self, string)
Definition: conftest.py:45
def __eq__(self, other)
Definition: conftest.py:52
def capture(capsys)
Definition: conftest.py:118
def __enter__(self)
Definition: conftest.py:86
def stderr(self)
Definition: conftest.py:113
def __str__(self)
Definition: conftest.py:49


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:03