Simon
Simon

Reputation: 3727

Graceful error handling and logging in Jinja extension

I'm developing a Jinja extension that performs a few potentially harmful operations, which on failure will raise an Exception that holds some information on what went wrong.

When this occurs, of course the Exception will prevent Jinja from completing its render process and return None rather than a render result. This problem is easily mitigated using a try/catch statement and returning an empty string or whatever is suitable.

However, that effectively throws away the Exception and the debugging info, which I would rather pass on to my error log. The system responsible for setting up the Jinja environment has it's own logging service, which I would prefer to keep decoupled from the extension. I am aware though, that Jinja has an Undefined class which I have successfully used to intercept access of undefined variables in another project.

Is there any way I could raise a special type of exception (UndefinedException did not work), or tell the Jinja environment to log a warning, when an error occurs in my extension, while still allowing it to continue its execution?

What I have in mind is something along the lines of this example:

def _render(*args, **kwrags):
    # ...
    try:
        self.potentially_harmful_operation()
    except Exception as e:
        self.environment.warning(e)
        return Markup("")
    # ...
    return Markup('<img src"{}">'.format(img_path))

So, to clarify, as I wrote in a comment below:

Fundamentally I guess my question boils down to "how can I make Jinja produce a warning, as it does for e.g. missing variables".

Upvotes: 2

Views: 2463

Answers (1)

Simon
Simon

Reputation: 3727

For anyone interested, I managed to solve this by implementing my own Undefined class (largely inspired by make_logging_undefined and supplying that to the environment using the undefined keyword. Depending on your needs, the default make_logging_undefined might very well suffice.

Once that's in place, the trick is to emit the warning in the environment. This is done by simply instantiating the environment's Undefined and executing one of its magic methods (e.g. __str__). Hooking on to my example code from above, that could be accomplished like this:

def _render(*args, **kwrags):
    # ...
    try:
        self.potentially_harmful_operation()
    except Exception as e:
        str(self.environment.undefined(e))
        return Markup("")
    # ...
    return Markup('<img src"{}">'.format(img_path))

Upvotes: 1

Related Questions