Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/pluggy/callers.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 """ | |
2 Call loop machinery | |
3 """ | |
4 import sys | |
5 import warnings | |
6 | |
7 _py3 = sys.version_info > (3, 0) | |
8 | |
9 | |
10 if not _py3: | |
11 exec( | |
12 """ | |
13 def _reraise(cls, val, tb): | |
14 raise cls, val, tb | |
15 """ | |
16 ) | |
17 | |
18 | |
19 def _raise_wrapfail(wrap_controller, msg): | |
20 co = wrap_controller.gi_code | |
21 raise RuntimeError( | |
22 "wrap_controller at %r %s:%d %s" | |
23 % (co.co_name, co.co_filename, co.co_firstlineno, msg) | |
24 ) | |
25 | |
26 | |
27 class HookCallError(Exception): | |
28 """ Hook was called wrongly. """ | |
29 | |
30 | |
31 class _Result(object): | |
32 def __init__(self, result, excinfo): | |
33 self._result = result | |
34 self._excinfo = excinfo | |
35 | |
36 @property | |
37 def excinfo(self): | |
38 return self._excinfo | |
39 | |
40 @property | |
41 def result(self): | |
42 """Get the result(s) for this hook call (DEPRECATED in favor of ``get_result()``).""" | |
43 msg = "Use get_result() which forces correct exception handling" | |
44 warnings.warn(DeprecationWarning(msg), stacklevel=2) | |
45 return self._result | |
46 | |
47 @classmethod | |
48 def from_call(cls, func): | |
49 __tracebackhide__ = True | |
50 result = excinfo = None | |
51 try: | |
52 result = func() | |
53 except BaseException: | |
54 excinfo = sys.exc_info() | |
55 | |
56 return cls(result, excinfo) | |
57 | |
58 def force_result(self, result): | |
59 """Force the result(s) to ``result``. | |
60 | |
61 If the hook was marked as a ``firstresult`` a single value should | |
62 be set otherwise set a (modified) list of results. Any exceptions | |
63 found during invocation will be deleted. | |
64 """ | |
65 self._result = result | |
66 self._excinfo = None | |
67 | |
68 def get_result(self): | |
69 """Get the result(s) for this hook call. | |
70 | |
71 If the hook was marked as a ``firstresult`` only a single value | |
72 will be returned otherwise a list of results. | |
73 """ | |
74 __tracebackhide__ = True | |
75 if self._excinfo is None: | |
76 return self._result | |
77 else: | |
78 ex = self._excinfo | |
79 if _py3: | |
80 raise ex[1].with_traceback(ex[2]) | |
81 _reraise(*ex) # noqa | |
82 | |
83 | |
84 def _wrapped_call(wrap_controller, func): | |
85 """ Wrap calling to a function with a generator which needs to yield | |
86 exactly once. The yield point will trigger calling the wrapped function | |
87 and return its ``_Result`` to the yield point. The generator then needs | |
88 to finish (raise StopIteration) in order for the wrapped call to complete. | |
89 """ | |
90 try: | |
91 next(wrap_controller) # first yield | |
92 except StopIteration: | |
93 _raise_wrapfail(wrap_controller, "did not yield") | |
94 call_outcome = _Result.from_call(func) | |
95 try: | |
96 wrap_controller.send(call_outcome) | |
97 _raise_wrapfail(wrap_controller, "has second yield") | |
98 except StopIteration: | |
99 pass | |
100 return call_outcome.get_result() | |
101 | |
102 | |
103 class _LegacyMultiCall(object): | |
104 """ execute a call into multiple python functions/methods. """ | |
105 | |
106 # XXX note that the __multicall__ argument is supported only | |
107 # for pytest compatibility reasons. It was never officially | |
108 # supported there and is explicitely deprecated since 2.8 | |
109 # so we can remove it soon, allowing to avoid the below recursion | |
110 # in execute() and simplify/speed up the execute loop. | |
111 | |
112 def __init__(self, hook_impls, kwargs, firstresult=False): | |
113 self.hook_impls = hook_impls | |
114 self.caller_kwargs = kwargs # come from _HookCaller.__call__() | |
115 self.caller_kwargs["__multicall__"] = self | |
116 self.firstresult = firstresult | |
117 | |
118 def execute(self): | |
119 caller_kwargs = self.caller_kwargs | |
120 self.results = results = [] | |
121 firstresult = self.firstresult | |
122 | |
123 while self.hook_impls: | |
124 hook_impl = self.hook_impls.pop() | |
125 try: | |
126 args = [caller_kwargs[argname] for argname in hook_impl.argnames] | |
127 except KeyError: | |
128 for argname in hook_impl.argnames: | |
129 if argname not in caller_kwargs: | |
130 raise HookCallError( | |
131 "hook call must provide argument %r" % (argname,) | |
132 ) | |
133 if hook_impl.hookwrapper: | |
134 return _wrapped_call(hook_impl.function(*args), self.execute) | |
135 res = hook_impl.function(*args) | |
136 if res is not None: | |
137 if firstresult: | |
138 return res | |
139 results.append(res) | |
140 | |
141 if not firstresult: | |
142 return results | |
143 | |
144 def __repr__(self): | |
145 status = "%d meths" % (len(self.hook_impls),) | |
146 if hasattr(self, "results"): | |
147 status = ("%d results, " % len(self.results)) + status | |
148 return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs) | |
149 | |
150 | |
151 def _legacymulticall(hook_impls, caller_kwargs, firstresult=False): | |
152 return _LegacyMultiCall( | |
153 hook_impls, caller_kwargs, firstresult=firstresult | |
154 ).execute() | |
155 | |
156 | |
157 def _multicall(hook_impls, caller_kwargs, firstresult=False): | |
158 """Execute a call into multiple python functions/methods and return the | |
159 result(s). | |
160 | |
161 ``caller_kwargs`` comes from _HookCaller.__call__(). | |
162 """ | |
163 __tracebackhide__ = True | |
164 results = [] | |
165 excinfo = None | |
166 try: # run impl and wrapper setup functions in a loop | |
167 teardowns = [] | |
168 try: | |
169 for hook_impl in reversed(hook_impls): | |
170 try: | |
171 args = [caller_kwargs[argname] for argname in hook_impl.argnames] | |
172 except KeyError: | |
173 for argname in hook_impl.argnames: | |
174 if argname not in caller_kwargs: | |
175 raise HookCallError( | |
176 "hook call must provide argument %r" % (argname,) | |
177 ) | |
178 | |
179 if hook_impl.hookwrapper: | |
180 try: | |
181 gen = hook_impl.function(*args) | |
182 next(gen) # first yield | |
183 teardowns.append(gen) | |
184 except StopIteration: | |
185 _raise_wrapfail(gen, "did not yield") | |
186 else: | |
187 res = hook_impl.function(*args) | |
188 if res is not None: | |
189 results.append(res) | |
190 if firstresult: # halt further impl calls | |
191 break | |
192 except BaseException: | |
193 excinfo = sys.exc_info() | |
194 finally: | |
195 if firstresult: # first result hooks return a single value | |
196 outcome = _Result(results[0] if results else None, excinfo) | |
197 else: | |
198 outcome = _Result(results, excinfo) | |
199 | |
200 # run all wrapper post-yield blocks | |
201 for gen in reversed(teardowns): | |
202 try: | |
203 gen.send(outcome) | |
204 _raise_wrapfail(gen, "has second yield") | |
205 except StopIteration: | |
206 pass | |
207 | |
208 return outcome.get_result() |