0

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>
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Eduardo
  • 687
  • 1
  • 6
  • 24

1 Answers1

1

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")
eyllanesc
  • 235,170
  • 19
  • 170
  • 241