Fix two examples that were broken by the new semantics.

This commit is contained in:
Guido van Rossum 2006-02-28 22:49:15 +00:00
parent a0a335673a
commit 1b6c373966
1 changed files with 59 additions and 65 deletions

View File

@ -576,7 +576,7 @@ Examples
The tense used in the names of the example context managers 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
__exit__ method. Progressive tense ("-ing") is used when the name
refers to an action which is to be done in the __exit__ method.
1. A template for ensuring that a lock, acquired at the start of a
@ -643,6 +643,8 @@ Examples
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
@ -769,34 +771,35 @@ Examples
# General Decimal Arithmetic Specification
return +s # Convert result to normal context
10. A generic "object-closing" template:
10. A generic "object-closing" template:
@contextmanager
def closing(obj):
try:
yield obj
finally:
try:
close = obj.close
except AttributeError:
pass
else:
close()
@contextmanager
def closing(obj):
try:
yield obj
finally:
try:
close = obj.close
except AttributeError:
pass
else:
close()
This can be used to deterministically close anything with a
close method, be it file, generator, or something else. It can
even be used when the object isn't guaranteed to require
closing (e.g., a function that accepts an arbitrary iterable):
This can be used to deterministically close anything with a
close method, be it file, generator, or something else. It
can even be used when the object isn't guaranteed to require
closing (e.g., a function that accepts an arbitrary
iterable):
# emulate opening():
with closing(open("argument.txt")) as contradiction:
for line in contradiction:
print line
# emulate opening():
with closing(open("argument.txt")) as contradiction:
for line in contradiction:
print line
# deterministically finalize an iterator:
with closing(iter(data_source)) as data:
for datum in data:
process(datum)
# deterministically finalize an iterator:
with closing(iter(data_source)) as data:
for datum in data:
process(datum)
11. Native contexts for objects with acquire/release methods:
@ -807,7 +810,7 @@ Examples
def released(self):
return unlocked(self)
Sample usage:
Sample usage:
with my_lock:
# Operations with the lock held
@ -820,54 +823,43 @@ Examples
supplied contexts from left-to-right to avoid excessive
indentation:
class nested(object):
def __init__(self, *contexts):
self.contexts = contexts
self.entered = None
def __context__(self):
return self
def __enter__(self):
if self.entered is not None:
raise RuntimeError("Context is not reentrant")
self.entered = deque()
vars = []
@contextmanager
def nested(*contexts):
exits = []
vars = []
exc = (None, None, None)
try:
try:
for context in self.contexts:
for context in contexts:
mgr = context.__context__()
vars.append(mgr.__enter__())
self.entered.appendleft(mgr)
exit = mgr.__exit__
enter = mgr.__enter__
vars.append(enter())
exits.append(exit)
yield vars
except:
self.__exit__(*sys.exc_info())
raise
return vars
def __exit__(self, *exc_info):
# Behave like nested with statements
# first in, last out
# New exceptions override old ones
ex = exc_info
for mgr in self.entered:
exc = sys.exc_info()
finally:
while exits:
exit = exits.pop()
try:
mgr.__exit__(*ex)
exit(*exc)
except:
ex = sys.exc_info()
self.entered = None
if ex is not exc_info:
raise ex[0], ex[1], ex[2]
exc = sys.exc_info()
if exc != (None, None, None):
raise
Sample usage:
Sample usage:
with nested(a, b, c) as (x, y, z):
# Perform operation
with nested(a, b, c) as (x, y, z):
# Perform operation
Is equivalent to:
Is equivalent to:
with a as x:
with b as y:
with c as z:
# Perform operation
with a as x:
with b as y:
with c as z:
# Perform operation
Reference Implementation
@ -911,6 +903,8 @@ References
[12]
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
Copyright