diff --git a/CHANGELOG.md b/CHANGELOG.md index 21bb927..eb9cf8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [unreleased] + +### Breaking + +* blag does not use default fallback templates anymore and will return an error + if it is unable to find required templates, e.g. in `templates/`. + + Users upgrading from older versions can either run `blag quickstart` (don't + forget to backup your `config.ini` or copy the templates from blag's + resources (the resource path is shown in the error message). + + New users are not affected as `blag quickstart` will generate the needed + templates. + + ## [1.5.0] - 2023-04-16 * moved to pyproject.toml diff --git a/blag/blag.py b/blag/blag.py index 490348b..8ef4b9b 100644 --- a/blag/blag.py +++ b/blag/blag.py @@ -16,13 +16,13 @@ import sys from jinja2 import ( Environment, - ChoiceLoader, FileSystemLoader, - PackageLoader, Template, + TemplateNotFound, ) import feedgenerator +import blag from blag.markdown import markdown_factory, convert_markdown from blag.devserver import serve from blag.version import __VERSION__ @@ -185,15 +185,14 @@ def get_config(configfile: str) -> configparser.SectionProxy: def environment_factory( - template_dir: str | None = None, + template_dir: str, globals_: dict[str, object] | None = None, ) -> Environment: """Environment factory. - Creates a Jinja2 Environment with the default templates and - additional templates from `template_dir` loaded. If `globals` are - provided, they are attached to the environment and thus available to - all contexts. + Creates a Jinja2 Environment with the templates from `template_dir` loaded. + If `globals` are provided, they are attached to the environment and thus + available to all contexts. Parameters ---------- @@ -206,13 +205,7 @@ def environment_factory( jinja2.Environment """ - # first we try the custom templates, and fall back the ones provided - # by blag - loaders: list[FileSystemLoader | PackageLoader] = [] - if template_dir: - loaders.append(FileSystemLoader([template_dir])) - loaders.append(PackageLoader('blag', 'templates')) - env = Environment(loader=ChoiceLoader(loaders)) + env = Environment(loader=FileSystemLoader(template_dir)) if globals_: env.globals = globals_ return env @@ -261,11 +254,21 @@ def build(args: argparse.Namespace) -> None: env = environment_factory(args.template_dir, dict(site=config)) - page_template = env.get_template('page.html') - article_template = env.get_template('article.html') - archive_template = env.get_template('archive.html') - tags_template = env.get_template('tags.html') - tag_template = env.get_template('tag.html') + try: + page_template = env.get_template('page.html') + article_template = env.get_template('article.html') + archive_template = env.get_template('archive.html') + tags_template = env.get_template('tags.html') + tag_template = env.get_template('tag.html') + except TemplateNotFound as exc: + tmpl = os.path.join(blag.__path__[0], 'templates') + logger.error( + f'Template "{exc.name}" not found in {args.template_dir}! ' + 'Consider running `blag quickstart` or copying the ' + f'missing template from {tmpl}.' + ) + + sys.exit(1) articles, pages = process_markdown( convertibles, @@ -309,7 +312,7 @@ def process_markdown( input_dir output_dir page_template, archive_template - templats for pages and articles + templates for pages and articles Returns ------- diff --git a/blag/quickstart.py b/blag/quickstart.py index c27e473..aee73e1 100644 --- a/blag/quickstart.py +++ b/blag/quickstart.py @@ -6,6 +6,10 @@ from __future__ import annotations import configparser import argparse +import shutil +import os + +import blag def get_input(question: str, default: str) -> str: @@ -33,6 +37,22 @@ def get_input(question: str, default: str) -> str: return reply +def copy_templates() -> None: + """Copy templates into current directory. + + It will not overwrite existing files. + + """ + print("Copying templates...") + try: + shutil.copytree( + os.path.join(blag.__path__[0], 'templates'), + 'templates', + ) + except FileExistsError: + print("Templates already exist. Skipping.") + + def quickstart(args: argparse.Namespace | None) -> None: """Quickstart. @@ -71,3 +91,5 @@ def quickstart(args: argparse.Namespace | None) -> None: } with open('config.ini', 'w') as fh: config.write(fh) + + copy_templates() diff --git a/docs/blag.rst b/docs/blag.rst index b00450e..2c7ac0c 100644 --- a/docs/blag.rst +++ b/docs/blag.rst @@ -13,7 +13,7 @@ Install blag from PyPI_ .. _pypi: https://pypi.org/project/blag/ -Run blag's quickstart command to create the configuration needed +Run blag's quickstart command to create the configuration and templates needed .. code-block:: sh @@ -40,8 +40,8 @@ If you want more separation between the static files and the markdown content, you can put all static files into the ``static`` directory. Blag will copy them over to the ``build`` directory. -If you want to customize the looks of the generated site, create a -``template`` directory and put your jinja2 templates here. +If you want to customize the look of the generated site, visit the ``template`` +directory. It contains jinja2 templates and can be modified as needed. Those directories can be changed via command line arguments. See @@ -186,9 +186,7 @@ becomes Templating ---------- -Custom templates are **optional** and stored by default in the ``templates`` -directory. blag will search the ``templates`` directory first, and fall back -to blag's default built-in templates. +Templates are stored by default in the ``templates`` directory. ============ ====================================== =================== Template Used For Variables diff --git a/tests/conftest.py b/tests/conftest.py index da40e05..4f49918 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,18 +8,18 @@ import os import pytest from jinja2 import Environment, Template -from blag import blag +from blag import blag, quickstart @pytest.fixture -def environment() -> Iterator[Environment]: +def environment(cleandir: str) -> Iterator[Environment]: site = { 'base_url': 'site base_url', 'title': 'site title', 'description': 'site description', 'author': 'site author', } - env = blag.environment_factory(globals_=dict(site=site)) + env = blag.environment_factory('templates', globals_=dict(site=site)) yield env @@ -50,7 +50,7 @@ def tag_template(environment: Environment) -> Iterator[Template]: @pytest.fixture def cleandir() -> Iterator[str]: - """Create a temporary workind directory and cwd.""" + """Create a temporary working directory and cwd.""" config = """ [main] base_url = https://example.com/ @@ -60,13 +60,14 @@ author = a. u. thor """ with TemporaryDirectory() as dir: - for d in 'content', 'build', 'static', 'templates': + for d in 'content', 'build', 'static': os.mkdir(f'{dir}/{d}') with open(f'{dir}/config.ini', 'w') as fh: fh.write(config) # change directory old_cwd = os.getcwd() os.chdir(dir) + quickstart.copy_templates() yield dir # and change back afterwards os.chdir(old_cwd) diff --git a/tests/test_blag.py b/tests/test_blag.py index 74e8512..56cd153 100644 --- a/tests/test_blag.py +++ b/tests/test_blag.py @@ -179,9 +179,9 @@ author = a. u. thor assert config_parsed['base_url'] == 'https://example.com/' -def test_environment_factory() -> None: +def test_environment_factory(cleandir: str) -> None: globals_: dict[str, object] = {'foo': 'bar', 'test': 'me'} - env = blag.environment_factory(globals_=globals_) + env = blag.environment_factory("templates", globals_=globals_) assert env.globals['foo'] == 'bar' assert env.globals['test'] == 'me' @@ -299,6 +299,22 @@ foo bar assert os.path.exists(f'{args.output_dir}/tags/bar.html') +@pytest.mark.parametrize( + 'template', + [ + 'page.html', + 'article.html', + 'archive.html', + 'tags.html', + 'tag.html', + ] +) +def test_missing_template_raises(template: str, args: Namespace) -> None: + os.remove(f'templates/{template}') + with pytest.raises(SystemExit): + blag.build(args) + + def test_main(cleandir: str) -> None: blag.main(['build'])