[Python-checkins] r45655 - peps/trunk/pep-0343.txt

nick.coghlan python-checkins at python.org
Sun Apr 23 07:14:11 CEST 2006


Author: nick.coghlan
Date: Sun Apr 23 07:14:10 2006
New Revision: 45655

Modified:
   peps/trunk/pep-0343.txt
Log:
Clarify the original meanings I intended for various terms, and record the fact that gaining consensus on the terminology is still an open issue

Modified: peps/trunk/pep-0343.txt
==============================================================================
--- peps/trunk/pep-0343.txt	(original)
+++ peps/trunk/pep-0343.txt	Sun Apr 23 07:14:10 2006
@@ -7,7 +7,7 @@
 Type: Standards Track
 Content-Type: text/plain
 Created: 13-May-2005
-Post-History: 2-Jun-2005, 16-Oct-2005, 29-Oct-2005
+Post-History: 2-Jun-2005, 16-Oct-2005, 29-Oct-2005, 23-Apr-2006
 
 Abstract
 
@@ -19,6 +19,7 @@
     section on Resolved Issues). It's still at Draft status until
     Guido gives a final blessing to the updated PEP.
 
+
 Author's Note
 
     This PEP was originally written in first person by Guido, and
@@ -26,6 +27,13 @@
     on python-dev. Any first person references are from Guido's
     original.
 
+    Python's alpha release cycle revealed terminology problems in this
+    PEP and in the associated documentation and implementation [14].
+    The current version of the PEP reflects the implementation and
+    documentation as at Python 2.5a2. The PEP will be updated to
+    reflect any changes made to the terminology prior to the final
+    Python 2.5 release.
+
 Introduction
 
     After a lot of discussion about PEP 340 and alternatives, I
@@ -225,9 +233,9 @@
 
     The translation of the above statement is:
 
-        ctx = (EXPR).__context__()
-        exit = ctx.__exit__  # Not calling it yet
-        value = ctx.__enter__()
+        mgr = (EXPR).__context__()
+        exit = mgr.__exit__  # Not calling it yet
+        value = mgr.__enter__()
         exc = True
         try:
             try:
@@ -244,7 +252,7 @@
             if exc:
                 exit(None, None, None)
 
-    Here, the lowercase variables (ctx, exit, value, exc) are internal
+    Here, the lowercase variables (mgr, exit, value, exc) are internal
     variables and not accessible to the user; they will most likely be
     implemented as special registers or stack positions.
 
@@ -260,37 +268,37 @@
     as exceptions by __exit__().)
 
     The call to the __context__() method serves a similar purpose to
-    that of the __iter__() method of iterator and iterables. An
-    object with with simple state requirements (such as
+    that of the __iter__() method of iterator and iterables. A context
+    object with simple state requirements (such as
     threading.RLock) may provide its own __enter__() and __exit__()
     methods, and simply return 'self' from its __context__ method. On
-    the other hand, an object with more complex state requirements
-    (such as decimal.Context) may return a distinct context object
+    the other hand, a context object with more complex state requirements
+    (such as decimal.Context) may return a distinct context manager
     each time its __context__ method is invoked.
 
     If the "as VAR" part of the syntax is omitted, the "VAR =" part of
-    the translation is omitted (but ctx.__enter__() is still called).
+    the translation is omitted (but mgr.__enter__() is still called).
 
-    The calling convention for ctx.__exit__() is as follows.  If the
+    The calling convention for mgr.__exit__() is as follows.  If the
     finally-suite was reached through normal completion of BLOCK or
     through a non-local goto (a break, continue or return statement in
-    BLOCK), ctx.__exit__() is called with three None arguments.  If
+    BLOCK), mgr.__exit__() is called with three None arguments.  If
     the finally-suite was reached through an exception raised in
-    BLOCK, ctx.__exit__() is called with three arguments representing
+    BLOCK, mgr.__exit__() is called with three arguments representing
     the exception type, value, and traceback.
 
