pythonenthoughttemplating-enginecheetah

How should I access Cheetah Template() variable placeholders in an object instance?


I'm trying to set up an object instance that will provide values to the Cheetah3 text templating engine.

This is my text template script...

#filename: py_text_template.py

from traits.api import String, Range
from traits.api import HasTraits

from loguru import logger

from Cheetah.Template import Template

class Info(HasTraits):
    keyword_integer = Range(value=0, low=1, high=60)
    keyword_string = String(value="snack", regex=r"^\w+")

@logger.catch(onerror=lambda _: sys.exit(1))
def generate_text_template():
    myinfo = Info(keyword_integer=10, keyword_string="snack-attack")
    t = Template("On the first $myinfo.keyword_string, my true love")
    print(t)

generate_text_template()

I expected to use the myinfo instance of the Info() class to populate the Template, but I get the following error...

Cheetah.NameMapper.NotFound: cannot find 'myinfo'

Solution

  • For reasons I don't yet understand, Cheetah does not follow normal conventions to access object instance attributes and methods.

    To fix the problem, I had to replace the $myinfo.keyword_string call with $keyword_string. Then I added searchList=[myinfo] to the Template() call...

    myinfo = Info(keyword_integer=10, keyword_string="snack-attack")
    t = Template("On the first $keyword_string, my true love",
        searchList=[myinfo])
    

    The object instances in searchList are searched for the dictionary key, attribute, or method in question.

    The complete working Cheetah script was:

    #filename: py_text_template.py
    
    from traits.api import String, Range
    from traits.api import HasTraits
    
    from loguru import logger
    
    from Cheetah.Template import Template
    
    class Info(HasTraits):
        keyword_integer = Range(value=0, low=1, high=60)
        keyword_string = String(value="snack", regex=r"^\w+")
    
    @logger.catch(onerror=lambda _: sys.exit(1))
    def generate_text_template():
        myinfo = Info(keyword_integer=10, keyword_string="snack-attack")
        t = Template("On the first $keyword_string, my true love",
                                  # ^^^^^^^^^^^^^^
            searchList=[myinfo])  # <--- put myinfo instance here
        print(t)
    
    generate_text_template()
    

    Running this under python3.7 yields the expected results...

    (py37_test) [mpenning@mudslide fixme]$ python py_text_template.py
    
    On the first snack-attack, my true love
    (py37_test) [mpenning@mudslide fixme]$
    

    This script requires installing:

    I'm using: