Source code for evariste.plugins.renderer.jinja2.readme

# Copyright Louis Paternault 2015-2022
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Common utilities for readme renderers using Jinja2.

.. autoclass:: Jinja2ReadmeRenderer
   :members:

"""

# Can be removed starting with python3.11
from __future__ import annotations

import glob
import os
import pathlib
import typing

from ... import Plugin

if typing.TYPE_CHECKING:
    from ....tree import Tree


[docs] class Jinja2ReadmeRenderer(Plugin): """Default readme renderer using jinja2. This is an abstract class that defines a default README renderer for files. From within a template, the `macro <https://jinja.palletsprojects.com/en/3.0.x/templates/#macros>`__ ``render_readme`` can be called to annotate a file, which: - looks for the first plugin that matches this file (that is, the first plugin where :meth:`Jinja2ReadmeRenderer.match` returns ``True``); - calls :meth:`Jinja2ReadmeRenderer.render`, and returns its return value. To implement such a renderer, in a subclass: - do one of: - set :attr:`Jinja2ReadmeRenderer.extensions` as a list of extensions: the README of any file ``foo`` is ``foo.{ext}``, the README of any directory is ``directory/README.{ext}``, where ``ext`` is one of the extensions listed here. - implement :meth:`Jinja2ReadmeRenderer.render`; - (optional) implement :meth:`Jinja2ReadmeRenderer.match` and :meth:`Jinja2ReadmeRenderer.get_readme` if the default implementation does not please you. """ # pylint: disable=too-few-public-methods, abstract-method #: List of extensions of the READMEs (see :class:`Jinja2ReadmeRenderer`). extensions: list[str] = []
[docs] def match(self, tree: Tree) -> bool: """Return ``True`` if this plugin can handle the README of the argument.""" # pylint: disable=arguments-renamed return self.get_readme(tree) is not None
[docs] def get_readme(self, tree: Tree) -> Tree | None: """Return readme file for ``tree``, or ``None`` if there is no such README file.""" if tree.is_dir(): return self._get_readme_dir(tree) return self._get_readme_file(tree)
def _get_readme_dir(self, tree): """Iterate over potential readme for the given directory ``tree``.""" for ext in self.extensions: for filename in glob.iglob((tree.from_fs / f"*.{ext}").as_posix()): basename = os.path.basename(filename) if not tree.find(basename): continue if basename.count(".") == 1: if basename.split(".")[0].lower() == "readme": return tree.root.find( pathlib.Path(filename).relative_to(tree.root.from_fs) ) return None def _get_readme_file(self, tree): """Iterate over potential readme for the given file ``tree``.""" for ext in self.extensions: for filename in glob.iglob(f"{tree.from_fs}.{ext}"): readme = tree.root.find( pathlib.Path(filename).relative_to(tree.root.from_fs) ) if readme: return readme return None
[docs] @staticmethod def render(tree: Tree) -> str: """Render argument as README. Return a string to be included when rendering the template. The functions and variables available in the template are described in :ref:`plugin_renderer_jinja2`. """ # pylint: disable=unused-argument with open(tree.from_fs, encoding="utf8") as source: return source.read()