]> granicus.if.org Git - python/commitdiff
Finish bringing SVN into line with latest version of PEP 343 by getting rid of all...
authorNick Coghlan <ncoghlan@gmail.com>
Wed, 3 May 2006 13:02:47 +0000 (13:02 +0000)
committerNick Coghlan <ncoghlan@gmail.com>
Wed, 3 May 2006 13:02:47 +0000 (13:02 +0000)
Doc/lib/libcontextlib.tex
Doc/lib/libstdtypes.tex
Doc/ref/ref3.tex
Doc/ref/ref7.tex
Lib/contextlib.py
Lib/decimal.py
Lib/test/test_contextlib.py
Lib/test/test_with.py

index 6c80a7162315606bc12fa70f593b774c2127e1c9..f28bdd098edad5c28fc2a4fcb3c106eb5f78c0a1 100644 (file)
@@ -11,19 +11,20 @@ This module provides utilities for common tasks involving the
 
 Functions provided:
 
-\begin{funcdesc}{context}{func}
+\begin{funcdesc}{contextmanager}{func}
 This function is a decorator that can be used to define a factory
 function for \keyword{with} statement context objects, without
 needing to create a class or separate \method{__enter__()} and
 \method{__exit__()} methods.
 
-A simple example:
+A simple example (this is not recommended as a real way of
+generating HTML!):
 
 \begin{verbatim}
 from __future__ import with_statement
-from contextlib import contextfactory
+from contextlib import contextmanager
 
-@contextfactory
+@contextmanager
 def tag(name):
     print "<%s>" % name
     yield
@@ -56,7 +57,7 @@ treat the exception as having been handled, and resume execution with
 the statement immediately following the \keyword{with} statement.
 \end{funcdesc}
 
-\begin{funcdesc}{nested}{ctx1\optional{, ctx2\optional{, ...}}}
+\begin{funcdesc}{nested}{mgr1\optional{, mgr2\optional{, ...}}}
 Combine multiple context managers into a single nested context manager.
 
 Code like this:
@@ -78,12 +79,12 @@ with A as X:
 \end{verbatim}
 
 Note that if the \method{__exit__()} method of one of the nested
-context objects indicates an exception should be suppressed, no
+context managers indicates an exception should be suppressed, no
 exception information will be passed to any remaining outer context
 objects. Similarly, if the \method{__exit__()} method of one of the
-nested context objects raises an exception, any previous exception
+nested context managers raises an exception, any previous exception
 state will be lost; the new exception will be passed to the
-\method{__exit__()} methods of any remaining outer context objects.
+\method{__exit__()} methods of any remaining outer context managers.
 In general, \method{__exit__()} methods should avoid raising
 exceptions, and in particular they should not re-raise a
 passed-in exception.
@@ -91,13 +92,13 @@ passed-in exception.
 
 \label{context-closing}
 \begin{funcdesc}{closing}{thing}
-Return a context that closes \var{thing} upon completion of the
-block.  This is basically equivalent to:
+Return a context manager that closes \var{thing} upon completion of
+the block.  This is basically equivalent to:
 
 \begin{verbatim}
-from contextlib import contextfactory
+from contextlib import contextmanager
 
-@contextfactory
+@contextmanager
 def closing(thing):
     try:
         yield thing
index cd9f7d4347f51cfb2c7c717df518283e791a68e1..d05b075ba13ee9d1b6a1f700dec4b6fba9b7f16f 100644 (file)
@@ -1753,67 +1753,50 @@ implemented in C will have to provide a writable
 \end{memberdesc}
 
 
-\subsection{Context Types \label{typecontext}}
+\subsection{Context Manager Types \label{typecontextmanager}}
 
 \versionadded{2.5}
-\index{with statement context protocol}
+\index{context manager}
 \index{context management protocol}
-\index{protocol!with statement context}
 \index{protocol!context management}
 
 Python's \keyword{with} statement supports the concept of a runtime
 context defined by a context manager.  This is implemented using
-three distinct methods; these are used to allow user-defined
-classes to define a runtime context.
+two separate methods that allow user-defined classes to define
+a runtime context that is entered before the statement body is
+executed and exited when the statement ends.
 
