[Python-Dev] PEP 340: Examples as class's.
Ron Adam
rrr at ronadam.com
Fri May 6 02:12:36 CEST 2005
Eric Nieuwland wrote:
> Ron Adam wrote:
>
>> Eric Nieuwland wrote:
>>
>>> This is linear. No looping whatsoever. And easily translated to a
>>> simple language construct and a protocol:
>>>
>>> class resource(object):
>>> def __init__(self,...):
>>> # store resource parameters
>>> def __acquire__(self):
>>> # whatever it takes to grab the resource
>>> def __release__(self):
>>> # free the resource
>>
>>
>>
>>
>> I wanted to see what the examples in PEP340 would look like written with
>> standard class's using object inheritance and overriding to define
>> resource managers. If anyone's interested I can post it.
>
>
> I'm interested.
>
>> My block class is non-looping as I found in most cases looping isn't
>> required, and looping complicates things because you have to pass around
>> a loop expression due to not all loops will want to behave that same
way.
>>
>> The solution was to put the loop in the body method and call a
>> repeat_body method (the repeated body section) which is added to the
>> class when needed.
>
>
> Show us your stuff! ;-)
>
> --eric
>
Ok, :)
These probably can be improved on, and renamed, and I don't know how
many problems there may be with it, but they work in these examples.
This is just one way to do it, so critique, correct, and improve as
needed. Just no flames please. ;-)
Cheers, Ron_Adam
# --- start ---
## blockclass.py
## A base class that manages resource acquire and release.
class Block(object):
"""A manager class for working with resources."""
def __init__(self,*args):
self._cleanup = False
self.__err__ = None
try:
self.start(*args)
self._cleanup = True
except:
raise
def __call__(self, *args):
self.block(*args)
self.__del__()
def __del__(self):
if self._cleanup:
try:
self.final()
self._cleanup = False
except:
raise
if self.__err__:
raise self.__err__
def start(self,*args):
"""Override to add initialization code"""
pass
def final(self):
"""Override to add finalization code"""
pass
def block(self,*args):
"""Override to add main block body"""
pass
## A dummy lock for test calls only
class mylock:
def acquire(self):
print "Lock acquired"
def release(self):
print "Lock released"
## 1. A template for ensuring that a lock, acquired at the start of a
## block, is released when the block is left:
class Get_Lock(Block):
def start(self, lock):
self.lock = lock
self.lock.acquire()
def final(self):
self.lock.release()
def block(self):
pass
class Lock_It(Get_Lock):
def block(self):
print "Do stuff while locked"
Lock_It(mylock())()
## 2. A template for opening a file that ensures the file is closed:
class File_Opener(Block):
def start(self, filename, mode='r'):
self.filename = filename
self.mode = mode
self.f = open(filename, mode)
def final(self):
self.f.close()
def block(self):
pass
class Line_Printer(File_Opener):
def block(self):
n = 0
for line in self.f:
print n, line.rstrip()
n += 1
Line_Printer('blockclass.py')()
### 3. A template for committing or rolling back a database:
#def transactional(db):
# try:
# yield
# except:
# db.rollback()
# raise
# else:
# db.commit()
"""I'm not exactly sure how this one should work, so maybe some
one else can give an example using the block class above."""
## 4. A template that tries something up to n times:
import urllib
class Auto_Retry(Block):
def start(self, n=3, exc=Exception):
self.n = n
self.exc = exc
def block(self, *args):
while self.n:
try:
self.repeat_block(*args)
break
except self.exc, self.__err__:
self.n -= 1
def repeat_block(self, *args):
"""Try this block n times"""
pass
class Retry_Url(Auto_Retry):
def repeat_block(self, url):
f = urllib.urlopen(url)
print f.read()
# This could be slow, so wait for it.
try:
Retry_Url(3, IOError)("http://cantfind.com/this.html")
except IOError, err:
print err
Retry_Url(3, IOError)("http://python.org/peps/pep-0340.html")
## 5. It is possible to nest blocks and combine templates:
class Lockit(Get_Lock):
def block(self, job):
job()
Lockit(mylock())(Line_Printer("blockclass.py"))
## 7. Redirect stdout temporarily:
import sys
class Redirect_Stdout(Block):
def start(self, handle=sys.stdout):
self.save_stdout = sys.stdout
sys.stdout = handle
def final(self):
sys.stdout.close()
sys.stdout = self.save_stdout
def block(self):
pass
class New_Out(Redirect_Stdout):
def block(self):
print "Writing to redirected std_out"
New_Out(open('newfile.txt','w'))()
## 8. A variant on opening() that also returns an
## error condition:
class Append_To(File_Opener):
def start(self, filename):
self.f = open(filename, 'a')
def block(self, string):
self.f.write(string)
def append_w_error(file,sting):
try:
Append_To(file)(string)
except IOError, err:
print "IOError:", err
append_w_error("/etc/passwd", "guido::0:0::/:/bin/sh\n")
# --- end ---
More information about the Python-Dev
mailing list