[Python-checkins] r45857 - peps/trunk/pep-0343.txt
nick.coghlan
python-checkins at python.org
Tue May 2 16:28:50 CEST 2006
Author: nick.coghlan
Date: Tue May 2 16:28:47 2006
New Revision: 45857
Modified:
peps/trunk/pep-0343.txt
Log:
Remove the __context__ method from PEP 343, and update the terminology section (again). Record a couple of remaining open issues, and try to clarify the resolved issues sections by only giving a very brief overview of all the rejected options that aren't relevant any more.
Modified: peps/trunk/pep-0343.txt
==============================================================================
--- peps/trunk/pep-0343.txt (original)
+++ peps/trunk/pep-0343.txt Tue May 2 16:28:47 2006
@@ -7,18 +7,16 @@
Type: Standards Track
Content-Type: text/plain
Created: 13-May-2005
-Post-History: 2-Jun-2005, 16-Oct-2005, 29-Oct-2005, 23-Apr-2006
+Post-History: 2-Jun-2005, 16-Oct-2005, 29-Oct-2005, 23-Apr-2006, 1-May-2006
Abstract
This PEP adds a new statement "with" to the Python language to make
it possible to factor out standard uses of try/finally statements.
- The PEP was approved in principle by the BDFL, but there were
- still a couple of implementation details to be worked out (see the
- section on Resolved Issues). It's still at Draft status until
- Guido gives a final blessing to the updated PEP.
-
+ In this PEP, context managers provide __enter__() and __exit__()
+ methods that are invoked on entry to and exit from the managed
+ context that forms the body of the with statement.
Author's Note
@@ -29,13 +27,17 @@
Python's alpha release cycle revealed terminology problems in this
PEP and in the associated documentation and implementation [14].
- So while the PEP is already accepted, this refers to the
- implementation rather than the exact terminology.
+ So while the PEP is already accepted in principle, it won't really
+ be considered stable until the status becomes Final.
- 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.
+ The current version of the PEP reflects the discussions that
+ occurred on python-dev shortly after the release of Python 2.5a2.
+ The PEP will continue to be updated to reflect any changes made to
+ the details of the feature prior to the final Python 2.5 release.
+
+ Yes, the verb tense is messed up in a few places. We've been
+ working on this PEP for nearly a year now, so things that were
+ originally in the future are now in the past :)
Introduction
@@ -48,11 +50,8 @@
[2] and universally approved of. I'm also changing the keyword to
'with'.
- On-line discussion of this PEP should take place in the Python
- Wiki [3].
-
- If this PEP is approved, the following PEPs will be rejected due
- to overlap:
+ Following acceptance of this PEP, the following PEPs have been
+ rejected due to overlap:
- PEP 310, Reliable Acquisition/Release Pairs. This is the
original with-statement proposal.
@@ -66,7 +65,11 @@
important; in fact it may be better to always be explicit about
the mutex being used.
- (PEP 340 and PEP 346 have already been withdrawn.)
+ PEP 340 and PEP 346 also overlapped with this PEP, but were
+ voluntarily withdrawn when this PEP was submitted.
+
+ Some discussion of earlier incarnations of this PEP took place on
+ the Python Wiki [3].
Motivation and Summary
@@ -92,7 +95,7 @@
control flow, in the end, the control flow resumes as if the
finally-suite wasn't there at all.
- Remember, PEP 310 proposes rougly this syntax (the "VAR =" part is
+ Remember, PEP 310 proposes roughly this syntax (the "VAR =" part is
optional):
with VAR = EXPR:
@@ -213,6 +216,9 @@
not make the same guarantee. This applies to Jython, IronPython,
and probably to Python running on Parrot.
+ (The details of the changes made to generators can now be found in
+ PEP 342 rather than in the current PEP)
+
Use Cases
See the Examples section near the end.
@@ -236,7 +242,7 @@
The translation of the above statement is:
- mgr = (EXPR).__context__()
+ mgr = (EXPR)
exit = mgr.__exit__ # Not calling it yet
value = mgr.__enter__()
exc = True
@@ -260,9 +266,9 @@
implemented as special registers or stack positions.
The details of the above translation are intended to prescribe the
- exact semantics. If any of the relevant methods are not found as
- expected, the interpreter will raise AttributeError, in the order
- that they are tried (__context__, __exit__, __enter__).
+ exact semantics. If either of the relevant methods are not found
+ as expected, the interpreter will raise AttributeError, in the
+ order that they are tried (__exit__, __enter__).
Similarly, if any of the calls raises an exception, the effect is
exactly as it would be in the above code. Finally, if BLOCK
contains a break, continue or return statement, the __exit__()
@@ -270,15 +276,6 @@
completed normally. (I.e. these "pseudo-exceptions" are not seen
as exceptions by __exit__().)
- The call to the __context__() method serves a similar purpose to
- that of the __iter__() method of iterator and iterables. A context
- specifier 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, a context specifier 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 mgr.__enter__() is still called).
@@ -324,38 +321,25 @@
of a database transaction roll-back decision.
To facilitate chaining of contexts in Python code that directly
- manipulates context specifiers and managers, __exit__() methods
- should *not* re-raise the error that is passed in to them, because
- it is always the responsibility of the *caller* to do any reraising
- in that case.
+ manipulates context managers, __exit__() methods should *not*
+ re-raise the error that is passed in to them. It is always the
+ responsibility of the *caller* of the __exit__() method to do any
+ reraising in that case.
That way, if the caller needs to tell whether the __exit__()
invocation *failed* (as opposed to successfully cleaning up before
propagating the original error), it can do so.
If __exit__() returns without an error, this can then be
- interpreted as success of the __exit__() method itself (whether the
- original error is to be propagated or suppressed).
+ interpreted as success of the __exit__() method itself (regardless
+ of whether or not the original error is to be propagated or
+ suppressed).
However, if __exit__() propagates an exception to its caller, this
means that __exit__() *itself* has failed. Thus, __exit__()
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
-
- The with statement implementation and examples like the nested()
- function require this behaviour in order to be able to deal
- transparently with both context specifiers and context managers.
Transition Plan
@@ -382,9 +366,6 @@
def __init__(self, gen):
self.gen = gen
- def __context__(self):
- return self
-
def __enter__(self):
try:
return self.gen.next()
@@ -435,17 +416,7 @@
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 context
- specifiers. 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
- promptly, use something similar to the duck-typed "closing" context
- manager in the examples.
-
-Optional Extensions
+Context Managers in the Standard Library
It would be possible to endow certain objects, like files,
sockets, and locks, with __enter__() and __exit__() methods so
@@ -476,133 +447,110 @@
second with-statement calls f.__enter__() again. A similar error
can be raised if __enter__ is invoked on a closed file object.
- For Python 2.5, the following candidates have been identified for
- native context managers:
+ For Python 2.5, the following types have been identified as
+ context managers:
- file
- - decimal.Context
- thread.LockType
- threading.Lock
- threading.RLock
- threading.Condition
- - threading.Semaphore and threading.BoundedSemaphore
+ - threading.Semaphore
+ - threading.BoundedSemaphore
-Standard Terminology
+ A context manager will also be added to the decimal module to
+ support using a local decimal arithmetic context within the body
+ of a with statement, automatically restoring the original context
+ when the with statement is exited.
- Discussions about iterators and iterables are aided by the standard
- terminology used to discuss them. The protocol used by the for
- statement is called the iterator protocol and an iterator is any
- object that properly implements that protocol. The term "iterable"
- then encompasses all objects with an __iter__() method that
- returns an iterator.
+Standard Terminology
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 specifier" then encompasses all objects with a
- __context__() method that returns a context manager. The protocol
- these objects implement is called the "context specification
- protocol". This means that all context managers are context
- specifiers, but not all context specifiers 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 specifier
- 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 specifier'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.
+ and __exit__() methods be known as the "context management protocol",
+ and that objects that implement that protocol be known as "context
+ managers". [4]
+
+ The code in the body of the with statement is a "managed context".
+ This term refers primarily to the code location, rather than to the
+ runtime environment established by the context manager.
+
+ The expression immediately following the with keyword in the
+ statement is a "context expression" as that expression provides the
+ main clue as to the runtime environment the context manager
+ establishes for the duration of the managed context.
+
+ The value assigned to the target list after the as keyword is the
+ "context entry value", as that value is returned as the result of
+ entering the context.
+
+ These terms are based on the idea that the context expression
+ provides a context manager to appropriately handle entry into the
+ managed context. The context manager may also provide a meaningful
+ context entry value and perform clean up operations on exit from
+ the managed context.
The general term "context" is unfortunately ambiguous. If necessary,
- it can be made more explicit by using the terms "context specifier"
- 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
- specifier fully defines the changes made to the runtime context.
- The distinction is more important when discussing the process of
- implementing context specifiers and context managers.
+ it can be made more explicit by using the terms "context manager"
+ for the concrete object created by the context expression,
+ "managed context" for the code in the body of the with statement,
+ and "runtime context" or (preferebly) "runtime environment" for the
+ actual state modifications made by the context manager. When solely
+ discussing use of the with statement, the distinction between these
+ shouldn't matter too much as the context manager fully defines the
+ changes made to the runtime environment, and those changes apply for
+ the duration of the managed context. The distinction is more
+ important when discussing the process of implementing context
+ managers and the mechanics of the with statement itself.
+
+Caching Context Managers
+
+ Many context managers (such as files and generator-based contexts)
+ will be single-use objects. Once the __exit__() method has been
+ called, the context manager will no longer be in a usable state
+ (e.g. the file has been closed, or the underlying generator has
+ finished execution).
+
+ Requiring a fresh manager object for each with statement is the
+ easiest way to avoid problems with multi-threaded code and nested
+ with statements trying to use the same context manager. It isn't
+ coincidental that all of the standard library context managers
+ that support reuse come from the threading module - they're all
+ already designed to deal with the problems created by threaded
+ and nested usage.
+
+ This means that in order to save a context manager with particular
+ initialisation arguments to be used in multiple with statements, it
+ will typically be necessary to store it in a zero-argument callable
+ that is then called in the context expression of each statement
+ rather than caching the context manager directly.
+
+ When this restriction does not apply, the documentation of the
+ affected context manager should make that clear.
+
Open Issues
- 1. After this PEP was originally approved, a subsequent discussion
- on python-dev [4] settled on the term "context manager" for
- objects which provide __enter__ and __exit__ methods, and
- "context management protocol" for the protocol itself. With the
- addition of the __context__ method to the protocol, the natural
- adjustment is to call all objects which provide a __context__
- method "context managers", and the objects with __enter__ and
- __exit__ methods "contexts" (or "manageable contexts" in
- situations where the general term "context" would be ambiguous).
-
- As noted above, the Python 2.5 release cycle revealed problems
- with the previously agreed terminology. The updated 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.
- The first change made as a result of the current discussion is
- replacement of the term "context object" with
- "context specifier".
-
- 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).
+ 1. Greg Ewing raised the question of whether or not the term
+ "context manager" was too generic and suggested "context guard"
+ as an alternative name.
+
+ 2. In Python 2.5a2, the decorator in contextlib to create a
+ context manager from a generator function is called
+ @contextfactory. This made sense when the __context__()
+ method existed and the result of the factory function was
+ a managed context object.
+ With the elimination of the __context__() method, the
+ result of the factory function is once again a context
+ manager, suggesting the decorator should be renamed to
+ either @contextmanager or @managerfactory.
+ The PEP currently uses @contextmanager.
Resolved Issues
- The following issues were resolved either by BDFL approval,
- consensus on python-dev, or a simple lack of objection to
- proposals in the original version of this PEP.
-
- 1. The __exit__() method of the GeneratorContextManager class
- catches StopIteration and considers it equivalent to re-raising
- the exception passed to throw(). Is allowing StopIteration
- right here?
-
- This is so that a generator doing cleanup depending on the
- exception thrown (like the transactional() example below) can
- *catch* the exception thrown if it wants to and doesn't have to
- worry about re-raising it. I find this more convenient for the
- generator writer. Against this was brought in that the
- generator *appears* to suppress an exception that it cannot
- suppress: the transactional() example would be more clear
- according to this view if it re-raised the original exception
- after the call to db.rollback(). I personally would find the
- requirement to re-raise the exception an annoyance in a
- generator used as a with-template, since all the code after
- yield is used for is cleanup, and it is invoked from a
- finally-clause (the one implicit in the with-statement) which
- re-raises the original exception anyway.
+ The following issues were resolved by BDFL approval (and a lack
+ of any major objections on python-dev).
- 2. What exception should GeneratorContextManager raise when the
+ 1. What exception should GeneratorContextManager raise when the
underlying generator-iterator misbehaves? The following quote is
the reason behind Guido's choice of RuntimeError for both this
and for the generator close() method in PEP 342 (from [8]):
@@ -617,61 +565,32 @@
and for uninitialized objects (and for a variety of
miscellaneous conditions)."
- 3. See item 1 in open issues :)
-
-
- 4. The originally approved version of this PEP did not include a
- __context__ method - the method was only added to the PEP after
- Jason Orendorff pointed out the difficulty of writing
- appropriate __enter__ and __exit__ methods for decimal.Context
- [5]. This approach allows a class to define a native context
- manager using generator syntax. It also allows a class to use an
- existing independent context as its native context object by
- applying the independent context to 'self' in its __context__
- method. It even allows a class written in C to
- use a generator context manager written in Python.
- The __context__ method parallels the __iter__ method which forms
- part of the iterator protocol.
- An earlier version of this PEP called this the __with__ method.
- This was later changed to match the name of the protocol rather
- than the keyword for the statement [9].
-
- 5. The suggestion was made by Jason Orendorff that the __enter__
- and __exit__ methods could be removed from the context
- management protocol, and the protocol instead defined directly
- in terms of the enhanced generator interface described in PEP
- 342 [6].
- Guido rejected this idea [7]. The following are some of benefits
- of keeping the __enter__ and __exit__ methods:
- - it makes it easy to implement a simple context in C
- without having to rely on a separate coroutine builder
- - it makes it easy to provide a low-overhead implementation
- for contexts that don't need to maintain any
- special state between the __enter__ and __exit__ methods
- (having to use a generator for these would impose
- unnecessary overhead without any compensating benefit)
- - it makes it possible to understand how the with statement
- works without having to first understand the mechanics of
- how generator context managers are implemented.
-
- 6. See item 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
- to have the correct behaviour. Otherwise, you will get an
- AttributeError when using the class in a with statement, as
- normal generator-iterators will NOT have __enter__ or __exit__
- methods.
- Getting deterministic closure of generators will require a
- separate context manager such as the closing example below.
- As Guido put it, "too much magic is bad for your health" [10].
-
- 8. It is fine to raise AttributeError instead of TypeError if the
+ 2. It is fine to raise AttributeError instead of TypeError if the
relevant methods aren't present on a class involved in a with
statement. The fact that the abstract object C API raises
TypeError rather than AttributeError is an accident of history,
rather than a deliberate design decision [11].
+Rejected Options
+
+ For several months, the PEP prohibited suppression of exceptions
+ in order to avoid hidden flow control. Implementation
+ revealed this to be a right royal pain, so Guido restored the
+ ability [13].
+
+ Another aspect of the PEP that caused no end of questions and
+ terminology debates was providing a __context__() method that
+ was analogous to an iterable's __iter__() method [5, 7, 9].
+ The ongoing problems [10, 13] with explaining what it was and why
+ it was and how it was meant to work eventually lead to Guido
+ killing the concept outright [15] (and there was much rejoicing!).
+
+ The notion of using the PEP 342 generator API directly to define
+ the with statement was also briefly entertained [6], but quickly
+ dismissed as making it too difficult to write non-generator
+ based context managers.
+
+
Examples
The generator based examples rely on PEP 342. Also, some of the
@@ -703,10 +622,6 @@
# guaranteed to be released when the block is left (even
# if via return or by an uncaught exception).
- PEP 319 gives a use case for also having an unlocked()
- 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
when the block is left:
@@ -743,14 +658,10 @@
class locked:
def __init__(self, lock):
self.lock = lock
- def __context__(self):
- return self
def __enter__(self):
self.lock.acquire()
def __exit__(self, type, value, tb):
self.lock.release()
- if type is not None:
- raise type, value, tb
(This example is easily modified to implement the other
relatively stateless examples; it shows that it is easy to avoid
@@ -844,52 +755,59 @@
# so this must be outside the with-statement:
return +s
- 9. Here's a proposed native context manager for decimal.Context:
+ 9. Here's a proposed context manager for the decimal module:
# This would be a new decimal.Context method
@contextmanager
- def __context__(self):
+ def localcontext(ctx=None):
+ """Set a new local decimal context for the block"""
+ # Default to using the current context
+ if ctx is None:
+ ctx = getcontext()
# We set the thread context to a copy of this context
# to ensure that changes within the block are kept
- # local to the block. This also gives us thread safety
- # and supports nested usage of a given context.
- newctx = self.copy()
+ # local to the block.
+ newctx = ctx.copy()
oldctx = decimal.getcontext()
decimal.setcontext(newctx)
try:
yield newctx
finally:
+ # Always restore the original context
decimal.setcontext(oldctx)
Sample usage:
+ from decimal import localcontext, ExtendedContext
+
def sin(x):
- with decimal.getcontext() as ctx:
+ with localcontext() as ctx:
ctx.prec += 2
# Rest of sin calculation algorithm
# uses a precision 2 greater than normal
return +s # Convert result to normal precision
def sin(x):
- with decimal.ExtendedContext:
+ with localcontext(ExtendedContext):
# Rest of sin calculation algorithm
# uses the Extended Context from the
# General Decimal Arithmetic Specification
return +s # Convert result to normal context
- 10. A generic "object-closing" template:
+ 10. A generic "object-closing" context manager:
- @contextmanager
- def closing(obj):
- try:
- yield obj
- finally:
+ class closing(object):
+ def __init__(self, obj):
+ self.obj = obj
+ def __enter__(self):
+ return self.obj
+ def __exit__(self, *exc_info):
try:
- close = obj.close
+ close_it = self.obj.close
except AttributeError:
pass
else:
- close()
+ close_it()
This can be used to deterministically close anything with a
close method, be it file, generator, or something else. It
@@ -907,20 +825,27 @@
for datum in data:
process(datum)
- 11. Native contexts for objects with acquire/release methods:
+ (Python 2.5's contextlib module contains a version
+ of this context manager)
- # This would be a new method of e.g., threading.RLock
- def __context__(self):
- return locked(self)
+ 11. PEP 319 gives a use case for also having a released()
+ context to temporarily release a previously acquired lock;
+ this can be written very similarly to the locked context
+ manager above by swapping the acquire() and release() calls.
- def released(self):
- return unlocked(self)
+ class released:
+ def __init__(self, lock):
+ self.lock = lock
+ def __enter__(self):
+ self.lock.release()
+ def __exit__(self, type, value, tb):
+ self.lock.acquire()
Sample usage:
with my_lock:
# Operations with the lock held
- with my_lock.released():
+ with released(my_lock):
# Operations without the lock
# e.g. blocking I/O
# Lock is held again here
@@ -973,56 +898,81 @@
with c as z:
# Perform operation
+ (Python 2.5's contextlib module contains a version
+ of this context manager)
Reference Implementation
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
+ The PEP was implemented in subversion for Python 2.5a1
+ The __context__() method will be removed in Python 2.5a3
+
+
+Ackowledgements
+
+ Many people contributed to the ideas and concepts in this PEP,
+ including all those mentioned in the acknowledgements for PEP 340
+ and PEP 346.
+
+ Additional thanks goes to (in no meaningful order): Paul Moore,
+ Phillip J. Eby, Greg Ewing, Jason Orendorff, Michael Hudson,
+ Raymond Hettinger, Walter Dörwald, Aahz, Georg Brandl, Terry Reedy,
+ A.M. Kuchling, Brett Cannon, and all those that participated in the
+ discussions on python-dev.
References
- [1] http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx
+ [1] Raymond Chen's article on hidden flow control
+ http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx
- [2] http://mail.python.org/pipermail/python-dev/2005-May/053885.html
+ [2] Guido suggests some generator changes that ended up in PEP 342
+ http://mail.python.org/pipermail/python-dev/2005-May/053885.html
- [3] http://wiki.python.org/moin/WithStatement
+ [3] Wiki discussion of PEP 343
+ http://wiki.python.org/moin/WithStatement
- [4]
+ [4] Early draft of some documentation for the with statement
http://mail.python.org/pipermail/python-dev/2005-July/054658.html
- [5]
+ [5] Proposal to add the __with__ method
http://mail.python.org/pipermail/python-dev/2005-October/056947.html
- [6]
+ [6] Proposal to use the PEP 342 enhanced generator API directly
http://mail.python.org/pipermail/python-dev/2005-October/056969.html
- [7]
+ [7] Guido lets me (Nick Coghlan) talk him into a bad idea ;)
http://mail.python.org/pipermail/python-dev/2005-October/057018.html
- [8]
+ [8] Guido raises some exception handling questions
http://mail.python.org/pipermail/python-dev/2005-June/054064.html
- [9]
+ [9] Guido answers some questions about the __context__ method
http://mail.python.org/pipermail/python-dev/2005-October/057520.html
- [10]
+ [10] Guido answers more questions about the __context__ method
http://mail.python.org/pipermail/python-dev/2005-October/057535.html
- [11]
+ [11] Guido says AttributeError is fine for missing special methods
http://mail.python.org/pipermail/python-dev/2005-October/057625.html
- [12]
+ [12] Original PEP 342 implementation patch
http://sourceforge.net/tracker/index.php?func=detail&aid=1223381&group_id=5470&atid=305470
- [13]
- http://mail.python.org/pipermail/python-dev/2006-February/061903.html
+ [13] Guido restores the ability to suppress exceptions
+ http://mail.python.org/pipermail/python-dev/2006-February/061909.html
- [14]
+ [14] A simple question kickstarts a thorough review of PEP 343
http://mail.python.org/pipermail/python-dev/2006-April/063859.html
+ [15] Guido kills the __context__() method
+ http://mail.python.org/pipermail/python-dev/2006-April/064632.html
+
+ [16] Greg propose 'context guard' instead of 'context manager'
+ http://mail.python.org/pipermail/python-dev/2006-May/064676.html
+
Copyright
This document has been placed in the public domain.
More information about the Python-checkins
mailing list