@@ -37,6 +37,16 @@ class _GeneratorContextManager(ContextDecorator):
37
37
def __init__ (self , func , * args , ** kwds ):
38
38
self .gen = func (* args , ** kwds )
39
39
self .func , self .args , self .kwds = func , args , kwds
40
+ # Issue 19330: ensure context manager instances have good docstrings
41
+ doc = getattr (func , "__doc__" , None )
42
+ if doc is None :
43
+ doc = type (self ).__doc__
44
+ self .__doc__ = doc
45
+ # Unfortunately, this still doesn't provide good help output when
46
+ # inspecting the created context manager instances, since pydoc
47
+ # currently bypasses the instance docstring and shows the docstring
48
+ # for the class instead.
49
+ # See http://bugs.python.org/issue19404 for more details.
40
50
41
51
def _recreate_cm (self ):
42
52
# _GCM instances are one-shot context managers, so the
@@ -117,9 +127,6 @@ def helper(*args, **kwds):
117
127
return helper
118
128
119
129
120
- # Unfortunately, this was originally published as a class, so
121
- # backwards compatibility prevents the use of the wrapper function
122
- # approach used for the other classes
123
130
class closing (object ):
124
131
"""Context to automatically close something at the end of a block.
125
132
@@ -144,8 +151,18 @@ def __enter__(self):
144
151
def __exit__ (self , * exc_info ):
145
152
self .thing .close ()
146
153
147
- class _RedirectStdout :
148
- """Helper for redirect_stdout."""
154
+ class redirect_stdout :
155
+ """Context manager for temporarily redirecting stdout to another file
156
+
157
+ # How to send help() to stderr
158
+ with redirect_stdout(sys.stderr):
159
+ help(dir)
160
+
161
+ # How to write help() to a file
162
+ with open('help.txt', 'w') as f:
163
+ with redirect_stdout(f):
164
+ help(pow)
165
+ """
149
166
150
167
def __init__ (self , new_target ):
151
168
self ._new_target = new_target
@@ -163,56 +180,37 @@ def __exit__(self, exctype, excinst, exctb):
163
180
self ._old_target = self ._sentinel
164
181
sys .stdout = restore_stdout
165
182
166
- # Use a wrapper function since we don't care about supporting inheritance
167
- # and a function gives much cleaner output in help()
168
- def redirect_stdout (target ):
169
- """Context manager for temporarily redirecting stdout to another file
170
183
171
- # How to send help() to stderr
172
- with redirect_stdout(sys.stderr):
173
- help(dir)
174
184
175
- # How to write help() to a file
176
- with open('help.txt', 'w') as f:
177
- with redirect_stdout(f):
178
- help(pow)
179
- """
180
- return _RedirectStdout (target )
185
+ class suppress :
186
+ """Context manager to suppress specified exceptions
187
+
188
+ After the exception is suppressed, execution proceeds with the next
189
+ statement following the with statement.
181
190
191
+ with suppress(FileNotFoundError):
192
+ os.remove(somefile)
193
+ # Execution still resumes here if the file was already removed
194
+ """
182
195
183
- class _SuppressExceptions :
184
- """Helper for suppress."""
185
196
def __init__ (self , * exceptions ):
186
197
self ._exceptions = exceptions
187
198
188
199
def __enter__ (self ):
189
200
pass
190
201
191
202
def __exit__ (self , exctype , excinst , exctb ):
192
- # Unlike isinstance and issubclass, exception handling only
193
- # looks at the concrete type heirarchy (ignoring the instance
194
- # and subclass checking hooks). However, all exceptions are
195
- # also required to be concrete subclasses of BaseException, so
196
- # if there's a discrepancy in behaviour, we currently consider it
197
- # the fault of the strange way the exception has been defined rather
198
- # than the fact that issubclass can be customised while the
199
- # exception checks can't.
203
+ # Unlike isinstance and issubclass, CPython exception handling
204
+ # currently only looks at the concrete type hierarchy (ignoring
205
+ # the instance and subclass checking hooks). While Guido considers
206
+ # that a bug rather than a feature, it's a fairly hard one to fix
207
+ # due to various internal implementation details. suppress provides
208
+ # the simpler issubclass based semantics, rather than trying to
209
+ # exactly reproduce the limitations of the CPython interpreter.
210
+ #
200
211
# See http://bugs.python.org/issue12029 for more details
201
212
return exctype is not None and issubclass (exctype , self ._exceptions )
202
213
203
- # Use a wrapper function since we don't care about supporting inheritance
204
- # and a function gives much cleaner output in help()
205
- def suppress (* exceptions ):
206
- """Context manager to suppress specified exceptions
207
-
208
- After the exception is suppressed, execution proceeds with the next
209
- statement following the with statement.
210
-
211
- with suppress(FileNotFoundError):
212
- os.remove(somefile)
213
- # Execution still resumes here if the file was already removed
214
- """
215
- return _SuppressExceptions (* exceptions )
216
214
217
215
# Inspired by discussions on http://bugs.python.org/issue13585
218
216
class ExitStack (object ):
0 commit comments