conftest.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """pytest configuration
3 
4 Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
5 Adds docstring and exceptions message sanitizers: ignore Python 2 vs 3 differences.
6 """
7 
8 import contextlib
9 import difflib
10 import gc
11 import re
12 import textwrap
13 
14 import pytest
15 
16 import env
17 
18 # Early diagnostic for failed imports
19 import pybind11_tests # noqa: F401
20 
21 _unicode_marker = re.compile(r'u(\'[^\']*\')')
22 _long_marker = re.compile(r'([0-9])L')
23 _hexadecimal = re.compile(r'0x[0-9a-fA-F]+')
24 
25 # Avoid collecting Python3 only files
26 collect_ignore = []
27 if env.PY2:
28  collect_ignore.append("test_async.py")
29 
30 
32  """For triple-quote strings"""
33  return textwrap.dedent(s.lstrip('\n').rstrip())
34 
35 
37  """For output which does not require specific line order"""
38  return sorted(_strip_and_dedent(s).splitlines())
39 
40 
42  """Explanation for a failed assert -- the a and b arguments are List[str]"""
43  return ["--- actual / +++ expected"] + [line.strip('\n') for line in difflib.ndiff(a, b)]
44 
45 
46 class Output(object):
47  """Basic output post-processing and comparison"""
48  def __init__(self, string):
49  self.string = string
50  self.explanation = []
51 
52  def __str__(self):
53  return self.string
54 
55  def __eq__(self, other):
56  # Ignore constructor/destructor output which is prefixed with "###"
57  a = [line for line in self.string.strip().splitlines() if not line.startswith("###")]
58  b = _strip_and_dedent(other).splitlines()
59  if a == b:
60  return True
61  else:
62  self.explanation = _make_explanation(a, b)
63  return False
64 
65 
67  """Custom comparison for output without strict line ordering"""
68  def __eq__(self, other):
69  a = _split_and_sort(self.string)
70  b = _split_and_sort(other)
71  if a == b:
72  return True
73  else:
75  return False
76 
77 
78 class Capture(object):
79  def __init__(self, capfd):
80  self.capfd = capfd
81  self.out = ""
82  self.err = ""
83 
84  def __enter__(self):
85  self.capfd.readouterr()
86  return self
87 
88  def __exit__(self, *args):
89  self.out, self.err = self.capfd.readouterr()
90 
91  def __eq__(self, other):
92  a = Output(self.out)
93  b = other
94  if a == b:
95  return True
96  else:
97  self.explanation = a.explanation
98  return False
99 
100  def __str__(self):
101  return self.out
102 
103  def __contains__(self, item):
104  return item in self.out
105 
106  @property
107  def unordered(self):
108  return Unordered(self.out)
109 
110  @property
111  def stderr(self):
112  return Output(self.err)
113 
114 
115 @pytest.fixture
116 def capture(capsys):
117  """Extended `capsys` with context manager and custom equality operators"""
118  return Capture(capsys)
119 
120 
122  def __init__(self, sanitizer):
123  self.sanitizer = sanitizer
124  self.string = ""
125  self.explanation = []
126 
127  def __call__(self, thing):
128  self.string = self.sanitizer(thing)
129  return self
130 
131  def __eq__(self, other):
132  a = self.string
133  b = _strip_and_dedent(other)
134  if a == b:
135  return True
136  else:
137  self.explanation = _make_explanation(a.splitlines(), b.splitlines())
138  return False
139 
140 
142  s = s.strip()
143  s = s.replace("pybind11_tests.", "m.")
144  s = s.replace("unicode", "str")
145  s = _long_marker.sub(r"\1", s)
146  s = _unicode_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
def _split_and_sort(s)
Definition: conftest.py:36
def pytest_configure()
Definition: conftest.py:198
bool hasattr(handle obj, handle name)
Definition: pytypes.h:403
def __contains__(self, item)
Definition: conftest.py:103
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:100
def pytest_assertrepr_compare(op, left, right)
Definition: conftest.py:176
def __eq__(self, other)
Definition: conftest.py:91
def unordered(self)
Definition: conftest.py:107
def _make_explanation(a, b)
Definition: conftest.py:41
Definition: pytypes.h:928
def _strip_and_dedent(s)
Definition: conftest.py:31
def __call__(self, thing)
Definition: conftest.py:127
def __eq__(self, other)
Definition: conftest.py:131
def __exit__(self, args)
Definition: conftest.py:88
def _sanitize_docstring(thing)
Definition: conftest.py:150
def _sanitize_message(thing)
Definition: conftest.py:162
def __eq__(self, other)
Definition: conftest.py:68
def __init__(self, capfd)
Definition: conftest.py:79
def doc()
Definition: conftest.py:157
def __init__(self, sanitizer)
Definition: conftest.py:122
def _sanitize_general(s)
Definition: conftest.py:141
def __init__(self, string)
Definition: conftest.py:48
def __eq__(self, other)
Definition: conftest.py:55
def capture(capsys)
Definition: conftest.py:116
def __enter__(self)
Definition: conftest.py:84
def stderr(self)
Definition: conftest.py:111
def __str__(self)
Definition: conftest.py:52


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:41:50