-The \dfn{context management protocol} consists of a single
-method that needs to be provided for a context manager object to
+The \dfn{context management protocol} consists of a pair of
+methods that need to be provided for a context manager object to
 define a runtime context:
 
-\begin{methoddesc}[context manager]{__context__}{}
-  Return a with statement context object.  The object is required to
-  support the with statement context protocol described below.  If an
-  object supports different kinds of runtime context, additional
-  methods can be provided to specifically request context objects for
-  those kinds of runtime context.  (An example of an object supporting
-  multiple kinds of context would be a synchronisation object which
-  supported both a locked context for normal thread synchronisation
-  and an unlocked context to temporarily release a held lock while
-  performing a potentially long running operation)
-\end{methoddesc}
-
-The with statement context objects themselves are required to support the
-following three methods, which together form the
-\dfn{with statement context protocol}:
+\begin{methoddesc}[context manager]{__enter__}{}
+  Enter the runtime context and return either this object or another
+  object related to the runtime context. The value returned by this
+  method is bound to the identifier in the \keyword{as} clause of
+  \keyword{with} statements using this context manager.
 
-\begin{methoddesc}[with statement context]{__context__}{}
-  Return the context object itself.  This is required to allow both
-  context objects and context managers to be used in a \keyword{with}
+  An example of a context manager that returns itself is a file object.
+  File objects return themselves from __enter__() to allow
+  \function{open()} to be used as the context expression in a with
   statement.
-\end{methoddesc}
 
-\begin{methoddesc}[with statement context]{__enter__}{}
-  Enter the runtime context and return either the defining context
-  manager or another object related to the runtime context. The value
-  returned by this method is bound to the identifier in the
-  \keyword{as} clause of \keyword{with} statements using this context.
-  (An example of a context object that returns the original context
-  manager is file objects, which are returned from __enter__() to
-  allow \function{open()} to be used directly in a with
-  statement. An example of a context object that returns a related
-  object is \code{decimal.Context} which sets the active decimal
-  context to a copy of the context manager and then returns the copy.
-  This allows changes to be made to the current decimal context in the
-  body of the \keyword{with} statement without affecting code outside
-  the \keyword{with} statement).
+  An example of a context manager that returns a related
+  object is the one returned by \code{decimal.Context.get_manager()}.
+  These managers set the active decimal context to a copy of the
+  original decimal context and then return the copy. This allows
+  changes to be made to the current decimal context in the body of
+  the \keyword{with} statement without affecting code outside
+  the \keyword{with} statement.
 \end{methoddesc}
 
-\begin{methoddesc}[with statement context]{__exit__}{exc_type, exc_val, exc_tb}
+\begin{methoddesc}[context manager]{__exit__}{exc_type, exc_val, exc_tb}
   Exit the runtime context and return a Boolean flag indicating if any
   expection that occurred should be suppressed. If an exception
   occurred while executing the body of the \keyword{with} statement, the
   arguments contain the exception type, value and traceback information.
   Otherwise, all three arguments are \var{None}.
+
   Returning a true value from this method will cause the \keyword{with}
   statement to suppress the exception and continue execution with the
   statement immediately following the \keyword{with} statement. Otherwise
@@ -1821,6 +1804,7 @@ following three methods, which together form the
   executing. Exceptions that occur during execution of this method will
   replace any exception that occurred in the body of the \keyword{with}
   statement.
+
   The exception passed in should never be reraised explicitly - instead,
   this method should return a false value to indicate that the method
   completed successfully and does not want to suppress the raised
@@ -1829,20 +1813,18 @@ following three methods, which together form the
   \method{__exit__()} method has actually failed.
 \end{methoddesc}
 
-Python defines several context objects and managers to support
-easy thread synchronisation, prompt closure of files or other
-objects, and thread-safe manipulation of the decimal arithmetic
-context. The specific types are not important beyond their
-implementation of the context management and with statement context
-protocols.
+Python defines several context managers to support easy thread
+synchronisation, prompt closure of files or other objects, and
+simpler manipulation of the active decimal arithmetic
+context. The specific types are not treated specially beyond
+their implementation of the context management protocol.
 
 Python's generators and the \code{contextlib.contextfactory} decorator
