Mercurial > repos > guerler > hhblits
comparison lib/python3.8/site-packages/pip/_vendor/contextlib2.py @ 1:64071f2a4cf0 draft default tip
Deleted selected files
author | guerler |
---|---|
date | Mon, 27 Jul 2020 03:55:49 -0400 |
parents | 9e54283cc701 |
children |
comparison
equal
deleted
inserted
replaced
0:9e54283cc701 | 1:64071f2a4cf0 |
---|---|
1 """contextlib2 - backports and enhancements to the contextlib module""" | |
2 | |
3 import abc | |
4 import sys | |
5 import warnings | |
6 from collections import deque | |
7 from functools import wraps | |
8 | |
9 __all__ = ["contextmanager", "closing", "nullcontext", | |
10 "AbstractContextManager", | |
11 "ContextDecorator", "ExitStack", | |
12 "redirect_stdout", "redirect_stderr", "suppress"] | |
13 | |
14 # Backwards compatibility | |
15 __all__ += ["ContextStack"] | |
16 | |
17 | |
18 # Backport abc.ABC | |
19 if sys.version_info[:2] >= (3, 4): | |
20 _abc_ABC = abc.ABC | |
21 else: | |
22 _abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) | |
23 | |
24 | |
25 # Backport classic class MRO | |
26 def _classic_mro(C, result): | |
27 if C in result: | |
28 return | |
29 result.append(C) | |
30 for B in C.__bases__: | |
31 _classic_mro(B, result) | |
32 return result | |
33 | |
34 | |
35 # Backport _collections_abc._check_methods | |
36 def _check_methods(C, *methods): | |
37 try: | |
38 mro = C.__mro__ | |
39 except AttributeError: | |
40 mro = tuple(_classic_mro(C, [])) | |
41 | |
42 for method in methods: | |
43 for B in mro: | |
44 if method in B.__dict__: | |
45 if B.__dict__[method] is None: | |
46 return NotImplemented | |
47 break | |
48 else: | |
49 return NotImplemented | |
50 return True | |
51 | |
52 | |
53 class AbstractContextManager(_abc_ABC): | |
54 """An abstract base class for context managers.""" | |
55 | |
56 def __enter__(self): | |
57 """Return `self` upon entering the runtime context.""" | |
58 return self | |
59 | |
60 @abc.abstractmethod | |
61 def __exit__(self, exc_type, exc_value, traceback): | |
62 """Raise any exception triggered within the runtime context.""" | |
63 return None | |
64 | |
65 @classmethod | |
66 def __subclasshook__(cls, C): | |
67 """Check whether subclass is considered a subclass of this ABC.""" | |
68 if cls is AbstractContextManager: | |
69 return _check_methods(C, "__enter__", "__exit__") | |
70 return NotImplemented | |
71 | |
72 | |
73 class ContextDecorator(object): | |
74 """A base class or mixin that enables context managers to work as decorators.""" | |
75 | |
76 def refresh_cm(self): | |
77 """Returns the context manager used to actually wrap the call to the | |
78 decorated function. | |
79 | |
80 The default implementation just returns *self*. | |
81 | |
82 Overriding this method allows otherwise one-shot context managers | |
83 like _GeneratorContextManager to support use as decorators via | |
84 implicit recreation. | |
85 | |
86 DEPRECATED: refresh_cm was never added to the standard library's | |
87 ContextDecorator API | |
88 """ | |
89 warnings.warn("refresh_cm was never added to the standard library", | |
90 DeprecationWarning) | |
91 return self._recreate_cm() | |
92 | |
93 def _recreate_cm(self): | |
94 """Return a recreated instance of self. | |
95 | |
96 Allows an otherwise one-shot context manager like | |
97 _GeneratorContextManager to support use as | |
98 a decorator via implicit recreation. | |
99 | |
100 This is a private interface just for _GeneratorContextManager. | |
101 See issue #11647 for details. | |
102 """ | |
103 return self | |
104 | |
105 def __call__(self, func): | |
106 @wraps(func) | |
107 def inner(*args, **kwds): | |
108 with self._recreate_cm(): | |
109 return func(*args, **kwds) | |
110 return inner | |
111 | |
112 | |
113 class _GeneratorContextManager(ContextDecorator): | |
114 """Helper for @contextmanager decorator.""" | |
115 | |
116 def __init__(self, func, args, kwds): | |
117 self.gen = func(*args, **kwds) | |
118 self.func, self.args, self.kwds = func, args, kwds | |
119 # Issue 19330: ensure context manager instances have good docstrings | |
120 doc = getattr(func, "__doc__", None) | |
121 if doc is None: | |
122 doc = type(self).__doc__ | |
123 self.__doc__ = doc | |
124 # Unfortunately, this still doesn't provide good help output when | |
125 # inspecting the created context manager instances, since pydoc | |
126 # currently bypasses the instance docstring and shows the docstring | |
127 # for the class instead. | |
128 # See http://bugs.python.org/issue19404 for more details. | |
129 | |
130 def _recreate_cm(self): | |
131 # _GCM instances are one-shot context managers, so the | |
132 # CM must be recreated each time a decorated function is | |
133 # called | |
134 return self.__class__(self.func, self.args, self.kwds) | |
135 | |
136 def __enter__(self): | |
137 try: | |
138 return next(self.gen) | |
139 except StopIteration: | |
140 raise RuntimeError("generator didn't yield") | |
141 | |
142 def __exit__(self, type, value, traceback): | |
143 if type is None: | |
144 try: | |
145 next(self.gen) | |
146 except StopIteration: | |
147 return | |
148 else: | |
149 raise RuntimeError("generator didn't stop") | |
150 else: | |
151 if value is None: | |
152 # Need to force instantiation so we can reliably | |
153 # tell if we get the same exception back | |
154 value = type() | |
155 try: | |
156 self.gen.throw(type, value, traceback) | |
157 raise RuntimeError("generator didn't stop after throw()") | |
158 except StopIteration as exc: | |
159 # Suppress StopIteration *unless* it's the same exception that | |
160 # was passed to throw(). This prevents a StopIteration | |
161 # raised inside the "with" statement from being suppressed. | |
162 return exc is not value | |
163 except RuntimeError as exc: | |
164 # Don't re-raise the passed in exception | |
165 if exc is value: | |
166 return False | |
167 # Likewise, avoid suppressing if a StopIteration exception | |
168 # was passed to throw() and later wrapped into a RuntimeError | |
169 # (see PEP 479). | |
170 if _HAVE_EXCEPTION_CHAINING and exc.__cause__ is value: | |
171 return False | |
172 raise | |
173 except: | |
174 # only re-raise if it's *not* the exception that was | |
175 # passed to throw(), because __exit__() must not raise | |
176 # an exception unless __exit__() itself failed. But throw() | |
177 # has to raise the exception to signal propagation, so this | |
178 # fixes the impedance mismatch between the throw() protocol | |
179 # and the __exit__() protocol. | |
180 # | |
181 if sys.exc_info()[1] is not value: | |
182 raise | |
183 | |
184 | |
185 def contextmanager(func): | |
186 """@contextmanager decorator. | |
187 | |
188 Typical usage: | |
189 | |
190 @contextmanager | |
191 def some_generator(<arguments>): | |
192 <setup> | |
193 try: | |
194 yield <value> | |
195 finally: | |
196 <cleanup> | |
197 | |
198 This makes this: | |
199 | |
200 with some_generator(<arguments>) as <variable>: | |
201 <body> | |
202 | |
203 equivalent to this: | |
204 | |
205 <setup> | |
206 try: | |
207 <variable> = <value> | |
208 <body> | |
209 finally: | |
210 <cleanup> | |
211 | |
212 """ | |
213 @wraps(func) | |
214 def helper(*args, **kwds): | |
215 return _GeneratorContextManager(func, args, kwds) | |
216 return helper | |
217 | |
218 | |
219 class closing(object): | |
220 """Context to automatically close something at the end of a block. | |
221 | |
222 Code like this: | |
223 | |
224 with closing(<module>.open(<arguments>)) as f: | |
225 <block> | |
226 | |
227 is equivalent to this: | |
228 | |
229 f = <module>.open(<arguments>) | |
230 try: | |
231 <block> | |
232 finally: | |
233 f.close() | |
234 | |
235 """ | |
236 def __init__(self, thing): | |
237 self.thing = thing | |
238 | |
239 def __enter__(self): | |
240 return self.thing | |
241 | |
242 def __exit__(self, *exc_info): | |
243 self.thing.close() | |
244 | |
245 | |
246 class _RedirectStream(object): | |
247 | |
248 _stream = None | |
249 | |
250 def __init__(self, new_target): | |
251 self._new_target = new_target | |
252 # We use a list of old targets to make this CM re-entrant | |
253 self._old_targets = [] | |
254 | |
255 def __enter__(self): | |
256 self._old_targets.append(getattr(sys, self._stream)) | |
257 setattr(sys, self._stream, self._new_target) | |
258 return self._new_target | |
259 | |
260 def __exit__(self, exctype, excinst, exctb): | |
261 setattr(sys, self._stream, self._old_targets.pop()) | |
262 | |
263 | |
264 class redirect_stdout(_RedirectStream): | |
265 """Context manager for temporarily redirecting stdout to another file. | |
266 | |
267 # How to send help() to stderr | |
268 with redirect_stdout(sys.stderr): | |
269 help(dir) | |
270 | |
271 # How to write help() to a file | |
272 with open('help.txt', 'w') as f: | |
273 with redirect_stdout(f): | |
274 help(pow) | |
275 """ | |
276 | |
277 _stream = "stdout" | |
278 | |
279 | |
280 class redirect_stderr(_RedirectStream): | |
281 """Context manager for temporarily redirecting stderr to another file.""" | |
282 | |
283 _stream = "stderr" | |
284 | |
285 | |
286 class suppress(object): | |
287 """Context manager to suppress specified exceptions | |
288 | |
289 After the exception is suppressed, execution proceeds with the next | |
290 statement following the with statement. | |
291 | |
292 with suppress(FileNotFoundError): | |
293 os.remove(somefile) | |
294 # Execution still resumes here if the file was already removed | |
295 """ | |
296 | |
297 def __init__(self, *exceptions): | |
298 self._exceptions = exceptions | |
299 | |
300 def __enter__(self): | |
301 pass | |
302 | |
303 def __exit__(self, exctype, excinst, exctb): | |
304 # Unlike isinstance and issubclass, CPython exception handling | |
305 # currently only looks at the concrete type hierarchy (ignoring | |
306 # the instance and subclass checking hooks). While Guido considers | |
307 # that a bug rather than a feature, it's a fairly hard one to fix | |
308 # due to various internal implementation details. suppress provides | |
309 # the simpler issubclass based semantics, rather than trying to | |
310 # exactly reproduce the limitations of the CPython interpreter. | |
311 # | |
312 # See http://bugs.python.org/issue12029 for more details | |
313 return exctype is not None and issubclass(exctype, self._exceptions) | |
314 | |
315 | |
316 # Context manipulation is Python 3 only | |
317 _HAVE_EXCEPTION_CHAINING = sys.version_info[0] >= 3 | |
318 if _HAVE_EXCEPTION_CHAINING: | |
319 def _make_context_fixer(frame_exc): | |
320 def _fix_exception_context(new_exc, old_exc): | |
321 # Context may not be correct, so find the end of the chain | |
322 while 1: | |
323 exc_context = new_exc.__context__ | |
324 if exc_context is old_exc: | |
325 # Context is already set correctly (see issue 20317) | |
326 return | |
327 if exc_context is None or exc_context is frame_exc: | |
328 break | |
329 new_exc = exc_context | |
330 # Change the end of the chain to point to the exception | |
331 # we expect it to reference | |
332 new_exc.__context__ = old_exc | |
333 return _fix_exception_context | |
334 | |
335 def _reraise_with_existing_context(exc_details): | |
336 try: | |
337 # bare "raise exc_details[1]" replaces our carefully | |
338 # set-up context | |
339 fixed_ctx = exc_details[1].__context__ | |
340 raise exc_details[1] | |
341 except BaseException: | |
342 exc_details[1].__context__ = fixed_ctx | |
343 raise | |
344 else: | |
345 # No exception context in Python 2 | |
346 def _make_context_fixer(frame_exc): | |
347 return lambda new_exc, old_exc: None | |
348 | |
349 # Use 3 argument raise in Python 2, | |
350 # but use exec to avoid SyntaxError in Python 3 | |
351 def _reraise_with_existing_context(exc_details): | |
352 exc_type, exc_value, exc_tb = exc_details | |
353 exec("raise exc_type, exc_value, exc_tb") | |
354 | |
355 # Handle old-style classes if they exist | |
356 try: | |
357 from types import InstanceType | |
358 except ImportError: | |
359 # Python 3 doesn't have old-style classes | |
360 _get_type = type | |
361 else: | |
362 # Need to handle old-style context managers on Python 2 | |
363 def _get_type(obj): | |
364 obj_type = type(obj) | |
365 if obj_type is InstanceType: | |
366 return obj.__class__ # Old-style class | |
367 return obj_type # New-style class | |
368 | |
369 | |
370 # Inspired by discussions on http://bugs.python.org/issue13585 | |
371 class ExitStack(object): | |
372 """Context manager for dynamic management of a stack of exit callbacks | |
373 | |
374 For example: | |
375 | |
376 with ExitStack() as stack: | |
377 files = [stack.enter_context(open(fname)) for fname in filenames] | |
378 # All opened files will automatically be closed at the end of | |
379 # the with statement, even if attempts to open files later | |
380 # in the list raise an exception | |
381 | |
382 """ | |
383 def __init__(self): | |
384 self._exit_callbacks = deque() | |
385 | |
386 def pop_all(self): | |
387 """Preserve the context stack by transferring it to a new instance""" | |
388 new_stack = type(self)() | |
389 new_stack._exit_callbacks = self._exit_callbacks | |
390 self._exit_callbacks = deque() | |
391 return new_stack | |
392 | |
393 def _push_cm_exit(self, cm, cm_exit): | |
394 """Helper to correctly register callbacks to __exit__ methods""" | |
395 def _exit_wrapper(*exc_details): | |
396 return cm_exit(cm, *exc_details) | |
397 _exit_wrapper.__self__ = cm | |
398 self.push(_exit_wrapper) | |
399 | |
400 def push(self, exit): | |
401 """Registers a callback with the standard __exit__ method signature | |
402 | |
403 Can suppress exceptions the same way __exit__ methods can. | |
404 | |
405 Also accepts any object with an __exit__ method (registering a call | |
406 to the method instead of the object itself) | |
407 """ | |
408 # We use an unbound method rather than a bound method to follow | |
409 # the standard lookup behaviour for special methods | |
410 _cb_type = _get_type(exit) | |
411 try: | |
412 exit_method = _cb_type.__exit__ | |
413 except AttributeError: | |
414 # Not a context manager, so assume its a callable | |
415 self._exit_callbacks.append(exit) | |
416 else: | |
417 self._push_cm_exit(exit, exit_method) | |
418 return exit # Allow use as a decorator | |
419 | |
420 def callback(self, callback, *args, **kwds): | |
421 """Registers an arbitrary callback and arguments. | |
422 | |
423 Cannot suppress exceptions. | |
424 """ | |
425 def _exit_wrapper(exc_type, exc, tb): | |
426 callback(*args, **kwds) | |
427 # We changed the signature, so using @wraps is not appropriate, but | |
428 # setting __wrapped__ may still help with introspection | |
429 _exit_wrapper.__wrapped__ = callback | |
430 self.push(_exit_wrapper) | |
431 return callback # Allow use as a decorator | |
432 | |
433 def enter_context(self, cm): | |
434 """Enters the supplied context manager | |
435 | |
436 If successful, also pushes its __exit__ method as a callback and | |
437 returns the result of the __enter__ method. | |
438 """ | |
439 # We look up the special methods on the type to match the with statement | |
440 _cm_type = _get_type(cm) | |
441 _exit = _cm_type.__exit__ | |
442 result = _cm_type.__enter__(cm) | |
443 self._push_cm_exit(cm, _exit) | |
444 return result | |
445 | |
446 def close(self): | |
447 """Immediately unwind the context stack""" | |
448 self.__exit__(None, None, None) | |
449 | |
450 def __enter__(self): | |
451 return self | |
452 | |
453 def __exit__(self, *exc_details): | |
454 received_exc = exc_details[0] is not None | |
455 | |
456 # We manipulate the exception state so it behaves as though | |
457 # we were actually nesting multiple with statements | |
458 frame_exc = sys.exc_info()[1] | |
459 _fix_exception_context = _make_context_fixer(frame_exc) | |
460 | |
461 # Callbacks are invoked in LIFO order to match the behaviour of | |
462 # nested context managers | |
463 suppressed_exc = False | |
464 pending_raise = False | |
465 while self._exit_callbacks: | |
466 cb = self._exit_callbacks.pop() | |
467 try: | |
468 if cb(*exc_details): | |
469 suppressed_exc = True | |
470 pending_raise = False | |
471 exc_details = (None, None, None) | |
472 except: | |
473 new_exc_details = sys.exc_info() | |
474 # simulate the stack of exceptions by setting the context | |
475 _fix_exception_context(new_exc_details[1], exc_details[1]) | |
476 pending_raise = True | |
477 exc_details = new_exc_details | |
478 if pending_raise: | |
479 _reraise_with_existing_context(exc_details) | |
480 return received_exc and suppressed_exc | |
481 | |
482 | |
483 # Preserve backwards compatibility | |
484 class ContextStack(ExitStack): | |
485 """Backwards compatibility alias for ExitStack""" | |
486 | |
487 def __init__(self): | |
488 warnings.warn("ContextStack has been renamed to ExitStack", | |
489 DeprecationWarning) | |
490 super(ContextStack, self).__init__() | |
491 | |
492 def register_exit(self, callback): | |
493 return self.push(callback) | |
494 | |
495 def register(self, callback, *args, **kwds): | |
496 return self.callback(callback, *args, **kwds) | |
497 | |
498 def preserve(self): | |
499 return self.pop_all() | |
500 | |
501 | |
502 class nullcontext(AbstractContextManager): | |
503 """Context manager that does no additional processing. | |
504 Used as a stand-in for a normal context manager, when a particular | |
505 block of code is only sometimes used with a normal context manager: | |
506 cm = optional_cm if condition else nullcontext() | |
507 with cm: | |
508 # Perform operation, using optional_cm if condition is True | |
509 """ | |
510 | |
511 def __init__(self, enter_result=None): | |
512 self.enter_result = enter_result | |
513 | |
514 def __enter__(self): | |
515 return self.enter_result | |
516 | |
517 def __exit__(self, *excinfo): | |
518 pass |