Load Jinja2 templates from Qt Resource System

315 views Asked by At

I'm trying to load some Jinja2 templates from the Qt Resource System. I'm using Python 3.8.3, Jinja 2.11.2 and PyQt 5.15.

The problem is that I can't even detect the qrc paths to load the templates. QRC only works with Qt classes?

Python code:

from jinja2 import Environment, FileSystemLoader

file_loader = FileSystemLoader(":/plantillas/")  # Here is my problem, how I should detect the qrc path?
env = Environment(loader=file_loader)
plantilla = env.get_template("base.md")

qrc:

<!DOCTYPE RCC>
<RCC version="1.0">
    <qresource prefix="plantillas">
        <file alias="base.md">plantillas/base.md</file>
    </qresource>
</RCC>
1

There are 1 answers

0
eyllanesc On BEST ANSWER

The QResource only works in the Qt world so a possible solution is to create a Loader using the Qt classes:

qloader.py

import os
from collections import abc

from jinja2.loaders import BaseLoader, split_template_path
from jinja2.exceptions import TemplateNotFound

from PyQt5.QtCore import QDir, QDirIterator, QFile, QFileInfo, QIODevice


class QFileSystemLoader(BaseLoader):
    def __init__(self, searchpath, encoding="utf-8", followlinks=False):
        if not isinstance(searchpath, abc.Iterable) or isinstance(searchpath, str):
            searchpath = [searchpath]

        self.searchpath = list(searchpath)
        self.encoding = encoding
        self.followlinks = followlinks

    def get_source(self, environment, template):
        pieces = split_template_path(template)
        for searchpath in self.searchpath:
            filename = os.path.join(searchpath, *pieces)

            f = QFile(filename)
            if not f.exists():
                continue
            if not f.open(QIODevice.ReadOnly):
                continue
            contents = f.readAll().data().decode(self.encoding)
            f.close()

            dt = QFileInfo(f).fileTime(QFile.FileModificationTime)

            def uptodate():
                return QFileInfo(filename).fileTime(QFile.FileModificationTime) == dt

            return contents, filename, uptodate
        raise TemplateNotFound(template)

    def list_templates(self):
        found = set()
        for searchpath in self.searchpath:
            d = QDir(searchpath)
            it_flag = QDirIterator.Subdirectories
            if self.followlinks:
                it_flag |= QDirIterator.FollowSymlinks
            it_filter = QDir.Files | QDir.NoDotAndDotDot | QDir.Hidden | QDir.Readable
            if not self.followlinks:
                it_filter |= QDir.NoSymLinks
            it = QDirIterator(searchpath, it_filter, it_flag)
            while it.hasNext():
                it.next()
                found.add(d.relativeFilePath(it.filePath()))
        return sorted(found)
from qloader import QFileSystemLoader


qfile_loader = QFileSystemLoader(":/plantillas/")
env = Environment(loader=qfile_loader)
plantilla = env.get_template("base.md")