-provide a convenient way to implement these protocols.  If a context
-manager's \method{__context__()} method is implemented as a
-generator decorated with the \code{contextlib.contextfactory}
-decorator, it will automatically return a with statement context
-object supplying the necessary \method{__context__()},
-\method{__enter__()} and \method{__exit__()} methods.
+provide a convenient way to implement these protocols.  If a generator
+function is decorated with the \code{contextlib.contextfactory}
+decorator, it will return a context manager implementing the necessary
+\method{__enter__()} and \method{__exit__()} methods, rather than the
+iterator produced by an undecorated generator function.
 
 Note that there is no specific slot for any of these methods in the
 type structure for Python objects in the Python/C API. Extension
index a756e3080c9d5782aed2e576ad8d6fbd48a462f8..296f79f473d29b57efb3b0693b9417f321e259b3 100644 (file)
@@ -2112,14 +2112,13 @@ implement a \method{__coerce__()} method, for use by the built-in
 
 \end{itemize}
 
-\subsection{With Statement Contexts and Context Managers\label{context-managers}}
+\subsection{With Statement Context Managers\label{context-managers}}
 
 \versionadded{2.5}
 
 A \dfn{context manager} is an object that defines the runtime
 context to be established when executing a \keyword{with}
-statement. The context manager provides a
-\dfn{with statement context object} which manages the entry into,
+statement. The context manager handles the entry into,
 and the exit from, the desired runtime context for the execution
 of the block of code.  Context managers are normally invoked using
 the \keyword{with} statement (described in section~\ref{with}), but
@@ -2127,18 +2126,16 @@ can also be used by directly invoking their methods.
 
 \stindex{with}
 \index{context manager}
-\index{context (with statement)}
-\index{with statement context}
 
-Typical uses of context managers and contexts include saving and
+Typical uses of context managers include saving and
 restoring various kinds of global state, locking and unlocking
 resources, closing opened files, etc.
 
-For more information on context managers and context objects,
-see ``\ulink{Context Types}{../lib/typecontext.html}'' in the
+For more information on context managers, see
+``\ulink{Context Types}{../lib/typecontextmanager.html}'' in the
 \citetitle[../lib/lib.html]{Python Library Reference}.
 
-\begin{methoddesc}[with statement context]{__enter__}{self}
+\begin{methoddesc}[context manager]{__enter__}{self}
 Enter the runtime context related to this object. The \keyword{with}
 statement will bind this method's return value to the target(s)
 specified in the \keyword{as} clause of the statement, if any.
index 4a231332e58b9e80bb20f5cd0c386dbbbcd68851..b213cb25e37ae8ba96729e9d164d115bdc742532 100644 (file)
@@ -315,8 +315,8 @@ statement to generate exceptions may be found in section~\ref{raise}.
 \versionadded{2.5}
 
 The \keyword{with} statement is used to wrap the execution of a block
-with methods defined by a context manager or \keyword{with} statement context
-object (see section~\ref{context-managers}). This allows common
+with methods defined by a context manager (see
+section~\ref{context-managers}). This allows common
 \keyword{try}...\keyword{except}...\keyword{finally} usage patterns to
 be encapsulated for convenient reuse.
 
index 9d2c6a3a144fa7e6e93107463b91d6018f5ef32b..a807c42ce47561c6a05f42123ad7e5582f02c4c2 100644 (file)
@@ -2,10 +2,10 @@
 
 import sys
 
-__all__ = ["contextfactory", "nested", "closing"]
+__all__ = ["contextmanager", "nested", "closing"]
 
-class GeneratorContext(object):
-    """Helper for @contextfactory decorator."""
+class GeneratorContextManager(object):
+    """Helper for @contextmanager decorator."""
 
     def __init__(self, gen):
         self.gen = gen
@@ -45,12 +45,12 @@ class GeneratorContext(object):
                     raise
 
 
-def contextfactory(func):
-    """@contextfactory decorator.
+def contextmanager(func):
+    """@contextmanager decorator.
 
     Typical usage:
 
-        @contextfactory
+        @contextmanager
         def some_generator(<arguments>):
             <setup>
             try:
