|
8 | 8 |
|
9 | 9 | """
|
10 | 10 |
|
11 |
| -class ContextDecorator(object): |
12 |
| - "A base class or mixin that enables context managers to work as decorators." |
13 |
| - |
14 |
| - def _recreate_cm(self): |
15 |
| - """Return a recreated instance of self. |
16 |
| -
|
17 |
| - Allows an otherwise one-shot context manager like |
18 |
| - _GeneratorContextManager to support use as |
19 |
| - a decorator via implicit recreation. |
20 |
| -
|
21 |
| - This is a private interface just for _GeneratorContextManager. |
22 |
| - See issue #11647 for details. |
23 |
| - """ |
24 |
| - return self |
25 |
| - |
26 |
| - def __call__(self, func): |
27 |
| - def inner(*args, **kwds): |
28 |
| - with self._recreate_cm(): |
29 |
| - return func(*args, **kwds) |
30 |
| - return inner |
31 |
| - |
32 |
| - |
33 |
| -class _GeneratorContextManager(ContextDecorator): |
34 |
| - """Helper for @contextmanager decorator.""" |
35 |
| - |
36 |
| - def __init__(self, func, *args, **kwds): |
37 |
| - self.gen = func(*args, **kwds) |
38 |
| - self.func, self.args, self.kwds = func, args, kwds |
39 |
| - |
40 |
| - def _recreate_cm(self): |
41 |
| - # _GCM instances are one-shot context managers, so the |
42 |
| - # CM must be recreated each time a decorated function is |
43 |
| - # called |
44 |
| - return self.__class__(self.func, *self.args, **self.kwds) |
45 |
| - |
46 |
| - def __enter__(self): |
47 |
| - try: |
48 |
| - return next(self.gen) |
49 |
| - except StopIteration: |
50 |
| - raise RuntimeError("generator didn't yield") from None |
51 |
| - |
52 |
| - def __exit__(self, type, value, traceback): |
53 |
| - if type is None: |
54 |
| - try: |
55 |
| - next(self.gen) |
56 |
| - except StopIteration: |
57 |
| - return |
58 |
| - else: |
59 |
| - raise RuntimeError("generator didn't stop") |
60 |
| - else: |
61 |
| - if value is None: |
62 |
| - # Need to force instantiation so we can reliably |
63 |
| - # tell if we get the same exception back |
64 |
| - value = type() |
65 |
| - try: |
66 |
| - self.gen.throw(type, value, traceback) |
67 |
| - raise RuntimeError("generator didn't stop after throw()") |
68 |
| - except StopIteration as exc: |
69 |
| - # Suppress the exception *unless* it's the same exception that |
70 |
| - # was passed to throw(). This prevents a StopIteration |
71 |
| - # raised inside the "with" statement from being suppressed |
72 |
| - return exc is not value |
73 |
| - |
74 |
| - |
75 |
| -def contextmanager(func): |
76 |
| - """@contextmanager decorator. |
77 |
| -
|
78 |
| - Typical usage: |
79 |
| -
|
80 |
| - @contextmanager |
81 |
| - def some_generator(<arguments>): |
82 |
| - <setup> |
83 |
| - try: |
84 |
| - yield <value> |
85 |
| - finally: |
86 |
| - <cleanup> |
87 |
| -
|
88 |
| - This makes this: |
89 |
| -
|
90 |
| - with some_generator(<arguments>) as <variable>: |
91 |
| - <body> |
92 |
| -
|
93 |
| - equivalent to this: |
94 |
| -
|
95 |
| - <setup> |
96 |
| - try: |
97 |
| - <variable> = <value> |
98 |
| - <body> |
99 |
| - finally: |
100 |
| - <cleanup> |
101 |
| -
|
102 |
| - """ |
103 |
| - def helper(*args, **kwds): |
104 |
| - return _GeneratorContextManager(func, *args, **kwds) |
105 |
| - return helper |
| 11 | +from ucontextlib import * |
106 | 12 |
|
107 | 13 |
|
108 | 14 | class closing(object):
|
|
0 commit comments