Jinja not loading correctly

Hi,
I'm completely new to developing OctoPrint plugins so i wanted to follow a few tutorials and see if i could get something working...
Now when trying to start Octoprint, jinja starts throwing these errors:

octoprint.util.jinja - ERROR - Caught exception while compiling template dialogs/about.jinja2 at line 41
ImportError: cannot import name 'open_if_exists' from 'jinja2.loaders'

Full traceback below:

2024-01-19 19:31:06,591 - octoprint.util.jinja - ERROR - Caught exception while compiling template dialogs/about.jinja2 at line 41
Traceback (most recent call last):
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 255, in _handle_body
    return caller()
           ^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
         ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\templates\dialogs\about.jinja2", line 161, in macro
  File "C:\Devel\OctoPrint\src\octoprint\templates\dialogs\about\supporters.jinja2", line 36, in root
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\environment.py", line 1010, in get_template
    return self._load_template(name, globals)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\environment.py", line 969, in _load_template
    template = self.loader.load(self, name, self.make_globals(globals))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py", line 125, in load
    source, filename, uptodate = self.get_source(environment, name)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\flask\templating.py", line 62, in get_source
    return self._get_source_fast(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\flask\templating.py", line 95, in _get_source_fast
    return loader.get_source(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py", line 558, in get_source
    return loader.get_source(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 106, in get_source
    contents = SelectedFilesLoader.get_source(self, environment, template)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 75, in get_source
    from jinja2.loaders import open_if_exists
ImportError: cannot import name 'open_if_exists' from 'jinja2.loaders' (c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py)
2024-01-19 19:31:06,596 - octoprint.util.jinja - ERROR - Caught exception while compiling template dialogs/about.jinja2 at line 41
Traceback (most recent call last):
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 255, in _handle_body
    return caller()
           ^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\runtime.py", line 763, in __call__
    return self._invoke(arguments, autoescape)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\runtime.py", line 777, in _invoke
    rv = self._func(*arguments)
         ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\templates\dialogs\about.jinja2", line 161, in macro
  File "C:\Devel\OctoPrint\src\octoprint\templates\dialogs\about\authors.jinja2", line 36, in root
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\environment.py", line 1010, in get_template
    return self._load_template(name, globals)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\environment.py", line 969, in _load_template
    template = self.loader.load(self, name, self.make_globals(globals))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py", line 125, in load
    source, filename, uptodate = self.get_source(environment, name)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\flask\templating.py", line 62, in get_source
    return self._get_source_fast(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\flask\templating.py", line 95, in _get_source_fast
    return loader.get_source(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py", line 558, in get_source
    return loader.get_source(environment, template)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 106, in get_source
    contents = SelectedFilesLoader.get_source(self, environment, template)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Devel\OctoPrint\src\octoprint\util\jinja.py", line 75, in get_source
    from jinja2.loaders import open_if_exists
ImportError: cannot import name 'open_if_exists' from 'jinja2.loaders' (c:\Devel\OctoPrint\venv\Lib\site-packages\jinja2\loaders.py)

The jinja file i'm trying to load looks like this:

<h1>Testing...<h1>
<p>Test Tab 123</p>

Nothing complicated just a header and some text...

Things i have tried:
Reinstalling jinja2 via python -m pip install and regular pip install
Restarting everything (obviously)

Any help would be much appreciated!

it's kind of dependent on how it's named and how you're loading it in the plugin via get_template_configs. is your full code somewhere to look at?

This is my init.py:

# coding=utf-8
from __future__ import absolute_import

### (Don't forget to remove me)
# This is a basic skeleton for your plugin's __init__.py. You probably want to adjust the class name of your plugin
# as well as the plugin mixins it's subclassing from. This is really just a basic skeleton to get you started,
# defining your plugin as a template plugin, settings and asset plugin. Feel free to add or remove mixins
# as necessary.
#
# Take a look at the documentation on what other plugin mixins are available.

import octoprint.plugin

class OctoqueuePlugin(octoprint.plugin.SettingsPlugin,
    octoprint.plugin.AssetPlugin,
    octoprint.plugin.TemplatePlugin
):

    def get_template_configs(self):
        return [
            {"type": "tab", "name": "Queue", "custom_bindings": False}
        ]

    ##~~ SettingsPlugin mixin

    def get_settings_defaults(self):
        return {
            # put your plugin's default settings here
        }

    ##~~ AssetPlugin mixin

    def get_assets(self):
        # Define your plugin's asset files to automatically include in the
        # core UI here.
        return {
            "js": ["js/OctoQueue.js"],
            "css": ["css/OctoQueue.css"],
            "less": ["less/OctoQueue.less"]
        }

    ##~~ Softwareupdate hook

    def get_update_information(self):
        # Define the configuration for your plugin to use with the Software Update
        # Plugin here. See https://docs.octoprint.org/en/master/bundledplugins/softwareupdate.html
        # for details.
        return {
            "OctoQueue": {
                "displayName": "Octoqueue Plugin",
                "displayVersion": self._plugin_version,

                # version check: github repository
                "type": "github_release",
                "user": "JokerZB",
                "repo": "Octoprint Queue",
                "current": self._plugin_version,

                # update method: pip
                "pip": "https://github.com/JokerZB/Octoprint Queue/archive/{target_version}.zip",
            }
        }
    



# If you want your plugin to be registered within OctoPrint under a different name than what you defined in setup.py
# ("OctoPrint-PluginSkeleton"), you may define that here. Same goes for the other metadata derived from setup.py that
# can be overwritten via __plugin_xyz__ control properties. See the documentation for that.
__plugin_name__ = "Octoqueue Plugin"


# Set the Python version your plugin is compatible with below. Recommended is Python 3 only for all new plugins.
# OctoPrint 1.4.0 - 1.7.x run under both Python 3 and the end-of-life Python 2.
# OctoPrint 1.8.0 onwards only supports Python 3.
__plugin_pythoncompat__ = ">=3,<4"  # Only Python 3

def __plugin_load__():
    global __plugin_implementation__
    __plugin_implementation__ = OctoqueuePlugin()
    global __plugin_hooks__
    __plugin_hooks__ = {
        "octoprint.ui.tab": __plugin_implementation__.get_template_configs,
        "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
    }

The .jinja2 file is called tab.jinja2 and resides in the templates folder

Also, I just uploaded my entire folder to github, here's the link:
https://github.com/Dannick-Hoorn/OctoQueue/tree/main

delete this line

and then rename your jinja file to match the name of your plugin's identifier defined in setup.py like this: <plugin_identifier>_tab.jinja2

FYI solely based on the name of the plugin, I'd like to mention there is a couple of plugins that do queuing. Continuous Print and my Print Scheduler plugin both can do this.

Thanks so much, this is the solution!

Thanks I'll take a look at yours, i have tried Continuous Print already but it doesn't quite hit the mark for me :slight_smile:

Understood, there's also my other Playlist plugin but I don't really develop/support that one anymore because of the way it monkey patches the comm layer.