Here is an example of strategy pattern in python. The alogrithm that varies in this example is the conversion of csv file to xml, html and any other formats. The client is the CsvUtil class. As you can see we can change the conversion at run time and also we can apply all the alogrithm if we wish to which we can’t achieve when we go for the regular inheritance model. Please do note that an abstract class is equivalent to interface when there is no implementation.
Source code for all the classes related to strategy.
HTML_TEMPATE="""<html><body>%s</body></html>
"""
class CsvConverter:
''' Abstract class or interface for conversion of csv file'''
def convert(self,csv):
pass #abstract method
class Csv2Html(CsvConverter):
''' Covert Csv to html table with alternativing row colors'''
def convert(self,csv):
''' convert the csv file to html file '''
htmltable = ''
csvfile = open(csv)
dialect = Sniffer().sniff(csvfile.read(2048))
csvfile.seek(0) #rewind after sniffing
csvreader = reader(csvfile,dialect)
i = 0
for line in csvreader:
#print line
if i == 0: #header row
htmltable += '<tr class="head">'
elif i % 2 == 0: #even row
htmltable += '<tr class="even">'
else: #odd row
htmltable += '<tr class="odd">'
for col in line:
htmltable += '<td>%s</td>'%col
htmltable += '</tr>'
i += 1
return HTML_TEMPLATE%htmltable
def __str__(self):
return 'Csv2Html'
class Csv2Xml(CsvConverter):
''' Covert Csv to Xml '''
def __init__(self,linetag='row'):
''' Constructor '''
self.linetag = linetag
def convert(self,csv):
''' convert the csv file to xml file '''
print 'hello'
xml = ''
csvfile = open(csv)
csvreader = DictReader(csvfile)
for row in csvreader:
xml += '<%s>'%self.linetag
for colname,colvalue in row.iteritems():
xml += '<%s>$%s</%s>'%(colname,colvalue,colname)
xml += '</%s>'%self.linetag
return xml
def __str__(self):
return 'Csv2Xml'
Here is the source code for the context. You can see the use of property in python here.
class CsvUtil(object):
''' A wrapper or utility class for dealing with csv files '''
def __init__(self,csv):
''' constructor '''
self.csv = csv
self._numlines = None #this information is computed lazily
self._numcols = None #this information is gathered lazily
self._wellformed = None #this information is gathered lazily
self._converter = Csv2Html() #default converter
def _gatherstats(self):
''' gather basic stats on the csv '''
with open(self.csv) as csvfile:
dialect = csv.Sniffer().sniff(csvfile.read(2048))
csvfile.seek(0) #rewind
reader = csv.reader(csvfile,dialect)
self._numlines = 0
self._wellformed = True
self._numcols = 0
for line in reader:
self._numlines += 1
if self._numcols != len(line):
self._wellformed = False
def convert(self):
''' convert the csv file to another format '''
return self._converter.convert(self.csv)
def get_wellformed(self):
''' a csv is wellformed if all the lines have same number of columns '''
if not self._wellformed:
self._gatherstats()
return self._wellformed
def get_numlines(self):
''' number of lines in the csv files '''
if not self._numlines:
self._gatherstats()
return self._numlines
def get_numcols(self):
''' number of lines in the csv files '''
if not self._numcols:
self._gatherstats()
return self._numcols
def get_converter(self):
''' getter for converter '''
return self._converter
def set_converter(self,value):
print 'set ',value
self._converter = value
#properties
wellformed = property(get_wellformed)
numlines = property(get_numlines)
numcols = property(get_numcols)
converter = property(get_converter,set_converter)
Finally the demonstration of using the context and strategy….
csvfile = "C:\sandbox\python\mycsv.txt"
util = CsvUtil(csvfile) # my utility class for handling csv
print util.numlines
print util.wellformed
print 'Default converter is',util.converter
print util.convert() #print using the default converter
#now changing my converter at run time :-)
util.converter = Csv2Xml()
print 'My new converter is',util.converter
print util.convert()
To maximize window in vim just set values for lines and columns.
:set lines = 999
:set columns = 999
To turn on/off the line number in vim use the following commands..
Turn on :set number
Turn off :set nonumber
I was using the target parser method of lxml as suggested here and could not turn off fully qualified name for tags and so wrote quick one to split namespace from tag name…
def _gettagns(self,tag):
""" returns a tuple of namespace,name """
if tag[:1] == "{":
return tag[1:].split("}", 1)
else:
return (None,tag)
Here is an example of implementing template method in python. This example assumes that ONLY meat in the burrito varies and so the child class implements the template method of selecting the meat while rest of the work is done by the base class…
import sys
class AbstractBurrito:
'Abstract class for the burrito'
"""
Constructor
"""
def __init__(self):
self.meat = None
def __heatTortilla(self):
print 'Warming tortilla'
def __addBeans(self):
print 'Adding beans...'
def __addSalsa(self):
print 'Adding salsa'
def __addCorns(self):
print 'Adding corns...'
"""
Our assumption is that the burritos vary ONLY by the meat in it.
So this method calls the template method on the child class.
Note: The template method on the child class should be non-private.
"""
def __addMeat(self):
self.selectMeat()
print 'Adding %s'%self.meat
"""
Steps to prepare a burrito
"""
def make(self):
self.__heatTortilla()
self.__addBeans()
self.__addMeat()
self.__addSalsa()
self.__addCorns()
print 'Your %s burrito is warm and ready'%self.meat
print 'Thank You \n'
class ChickenBurrito(AbstractBurrito):
"""
Chicken burrito
"""
def selectMeat(self):
self.meat = 'Chicken'
class BeefBurrito(AbstractBurrito):
"""
Beef burrito
"""
def selectMeat(self):
self.meat = 'Beef'
if __name__ == "__main__":
myburrito = ChickenBurrito()
myburrito.make()
urburrito = BeefBurrito()
urburrito.make()
macvim is the equilvalent of gvim in windows.
Cook book on macvim.
.vimrc example
I liked the virtualenv to sandbox the development environment for django development. Had to write a big instruction for other contributor/s to follow the steps. Then i found this buildout but did’nt like it initially as it was more of declarative approach but it does the job and perfectly. It is very simple as it is declarative. I’m using it now and i can always nuke my local dev and just redo the whole environment setup with just one or two commands. Look here for further information on buildout and how to use it with django.
- buildout (sounds closer to bailout)
- Using buildout with django
- Complete list of buildout recipes under cheese shop
Don’t need a gui tool (os/x) for myself but was looking for it for other key contributor/s of the project who has limited SCM experience. Found this open source tool – GitX. Looks good from screen shots/casts. Will have the other contributor explore it and let know how it goes.
Having used windows for a long time which uses nslookup command tool to do the reverse dns, i was trying to find a similar tool in mac. I always tend to forget that Mr.Mac is built on Unix. So you can use the host command just as in any other unix to do reverse dns lookup.
$ host (ip address)