11import inspect
2- from contextlib import contextmanager
2+ from contextlib import ExitStack , contextmanager
33from typing import (
44 Any ,
55 Callable ,
@@ -52,7 +52,7 @@ def check_all_laws(
5252
5353 .. code:: python
5454
55- check_all_laws(IO, {'max_examples': 100})
55+ check_all_laws(IO, settings_kwargs= {'max_examples': 100})
5656
5757 Note:
5858 Cannot be used inside doctests because of the magic we use inside.
@@ -113,37 +113,38 @@ def container_strategies(
113113 ),
114114 )
115115
116- with maybe_register_container (
117- container_type ,
118- use_init = settings .use_init ,
119- ):
116+ try :
120117 yield
121-
122- for interface in our_interfaces :
123- types ._global_type_lookup .pop (interface ) # noqa: WPS441
118+ finally :
119+ for interface in our_interfaces :
120+ types ._global_type_lookup .pop (interface )
121+ _clean_caches ()
124122
125123
126124@contextmanager
127- def maybe_register_container (
125+ def register_container (
128126 container_type : Type ['Lawful' ],
129127 * ,
130128 use_init : bool ,
131129) -> Iterator [None ]:
132130 """Temporary registers a container if it is not registered yet."""
133- unknown_container = container_type not in types ._global_type_lookup
134- if unknown_container :
135- st .register_type_strategy (
131+ used = types ._global_type_lookup .pop (container_type , None )
132+ st .register_type_strategy (
133+ container_type ,
134+ strategy_from_container (
136135 container_type ,
137- strategy_from_container (
138- container_type ,
139- use_init = use_init ,
140- ),
141- )
142-
143- yield
136+ use_init = use_init ,
137+ ),
138+ )
144139
145- if unknown_container :
146- types ._global_type_lookup .pop (container_type ) # noqa: WPS441
140+ try :
141+ yield
142+ finally :
143+ types ._global_type_lookup .pop (container_type )
144+ if used :
145+ st .register_type_strategy (container_type , used )
146+ else :
147+ _clean_caches ()
147148
148149
149150@contextmanager
@@ -154,10 +155,11 @@ def pure_functions() -> Iterator[None]:
154155 It is not a default in ``hypothesis``.
155156 """
156157 def factory (thing ) -> st .SearchStrategy :
157- like = (lambda : None ) if len (
158- thing .__args__ ,
159- ) == 1 else (lambda * args , ** kwargs : None )
160-
158+ like = (
159+ (lambda : None )
160+ if len (thing .__args__ ) == 1
161+ else (lambda * args , ** kwargs : None )
162+ )
161163 return st .functions (
162164 like = like ,
163165 returns = st .from_type (thing .__args__ [- 1 ]),
@@ -168,10 +170,11 @@ def factory(thing) -> st.SearchStrategy:
168170 used = types ._global_type_lookup [callable_type ]
169171 st .register_type_strategy (callable_type , factory )
170172
171- yield
172-
173- types ._global_type_lookup .pop (callable_type )
174- st .register_type_strategy (callable_type , used )
173+ try :
174+ yield
175+ finally :
176+ types ._global_type_lookup .pop (callable_type )
177+ st .register_type_strategy (callable_type , used )
175178
176179
177180def _get_callable_type () -> Any :
@@ -195,23 +198,47 @@ def type_vars() -> Iterator[None]:
195198 for example, ``nan`` does not work for us
196199
197200 """
198- used = types ._global_type_lookup [TypeVar ]
199-
200201 def factory (thing ):
201- type_strategies = [
202- types .resolve_TypeVar (thing ),
203- # TODO: add mutable strategies
204- ]
205- return st .one_of (type_strategies ).filter (
202+ return types .resolve_TypeVar (thing ).filter (
206203 lambda inner : inner == inner , # noqa: WPS312
207204 )
208205
206+ used = types ._global_type_lookup .pop (TypeVar )
209207 st .register_type_strategy (TypeVar , factory )
210208
211- yield
209+ try :
210+ yield
211+ finally :
212+ types ._global_type_lookup .pop (TypeVar )
213+ st .register_type_strategy (TypeVar , used )
214+
215+
216+ @contextmanager
217+ def clean_plugin_context () -> Iterator [None ]:
218+ """
219+ We register a lot of types in `_entrypoint.py`, we need to clean them.
220+
221+ Otherwise, some types might be messed up.
222+ """
223+ saved_stategies = {}
224+ for strategy_key , strategy in types ._global_type_lookup .items ():
225+ if isinstance (strategy_key , type ):
226+ if strategy_key .__module__ .startswith ('returns.' ):
227+ saved_stategies .update ({strategy_key : strategy })
228+
229+ for key_to_remove in saved_stategies :
230+ types ._global_type_lookup .pop (key_to_remove )
231+ _clean_caches ()
232+
233+ try :
234+ yield
235+ finally :
236+ for saved_state in saved_stategies .items ():
237+ st .register_type_strategy (* saved_state )
212238
213- types ._global_type_lookup .pop (TypeVar )
214- st .register_type_strategy (TypeVar , used )
239+
240+ def _clean_caches () -> None :
241+ st .from_type .__clear_cache () # type: ignore[attr-defined]
215242
216243
217244def _run_law (
@@ -221,10 +248,17 @@ def _run_law(
221248 settings : _Settings ,
222249) -> Callable [[st .DataObject ], None ]:
223250 def factory (source : st .DataObject ) -> None :
224- with type_vars ():
225- with pure_functions ():
226- with container_strategies (container_type , settings = settings ):
227- source .draw (st .builds (law .definition ))
251+ with ExitStack () as stack :
252+ stack .enter_context (clean_plugin_context ())
253+ stack .enter_context (type_vars ())
254+ stack .enter_context (pure_functions ())
255+ stack .enter_context (
256+ container_strategies (container_type , settings = settings ),
257+ )
258+ stack .enter_context (
259+ register_container (container_type , use_init = settings .use_init ),
260+ )
261+ source .draw (st .builds (law .definition ))
228262 return factory
229263
230264
@@ -254,7 +288,12 @@ def _create_law_test_case(
254288 setattr (
255289 module ,
256290 test_function .__name__ ,
257- # We mark all tests with `returns_lawful` marker,
258- # so users can easily skip them if needed.
259- pytest .mark .returns_lawful (test_function ),
291+ pytest .mark .filterwarnings (
292+ # We ignore multiple warnings about unused coroutines and stuff:
293+ 'ignore::pytest.PytestUnraisableExceptionWarning' ,
294+ )(
295+ # We mark all tests with `returns_lawful` marker,
296+ # so users can easily skip them if needed.
297+ pytest .mark .returns_lawful (test_function ),
298+ ),
260299 )
0 commit comments