Welcome, guest | Sign In | My Account | Store | Cart
"""
Name-Value Object: $obj.attr.attr2|filter|filter2|filterN
Numbered Argument: $[0].attr.attr2|filter|filter2|filterN

To create new filters, subclass and create do_ method.
do_ALL is the general method for any filters not found. It should raise FilterError if the
filter is still not available.

Use $$ to avoid replacement
"""


import re
from string import capwords

class FilterError(Exception): pass

r_macro
= re.compile(r"""
                    \$                                                  # must start with $, not $$
                    (                                                   # start group
                    \[\d+\][.|][a-zA-Z0-9]+[a-zA-Z0-9|.]*               # opening [number] + attrs / filters
                    |                                                   # 2nd case
                    \[\d+\]                                             # opening [number] + filters
                    |                                                   # 3rd case
                    [a-zA-Z][a-zA-Z0-9]+[.|][a-zA-Z0-9]+[a-zA-Z0-9|.]*  # obj + attrs / filters
                    |                                                   # 4th case
                    [a-zA-Z][a-zA-Z0-9]+                                # obj + attrs / filters
                    )                                                   # done
                    """
, re.VERBOSE)

class Template:

   
def __init__(self, string=''):
       
self.buffer = string
       
self.filterregister = {'length': len}

   
def load(self, string):
       
self.buffer += string

   
def register_filter(self, name, func):
       
self.filterregister[name] = func

   
def remove_filter(self, name):
        func
= self.filterregister[name]
       
del self.filterregister[name]
       
return func

   
def do_capwords(self, string):
       
return capwords(string)

   
def do_capfirst(self, string):
       
return string[0].capitalize() + string[1:]

   
def do_ALL(self, string, filter_name):
       
"""General filter for all filter types not found"""
       
if hasattr(str, filter_name):
           
return getattr(str, filter_name)(string)
       
else:
           
raise FilterError('No such filter as %r'%filter_name)

   
def render(self, *args, **kwargs):
       
"""Render the template, replacing macros along the way"""
        bufferstring
= str(self.buffer)
       
for matchedstring in r_macro.findall(self.buffer):
           
# this list should contain the name of the object first, then the attrs needed
            obj_and_attrs
= matchedstring.split('.')
           
# remove the filters from the attr string
            obj_and_attrs
[-1] = obj_and_attrs[-1].split('|', 1)[0]
            obj
, attrs = obj_and_attrs[0], obj_and_attrs[1:]

           
if obj.startswith('['):
                index
= int(obj[1:-1])
               
if not index < len(args):
                   
#raise ValueError("No object at index %s!"%index)
                    bufferstring
= bufferstring.replace('$'+matchedstring, '')
                   
continue
               
else:
                    obj
= args[index]
           
           
else:
               
if obj not in kwargs:
                   
#raise ValueError("No object with name %r"%obj)
                    bufferstring
= bufferstring.replace('$'+matchedstring, '')
                   
continue
                obj
= kwargs[obj]

            value
= obj
           
if len(attrs) > 0:
               
for attr in attrs:
                   
if not attr:
                       
raise ValueError("Cannot have empty attr!")
                   
try:
                        value
= getattr(value, attr)
                   
except AttributeError:
                        value
= value[attr]

            filters
= matchedstring.split('|')[1:]

           
for filtername in filters:
               
if not filtername:
                   
raise ValueError("Cannot have empty filter!")
               
try:
                    value
= getattr(self, "do_"+filtername)(value)
               
except AttributeError:
                   
try:
                        value
= self.filterregister[filtername](value)
                   
except KeyError:
                        value
= self.do_ALL(value, filtername)

            bufferstring
= bufferstring.replace('$'+matchedstring, str(value))
                   
       
return bufferstring.replace('$$', '$').replace('\.', '.')


def render_from_string(templatestring, *args, **kwargs):
   
"""Shortcut function"""
    t
= Template(templatestring)
   
return t.render(*args, **kwargs)
   
if __name__ == "__main__":
    tempstr
= """Hello $fullname|capwords,
I am writing to inform you that your child, $firstname|capitalize $lastname|capitalize has recieved
a grade of $grade% in this $coursename course. I strongly believe that your child has much potential
and could do much better if he/she tried.

I require $$100.00 for the field trip next week. We will be going to $[0] on $[1]\."""


   
print render_from_string(tempstr, "Edworthy Park", "Tuesday", fullname="Bob joe", firstname="James", lastname="Clark maxwell", grade=75, coursename="Astronomy")

History