Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get line number causing an exception (other than TemplateSyntaxError) in Jinja2 template?

Tags:

python

jinja2

When a template contains a syntax error, Jinja throws a TemplateSyntaxError which has a lineno attribute containing the template line number where the error occurred.

How can I get the line number when an error occurs which is not a syntax error? For example, the following tag:

{{ len(SettlementDate)+1 }}

causes Jinja to throw a TypeError if SettlementDate is not something list-like. How can I then find out where this error occurred, for reporting to the user? For my use case, sanitizing the context variables in advance is not an option.

like image 616
RichardW Avatar asked Nov 17 '14 07:11

RichardW


People also ask

What is Autoescape in Jinja2?

B701: Test for not auto escaping in jinja2 When autoescaping is enabled, Jinja2 will filter input strings to escape any HTML content submitted via template variables. Without escaping HTML input the application becomes vulnerable to Cross Site Scripting (XSS) attacks. Unfortunately, autoescaping is False by default.


1 Answers

I just ran across this problem. Unfortunately it seems to be a common problem with no solution. Just to make the research easier for the next character who comes along, here are some related references:

https://github.com/saltstack/salt/issues/21298 https://github.com/saltstack/salt/issues/28345

Yes, those references are related to saltstack specifically but the underlying problem in jinja is there.

I built a workaround in my specific use-case:

  try:
    output = env.get_template(
        "envoy.{}.yaml".format(args.type.lower())
    ).render(**context)
    print("Template is hydrated")
  except Exception as e:
    print(
        """
            Error Generating Template!
            --------------------------
            Error:    {}
            Template: {}

            An error occurred hydrating the template with the context
            parameters.  The error exists in either the context or the
            template but has nothing to do with the YAML formatting of
            the template at this time.

        """.format(e,args.template)
    )
    if args.debug:
        print(output)
    else:
        print("\nTry running with --debug for more info.")
    sys.exit(1)

Disclaimer: Using --debug in my actual solution pukes an ugly stacktrace that increases the learning curve for a user. You have to read that stacktrace to find the line specific to the template, e.g. this one:

File "/Users/scaldwell/git//src/serviceProxy/.yaml", line 4, in template {% from "includes/listener.payload.noop.yaml" import payload_listener_noop with context %}

This should be cleaner output.... Maybe I will make fixing this a weekend project or Atlassian ShipIt Project some day. Until then, this is what JINJA seems to offer.

like image 172
Sam Caldwell Avatar answered Nov 04 '22 00:11

Sam Caldwell