-    IMPORTANT: if ctx.__exit__() returns a "true" value, the exception
+    IMPORTANT: if mgr.__exit__() returns a "true" value, the exception
     is "swallowed".  That is, if it returns "true", execution
     continues at the next statement after the with-statement, even if
     an exception happened inside the with-statement.  However, if the
     with-statement was left via a non-local goto (break, continue or
-    return), this non-local return is resumed when ctx.__exit__()
+    return), this non-local return is resumed when mgr.__exit__()
     returns regardless of the return value.  The motivation for this
-    detail is to make it possible for ctx.__exit__() to swallow
+    detail is to make it possible for mgr.__exit__() to swallow
     exceptions, without making it too easy (since the default return
     value, None, is false and this causes the exception to be
     re-raised).  The main use case for swallowing exceptions is to
-    make it possible to write the @contextmanager decorator so thatn
+    make it possible to write the @contextmanager decorator so
     that a try/except block in a decorated generator behaves exactly
     as if the body of the generator were expanded in-line at the place
     of the with-statement.
@@ -330,6 +338,17 @@
     methods should avoid raising errors unless they have actually 
     failed.  (And allowing the original error to proceed isn't a 
     failure.)
+    
+    Objects returned by __context__() methods should also provide a 
+    __context__() method that returns self. This allows a program to
+    retrieve the context manager directly without breaking anything.
+    For example, the following should work just as well as the normal
+    case where the extra variable isn't used:
+
+        mgr = (EXPR).__context__()
+        with mgr as VAR:
+            BLOCK
+
 
 Transition Plan
 
@@ -406,13 +425,13 @@
            finally:
                f.close() # Ditto for errors here (however unlikely)
 
-    A robust builtin implementation of this decorator will be made
+    A robust implementation of this decorator will be made
     part of the standard library.
 
     Just as generator-iterator functions are very useful for writing
-    __iter__() methods for iterables, generator-context functions will
-    be very useful for writing __context__() methods for contexts.
-    These methods will still need to be decorated using the
+    __iter__() methods for iterables, generator context functions will
+    be very useful for writing __context__() methods for context
+    objects. These methods will still need to be decorated using the
     contextmanager decorator. To ensure an obvious error message if the
     decorator is left out, generator-iterator objects will NOT be given
     a native context - if you want to ensure a generator is closed
@@ -446,7 +465,7 @@
     is entered).
 
     OTOH such mistakes are easily diagnosed; for example, the
-    generator-context decorator above raises RuntimeError when a
+    generator context decorator above raises RuntimeError when a
     second  with-statement calls f.__enter__() again. A similar error
     can be raised if __enter__ is invoked on a closed file object.
 
@@ -470,19 +489,70 @@
     returns an iterator (this means that all iterators are iterables,
     but not all iterables are iterators).
 
