pytest-dev / pytest-flask

A set of pytest fixtures to test Flask applications

Home Page:http://pytest-flask.readthedocs.org/en/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rendering Templates with Jinja 2 Does Not Work

agentS opened this issue · comments

commented

Hi,

First of all thank you for your great library, I really appreciate your effort.

I am having an issue with testing a function which calls Flask's render_template function. Whenever executing the command pytest the error shown below is thrown.

    def test_generate_notebook_for_experiment():
>       notebook = generate_notebook_for_experiment(constants.EXPERIMENT_CONFIG)

test\jupyterlab\jupyter_hub_test.py:16:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
jupyterlab\jupyter_hub.py:31: in generate_notebook_for_experiment
    import_code = render_template(f'{TEMPLATE_FOLDER}/imports.pytemplate', configuration = notebook_configuration)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

template_name_or_list = 'notebook/imports.pytemplate'
context = {'configuration': {'collections': {'edge_collections': {'BNL_data_juvnf6wv': 'pcbs_local_BNL_data_juvnf6wv_data_edges'...': 'gduser@Siemens', 'port': 8080, ...}, 'graphname': 'pcbs_local', 'module': 'gdf.contrib.managers.ArangoDBManager'}}}
ctx = None

    def render_template(template_name_or_list, **context):
        """Renders a template from the template folder with the given
        context.

        :param template_name_or_list: the name of the template to be
                                      rendered, or an iterable with template names
                                      the first one existing will be rendered
        :param context: the variables that should be available in the
                        context of the template.
        """
        ctx = _app_ctx_stack.top
>       ctx.app.update_template_context(context)
E       AttributeError: 'NoneType' object has no attribute 'app'

The following snippet shows the method to be tested, which invokes the render_template function.

from nbformat.v4 import new_notebook, new_code_cell, new_markdown_cell
from nbformat import NotebookNode

from flask import Flask, render_template

def generate_notebook_for_experiment(notebook_configuration: Dict) -> NotebookNode:
    """Create a new Jupyter notebook with template code for the specified experiment."""

    TEMPLATE_FOLDER = 'notebook'
    title = new_markdown_cell('# Experiment Notebook')
    import_code = render_template(f'{TEMPLATE_FOLDER}/imports.pytemplate', configuration = notebook_configuration)
    import_code_cell = new_code_cell(import_code, metadata = __create_metadata_for_hidden_cell__())

    notebook = new_notebook(
        cells=[ title, import_code_cell ],
        ...
    )
    return notebook

This is the complete test method causing the error:

def test_generate_notebook_for_experiment():
    notebook = generate_notebook_for_experiment(constants.EXPERIMENT_CONFIG)
    assert notebook.nbformat == 4
    nbformat.validate(nbjson=notebook, version=4, version_minor=2)

My code for creating the fixture is shown below.

import pytest

from gdrest.application import create_app

@pytest.fixture
def app():
    app, _ = create_app()
    return app

What do I need to do to make sure the Jinja2 runtime environment is appropriately configured by Flask so the function render_template is safe to execute? Thank you so much for your answers!

Hi there @agentS. I believe this isn't a pytest-flask related issue, but rather a question about Flask. Flask works with application contexts and the render_template method requires such a context. Lets go through the more relevant lines in your traceback:

ctx = _app_ctx_stack.top  # <<< this tries to fetch the topmost context from stack
ctx.app.update_template_context(context)  # <<< this will fail since ctx = None

flask.templating.render_template implementation for the curious ones

So this is happening because render_template is being called from "outside" a valid flask application context. Finally, stack overflow would probably be better suited for questions of this nature considering the issue tracker is a tool to address bugs and feature requests in pytest-flask itself.