Loading ...
Sorry, an error occurred while loading the content.

Re: [Cheetahtemplate-discuss] relocation (2)

Expand Messages
  • Mike Orr
    ... There should be no problem creating a subclass of Template with a unique method (or an overriding method), instantiating that, and calling the $method().
    Message 1 of 6 , May 4, 2003
    • 0 Attachment
      On Sat, May 03, 2003 at 06:13:16PM +0200, Dirk Hoffmann wrote:
      > Unfortunately when I try to view the page with my browser I get an error
      > page telling me that relocateImage is unknown (or so). Just to see
      > what's going wrong I replaced the method placeholder
      > $relocateImage()with a variable placeholder and assigned to it a value
      > in MyTemplate. That worked as expected so apparently it is only possible
      > to define placeholders as variables but not as methods in inherited
      > classes. Is that so or have I just made some mistakes?
      >
      > I also created a Template named RootPage.tmpl as a superclass of
      > Template containing
      >
      > #def relocateImage(src): This is relocateImage("$src")
      >
      > Now the error page disappeared and I found the output of this method in
      > the page's HTML source. But I can't use this method to do the actual
      > path calculation since it hasn't access to the servlet's SSP. And
      > obviously MyTemplate.relocateImage() didn't overwrite
      > RootPage.relocateImage(). I had a look into cheetah's output and found
      > that the compiled version of the method has a different signature (some
      > additional cheetah specific args). To be sure to have methods with
      > matching signatures I wrote my own superclass RootPage.py. But then I
      > got a blank page in my browser.
      >
      > At that point I stopped, thinking that there must be a simpler solution
      > than to sandwich my Template between a super and a sub class and that
      > this problem has probably been addressed before.

      There should be no problem creating a subclass of Template with a
      unique method (or an overriding method), instantiating that, and
      calling the $method(). For specificity you can do $self.method(),
      which isn't necessary but may help in troubleshooting why the method
      isn't being found by narrowing the scope of possibilities.

      There should also be no problem accessing accessing a method inherited
      directly or indirectly via #extends because people do it all the time.

      #def methods do get a bunch of arguments tacked on. These are the
      Webware transaction or a dummy transaction, and local names for global
      variables, which is the standard Python speedup kludge. Section 7.7 in
      the Cheetah Developers' Guide discusses this.

      If you want to post some small source templates and what they compile
      to, I'll see if I can figure out anything more about why it's not
      finding the method.

      The following test works OK:

      ===MyTemplate.py===
      from Cheetah.Template import Template
      class MyTemplate(Template):
      def relocateImage(self, src):
      return "relocateImage called with arg %r." % src
      ===end MyTemplate.py===

      % python -i MyTemplate.py
      >>> templateDef = '===> $relocateImage("la la la") <===\n'
      >>> t = MyTemplate(templateDef)
      >>> print t
      ===> relocateImage called with arg 'la la la'. <===

      >>>


      --
      -Mike (Iron) Orr, mso@... (iron@...)
      English * Esperanto * Russkiy * Deutsch * Espan~ol


      -------------------------------------------------------
      This sf.net email is sponsored by:ThinkGeek
      Welcome to geek heaven.
      http://thinkgeek.com/sf
      _______________________________________________
      Cheetahtemplate-discuss mailing list
      Cheetahtemplate-discuss@...
      https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
    • Dirk Hoffmann
      ... Hi Mike, thanks for the advice. In my previous emails I had tried to reduce the problem to its essence but unfortunately eliminated those parts that
      Message 2 of 6 , May 6, 2003
      • 0 Attachment
        Mike Orr wrote:
        On Sat, May 03, 2003 at 06:13:16PM +0200, Dirk Hoffmann wrote:
          
        Unfortunately when I try to view the page with my browser I get an error 
        page telling me that relocateImage is unknown (or so). Just to see 
        what's going wrong I replaced the method placeholder 
        $relocateImage()with a variable placeholder and assigned to it a value 
        in MyTemplate. That worked as expected so apparently it is only possible 
        to define placeholders as variables but not as methods in inherited 
        classes. Is that so or have I just made some mistakes?
        
        I also created a Template named RootPage.tmpl as a superclass of 
        Template containing
        
        #def relocateImage(src): This is relocateImage("$src")
        
        Now the error page disappeared and I found the output of this method in 
        the page's HTML source. But I can't use this method to do the actual 
        path calculation since it hasn't access to the servlet's SSP. And 
        obviously MyTemplate.relocateImage() didn't overwrite 
        RootPage.relocateImage(). I had a look into cheetah's output and found 
        that the compiled version of the method has a different signature (some 
        additional cheetah specific args). To be sure to have methods with 
        matching signatures I wrote my own superclass RootPage.py. But then I 
        got a blank page in my browser.
        
        At that point I stopped, thinking that there must be a simpler solution 
        than to sandwich my Template between a super and a sub class and that 
        this problem has probably been addressed before.
            
        There should be no problem creating a subclass of Template with a
        unique method (or an overriding method), instantiating that, and
        calling the $method().  For specificity you can do $self.method(),
        which isn't necessary but may help in troubleshooting why the method
        isn't being found by narrowing the scope of possibilities.
        
        There should also be no problem accessing accessing a method inherited
        directly or indirectly via #extends because people do it all the time.
        
        #def methods do get a bunch of arguments tacked on.  These are the
        Webware transaction or a dummy transaction, and local names for global
        variables, which is the standard Python speedup kludge.  Section 7.7 in
        the Cheetah Developers' Guide discusses this.  
        
        If you want to post some small source templates and what they compile
        to, I'll see if I can figure out anything more about why it's not
        finding the method.
        
        The following test works OK:
        
        ===MyTemplate.py===
        from Cheetah.Template import Template
        class MyTemplate(Template):
            def relocateImage(self, src):
               return "relocateImage called with arg %r." % src
        ===end MyTemplate.py===
        
        % python -i MyTemplate.py
          
        templateDef = '===> $relocateImage("la la la") <===\n'
        t = MyTemplate(templateDef)
        print t
                
        ===> relocateImage called with arg 'la la la'. <===
        Hi Mike,

        thanks for the advice.

        In my previous emails I had tried to reduce the problem to its essence but unfortunately eliminated those parts that apparently cause the failure.

        I now started with a very simple example and evolved it into a more complex one to get the real problem. I also completely left the Webware context. Let's get into the details:

        Case A

        The example starts with three files:

        1. ATemplate.tmpl - A template containing a method placeholder

        $sayHelloTo("World")



        2. MyTemplate.py - A python class defining the method

        from Cheetah.Template import Template
        
        class MyTemplate(Template):
            def __init__(self, file):
                Template.__init__(self,file=file)
        
            def sayHelloTo(self,arg):
                return 'Hello ' + arg
        



        3. HelloWorld.py - A python file using the class with the new method
        from MyTemplate import MyTemplate
        
        t = MyTemplate(file = "ATemplate.tmpl")
        print(t)



        This example works fine: python HelloWorld.py  prints "Hello World".

        Case B

        MyTemplate.py and HelloWorld.py remain the same throughout the whole experiment.

        I rename ATemplate.tmpl to SuperTemplate.tmpl and create a new ATemplate.tmpl just extending SuperTemplate.tmpl so having the following files besides MyTemplate.py and HelloWorld.py :

        SuperTemplate.tmpl - contains the method placeholder now

        $sayHelloTo("World")
        


        ATemplate.tmpl - just extends SuperTemplate.tmpl

        #extends SuperTemplate
        



        Now I get the following message:
        Traceback (most recent call last):
          File "HelloWorld.py", line 5, in ?
            print(t)
          File "SuperTemplate.py", line 89, in respond
            write(filter(VFS(SL + [globals(), __builtin__],"sayHelloTo",0)("World"), rawExpr='$sayHelloTo("World")')) # from line 1, col 1.
        NameMapper.NotFound: sayHelloTo
        


        Case C

        I alter SuperTemplate.tmpl and ATemplate.tmpl as follows:

        SuperTemplate.tmpl - just contains a simple variable placeholder

        $content
        



        ATemplate.tmpl - defines the variable placeholder

        #extends SuperTemplate
        
        #def content
        $sayHelloTo("World")
        #end def
        



        This results in the following message:

        Traceback (most recent call last):
          File "HelloWorld.py", line 5, in ?
            print(t)
          File "/home/hoffmann/castle/projects/develop/labor/python/cheetah/methodPlaceholder/SuperTemplate.py", line 89, in respond
            write(filter(VFS(SL + [globals(), __builtin__],"content",1), rawExpr='$content')) # from line 1, col 1.
          File "<string>", line 28, in content
        NameMapper.NotFound: sayHelloTo
        



        I also used $self.sayHelloTo("World") in cases B and C, but that didn't help.

        It should be quite simple to reproduce these cases.

        Thanx for spending time on solving these problems.

        regards
        Dirk
         
         

      • Mike Orr
        ... It was an unintended feature that you can instantiate a subclass of Template, with additional methods for placeholders, passing it a template definition
        Message 3 of 6 , May 6, 2003
        • 0 Attachment
          On Tue, May 06, 2003 at 11:37:50PM +0200, Dirk Hoffmann wrote:
          > Case A
          >
          > The example starts with three files:
          >
          > 1. ATemplate.tmpl - A template containing a method placeholder
          > ------------------------------------------------------------------------
          >
          > $sayHelloTo("World")
          >
          > ------------------------------------------------------------------------
          >
          >
          > 2. MyTemplate.py - A python class defining the method
          > ------------------------------------------------------------------------
          >
          > from Cheetah.Template import Template
          >
          > class MyTemplate(Template):
          > def __init__(self, file):
          > Template.__init__(self,file=file)
          >
          > def sayHelloTo(self,arg):
          > return 'Hello ' + arg
          >
          > ------------------------------------------------------------------------
          >
          >
          > 3. HelloWorld.py - A python file using the class with the new method
          > ------------------------------------------------------------------------
          >
          > from MyTemplate import MyTemplate
          >
          > t = MyTemplate(file = "ATemplate.tmpl")
          > print(t)
          >
          > ------------------------------------------------------------------------
          > This example works fine: python HelloWorld.py prints "Hello World".
          >

          It was an unintended feature that you can instantiate a subclass of
          Template, with additional methods for placeholders, passing it a template
          definition from a third source, but logically it looks OK. And you
          correctly call Template.__init__, which is necessary if you override
          .__init__ . Theoretically it should not be necessary if you don't
          override .__init__.


          > Case B
          >
          > MyTemplate.py and HelloWorld.py remain the same throughout the whole
          > experiment.
          >
          > I rename ATemplate.tmpl to SuperTemplate.tmpl and create a new
          > ATemplate.tmpl just extending SuperTemplate.tmpl so having the following
          > files besides MyTemplate.py and HelloWorld.py :
          >
          > SuperTemplate.tmpl - contains the method placeholder now
          > ------------------------------------------------------------------------
          >
          > $sayHelloTo("World")
          >
          > ------------------------------------------------------------------------
          >
          > ATemplate.tmpl - just extends SuperTemplate.tmpl
          > ------------------------------------------------------------------------
          >
          > #extends SuperTemplate
          >
          > ------------------------------------------------------------------------
          >
          >
          > Now I get the following message:
          > ------------------------------------------------------------------------
          >
          > Traceback (most recent call last):
          > File "HelloWorld.py", line 5, in ?
          > print(t)
          > File "SuperTemplate.py", line 89, in respond
          > write(filter(VFS(SL + [globals(), __builtin__],"sayHelloTo",0)("World"),
          > rawExpr='$sayHelloTo("World")')) # from line 1, col 1.
          > NameMapper.NotFound: sayHelloTo
          >
          > ------------------------------------------------------------------------

          I get "ImportError: No module named SuperTemplate:. I run
          "cheetah compile SuperTemplate". Now I run HelloWorld.py and get
          the same error you did.

          So what's happening? I suspect there's a breakdown in the inheritance
          chain, or that in the peculiar way you arrange the files and invoke
          the template, there might be two inheritance chains, one of which is
          incomplete; i.e., .sayHelloTo() exists in the wrong chain.

          Let's first look at the placeholder values. Rename SuperTemplate.tmpl
          back to ATemplate.tmpl and prepend:

          ===> Dump of the searchList <===
          $_searchList
          ===> Dump of 'self' <===
          $dir($self)
          ===> End of dumps <===

          The first dump produces
          [{}, <MyTemplate.MyTemplate instance at 0x40209f2c>]
          which is normal. (The {} is for the "#set global" variables.)
          The second dump is long but includes 'sayHelloTo' as expected. Good.

          Now change the files for case B, leaving the dump lines intact.
          Recompile SuperTemplate. Run HelloWorld.py, and voila, the expected
          error. Unfortunately our dumps don't show up because the output is
          completely aborted. So let's comment out the error-prone placeholder.

          The first dump now looks like:
          [{}, <Cheetah.Parser.GenTemplate instance at 0x40209f2c>]
          The second element is typical for a template compiled from a string.
          The second shows no 'sayHelloTo' method. Ah ha! I don't know of a
          Python tool to show the inheritance tree all at once, but the
          "GenTemplate instance" gives a clue. The template that's in effect
          is not your MyTemplate, it's the generic one used for dynamic
          compilations, which doesn't have .sayHelloTo(). Delving into how
          dynamic compilation and #extends interact is a hairy subject which only
          Tavis is qualified to answer. The moral of the story is, don't play
          games with #extends, use it only with precompiled templates or expect
          to spend hours coming up with a workable situation. Whether this is a
          bug or not, Tavis will have to answer. Dynamically-compiled templates
          switch their base class behind the scenes, which usually works to your
          favor, but in this case it may be working to your disfavor.

          Let's try precompiling ATemplate (the one containing #extends) and
          see if it solves our problem. Let's be optimistic and uncomment the
          placeholder in SuperTemplate too and recompile it.

          The first dump changes to:
          [{}, <__main__.ATemplate instance at 0x4021c7cc>]
          but the NotFound error persists. Of course! MyTemplate is no longer
          in the loop, so of course .sayHelloTo() doesn't exist. Tne next step
          would be to move .sayHelloTo() into ATemplate, SuperTemplate, or a
          Python superclass of these two.


          > Case C
          >
          > I alter SuperTemplate.tmpl and ATemplate.tmpl as follows:
          >
          > SuperTemplate.tmpl - just contains a simple variable placeholder
          > ------------------------------------------------------------------------
          >
          > $content
          >
          > ------------------------------------------------------------------------
          >
          >
          > ATemplate.tmpl - defines the variable placeholder
          > ------------------------------------------------------------------------
          >
          > #extends SuperTemplate
          >
          > #def content
          > $sayHelloTo("World")
          > #end def
          >
          > ------------------------------------------------------------------------
          >
          >
          > This results in the following message:
          > ------------------------------------------------------------------------
          >
          > Traceback (most recent call last):
          > File "HelloWorld.py", line 5, in ?
          > print(t)
          > File
          > "/home/hoffmann/castle/projects/develop/labor/python/cheetah/methodPlaceholder/SuperTemplate.py", line 89, in respond
          > write(filter(VFS(SL + [globals(), __builtin__],"content",1),
          > rawExpr='$content')) # from line 1, col 1.
          > File "<string>", line 28, in content
          > NameMapper.NotFound: sayHelloTo
          >
          > ------------------------------------------------------------------------

          We know that .sayHelloTo() won't be found for the same reason as above.
          So it's not worth analyzing this one. $content is found, and that's
          as much reliability as we're going to get with this arrangement.

          --
          -Mike (Iron) Orr, mso@... (iron@...)
          English * Esperanto * Russkiy * Deutsch * Espan~ol


          -------------------------------------------------------
          Enterprise Linux Forum Conference & Expo, June 4-6, 2003, Santa Clara
          The only event dedicated to issues related to Linux enterprise solutions
          www.enterpriselinuxforum.com

          _______________________________________________
          Cheetahtemplate-discuss mailing list
          Cheetahtemplate-discuss@...
          https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
        • Dirk Hoffmann
          Hello Mike, thanks a lot. You gave me the right clues to find a solution to the problem. The only change takes place in MyTemplate.py. I created a helper class
          Message 4 of 6 , May 7, 2003
          • 0 Attachment
            Hello Mike,

            thanks a lot. You gave me the right clues to find a solution to the problem. The only change takes place in MyTemplate.py. I created a helper class which defines the .sayHelloTo() method. The constructor of MyTemplate then adds an object of this class to the Template object's search list:


            MyTemplate.py


            from Cheetah.Template import Template
            
            class Functor:
            	def sayHelloTo(self,arg):
            		return 'Hello ' + arg
            	
            class MyTemplate(Template):
            	def __init__(self,file):
            		Template.__init__(self,file = file,
            				  searchList = [Functor()])
            


            With this solution you must not use $self.sayHelloTo("World") in the template, but instead just $sayHelloTo("World").

            Now I can continue solving the original problem, which was to implement the .relocImage() method.

            I'm learning that python is quite different from C++ or Java, the programming languages I used to program in. Dynamically changing the super class really is a new concept to me.

            Thanks for your help!

            Regards
            Dirk



            Mike Orr wrote:
            On Tue, May 06, 2003 at 11:37:50PM +0200, Dirk Hoffmann wrote:
              
             Case A
            
            The example starts with three files:
            
            1. ATemplate.tmpl - A template containing a method placeholder
            ------------------------------------------------------------------------
            
            $sayHelloTo("World")
            
            ------------------------------------------------------------------------
            
            
            2. MyTemplate.py - A python class defining the method
            ------------------------------------------------------------------------
            
            from Cheetah.Template import Template
            
            class MyTemplate(Template):
               def __init__(self, file):
                   Template.__init__(self,file=file)
            
               def sayHelloTo(self,arg):
                   return 'Hello ' + arg
            
            ------------------------------------------------------------------------
            
            
            3. HelloWorld.py - A python file using the class with the new method
            ------------------------------------------------------------------------
            
            from MyTemplate import MyTemplate
            
            t = MyTemplate(file = "ATemplate.tmpl")
            print(t)
            
            ------------------------------------------------------------------------
            This example works fine: python HelloWorld.py prints "Hello World".
            
                
            It was an unintended feature that you can instantiate a subclass of
            Template, with additional methods for placeholders, passing it a template
            definition from a third source, but logically it looks OK.  And you
            correctly call Template.__init__, which is necessary if you override
            .__init__ .  Theoretically it should not be necessary if you don't
            override .__init__.
            
            
              
             Case B
            
            MyTemplate.py and HelloWorld.py remain the same throughout the whole 
            experiment.
            
            I rename ATemplate.tmpl to SuperTemplate.tmpl and create a new 
            ATemplate.tmpl just extending SuperTemplate.tmpl so having the following 
            files besides MyTemplate.py and HelloWorld.py :
            
            SuperTemplate.tmpl - contains the method placeholder now
            ------------------------------------------------------------------------
            
            $sayHelloTo("World")
            
            ------------------------------------------------------------------------
            
            ATemplate.tmpl - just extends SuperTemplate.tmpl
            ------------------------------------------------------------------------
            
            #extends SuperTemplate
            
            ------------------------------------------------------------------------
            
            
            Now I get the following message:
            ------------------------------------------------------------------------
            
            Traceback (most recent call last):
             File "HelloWorld.py", line 5, in ?
               print(t)
             File "SuperTemplate.py", line 89, in respond
               write(filter(VFS(SL + [globals(), __builtin__],"sayHelloTo",0)("World"), 
               rawExpr='$sayHelloTo("World")')) # from line 1, col 1.
            NameMapper.NotFound: sayHelloTo
            
            ------------------------------------------------------------------------
                
            I get "ImportError: No module named SuperTemplate:.  I run
            "cheetah compile SuperTemplate".  Now I run HelloWorld.py and get
            the same error you did.
            
            So what's happening?  I suspect there's a breakdown in the inheritance
            chain, or that in the peculiar way you arrange the files and invoke
            the template, there might be two inheritance chains, one of which is
            incomplete; i.e., .sayHelloTo() exists in the wrong chain.  
            
            Let's first look at the placeholder values.    Rename SuperTemplate.tmpl
            back to ATemplate.tmpl and prepend:
            
                  ===> Dump of the searchList <===
                  $_searchList
                  ===> Dump of 'self' <===
                  $dir($self)
                  ===> End of dumps <===
            
            The first dump produces
            [{}, <MyTemplate.MyTemplate instance at 0x40209f2c>]
            which is normal.  (The {} is for the "#set global" variables.)
            The second dump is long but includes 'sayHelloTo' as expected.  Good.
            
            Now change the files for case B, leaving the dump lines intact.
            Recompile SuperTemplate.  Run HelloWorld.py, and voila, the expected
            error.  Unfortunately our dumps don't show up because the output is
            completely aborted.  So let's comment out the error-prone placeholder.
            
            The first dump now looks like:
            [{}, <Cheetah.Parser.GenTemplate instance at 0x40209f2c>]
            The second element is typical for a template compiled from a string.
            The second shows no 'sayHelloTo' method.  Ah ha!  I don't know of a
            Python tool to show the inheritance tree all at once, but the
            "GenTemplate instance" gives a clue.  The template that's in effect
            is not your MyTemplate, it's the generic one used for dynamic
            compilations, which doesn't have .sayHelloTo().  Delving into how 
            dynamic compilation and #extends interact is a hairy subject which only
            Tavis is qualified to answer.  The moral of the story is, don't play
            games with #extends, use it only with precompiled templates or expect
            to spend hours coming up with a workable situation.   Whether this is a
            bug or not, Tavis will have to answer.  Dynamically-compiled templates
            switch their base class behind the scenes, which usually works to your
            favor, but in this case it may be working to your disfavor.
            
            Let's try precompiling ATemplate (the one containing #extends) and
            see if it solves our problem.  Let's be optimistic and uncomment the
            placeholder in SuperTemplate too and recompile it.
            
            The first dump changes to:
            [{}, <__main__.ATemplate instance at 0x4021c7cc>]
            but the NotFound error persists.  Of course!  MyTemplate is no longer
            in the loop, so of course .sayHelloTo() doesn't exist.  Tne next step
            would be to move .sayHelloTo() into ATemplate, SuperTemplate, or a
            Python superclass of these two.
            
            
              
             Case C
            
            I alter SuperTemplate.tmpl and ATemplate.tmpl as follows:
            
            SuperTemplate.tmpl - just contains a simple variable placeholder
            ------------------------------------------------------------------------
            
            $content
            
            ------------------------------------------------------------------------
            
            
            ATemplate.tmpl - defines the variable placeholder
            ------------------------------------------------------------------------
            
            #extends SuperTemplate
            
            #def content
            $sayHelloTo("World")
            #end def
            
            ------------------------------------------------------------------------
            
            
            This results in the following message:
            ------------------------------------------------------------------------
            
            Traceback (most recent call last):
             File "HelloWorld.py", line 5, in ?
               print(t)
             File 
             "/home/hoffmann/castle/projects/develop/labor/python/cheetah/methodPlaceholder/SuperTemplate.py", line 89, in respond
               write(filter(VFS(SL + [globals(), __builtin__],"content",1), 
               rawExpr='$content')) # from line 1, col 1.
             File "<string>", line 28, in content
            NameMapper.NotFound: sayHelloTo
            
            ------------------------------------------------------------------------
                
            We know that .sayHelloTo() won't be found for the same reason as above.
            So it's not worth analyzing this one.  $content is found, and that's
            as much reliability as we're going to get with this arrangement.
            
              


          • Mike Orr
            ... I have reservations about Cheetah dynamically changing the base class, because it s both easy for users to misunderstand and could cause potential bugs.
            Message 5 of 6 , May 7, 2003
            • 0 Attachment
              On Wed, May 07, 2003 at 08:22:49PM +0200, Dirk Hoffmann wrote:
              > I'm learning that python is quite different from C++ or Java, the
              > programming languages I used to program in. Dynamically changing the
              > super class really is a new concept to me.

              I have reservations about Cheetah dynamically changing the base class,
              because it's both easy for users to misunderstand and could cause
              potential bugs. But it has performed solidly, and the release notes
              for Python 2.3 beta 1 explicitly say it's OK to modify
              .__class__.__bases__ . However, I wouldn't do it in my application
              if I could avoid it. Adding and deleting *attributes* in class
              instances dynamically, however, has long been a well-supported
              feature of Python. Some people use it to create an empty class
              and then add whatever attributes they want to the instance,
              essentially using it like a dictionary.

              --
              -Mike (Iron) Orr, mso@... (iron@...)
              English * Esperanto * Russkiy * Deutsch * Espan~ol


              -------------------------------------------------------
              Enterprise Linux Forum Conference & Expo, June 4-6, 2003, Santa Clara
              The only event dedicated to issues related to Linux enterprise solutions
              www.enterpriselinuxforum.com

              _______________________________________________
              Cheetahtemplate-discuss mailing list
              Cheetahtemplate-discuss@...
              https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
            Your message has been successfully submitted and would be delivered to recipients shortly.