-    This PEP proposes that the protocol used by the with statement be
-    known as the "context management protocol", and that objects that
-    implement that protocol be known as "context managers". The term
-    "context manager" then encompasses all objects with a __context__()
-    method that returns a context object.  (This means that all contexts
-    are context managers, but not all context managers are contexts).
-
-    The term "context" is based on the concept that the context object
-    defines a context of execution for the code that forms the body
-    of the with statement.
+    This PEP proposes that the protocol consisting of the __enter__()
+    and __exit__() methods, and a __context__() method that returns
+    self be known as the "context management protocol", and that
+    objects that implement that protocol be known as "context
+    managers".
+
+    The term "context object" then encompasses all objects with a
+    __context__() method that returns a context manager.  The protocol
+    these objects implement is called the "context protocol". This
+    means that all context managers are context objects, but not all
+    context objects are context managers, just as all iterators are
+    iterables, but not all iterables are iterators.
+
+    These terms are based on the concept that the context object
+    defines a context of execution for the code that forms the body of
+    the with statement. The role of the context manager is to
+    translate the context object's stored state into an active
+    manipulation of the runtime environment to setup and tear down the
+    desired runtime context for the duration of the with statement.
+    For example, a synchronisation lock's context manager acquires the
+    lock when entering the with statement, and releases the lock when
+    leaving it. The runtime context established within the body of the
+    with statement is that the synchronisation lock is currently held.
+
+    The general term "context" is unfortunately ambiguous. If necessary,
+    it can be made more explicit by using the terms "context objext" for
+    objects providing a __context__() method and "runtime context" for
+    the runtime environment modifications made by the context manager.
+    When solely discussing use of the with statement, the distinction
+    between the two shouldn't matter as the context object fully
+    defines the changes made to the runtime context. The distinction is
+    more important when discussing the process of implementing context
+    objects and context managers.
+
+Open Issues
+
+    1. As noted earlier, the standard terminology section has not yet
+       met with consensus on python-dev. It will be refined throughout
+       the Python 2.5 release cycle based on user feedback on the
+       usability of the documentation.
+
+    2. The original resolution was for the decorator to make a context
+       manager from a generator to be a builtin called "contextmanager".
+       The shorter term "context" was considered too ambiguous and
+       potentially confusing [9].
+       The different flavours of generators could then be described as:
+        - A "generator function" is an undecorated function containing
+          the 'yield' keyword, and the objects produced by
+          such functions are "generator-iterators". The term
+          "generator" may refer to either a generator function or a
+          generator-iterator depending on the situation.
+        - A "generator context function" is a generator function to
+          which the "contextmanager" decorator is applied and the
+          objects produced by such functions are "generator-context-
+          managers". The term "generator context" may refer to either
+          a generator context function or a generator-context-manager
+          depending on the situation.
+
+       In the Python 2.5 implementation, the decorator is actually part
+       of the standard library module contextlib. The ongoing
+       terminology review may lead to it being renamed
+       "contextlib.context" (with the existence of the underlying context
+       manager being an implementation detail).
 
-    In cases where the general term "context" would be ambiguous, it
-    can be made explicit by expanding it to "manageable context".
 
 Resolved Issues
 
@@ -570,21 +640,7 @@
             works without having to first understand the mechanics of
             how generator context managers are implemented.
 
-    6. The decorator to make a context manager from a generator will be
-       a builtin called "contextmanager". The shorter term "context" was
-       considered too ambiguous and potentially confusing [9].
-       The different flavours of generators can then be described as:
-        - A "generator function" is an undecorated function containing
-          the 'yield' keyword, and the objects produced by
-          such functions are "generator-iterators". The term
-          "generator" may refer to either a generator function or a
-          generator-iterator depending on the situation.
-        - A "generator context function" is a generator function to
-          which the "contextmanager" decorator is applied and the
-          objects produced by such functions are "generator-context-
-          managers". The term "generator context" may refer to either a
-          generator context function or a generator-context-manager
-          depending on the situation.
+    6. See point 2 in open issues :)
 
     7. A generator function used to implement a __context__ method will
        need to be decorated with the contextmanager decorator in order
@@ -609,7 +665,7 @@
     appropriate objects, such as threading.RLock, will be able to be
     used directly in with statements.
 
-    The tense used in the names of the example context managers is not
+    The tense used in the names of the example contexts is not
     arbitrary. Past tense ("-ed") is used when the name refers to an
     action which is done in the __enter__ method and undone in the
     __exit__ method. Progressive tense ("-ing") is used when the name
@@ -634,7 +690,7 @@
             # if via return or by an uncaught exception).
 
        PEP 319 gives a use case for also having an unlocked()
-       template; this can be written very similarly (just swap the
+       context; this can be written very similarly (just swap the
        acquire() and release() calls).
 
     2. A template for opening a file that ensures the file is closed
@@ -903,8 +959,10 @@
 
 Reference Implementation
 
-    There is no implementation at this time.  This PEP was accepted
-    by Guido at his EuroPython keynote, 27 June 2005.
+    This PEP was first accepted by Guido at his EuroPython
+    keynote, 27 June 2005.
+    It was accepted again later, with the __context__ method added.
+    The PEP was implemented for Python 2.5a1
 
 
 References
@@ -945,6 +1003,9 @@
     [13]
     http://mail.python.org/pipermail/python-dev/2006-February/061903.html
 
+    [14]
+    http://mail.python.org/pipermail/python-dev/2006-April/063859.html
+
 Copyright
 
     This document has been placed in the public domain.


More information about the Python-checkins mailing list