@@ -74,7 +74,7 @@ def contextfactory(func):
 
     """
     def helper(*args, **kwds):
-        return GeneratorContext(func(*args, **kwds))
+        return GeneratorContextManager(func(*args, **kwds))
     try:
         helper.__name__ = func.__name__
         helper.__doc__ = func.__doc__
@@ -84,7 +84,7 @@ def contextfactory(func):
     return helper
 
 
-@contextfactory
+@contextmanager
 def nested(*managers):
     """Support multiple context managers in a single with-statement.
 
index 2f989a8524e18d011875a3247db6f609c61b5656..2e0afffd07704181ac119ca1c281ae7f396cd929 100644 (file)
@@ -2173,7 +2173,7 @@ for name in rounding_functions:
 
 del name, val, globalname, rounding_functions
 
-class WithStatementContext(object):
+class ContextManager(object):
     """Helper class to simplify Context management.
 
     Sample usage:
@@ -2248,8 +2248,8 @@ class Context(object):
         s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']')
         return ', '.join(s) + ')'
 
-    def context_manager(self):
-        return WithStatementContext(self.copy())
+    def get_manager(self):
+        return ContextManager(self.copy())
 
     def clear_flags(self):
         """Reset all flags to zero"""
index 8d3dd1a72e8b89310f67337192498e91ad5a284e..2cf39ae6672fb2c595221392df38825d31e3a2c2 100644 (file)
@@ -13,9 +13,9 @@ from test.test_support import run_suite
 
 class ContextManagerTestCase(unittest.TestCase):
 
-    def test_contextfactory_plain(self):
+    def test_contextmanager_plain(self):
         state = []
-        @contextfactory
+        @contextmanager
         def woohoo():
             state.append(1)
             yield 42
@@ -26,9 +26,9 @@ class ContextManagerTestCase(unittest.TestCase):
             state.append(x)
         self.assertEqual(state, [1, 42, 999])
 
-    def test_contextfactory_finally(self):
+    def test_contextmanager_finally(self):
         state = []
-        @contextfactory
+        @contextmanager
         def woohoo():
             state.append(1)
             try:
@@ -47,8 +47,8 @@ class ContextManagerTestCase(unittest.TestCase):
             self.fail("Expected ZeroDivisionError")
         self.assertEqual(state, [1, 42, 999])
 
-    def test_contextfactory_no_reraise(self):
-        @contextfactory
+    def test_contextmanager_no_reraise(self):
+        @contextmanager
         def whee():
             yield
         ctx = whee()
@@ -56,8 +56,8 @@ class ContextManagerTestCase(unittest.TestCase):
         # Calling __exit__ should not result in an exception
         self.failIf(ctx.__exit__(TypeError, TypeError("foo"), None))
 
-    def test_contextfactory_trap_yield_after_throw(self):
-        @contextfactory
+    def test_contextmanager_trap_yield_after_throw(self):
+        @contextmanager
         def whoo():
             try:
                 yield
@@ -69,9 +69,9 @@ class ContextManagerTestCase(unittest.TestCase):
             RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None
         )
 
-    def test_contextfactory_except(self):
+    def test_contextmanager_except(self):
         state = []
-        @contextfactory
+        @contextmanager
         def woohoo():
             state.append(1)
             try:
@@ -86,14 +86,14 @@ class ContextManagerTestCase(unittest.TestCase):
             raise ZeroDivisionError(999)
         self.assertEqual(state, [1, 42, 999])
 
-    def test_contextfactory_attribs(self):
+    def test_contextmanager_attribs(self):
         def attribs(**kw):
             def decorate(func):
                 for k,v in kw.items():
                     setattr(func,k,v)
                 return func
             return decorate
-        @contextfactory
+        @contextmanager
         @attribs(foo='bar')
         def baz(spam):
             """Whee!"""
@@ -106,13 +106,13 @@ class NestedTestCase(unittest.TestCase):
     # XXX This needs more work
 
     def test_nested(self):
-        @contextfactory
+        @contextmanager
         def a():
             yield 1
-        @contextfactory
+        @contextmanager
         def b():
             yield 2
-        @contextfactory
+        @contextmanager
         def c():
             yield 3
         with nested(a(), b(), c()) as (x, y, z):
@@ -122,14 +122,14 @@ class NestedTestCase(unittest.TestCase):
 
     def test_nested_cleanup(self):
         state = []
-        @contextfactory
+        @contextmanager
         def a():
             state.append(1)
             try:
                 yield 2
             finally:
                 state.append(3)
-        @contextfactory
+        @contextmanager
         def b():
             state.append(4)
             try:
@@ -148,7 +148,7 @@ class NestedTestCase(unittest.TestCase):
 
     def test_nested_right_exception(self):
         state = []
-        @contextfactory
+        @contextmanager
         def a():
             yield 1
         class b(object):
@@ -170,10 +170,10 @@ class NestedTestCase(unittest.TestCase):
             self.fail("Didn't raise ZeroDivisionError")
 
     def test_nested_b_swallows(self):
-        @contextfactory
+        @contextmanager
         def a():
             yield
-        @contextfactory
+        @contextmanager
         def b():
             try:
                 yield
@@ -187,7 +187,7 @@ class NestedTestCase(unittest.TestCase):
             self.fail("Didn't swallow ZeroDivisionError")
 
     def test_nested_break(self):
-        @contextfactory
+        @contextmanager
         def a():
             yield
         state = 0
@@ -199,7 +199,7 @@ class NestedTestCase(unittest.TestCase):
         self.assertEqual(state, 1)
 
     def test_nested_continue(self):
-        @contextfactory
+        @contextmanager
         def a():
             yield
         state = 0
@@ -211,7 +211,7 @@ class NestedTestCase(unittest.TestCase):
         self.assertEqual(state, 3)
 
     def test_nested_return(self):
-        @contextfactory
+        @contextmanager
         def a():
             try:
                 yield
@@ -339,12 +339,12 @@ class DecimalContextTestCase(unittest.TestCase):
         orig_context = ctx.copy()
         try:
             ctx.prec = save_prec = decimal.ExtendedContext.prec + 5
-            with decimal.ExtendedContext.context_manager():
+            with decimal.ExtendedContext.get_manager():
                 self.assertEqual(decimal.getcontext().prec,
                                  decimal.ExtendedContext.prec)
             self.assertEqual(decimal.getcontext().prec, save_prec)
             try:
-                with decimal.ExtendedContext.context_manager():
+                with decimal.ExtendedContext.get_manager():
                     self.assertEqual(decimal.getcontext().prec,
                                      decimal.ExtendedContext.prec)
                     1/0
index 765bfec397933a335e551779caeef7a2e5b64736..57505085dd3e5a6d4bdab8924b4ea0ffd54e0df7 100644 (file)
@@ -10,25 +10,26 @@ __email__ = "mbland at acm dot org"
 import sys
 import unittest
 from collections import deque
-from contextlib import GeneratorContext, contextfactory
+from contextlib import GeneratorContextManager, contextmanager
 from test.test_support import run_unittest
 
 
-class MockContextManager(GeneratorContext):
+class MockContextManager(GeneratorContextManager):
     def __init__(self, gen):
-        GeneratorContext.__init__(self, gen)
+        GeneratorContextManager.__init__(self, gen)
         self.enter_called = False
         self.exit_called = False
         self.exit_args = None
 
     def __enter__(self):
         self.enter_called = True
-        return GeneratorContext.__enter__(self)
+        return GeneratorContextManager.__enter__(self)
 
     def __exit__(self, type, value, traceback):
         self.exit_called = True
         self.exit_args = (type, value, traceback)
-        return GeneratorContext.__exit__(self, type, value, traceback)
+        return GeneratorContextManager.__exit__(self, type,
+                                                value, traceback)
 
 
 def mock_contextmanager(func):
@@ -439,7 +440,7 @@ class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
         self.assertAfterWithGeneratorInvariantsNoError(self.bar)
 
     def testRaisedStopIteration1(self):
-        @contextfactory
+        @contextmanager
         def cm():
             yield
 
@@ -463,7 +464,7 @@ class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
         self.assertRaises(StopIteration, shouldThrow)
 
     def testRaisedGeneratorExit1(self):
-        @contextfactory
+        @contextmanager
         def cm():
             yield