1
1
"""pytest-asyncio implementation."""
2
2
import asyncio
3
3
import contextlib
4
+ import functools
4
5
import inspect
5
6
import socket
6
7
@@ -139,7 +140,8 @@ def pytest_pyfunc_call(pyfuncitem):
139
140
function call.
140
141
"""
141
142
for marker_name , fixture_name in _markers_2_fixtures .items ():
142
- if marker_name in pyfuncitem .keywords :
143
+ if inspect .isasyncgenfunction (pyfuncitem .obj ) \
144
+ and marker_name in pyfuncitem .keywords :
143
145
event_loop = pyfuncitem .funcargs [fixture_name ]
144
146
145
147
funcargs = pyfuncitem .funcargs
@@ -152,11 +154,39 @@ def pytest_pyfunc_call(pyfuncitem):
152
154
return True
153
155
154
156
157
+ def wrap_in_sync (func ):
158
+ """Return a sync wrapper around an async function."""
159
+
160
+ @functools .wraps (func )
161
+ def inner (** kwargs ):
162
+ loop = asyncio .get_event_loop_policy ().new_event_loop ()
163
+ try :
164
+ coro = func (** kwargs )
165
+ if coro is not None :
166
+ future = asyncio .ensure_future (coro , loop = loop )
167
+ loop .run_until_complete (future )
168
+ finally :
169
+ loop .close ()
170
+
171
+ return inner
172
+
173
+
155
174
def pytest_runtest_setup (item ):
156
175
for marker , fixture in _markers_2_fixtures .items ():
157
176
if marker in item .keywords and fixture not in item .fixturenames :
158
177
# inject an event loop fixture for all async tests
159
178
item .fixturenames .append (fixture )
179
+ if item .get_closest_marker ("asyncio" ) is not None :
180
+ if hasattr (item .obj , 'hypothesis' ):
181
+ # If it's a Hypothesis test, we insert the wrap_in_sync decorator
182
+ item .obj .hypothesis .inner_test = wrap_in_sync (
183
+ item .obj .hypothesis .inner_test
184
+ )
185
+ elif getattr (item .obj , 'is_hypothesis_test' , False ):
186
+ pytest .fail (
187
+ 'test function `%r` is using Hypothesis, but pytest-asyncio '
188
+ 'only works with Hypothesis 3.64.0 or later.' % item
189
+ )
160
190
161
191
162
192
# maps marker to the name of the event loop fixture that will be available
0 commit comments