prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Use a FS cache for Jinja to speed it up a bit
  http://jinja.pocoo.org/docs/dev/api/#bytecode-cache
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `nikola/plugins/template/jinja.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 
  3 # Copyright © 2012-2015 Roberto Alsina and others.
  4 
  5 # Permission is hereby granted, free of charge, to any
  6 # person obtaining a copy of this software and associated
  7 # documentation files (the "Software"), to deal in the
  8 # Software without restriction, including without limitation
  9 # the rights to use, copy, modify, merge, publish,
  10 # distribute, sublicense, and/or sell copies of the
  11 # Software, and to permit persons to whom the Software is
  12 # furnished to do so, subject to the following conditions:
  13 #
  14 # The above copyright notice and this permission notice
  15 # shall be included in all copies or substantial portions of
  16 # the Software.
  17 #
  18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  19 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  21 # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  22 # OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23 # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26 
  27 
  28 """Jinja template handler."""
  29 
  30 from __future__ import unicode_literals
  31 import os
  32 import json
  33 from collections import deque
  34 try:
  35     import jinja2
  36     from jinja2 import meta
  37 except ImportError:
  38     jinja2 = None  # NOQA
  39 
  40 from nikola.plugin_categories import TemplateSystem
  41 from nikola.utils import makedirs, req_missing
  42 
  43 
  44 class JinjaTemplates(TemplateSystem):
  45     """Support for Jinja2 templates."""
  46 
  47     name = "jinja"
  48     lookup = None
  49     dependency_cache = {}
  50 
  51     def __init__(self):
  52         """Initialize Jinja2 environment with extended set of filters."""
  53         if jinja2 is None:
  54             return
  55         self.lookup = jinja2.Environment()
  56         self.lookup.trim_blocks = True
  57         self.lookup.lstrip_blocks = True
  58         self.lookup.filters['tojson'] = json.dumps
  59         self.lookup.globals['enumerate'] = enumerate
  60         self.lookup.globals['isinstance'] = isinstance
  61         self.lookup.globals['tuple'] = tuple
  62 
  63     def set_directories(self, directories, cache_folder):
  64         """Create a new template lookup with set directories."""
  65         if jinja2 is None:
  66             req_missing(['jinja2'], 'use this theme')
  67         self.directories = directories
  68         self.create_lookup()
  69 
  70     def inject_directory(self, directory):
  71         """Add a directory to the lookup and recreate it if it's not there yet."""
  72         if directory not in self.directories:
  73             self.directories.append(directory)
  74             self.create_lookup()
  75 
  76     def create_lookup(self):
  77         """Create a template lookup."""
  78         self.lookup.loader = jinja2.FileSystemLoader(self.directories,
  79                                                      encoding='utf-8')
  80 
  81     def set_site(self, site):
  82         """Set the Nikola site."""
  83         self.site = site
  84         self.lookup.filters.update(self.site.config['TEMPLATE_FILTERS'])
  85 
  86     def render_template(self, template_name, output_name, context):
  87         """Render the template into output_name using context."""
  88         if jinja2 is None:
  89             req_missing(['jinja2'], 'use this theme')
  90         template = self.lookup.get_template(template_name)
  91         output = template.render(**context)
  92         if output_name is not None:
  93             makedirs(os.path.dirname(output_name))
  94             with open(output_name, 'w+') as output:
  95                 output.write(output.encode('utf8'))
  96         return output
  97 
  98     def render_template_to_string(self, template, context):
  99         """Render template to a string using context."""
  100         return self.lookup.from_string(template).render(**context)
  101 
  102     def template_deps(self, template_name):
  103         """Generate list of dependencies for a template."""
  104         # Cache the lists of dependencies for each template name.
  105         if self.dependency_cache.get(template_name) is None:
  106             # Use a breadth-first search to find all templates this one
  107             # depends on.
  108             queue = deque([template_name])
  109             visited_templates = set([template_name])
  110             deps = []
  111             while len(queue) > 0:
  112                 curr = queue.popleft()
  113                 source, filename = self.lookup.loader.get_source(self.lookup,
  114                                                                  curr)[:2]
  115                 deps.append(filename)
  116                 ast = self.lookup.parse(source)
  117                 dep_names = meta.find_referenced_templates(ast)
  118                 for dep_name in dep_names:
  119                     if (dep_name not in visited_templates and dep_name is not None):
  120                         visited_templates.add(dep_name)
  121                         queue.append(dep_name)
  122             self.dependency_cache[template_name] = deps
  123         return self.dependency_cache[template_name]
  124
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/nikola/plugins/template/jinja.py b/nikola/plugins/template/jinja.py
  --- a/nikola/plugins/template/jinja.py
  +++ b/nikola/plugins/template/jinja.py
  @@ -52,18 +52,21 @@
           """Initialize Jinja2 environment with extended set of filters."""
           if jinja2 is None:
               return
  -        self.lookup = jinja2.Environment()
  +
  +    def set_directories(self, directories, cache_folder):
  +        """Create a new template lookup with set directories."""
  +        if jinja2 is None:
  +            req_missing(['jinja2'], 'use this theme')
  +        cache_folder = os.path.join(cache_folder, 'jinja')
  +        makedirs(cache_folder)
  +        cache = jinja2.FileSystemBytecodeCache(cache_folder)
  +        self.lookup = jinja2.Environment(bytecode_cache=cache)
           self.lookup.trim_blocks = True
           self.lookup.lstrip_blocks = True
           self.lookup.filters['tojson'] = json.dumps
           self.lookup.globals['enumerate'] = enumerate
           self.lookup.globals['isinstance'] = isinstance
           self.lookup.globals['tuple'] = tuple
  -
  -    def set_directories(self, directories, cache_folder):
  -        """Create a new template lookup with set directories."""
  -        if jinja2 is None:
  -            req_missing(['jinja2'], 'use this theme')
           self.directories = directories
           self.create_lookup()
  
verification_info: {"golden_diff": "diff --git a/nikola/plugins/template/jinja.py b/nikola/plugins/template/jinja.py\n--- a/nikola/plugins/template/jinja.py\n+++ b/nikola/plugins/template/jinja.py\n@@ -52,18 +52,21 @@\n         \"\"\"Initialize Jinja2 environment with extended set of filters.\"\"\"\n         if jinja2 is None:\n             return\n-        self.lookup = jinja2.Environment()\n+\n+    def set_directories(self, directories, cache_folder):\n+        \"\"\"Create a new template lookup with set directories.\"\"\"\n+        if jinja2 is None:\n+            req_missing(['jinja2'], 'use this theme')\n+        cache_folder = os.path.join(cache_folder, 'jinja')\n+        makedirs(cache_folder)\n+        cache = jinja2.FileSystemBytecodeCache(cache_folder)\n+        self.lookup = jinja2.Environment(bytecode_cache=cache)\n         self.lookup.trim_blocks = True\n         self.lookup.lstrip_blocks = True\n         self.lookup.filters['tojson'] = json.dumps\n         self.lookup.globals['enumerate'] = enumerate\n         self.lookup.globals['isinstance'] = isinstance\n         self.lookup.globals['tuple'] = tuple\n-\n-    def set_directories(self, directories, cache_folder):\n-        \"\"\"Create a new template lookup with set directories.\"\"\"\n-        if jinja2 is None:\n-            req_missing(['jinja2'], 'use this theme')\n         self.directories = directories\n         self.create_lookup()\n", "issue": "Use a FS cache for Jinja to speed it up a bit\nhttp://jinja.pocoo.org/docs/dev/api/#bytecode-cache\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 2012-2015 Roberto Alsina and others.\n\n# Permission is hereby granted, free of charge, to any\n# person obtaining a copy of this software and associated\n# documentation files (the \"Software\"), to deal in the\n# Software without restriction, including without limitation\n# the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the\n# Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice\n# shall be included in all copies or substantial portions of\n# the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY\n# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\n# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\n# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n\"\"\"Jinja template handler.\"\"\"\n\nfrom __future__ import unicode_literals\nimport os\nimport json\nfrom collections import deque\ntry:\n    import jinja2\n    from jinja2 import meta\nexcept ImportError:\n    jinja2 = None  # NOQA\n\nfrom nikola.plugin_categories import TemplateSystem\nfrom nikola.utils import makedirs, req_missing\n\n\nclass JinjaTemplates(TemplateSystem):\n    \"\"\"Support for Jinja2 templates.\"\"\"\n\n    name = \"jinja\"\n    lookup = None\n    dependency_cache = {}\n\n    def __init__(self):\n        \"\"\"Initialize Jinja2 environment with extended set of filters.\"\"\"\n        if jinja2 is None:\n            return\n        self.lookup = jinja2.Environment()\n        self.lookup.trim_blocks = True\n        self.lookup.lstrip_blocks = True\n        self.lookup.filters['tojson'] = json.dumps\n        self.lookup.globals['enumerate'] = enumerate\n        self.lookup.globals['isinstance'] = isinstance\n        self.lookup.globals['tuple'] = tuple\n\n    def set_directories(self, directories, cache_folder):\n        \"\"\"Create a new template lookup with set directories.\"\"\"\n        if jinja2 is None:\n            req_missing(['jinja2'], 'use this theme')\n        self.directories = directories\n        self.create_lookup()\n\n    def inject_directory(self, directory):\n        \"\"\"Add a directory to the lookup and recreate it if it's not there yet.\"\"\"\n        if directory not in self.directories:\n            self.directories.append(directory)\n            self.create_lookup()\n\n    def create_lookup(self):\n        \"\"\"Create a template lookup.\"\"\"\n        self.lookup.loader = jinja2.FileSystemLoader(self.directories,\n                                                     encoding='utf-8')\n\n    def set_site(self, site):\n        \"\"\"Set the Nikola site.\"\"\"\n        self.site = site\n        self.lookup.filters.update(self.site.config['TEMPLATE_FILTERS'])\n\n    def render_template(self, template_name, output_name, context):\n        \"\"\"Render the template into output_name using context.\"\"\"\n        if jinja2 is None:\n            req_missing(['jinja2'], 'use this theme')\n        template = self.lookup.get_template(template_name)\n        output = template.render(**context)\n        if output_name is not None:\n            makedirs(os.path.dirname(output_name))\n            with open(output_name, 'w+') as output:\n                output.write(output.encode('utf8'))\n        return output\n\n    def render_template_to_string(self, template, context):\n        \"\"\"Render template to a string using context.\"\"\"\n        return self.lookup.from_string(template).render(**context)\n\n    def template_deps(self, template_name):\n        \"\"\"Generate list of dependencies for a template.\"\"\"\n        # Cache the lists of dependencies for each template name.\n        if self.dependency_cache.get(template_name) is None:\n            # Use a breadth-first search to find all templates this one\n            # depends on.\n            queue = deque([template_name])\n            visited_templates = set([template_name])\n            deps = []\n            while len(queue) > 0:\n                curr = queue.popleft()\n                source, filename = self.lookup.loader.get_source(self.lookup,\n                                                                 curr)[:2]\n                deps.append(filename)\n                ast = self.lookup.parse(source)\n                dep_names = meta.find_referenced_templates(ast)\n                for dep_name in dep_names:\n                    if (dep_name not in visited_templates and dep_name is not None):\n                        visited_templates.add(dep_name)\n                        queue.append(dep_name)\n            self.dependency_cache[template_name] = deps\n        return self.dependency_cache[template_name]\n", "path": "nikola/plugins/template/jinja.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Copyright \u00a9 2012-2015 Roberto Alsina and others.\n\n# Permission is hereby granted, free of charge, to any\n# person obtaining a copy of this software and associated\n# documentation files (the \"Software\"), to deal in the\n# Software without restriction, including without limitation\n# the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the\n# Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice\n# shall be included in all copies or substantial portions of\n# the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY\n# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\n# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\n# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n\"\"\"Jinja template handler.\"\"\"\n\nfrom __future__ import unicode_literals\nimport os\nimport json\nfrom collections import deque\ntry:\n    import jinja2\n    from jinja2 import meta\nexcept ImportError:\n    jinja2 = None  # NOQA\n\nfrom nikola.plugin_categories import TemplateSystem\nfrom nikola.utils import makedirs, req_missing\n\n\nclass JinjaTemplates(TemplateSystem):\n    \"\"\"Support for Jinja2 templates.\"\"\"\n\n    name = \"jinja\"\n    lookup = None\n    dependency_cache = {}\n\n    def __init__(self):\n        \"\"\"Initialize Jinja2 environment with extended set of filters.\"\"\"\n        if jinja2 is None:\n            return\n\n    def set_directories(self, directories, cache_folder):\n        \"\"\"Create a new template lookup with set directories.\"\"\"\n        if jinja2 is None:\n            req_missing(['jinja2'], 'use this theme')\n        cache_folder = os.path.join(cache_folder, 'jinja')\n        makedirs(cache_folder)\n        cache = jinja2.FileSystemBytecodeCache(cache_folder)\n        self.lookup = jinja2.Environment(bytecode_cache=cache)\n        self.lookup.trim_blocks = True\n        self.lookup.lstrip_blocks = True\n        self.lookup.filters['tojson'] = json.dumps\n        self.lookup.globals['enumerate'] = enumerate\n        self.lookup.globals['isinstance'] = isinstance\n        self.lookup.globals['tuple'] = tuple\n        self.directories = directories\n        self.create_lookup()\n\n    def inject_directory(self, directory):\n        \"\"\"Add a directory to the lookup and recreate it if it's not there yet.\"\"\"\n        if directory not in self.directories:\n            self.directories.append(directory)\n            self.create_lookup()\n\n    def create_lookup(self):\n        \"\"\"Create a template lookup.\"\"\"\n        self.lookup.loader = jinja2.FileSystemLoader(self.directories,\n                                                     encoding='utf-8')\n\n    def set_site(self, site):\n        \"\"\"Set the Nikola site.\"\"\"\n        self.site = site\n        self.lookup.filters.update(self.site.config['TEMPLATE_FILTERS'])\n\n    def render_template(self, template_name, output_name, context):\n        \"\"\"Render the template into output_name using context.\"\"\"\n        if jinja2 is None:\n            req_missing(['jinja2'], 'use this theme')\n        template = self.lookup.get_template(template_name)\n        output = template.render(**context)\n        if output_name is not None:\n            makedirs(os.path.dirname(output_name))\n            with open(output_name, 'w+') as output:\n                output.write(output.encode('utf8'))\n        return output\n\n    def render_template_to_string(self, template, context):\n        \"\"\"Render template to a string using context.\"\"\"\n        return self.lookup.from_string(template).render(**context)\n\n    def template_deps(self, template_name):\n        \"\"\"Generate list of dependencies for a template.\"\"\"\n        # Cache the lists of dependencies for each template name.\n        if self.dependency_cache.get(template_name) is None:\n            # Use a breadth-first search to find all templates this one\n            # depends on.\n            queue = deque([template_name])\n            visited_templates = set([template_name])\n            deps = []\n            while len(queue) > 0:\n                curr = queue.popleft()\n                source, filename = self.lookup.loader.get_source(self.lookup,\n                                                                 curr)[:2]\n                deps.append(filename)\n                ast = self.lookup.parse(source)\n                dep_names = meta.find_referenced_templates(ast)\n                for dep_name in dep_names:\n                    if (dep_name not in visited_templates and dep_name is not None):\n                        visited_templates.add(dep_name)\n                        queue.append(dep_name)\n            self.dependency_cache[template_name] = deps\n        return self.dependency_cache[template_name]\n", "path": "nikola/plugins/template/jinja.py"}]}