Mike Pennington
Mike Pennington

Reputation: 43077

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'

Upvotes: 2

Views: 378

Answers (1)

Mike Pennington
Mike Pennington

Reputation: 43077

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:

  • Linux mudslide 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux
  • Python 3.7.0
  • Traits 6.3.2
  • loguru 0.5.3
  • Cheetah 3.2.6.post1

Upvotes: 1

Related Questions