From ad0ab1a0feee702c3dbfe3322c576736fbef7641 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 8 Aug 2022 14:09:45 +0000
Subject: [PATCH 001/123] Bump flake8 from 5.0.2 to 5.0.4
Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.2 to 5.0.4.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/5.0.2...5.0.4)
---
updated-dependencies:
- dependency-name: flake8
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 1292db9..7d6b6ab 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,4 +3,4 @@ twine==4.0.1
wheel==0.37.1
pytest==7.1.2
pytest-cov==3.0.0
-flake8==5.0.2
+flake8==5.0.4
From f8cd915ac23bf4a9f59f782812b4ad071aeff605 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 22 Aug 2022 14:09:03 +0000
Subject: [PATCH 002/123] Bump pygments from 2.12.0 to 2.13.0
Bumps [pygments](https://github.com/pygments/pygments) from 2.12.0 to 2.13.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.12.0...2.13.0)
---
updated-dependencies:
- dependency-name: pygments
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index c964cc4..58367ba 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
markdown==3.4.1
feedgenerator==2.0.0
jinja2==3.1.2
-pygments==2.12.0
+pygments==2.13.0
From 322154041ad6ac48d26e409512445993c59fd452 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 17:17:02 +0200
Subject: [PATCH 003/123] WIP
---
Makefile | 4 +++
blag/blag.py | 83 ++++++++++++++++++++++++++++----------------
blag/devserver.py | 13 +++----
blag/markdown.py | 17 +++++----
blag/quickstart.py | 5 +--
requirements-dev.txt | 2 ++
setup.cfg | 6 ++++
7 files changed, 87 insertions(+), 43 deletions(-)
diff --git a/Makefile b/Makefile
index d973043..3199902 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,10 @@ $(VENV): requirements.txt requirements-dev.txt setup.py
test: $(VENV)
$(BIN)/pytest
+.PHONY: mypy
+mypy: $(VENV)
+ $(BIN)/mypy
+
.PHONY: lint
lint: $(VENV)
$(BIN)/flake8
diff --git a/blag/blag.py b/blag/blag.py
index e84bc2b..bf70e3d 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -11,7 +11,13 @@ import logging
import configparser
import sys
-from jinja2 import Environment, ChoiceLoader, FileSystemLoader, PackageLoader
+from jinja2 import (
+ Environment,
+ ChoiceLoader,
+ FileSystemLoader,
+ PackageLoader,
+ Template,
+)
import feedgenerator
from blag.markdown import markdown_factory, convert_markdown
@@ -26,7 +32,7 @@ logging.basicConfig(
)
-def main(args=None):
+def main(arguments: list[str] = None) -> None:
"""Main entrypoint for the CLI.
This method parses the CLI arguments and executes the respective
@@ -34,11 +40,11 @@ def main(args=None):
Parameters
----------
- args : list[str]
+ arguments : list[str]
optional parameters, used for testing
"""
- args = parse_args(args)
+ args = parse_args(arguments)
# set loglevel
if args.verbose:
logger.setLevel(logging.DEBUG)
@@ -46,7 +52,7 @@ def main(args=None):
args.func(args)
-def parse_args(args=None):
+def parse_args(args: list[str] = None) -> argparse.Namespace:
"""Parse command line arguments.
Parameters
@@ -135,7 +141,7 @@ def parse_args(args=None):
return parser.parse_args(args)
-def get_config(configfile):
+def get_config(configfile: str) -> configparser.SectionProxy:
"""Load site configuration from configfile.
Parameters
@@ -146,7 +152,7 @@ def get_config(configfile):
Returns
-------
- dict
+ configparser.SectionProxy
"""
config = configparser.ConfigParser()
@@ -166,7 +172,10 @@ def get_config(configfile):
return config['main']
-def environment_factory(template_dir=None, globals_=None):
+def environment_factory(
+ template_dir: str = None,
+ globals_: dict = None,
+) -> Environment:
"""Environment factory.
Creates a Jinja2 Environment with the default templates and
@@ -186,7 +195,7 @@ def environment_factory(template_dir=None, globals_=None):
"""
# first we try the custom templates, and fall back the ones provided
# by blag
- loaders = []
+ loaders: list[FileSystemLoader | PackageLoader] = []
if template_dir:
loaders.append(FileSystemLoader([template_dir]))
loaders.append(PackageLoader('blag', 'templates'))
@@ -196,7 +205,7 @@ def environment_factory(template_dir=None, globals_=None):
return env
-def build(args):
+def build(args: argparse.Namespace) -> None:
"""Build the site.
This is blag's main method that builds the site, generates the feed
@@ -261,8 +270,13 @@ def build(args):
generate_tags(articles, tags_template, tag_template, args.output_dir)
-def process_markdown(convertibles, input_dir, output_dir,
- page_template, article_template):
+def process_markdown(
+ convertibles: list[tuple[str, str]],
+ input_dir: str,
+ output_dir: str,
+ page_template: Template,
+ article_template: Template,
+) -> tuple[list[tuple[str, dict]], list[tuple[str, dict]]]:
"""Process markdown files.
This method processes the convertibles, converts them to html and
@@ -273,7 +287,7 @@ def process_markdown(convertibles, input_dir, output_dir,
Parameters
----------
- convertibles : List[Tuple[str, str]]
+ convertibles : list[tuple[str, str]]
relative paths to markdown- (src) html- (dest) files
input_dir : str
output_dir : str
@@ -282,7 +296,7 @@ def process_markdown(convertibles, input_dir, output_dir,
Returns
-------
- articles, pages : List[Tuple[str, Dict]]
+ articles, pages : list[tuple[str, dict]]
"""
logger.info("Converting Markdown files...")
@@ -318,18 +332,18 @@ def process_markdown(convertibles, input_dir, output_dir,
def generate_feed(
- articles,
- output_dir,
- base_url,
- blog_title,
- blog_description,
- blog_author,
-):
+ articles: list[tuple[str, dict]],
+ output_dir: str,
+ base_url: str,
+ blog_title: str,
+ blog_description: str,
+ blog_author: str,
+) -> None:
"""Generate Atom feed.
Parameters
----------
- articles : list[list[str, dict]]
+ articles : list[tuple[str, dict]]
list of relative output path and article dictionary
output_dir : str
where the feed is stored
@@ -369,12 +383,16 @@ def generate_feed(
feed.write(fh, encoding='utf8')
-def generate_archive(articles, template, output_dir):
+def generate_archive(
+ articles: list[tuple[str, dict]],
+ template: Template,
+ output_dir: str,
+) -> None:
"""Generate the archive page.
Parameters
----------
- articles : list[list[str, dict]]
+ articles : list[tuple[str, dict]]
List of articles. Each article has the destination path and a
dictionary with the content.
template : jinja2.Template instance
@@ -392,12 +410,17 @@ def generate_archive(articles, template, output_dir):
fh.write(result)
-def generate_tags(articles, tags_template, tag_template, output_dir):
+def generate_tags(
+ articles: list[tuple[str, dict]],
+ tags_template: Template,
+ tag_template: Template,
+ output_dir: str,
+) -> None:
"""Generate the tags page.
Parameters
----------
- articles : list[list[str, dict]]
+ articles : list[tuple[str, dict]]
List of articles. Each article has the destination path and a
dictionary with the content.
tags_template, tag_template : jinja2.Template instance
@@ -408,15 +431,17 @@ def generate_tags(articles, tags_template, tag_template, output_dir):
os.makedirs(f'{output_dir}/tags', exist_ok=True)
# get tags number of occurrences
- all_tags = {}
+ all_tags: dict = {}
for _, context in articles:
tags = context.get('tags', [])
for tag in tags:
all_tags[tag] = all_tags.get(tag, 0) + 1
# sort by occurrence
- all_tags = sorted(all_tags.items(), key=lambda x: x[1], reverse=True)
+ taglist: list[tuple[str, int]] = sorted(
+ all_tags.items(), key=lambda x: x[1], reverse=True
+ )
- result = tags_template.render(dict(tags=all_tags))
+ result = tags_template.render(dict(tags=taglist))
with open(f'{output_dir}/tags/index.html', 'w') as fh:
fh.write(result)
diff --git a/blag/devserver.py b/blag/devserver.py
index dbc7386..c49cdfe 100644
--- a/blag/devserver.py
+++ b/blag/devserver.py
@@ -12,6 +12,7 @@ import time
import multiprocessing
from http.server import SimpleHTTPRequestHandler, HTTPServer
from functools import partial
+import argparse
from blag import blag
@@ -19,7 +20,7 @@ from blag import blag
logger = logging.getLogger(__name__)
-def get_last_modified(dirs):
+def get_last_modified(dirs: list[str]) -> float:
"""Get the last modified time.
This method recursively goes through `dirs` and returns the most
@@ -32,11 +33,11 @@ def get_last_modified(dirs):
Returns
-------
- int
+ float
most recent modification time found in `dirs`
"""
- last_mtime = 0
+ last_mtime = 0.0
for dir in dirs:
for root, dirs, files in os.walk(dir):
@@ -48,7 +49,7 @@ def get_last_modified(dirs):
return last_mtime
-def autoreload(args):
+def autoreload(args: argparse.Namespace) -> None:
"""Start the autoreloader.
This method monitors the given directories for changes (i.e. the
@@ -67,7 +68,7 @@ def autoreload(args):
logger.info(f'Monitoring {dirs} for changes...')
# make sure we trigger the rebuild immediately when we enter the
# loop to avoid serving stale contents
- last_mtime = 0
+ last_mtime = 0.0
while True:
mtime = get_last_modified(dirs)
if mtime > last_mtime:
@@ -77,7 +78,7 @@ def autoreload(args):
time.sleep(1)
-def serve(args):
+def serve(args: argparse.Namespace) -> None:
"""Start the webserver and the autoreloader.
Parameters
diff --git a/blag/markdown.py b/blag/markdown.py
index 328b0d0..640bb3b 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -8,6 +8,7 @@ processing.
from datetime import datetime
import logging
from urllib.parse import urlsplit, urlunsplit
+from xml.etree.ElementTree import Element
from markdown import Markdown
from markdown.extensions import Extension
@@ -17,7 +18,7 @@ from markdown.treeprocessors import Treeprocessor
logger = logging.getLogger(__name__)
-def markdown_factory():
+def markdown_factory() -> Markdown:
"""Create a Markdown instance.
This method exists only to ensure we use the same Markdown instance
@@ -33,12 +34,12 @@ def markdown_factory():
'meta', 'fenced_code', 'codehilite', 'smarty',
MarkdownLinkExtension()
],
- output_format='html5',
+ output_format='html',
)
return md
-def convert_markdown(md, markdown):
+def convert_markdown(md: Markdown, markdown: str) -> tuple[str, dict]:
"""Convert markdown into html and extract meta data.
Some meta data is treated special:
@@ -87,15 +88,19 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
"""
- def run(self, root):
+ def run(self, root: Element):
for element in root.iter():
if element.tag == 'a':
url = element.get('href')
+ # element.get could also return None, we haven't seen this so
+ # far, so lets wait if we raise this
+ assert url is not None
+ url = str(url)
converted = self.convert(url)
element.set('href', converted)
return root
- def convert(self, url):
+ def convert(self, url: str):
scheme, netloc, path, query, fragment = urlsplit(url)
logger.debug(
f'{url}: {scheme=} {netloc=} {path=} {query=} {fragment=}'
@@ -113,7 +118,7 @@ class MarkdownLinkExtension(Extension):
"""markdown.extension that converts relative .md- to .html-links.
"""
- def extendMarkdown(self, md):
+ def extendMarkdown(self, md: Markdown):
md.treeprocessors.register(
MarkdownLinkTreeprocessor(md), 'mdlink', 0,
)
diff --git a/blag/quickstart.py b/blag/quickstart.py
index 00b4725..7bffc2c 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -3,9 +3,10 @@
"""
import configparser
+import argparse
-def get_input(question, default):
+def get_input(question: str, default: str) -> str:
"""Prompt for user input.
This is a wrapper around the input-builtin. It will show the default answer
@@ -29,7 +30,7 @@ def get_input(question, default):
return reply
-def quickstart(args):
+def quickstart(args: argparse.Namespace) -> None:
"""Quickstart.
This method asks the user some questions and generates a
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 1292db9..fd43f91 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -4,3 +4,5 @@ wheel==0.37.1
pytest==7.1.2
pytest-cov==3.0.0
flake8==5.0.2
+mypy==0.971
+types-markdown==3.4.1
diff --git a/setup.cfg b/setup.cfg
index 681fad8..71030af 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -7,3 +7,9 @@ addopts =
[flake8]
exclude = venv,build,docs
+
+[mypy]
+files = blag,tests
+
+[mypy-feedgenerator.*]
+ignore_missing_imports = True
From 451fb1b2609fb0099b475ef74787786f158151b1 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 19:54:32 +0200
Subject: [PATCH 004/123] try supporting py38
---
blag/blag.py | 2 ++
blag/devserver.py | 2 ++
blag/markdown.py | 2 ++
blag/quickstart.py | 2 ++
4 files changed, 8 insertions(+)
diff --git a/blag/blag.py b/blag/blag.py
index bf70e3d..f1c1b1a 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -4,6 +4,8 @@
"""
+# remove when we don't support py38 anymore
+from __future__ import annotations
import argparse
import os
import shutil
diff --git a/blag/devserver.py b/blag/devserver.py
index c49cdfe..1f2a8be 100644
--- a/blag/devserver.py
+++ b/blag/devserver.py
@@ -6,6 +6,8 @@ site if necessary.
"""
+# remove when we don't support py38 anymore
+from __future__ import annotations
import os
import logging
import time
diff --git a/blag/markdown.py b/blag/markdown.py
index 640bb3b..b71df4b 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -5,6 +5,8 @@ processing.
"""
+# remove when we don't support py38 anymore
+from __future__ import annotations
from datetime import datetime
import logging
from urllib.parse import urlsplit, urlunsplit
diff --git a/blag/quickstart.py b/blag/quickstart.py
index 7bffc2c..dc82380 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -2,6 +2,8 @@
"""
+# remove when we don't support py38 anymore
+from __future__ import annotations
import configparser
import argparse
From 10f84ebb160521237a15e5fdea59829cae57366e Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 22:57:02 +0200
Subject: [PATCH 005/123] added mypy to github action
---
.github/workflows/python-package.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index fdccf0d..cb0b346 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -36,3 +36,7 @@ jobs:
- name: Run linter
run: |
make lint
+
+ - name: Run mypy
+ run: |
+ make mypy
From 2adc7b3bd4d51cba9b3946267fc4cc1d3c85e011 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 22:57:30 +0200
Subject: [PATCH 006/123] added mypy to all target
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 3199902..87cec44 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ endif
.PHONY: all
-all: lint test
+all: lint mypy test
$(VENV): requirements.txt requirements-dev.txt setup.py
$(PY) -m venv $(VENV)
From ebac0a8fc4ba07bdf07e3e7be7d45d69e8cca0de Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 22:59:55 +0200
Subject: [PATCH 007/123] fixed for mypy --strict testing
---
blag/__init__.py | 2 +-
blag/blag.py | 40 +++++++++++++-------------
blag/markdown.py | 15 ++++++----
blag/quickstart.py | 2 +-
setup.cfg | 1 +
tests/conftest.py | 26 ++++++++---------
tests/test_blag.py | 62 ++++++++++++++++++++++------------------
tests/test_devserver.py | 7 +++--
tests/test_markdown.py | 13 +++++----
tests/test_quickstart.py | 8 ++++--
tests/test_templates.py | 12 ++++----
tests/test_version.py | 2 +-
12 files changed, 102 insertions(+), 88 deletions(-)
diff --git a/blag/__init__.py b/blag/__init__.py
index 6527216..318e4f3 100644
--- a/blag/__init__.py
+++ b/blag/__init__.py
@@ -1 +1 @@
-from blag.version import __VERSION__ # noqa
+from blag.version import __VERSION__ as __VERSION__ # noqa
diff --git a/blag/blag.py b/blag/blag.py
index f1c1b1a..8a9ce81 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -6,6 +6,7 @@
# remove when we don't support py38 anymore
from __future__ import annotations
+from typing import Any
import argparse
import os
import shutil
@@ -34,7 +35,7 @@ logging.basicConfig(
)
-def main(arguments: list[str] = None) -> None:
+def main(arguments: list[str] | None = None) -> None:
"""Main entrypoint for the CLI.
This method parses the CLI arguments and executes the respective
@@ -54,7 +55,7 @@ def main(arguments: list[str] = None) -> None:
args.func(args)
-def parse_args(args: list[str] = None) -> argparse.Namespace:
+def parse_args(args: list[str] | None = None) -> argparse.Namespace:
"""Parse command line arguments.
Parameters
@@ -175,8 +176,8 @@ def get_config(configfile: str) -> configparser.SectionProxy:
def environment_factory(
- template_dir: str = None,
- globals_: dict = None,
+ template_dir: str | None = None,
+ globals_: dict[str, object] | None = None,
) -> Environment:
"""Environment factory.
@@ -188,7 +189,7 @@ def environment_factory(
Parameters
----------
template_dir : str
- globals_ : dict
+ globals_ : dict[str, object]
Returns
-------
@@ -278,7 +279,7 @@ def process_markdown(
output_dir: str,
page_template: Template,
article_template: Template,
-) -> tuple[list[tuple[str, dict]], list[tuple[str, dict]]]:
+) -> tuple[list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str, Any]]]]:
"""Process markdown files.
This method processes the convertibles, converts them to html and
@@ -298,7 +299,7 @@ def process_markdown(
Returns
-------
- articles, pages : list[tuple[str, dict]]
+ articles, pages : list[tuple[str, dict[str, Any]]]
"""
logger.info("Converting Markdown files...")
@@ -334,7 +335,7 @@ def process_markdown(
def generate_feed(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
output_dir: str,
base_url: str,
blog_title: str,
@@ -345,7 +346,7 @@ def generate_feed(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
list of relative output path and article dictionary
output_dir : str
where the feed is stored
@@ -386,7 +387,7 @@ def generate_feed(
def generate_archive(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
template: Template,
output_dir: str,
) -> None:
@@ -394,7 +395,7 @@ def generate_archive(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
List of articles. Each article has the destination path and a
dictionary with the content.
template : jinja2.Template instance
@@ -413,7 +414,7 @@ def generate_archive(
def generate_tags(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
tags_template: Template,
tag_template: Template,
output_dir: str,
@@ -422,7 +423,7 @@ def generate_tags(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
List of articles. Each article has the destination path and a
dictionary with the content.
tags_template, tag_template : jinja2.Template instance
@@ -431,11 +432,10 @@ def generate_tags(
"""
logger.info("Generating Tag-pages.")
os.makedirs(f'{output_dir}/tags', exist_ok=True)
-
# get tags number of occurrences
- all_tags: dict = {}
+ all_tags: dict[str, int] = {}
for _, context in articles:
- tags = context.get('tags', [])
+ tags: list[str] = context.get('tags', [])
for tag in tags:
all_tags[tag] = all_tags.get(tag, 0) + 1
# sort by occurrence
@@ -448,17 +448,17 @@ def generate_tags(
fh.write(result)
# get tags and archive per tag
- all_tags = {}
+ all_tags2: dict[str, list[dict[str, Any]]] = {}
for dst, context in articles:
tags = context.get('tags', [])
for tag in tags:
- archive = all_tags.get(tag, [])
+ archive: list[dict[str, Any]] = all_tags2.get(tag, [])
entry = context.copy()
entry['dst'] = dst
archive.append(entry)
- all_tags[tag] = archive
+ all_tags2[tag] = archive
- for tag, archive in all_tags.items():
+ for tag, archive in all_tags2.items():
result = tag_template.render(dict(archive=archive, tag=tag))
with open(f'{output_dir}/tags/{tag}.html', 'w') as fh:
fh.write(result)
diff --git a/blag/markdown.py b/blag/markdown.py
index b71df4b..efe0926 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -41,7 +41,10 @@ def markdown_factory() -> Markdown:
return md
-def convert_markdown(md: Markdown, markdown: str) -> tuple[str, dict]:
+def convert_markdown(
+ md: Markdown,
+ markdown: str,
+) -> tuple[str, dict[str, str]]:
"""Convert markdown into html and extract meta data.
Some meta data is treated special:
@@ -56,13 +59,13 @@ def convert_markdown(md: Markdown, markdown: str) -> tuple[str, dict]:
Returns
-------
- str, dict :
+ str, dict[str, str] :
html and metadata
"""
md.reset()
content = md.convert(markdown)
- meta = md.Meta
+ meta = md.Meta # type: ignore
# markdowns metadata consists as list of strings -- one item per
# line. let's convert into single strings.
@@ -90,7 +93,7 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
"""
- def run(self, root: Element):
+ def run(self, root: Element) -> Element:
for element in root.iter():
if element.tag == 'a':
url = element.get('href')
@@ -102,7 +105,7 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
element.set('href', converted)
return root
- def convert(self, url: str):
+ def convert(self, url: str) -> str:
scheme, netloc, path, query, fragment = urlsplit(url)
logger.debug(
f'{url}: {scheme=} {netloc=} {path=} {query=} {fragment=}'
@@ -120,7 +123,7 @@ class MarkdownLinkExtension(Extension):
"""markdown.extension that converts relative .md- to .html-links.
"""
- def extendMarkdown(self, md: Markdown):
+ def extendMarkdown(self, md: Markdown) -> None:
md.treeprocessors.register(
MarkdownLinkTreeprocessor(md), 'mdlink', 0,
)
diff --git a/blag/quickstart.py b/blag/quickstart.py
index dc82380..cbdcaac 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -32,7 +32,7 @@ def get_input(question: str, default: str) -> str:
return reply
-def quickstart(args: argparse.Namespace) -> None:
+def quickstart(args: argparse.Namespace | None) -> None:
"""Quickstart.
This method asks the user some questions and generates a
diff --git a/setup.cfg b/setup.cfg
index 71030af..94d778c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,6 +10,7 @@ exclude = venv,build,docs
[mypy]
files = blag,tests
+strict = True
[mypy-feedgenerator.*]
ignore_missing_imports = True
diff --git a/tests/conftest.py b/tests/conftest.py
index 221078c..f774841 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,13 +1,16 @@
+from argparse import Namespace
+from typing import Iterator, Callable
from tempfile import TemporaryDirectory
import os
import pytest
+from jinja2 import Environment, Template
from blag import blag
@pytest.fixture
-def environment():
+def environment() -> Iterator[Environment]:
site = {
'base_url': 'site base_url',
'title': 'site title',
@@ -19,32 +22,32 @@ def environment():
@pytest.fixture
-def page_template(environment):
+def page_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('page.html')
@pytest.fixture
-def article_template(environment):
+def article_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('article.html')
@pytest.fixture
-def archive_template(environment):
+def archive_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('archive.html')
@pytest.fixture
-def tags_template(environment):
+def tags_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('tags.html')
@pytest.fixture
-def tag_template(environment):
+def tag_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('tag.html')
@pytest.fixture
-def cleandir():
+def cleandir() -> Iterator[str]:
"""Create a temporary workind directory and cwd.
"""
@@ -70,14 +73,9 @@ author = a. u. thor
@pytest.fixture
-def args(cleandir):
+def args(cleandir: Callable[[], Iterator[str]]) -> Iterator[Namespace]:
- class NameSpace:
- def __init__(self, **kwargs):
- for name in kwargs:
- setattr(self, name, kwargs[name])
-
- args = NameSpace(
+ args = Namespace(
input_dir='content',
output_dir='build',
static_dir='static',
diff --git a/tests/test_blag.py b/tests/test_blag.py
index eeafbae..d4f40ae 100644
--- a/tests/test_blag.py
+++ b/tests/test_blag.py
@@ -1,37 +1,41 @@
from tempfile import TemporaryDirectory
import os
from datetime import datetime
+from typing import Any
+from argparse import Namespace
import pytest
+from pytest import CaptureFixture, LogCaptureFixture
+from jinja2 import Template
+from blag import __VERSION__
from blag import blag
-def test_generate_feed(cleandir):
- articles = []
+def test_generate_feed(cleandir: str) -> None:
+ articles: list[tuple[str, dict[str, Any]]] = []
blag.generate_feed(articles, 'build', ' ', ' ', ' ', ' ')
assert os.path.exists('build/atom.xml')
-def test_feed(cleandir):
- articles = [
- [
+def test_feed(cleandir: str) -> None:
+ articles: list[tuple[str, dict[str, Any]]] = [
+ (
'dest1.html',
{
'title': 'title1',
'date': datetime(2019, 6, 6),
'content': 'content1',
}
- ],
- [
+ ),
+ (
'dest2.html',
{
'title': 'title2',
'date': datetime(1980, 5, 9),
'content': 'content2',
}
- ],
-
+ ),
]
blag.generate_feed(articles, 'build', 'https://example.com/',
@@ -60,10 +64,10 @@ def test_feed(cleandir):
assert ' None:
# if a description is provided, it will be used as the summary in
# the feed, otherwise we simply use the title of the article
- articles = [[
+ articles: list[tuple[str, dict[str, Any]]] = [(
'dest.html',
{
'title': 'title',
@@ -71,7 +75,7 @@ def test_generate_feed_with_description(cleandir):
'date': datetime(2019, 6, 6),
'content': 'content',
}
- ]]
+ )]
blag.generate_feed(articles, 'build', ' ', ' ', ' ', ' ')
with open('build/atom.xml') as fh:
@@ -83,7 +87,7 @@ def test_generate_feed_with_description(cleandir):
assert 'content' in feed
-def test_parse_args_build():
+def test_parse_args_build() -> None:
# test default args
args = blag.parse_args(['build'])
assert args.input_dir == 'content'
@@ -116,7 +120,7 @@ def test_parse_args_build():
assert args.static_dir == 'foo'
-def test_get_config():
+def test_get_config() -> None:
config = """
[main]
base_url = https://example.com/
@@ -166,8 +170,8 @@ author = a. u. thor
assert config_parsed['base_url'] == 'https://example.com/'
-def test_environment_factory():
- globals_ = {
+def test_environment_factory() -> None:
+ globals_: dict[str, object] = {
'foo': 'bar',
'test': 'me'
}
@@ -176,7 +180,11 @@ def test_environment_factory():
assert env.globals['test'] == 'me'
-def test_process_markdown(cleandir, page_template, article_template):
+def test_process_markdown(
+ cleandir: str,
+ page_template: Template,
+ article_template: Template,
+) -> None:
page1 = """\
title: some page
@@ -202,10 +210,9 @@ foo bar
convertibles = []
for i, txt in enumerate((page1, article1, article2)):
- i = str(i)
- with open(f'content/{i}', 'w') as fh:
+ with open(f'content/{str(i)}', 'w') as fh:
fh.write(txt)
- convertibles.append([i, i])
+ convertibles.append((str(i), str(i)))
articles, pages = blag.process_markdown(
convertibles,
@@ -230,7 +237,7 @@ foo bar
assert 'content' in context
-def test_build(args):
+def test_build(args: Namespace) -> None:
page1 = """\
title: some page
@@ -259,10 +266,9 @@ foo bar
# write some convertibles
convertibles = []
for i, txt in enumerate((page1, article1, article2)):
- i = str(i)
- with open(f'{args.input_dir}/{i}.md', 'w') as fh:
+ with open(f'{args.input_dir}/{str(i)}.md', 'w') as fh:
fh.write(txt)
- convertibles.append([i, i])
+ convertibles.append((str(i), str(i)))
# some static files
with open(f'{args.static_dir}/test', 'w') as fh:
@@ -291,21 +297,21 @@ foo bar
assert os.path.exists(f'{args.output_dir}/tags/bar.html')
-def test_main(cleandir):
+def test_main(cleandir: str) -> None:
blag.main(['build'])
-def test_cli_version(capsys):
+def test_cli_version(capsys: CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as ex:
blag.main(['--version'])
# normal system exit
assert ex.value.code == 0
# proper version reported
out, _ = capsys.readouterr()
- assert blag.__VERSION__ in out
+ assert __VERSION__ in out
-def test_cli_verbose(cleandir, caplog):
+def test_cli_verbose(cleandir: str, caplog: LogCaptureFixture) -> None:
blag.main(['build'])
assert 'DEBUG' not in caplog.text
diff --git a/tests/test_devserver.py b/tests/test_devserver.py
index 7f56a40..cdbb842 100644
--- a/tests/test_devserver.py
+++ b/tests/test_devserver.py
@@ -1,12 +1,13 @@
import time
import threading
+from argparse import Namespace
import pytest
from blag import devserver
-def test_get_last_modified(cleandir):
+def test_get_last_modified(cleandir: str) -> None:
# take initial time
t1 = devserver.get_last_modified(['content'])
@@ -24,7 +25,7 @@ def test_get_last_modified(cleandir):
assert t2 == t3
-def test_autoreload_builds_immediately(args):
+def test_autoreload_builds_immediately(args: Namespace) -> None:
# create a dummy file that can be build
with open('content/test.md', 'w') as fh:
fh.write('boo')
@@ -45,7 +46,7 @@ def test_autoreload_builds_immediately(args):
@pytest.mark.filterwarnings("ignore::pytest.PytestUnhandledThreadExceptionWarning") # noqa
-def test_autoreload(args):
+def test_autoreload(args: Namespace) -> None:
t = threading.Thread(target=devserver.autoreload,
args=(args, ),
daemon=True,)
diff --git a/tests/test_markdown.py b/tests/test_markdown.py
index 9103ec1..4cee8c2 100644
--- a/tests/test_markdown.py
+++ b/tests/test_markdown.py
@@ -1,4 +1,5 @@
from datetime import datetime
+from typing import Any
import pytest
import markdown
@@ -26,7 +27,7 @@ from blag.markdown import convert_markdown, markdown_factory
('[test][]\n[test]: /a/test.md', '/a/test.html'),
('[test][]\n[test]: /a/test.md "test"', '/a/test.html'),
])
-def test_convert_markdown_links(input_, expected):
+def test_convert_markdown_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
@@ -40,7 +41,7 @@ def test_convert_markdown_links(input_, expected):
# no path
('[test]()', ''),
])
-def test_dont_convert_normal_links(input_, expected):
+def test_dont_convert_normal_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
@@ -54,18 +55,18 @@ def test_dont_convert_normal_links(input_, expected):
('date: 2020-01-01 12:10', {'date':
datetime(2020, 1, 1, 12, 10).astimezone()}),
])
-def test_convert_metadata(input_, expected):
+def test_convert_metadata(input_: str, expected: dict[str, Any]) -> None:
md = markdown_factory()
_, meta = convert_markdown(md, input_)
assert expected == meta
-def test_markdown_factory():
+def test_markdown_factory() -> None:
md = markdown_factory()
assert isinstance(md, markdown.Markdown)
-def test_smarty():
+def test_smarty() -> None:
md = markdown_factory()
md1 = """
@@ -79,7 +80,7 @@ this --- is -- a test ...
assert 'hellip' in html
-def test_smarty_code():
+def test_smarty_code() -> None:
md = markdown_factory()
md1 = """
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index 4594497..ada2844 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -1,19 +1,21 @@
+from pytest import MonkeyPatch
+
from blag.quickstart import get_input, quickstart
-def test_get_input_default_answer(monkeypatch):
+def test_get_input_default_answer(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: '')
answer = get_input("foo", "bar")
assert answer == 'bar'
-def test_get_input(monkeypatch):
+def test_get_input(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: 'baz')
answer = get_input("foo", "bar")
assert answer == 'baz'
-def test_quickstart(cleandir, monkeypatch):
+def test_quickstart(cleandir: str, monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: 'foo')
quickstart(None)
with open('config.ini', 'r') as fh:
diff --git a/tests/test_templates.py b/tests/test_templates.py
index e420891..dc3395a 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -1,7 +1,9 @@
import datetime
+from jinja2 import Template
-def test_page(page_template):
+
+def test_page(page_template: Template) -> None:
ctx = {
'content': 'this is the content',
'title': 'this is the title',
@@ -11,7 +13,7 @@ def test_page(page_template):
assert 'this is the title' in result
-def test_article(article_template):
+def test_article(article_template: Template) -> None:
ctx = {
'content': 'this is the content',
'title': 'this is the title',
@@ -23,7 +25,7 @@ def test_article(article_template):
assert '1980-05-09' in result
-def test_archive(archive_template):
+def test_archive(archive_template: Template) -> None:
entry = {
'title': 'this is a title',
'dst': 'https://example.com/link',
@@ -41,7 +43,7 @@ def test_archive(archive_template):
assert 'https://example.com/link' in result
-def test_tags(tags_template):
+def test_tags(tags_template: Template) -> None:
tags = [('foo', 42)]
ctx = {
'tags': tags,
@@ -54,7 +56,7 @@ def test_tags(tags_template):
assert '42' in result
-def test_tag(tag_template):
+def test_tag(tag_template: Template) -> None:
entry = {
'title': 'this is a title',
'dst': 'https://example.com/link',
diff --git a/tests/test_version.py b/tests/test_version.py
index 04f8d9a..d978f67 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -1,5 +1,5 @@
import blag
-def test_version():
+def test_version() -> None:
assert isinstance(blag.__VERSION__, str)
From f59a6487796d3a5a42dcdc6e3e1f00c114aaa7c2 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 Aug 2022 23:04:30 +0200
Subject: [PATCH 008/123] import future annotations to make mypy work on py38
---
tests/conftest.py | 2 ++
tests/test_blag.py | 2 ++
tests/test_devserver.py | 2 ++
tests/test_markdown.py | 2 ++
tests/test_quickstart.py | 3 +++
tests/test_templates.py | 2 ++
tests/test_version.py | 3 +++
7 files changed, 16 insertions(+)
diff --git a/tests/conftest.py b/tests/conftest.py
index f774841..0b530e7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,5 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
from argparse import Namespace
from typing import Iterator, Callable
from tempfile import TemporaryDirectory
diff --git a/tests/test_blag.py b/tests/test_blag.py
index d4f40ae..cb200f4 100644
--- a/tests/test_blag.py
+++ b/tests/test_blag.py
@@ -1,3 +1,5 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
from tempfile import TemporaryDirectory
import os
from datetime import datetime
diff --git a/tests/test_devserver.py b/tests/test_devserver.py
index cdbb842..9699f91 100644
--- a/tests/test_devserver.py
+++ b/tests/test_devserver.py
@@ -1,3 +1,5 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
import time
import threading
from argparse import Namespace
diff --git a/tests/test_markdown.py b/tests/test_markdown.py
index 4cee8c2..670a4e1 100644
--- a/tests/test_markdown.py
+++ b/tests/test_markdown.py
@@ -1,3 +1,5 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
from datetime import datetime
from typing import Any
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index ada2844..ac6ccaf 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -1,3 +1,6 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
+
from pytest import MonkeyPatch
from blag.quickstart import get_input, quickstart
diff --git a/tests/test_templates.py b/tests/test_templates.py
index dc3395a..b25388e 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -1,3 +1,5 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
import datetime
from jinja2 import Template
diff --git a/tests/test_version.py b/tests/test_version.py
index d978f67..b772f4b 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -1,3 +1,6 @@
+# remove when we don't support py38 anymore
+from __future__ import annotations
+
import blag
From 875fd85d659fb10d978419ccad4c2584589f96f0 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 10:51:32 +0200
Subject: [PATCH 009/123] removed types from docstrings now that we have type
annotations.
note, the return value still needs to be in there.
---
blag/blag.py | 48 ++++++++++++++++++++++++----------------------
blag/devserver.py | 8 +++++---
blag/markdown.py | 8 +++++---
blag/quickstart.py | 8 +++++---
4 files changed, 40 insertions(+), 32 deletions(-)
diff --git a/blag/blag.py b/blag/blag.py
index 8a9ce81..60fdb33 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -43,7 +43,7 @@ def main(arguments: list[str] | None = None) -> None:
Parameters
----------
- arguments : list[str]
+ arguments
optional parameters, used for testing
"""
@@ -60,7 +60,7 @@ def parse_args(args: list[str] | None = None) -> argparse.Namespace:
Parameters
----------
- args : List[str]
+ args
optional parameters, used for testing
Returns
@@ -149,7 +149,7 @@ def get_config(configfile: str) -> configparser.SectionProxy:
Parameters
----------
- configfile : str
+ configfile
path to configuration file
@@ -188,8 +188,9 @@ def environment_factory(
Parameters
----------
- template_dir : str
- globals_ : dict[str, object]
+ template_dir
+ directory containing the templates
+ globals_
Returns
-------
@@ -216,7 +217,7 @@ def build(args: argparse.Namespace) -> None:
Parameters
----------
- args : argparse.Namespace
+ args
"""
os.makedirs(f'{args.output_dir}', exist_ok=True)
@@ -290,16 +291,17 @@ def process_markdown(
Parameters
----------
- convertibles : list[tuple[str, str]]
+ convertibles
relative paths to markdown- (src) html- (dest) files
- input_dir : str
- output_dir : str
- page_template, archive_template : jinja2 template
+ input_dir
+ output_dir
+ page_template, archive_template
templats for pages and articles
Returns
-------
- articles, pages : list[tuple[str, dict[str, Any]]]
+ list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str, Any]]]
+ articles and pages
"""
logger.info("Converting Markdown files...")
@@ -346,17 +348,17 @@ def generate_feed(
Parameters
----------
- articles : list[tuple[str, dict[str, Any]]]
+ articles
list of relative output path and article dictionary
- output_dir : str
+ output_dir
where the feed is stored
- base_url : str
+ base_url
base url
- blog_title : str
+ blog_title
blog title
- blog_description : str
+ blog_description
blog description
- blog_author : str
+ blog_author
blog author
"""
@@ -395,11 +397,11 @@ def generate_archive(
Parameters
----------
- articles : list[tuple[str, dict[str, Any]]]
+ articles
List of articles. Each article has the destination path and a
dictionary with the content.
- template : jinja2.Template instance
- output_dir : str
+ template
+ output_dir
"""
archive = []
@@ -423,11 +425,11 @@ def generate_tags(
Parameters
----------
- articles : list[tuple[str, dict[str, Any]]]
+ articles
List of articles. Each article has the destination path and a
dictionary with the content.
- tags_template, tag_template : jinja2.Template instance
- output_dir : str
+ tags_template, tag_template
+ output_dir
"""
logger.info("Generating Tag-pages.")
diff --git a/blag/devserver.py b/blag/devserver.py
index 1f2a8be..2c31046 100644
--- a/blag/devserver.py
+++ b/blag/devserver.py
@@ -30,7 +30,7 @@ def get_last_modified(dirs: list[str]) -> float:
Parameters
----------
- dirs : list[str]
+ dirs
list of directories to search
Returns
@@ -63,7 +63,8 @@ def autoreload(args: argparse.Namespace) -> None:
Parameters
----------
- args : argparse.Namespace
+ args
+ contains the input-, template- and static dir
"""
dirs = [args.input_dir, args.template_dir, args.static_dir]
@@ -85,7 +86,8 @@ def serve(args: argparse.Namespace) -> None:
Parameters
----------
- args : arparse.Namespace
+ args
+ contains the input-, template- and static dir
"""
httpd = HTTPServer(('', 8000), partial(SimpleHTTPRequestHandler,
diff --git a/blag/markdown.py b/blag/markdown.py
index efe0926..fa6d908 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -54,12 +54,14 @@ def convert_markdown(
Parameters
----------
- md : markdown.Markdown instance
- markdown : str
+ md
+ the Markdown instance
+ markdown
+ the markdown text that should be converted
Returns
-------
- str, dict[str, str] :
+ str, dict[str, str]
html and metadata
"""
diff --git a/blag/quickstart.py b/blag/quickstart.py
index cbdcaac..4f4678d 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -16,14 +16,15 @@ def get_input(question: str, default: str) -> str:
Parameters
----------
- question : str
+ question
the question the user is presented
- default : str
+ default
the default value that will be used if no answer was given
Returns
-------
str
+ the answer
"""
reply = input(f"{question} [{default}]: ")
@@ -40,7 +41,8 @@ def quickstart(args: argparse.Namespace | None) -> None:
Parameters
----------
- args : argparse.Namespace
+ args
+ not used
"""
base_url = get_input(
From 7b6b219cdf52b003f2d5d089927a02e3eb425571 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 11:11:53 +0200
Subject: [PATCH 010/123] mark autoreload as NoReturn
---
blag/devserver.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/blag/devserver.py b/blag/devserver.py
index 2c31046..42feac0 100644
--- a/blag/devserver.py
+++ b/blag/devserver.py
@@ -8,6 +8,7 @@ site if necessary.
# remove when we don't support py38 anymore
from __future__ import annotations
+from typing import NoReturn
import os
import logging
import time
@@ -51,7 +52,7 @@ def get_last_modified(dirs: list[str]) -> float:
return last_mtime
-def autoreload(args: argparse.Namespace) -> None:
+def autoreload(args: argparse.Namespace) -> NoReturn:
"""Start the autoreloader.
This method monitors the given directories for changes (i.e. the
From 87d619cc1c057e39c1a534840f4889a8eb0aa6c9 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 12:41:25 +0200
Subject: [PATCH 011/123] Re-formatted the code
---
blag/__init__.py | 2 +-
blag/blag.py | 99 +++++++++++++++++++++++------------------
blag/devserver.py | 6 ++-
blag/markdown.py | 20 +++++----
blag/quickstart.py | 8 ++--
tests/conftest.py | 12 +++--
tests/test_blag.py | 52 +++++++++++-----------
tests/test_devserver.py | 20 ++++++---
tests/test_markdown.py | 83 +++++++++++++++++++---------------
9 files changed, 167 insertions(+), 135 deletions(-)
diff --git a/blag/__init__.py b/blag/__init__.py
index 318e4f3..189ce64 100644
--- a/blag/__init__.py
+++ b/blag/__init__.py
@@ -1 +1 @@
-from blag.version import __VERSION__ as __VERSION__ # noqa
+from blag.version import __VERSION__ as __VERSION__ # noqa
diff --git a/blag/blag.py b/blag/blag.py
index 60fdb33..490348b 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -30,8 +30,8 @@ from blag.quickstart import quickstart
logger = logging.getLogger(__name__)
logging.basicConfig(
- level=logging.INFO,
- format='%(asctime)s %(levelname)s %(name)s %(message)s',
+ level=logging.INFO,
+ format='%(asctime)s %(levelname)s %(name)s %(message)s',
)
@@ -72,10 +72,11 @@ def parse_args(args: list[str] | None = None) -> argparse.Namespace:
parser.add_argument(
'--version',
action='version',
- version='%(prog)s '+__VERSION__,
+ version='%(prog)s ' + __VERSION__,
)
parser.add_argument(
- '-v', '--verbose',
+ '-v',
+ '--verbose',
action='store_true',
help='Verbose output.',
)
@@ -84,61 +85,69 @@ def parse_args(args: list[str] | None = None) -> argparse.Namespace:
commands.required = True
build_parser = commands.add_parser(
- 'build',
- help='Build website.',
+ 'build',
+ help='Build website.',
)
build_parser.set_defaults(func=build)
build_parser.add_argument(
- '-i', '--input-dir',
- default='content',
- help='Input directory (default: content)',
+ '-i',
+ '--input-dir',
+ default='content',
+ help='Input directory (default: content)',
)
build_parser.add_argument(
- '-o', '--output-dir',
- default='build',
- help='Ouptut directory (default: build)',
+ '-o',
+ '--output-dir',
+ default='build',
+ help='Ouptut directory (default: build)',
)
build_parser.add_argument(
- '-t', '--template-dir',
- default='templates',
- help='Template directory (default: templates)',
+ '-t',
+ '--template-dir',
+ default='templates',
+ help='Template directory (default: templates)',
)
build_parser.add_argument(
- '-s', '--static-dir',
- default='static',
- help='Static directory (default: static)',
+ '-s',
+ '--static-dir',
+ default='static',
+ help='Static directory (default: static)',
)
quickstart_parser = commands.add_parser(
- 'quickstart',
- help="Quickstart blag, creating necessary configuration.",
+ 'quickstart',
+ help="Quickstart blag, creating necessary configuration.",
)
quickstart_parser.set_defaults(func=quickstart)
serve_parser = commands.add_parser(
- 'serve',
- help="Start development server.",
+ 'serve',
+ help="Start development server.",
)
serve_parser.set_defaults(func=serve)
serve_parser.add_argument(
- '-i', '--input-dir',
- default='content',
- help='Input directory (default: content)',
+ '-i',
+ '--input-dir',
+ default='content',
+ help='Input directory (default: content)',
)
serve_parser.add_argument(
- '-o', '--output-dir',
- default='build',
- help='Ouptut directory (default: build)',
+ '-o',
+ '--output-dir',
+ default='build',
+ help='Ouptut directory (default: build)',
)
serve_parser.add_argument(
- '-t', '--template-dir',
- default='templates',
- help='Template directory (default: templates)',
+ '-t',
+ '--template-dir',
+ default='templates',
+ help='Template directory (default: templates)',
)
serve_parser.add_argument(
- '-s', '--static-dir',
- default='static',
- help='Static directory (default: static)',
+ '-s',
+ '--static-dir',
+ default='static',
+ help='Static directory (default: static)',
)
return parser.parse_args(args)
@@ -224,8 +233,9 @@ def build(args: argparse.Namespace) -> None:
convertibles = []
for root, dirnames, filenames in os.walk(args.input_dir):
for filename in filenames:
- rel_src = os.path.relpath(f'{root}/{filename}',
- start=args.input_dir)
+ rel_src = os.path.relpath(
+ f'{root}/{filename}', start=args.input_dir
+ )
# all non-markdown files are just copied over, the markdown
# files are converted to html
if rel_src.endswith('.md'):
@@ -233,8 +243,10 @@ def build(args: argparse.Namespace) -> None:
rel_dst = rel_dst[:-3] + '.html'
convertibles.append((rel_src, rel_dst))
else:
- shutil.copy(f'{args.input_dir}/{rel_src}',
- f'{args.output_dir}/{rel_src}')
+ shutil.copy(
+ f'{args.input_dir}/{rel_src}',
+ f'{args.output_dir}/{rel_src}',
+ )
for dirname in dirnames:
# all directories are copied into the output directory
path = os.path.relpath(f'{root}/{dirname}', start=args.input_dir)
@@ -264,7 +276,8 @@ def build(args: argparse.Namespace) -> None:
)
generate_feed(
- articles, args.output_dir,
+ articles,
+ args.output_dir,
base_url=config['base_url'],
blog_title=config['title'],
blog_description=config['description'],
@@ -364,10 +377,10 @@ def generate_feed(
"""
logger.info('Generating Atom feed.')
feed = feedgenerator.Atom1Feed(
- link=base_url,
- title=blog_title,
- description=blog_description,
- feed_url=base_url + 'atom.xml',
+ link=base_url,
+ title=blog_title,
+ description=blog_description,
+ feed_url=base_url + 'atom.xml',
)
for dst, context in articles:
diff --git a/blag/devserver.py b/blag/devserver.py
index 42feac0..a57ad71 100644
--- a/blag/devserver.py
+++ b/blag/devserver.py
@@ -91,8 +91,10 @@ def serve(args: argparse.Namespace) -> None:
contains the input-, template- and static dir
"""
- httpd = HTTPServer(('', 8000), partial(SimpleHTTPRequestHandler,
- directory=args.output_dir))
+ httpd = HTTPServer(
+ ('', 8000),
+ partial(SimpleHTTPRequestHandler, directory=args.output_dir),
+ )
proc = multiprocessing.Process(target=autoreload, args=(args,))
proc.start()
logger.info("\n\n Devserver Started -- visit http://localhost:8000\n")
diff --git a/blag/markdown.py b/blag/markdown.py
index fa6d908..6b055ed 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -33,8 +33,11 @@ def markdown_factory() -> Markdown:
"""
md = Markdown(
extensions=[
- 'meta', 'fenced_code', 'codehilite', 'smarty',
- MarkdownLinkExtension()
+ 'meta',
+ 'fenced_code',
+ 'codehilite',
+ 'smarty',
+ MarkdownLinkExtension(),
],
output_format='html',
)
@@ -91,9 +94,7 @@ def convert_markdown(
class MarkdownLinkTreeprocessor(Treeprocessor):
- """Converts relative links to .md files to .html
-
- """
+ """Converts relative links to .md files to .html"""
def run(self, root: Element) -> Element:
for element in root.iter():
@@ -112,7 +113,7 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
logger.debug(
f'{url}: {scheme=} {netloc=} {path=} {query=} {fragment=}'
)
- if (scheme or netloc or not path):
+ if scheme or netloc or not path:
return url
if path.endswith('.md'):
path = path[:-3] + '.html'
@@ -122,10 +123,11 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
class MarkdownLinkExtension(Extension):
- """markdown.extension that converts relative .md- to .html-links.
+ """markdown.extension that converts relative .md- to .html-links."""
- """
def extendMarkdown(self, md: Markdown) -> None:
md.treeprocessors.register(
- MarkdownLinkTreeprocessor(md), 'mdlink', 0,
+ MarkdownLinkTreeprocessor(md),
+ 'mdlink',
+ 0,
)
diff --git a/blag/quickstart.py b/blag/quickstart.py
index 4f4678d..c27e473 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -64,10 +64,10 @@ def quickstart(args: argparse.Namespace | None) -> None:
config = configparser.ConfigParser()
config['main'] = {
- 'base_url': base_url,
- 'title': title,
- 'description': description,
- 'author': author,
+ 'base_url': base_url,
+ 'title': title,
+ 'description': description,
+ 'author': author,
}
with open('config.ini', 'w') as fh:
config.write(fh)
diff --git a/tests/conftest.py b/tests/conftest.py
index 0b530e7..da40e05 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -50,9 +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 workind directory and cwd."""
config = """
[main]
base_url = https://example.com/
@@ -78,9 +76,9 @@ author = a. u. thor
def args(cleandir: Callable[[], Iterator[str]]) -> Iterator[Namespace]:
args = Namespace(
- input_dir='content',
- output_dir='build',
- static_dir='static',
- template_dir='templates',
+ input_dir='content',
+ output_dir='build',
+ static_dir='static',
+ template_dir='templates',
)
yield args
diff --git a/tests/test_blag.py b/tests/test_blag.py
index cb200f4..74e8512 100644
--- a/tests/test_blag.py
+++ b/tests/test_blag.py
@@ -28,7 +28,7 @@ def test_feed(cleandir: str) -> None:
'title': 'title1',
'date': datetime(2019, 6, 6),
'content': 'content1',
- }
+ },
),
(
'dest2.html',
@@ -36,12 +36,18 @@ def test_feed(cleandir: str) -> None:
'title': 'title2',
'date': datetime(1980, 5, 9),
'content': 'content2',
- }
+ },
),
]
- blag.generate_feed(articles, 'build', 'https://example.com/',
- 'blog title', 'blog description', 'blog author')
+ blag.generate_feed(
+ articles,
+ 'build',
+ 'https://example.com/',
+ 'blog title',
+ 'blog description',
+ 'blog author',
+ )
with open('build/atom.xml') as fh:
feed = fh.read()
@@ -69,15 +75,17 @@ def test_feed(cleandir: str) -> None:
def test_generate_feed_with_description(cleandir: str) -> None:
# if a description is provided, it will be used as the summary in
# the feed, otherwise we simply use the title of the article
- articles: list[tuple[str, dict[str, Any]]] = [(
- 'dest.html',
- {
- 'title': 'title',
- 'description': 'description',
- 'date': datetime(2019, 6, 6),
- 'content': 'content',
- }
- )]
+ articles: list[tuple[str, dict[str, Any]]] = [
+ (
+ 'dest.html',
+ {
+ 'title': 'title',
+ 'description': 'description',
+ 'date': datetime(2019, 6, 6),
+ 'content': 'content',
+ },
+ )
+ ]
blag.generate_feed(articles, 'build', ' ', ' ', ' ', ' ')
with open('build/atom.xml') as fh:
@@ -144,10 +152,9 @@ author = a. u. thor
# a missing required config causes a sys.exit
for x in 'base_url', 'title', 'description', 'author':
- config2 = '\n'.join([line
- for line
- in config.splitlines()
- if not line.startswith(x)])
+ config2 = '\n'.join(
+ [line for line in config.splitlines() if not line.startswith(x)]
+ )
with TemporaryDirectory() as dir:
configfile = f'{dir}/config.ini'
with open(configfile, 'w') as fh:
@@ -173,10 +180,7 @@ author = a. u. thor
def test_environment_factory() -> None:
- globals_: dict[str, object] = {
- 'foo': 'bar',
- 'test': 'me'
- }
+ globals_: dict[str, object] = {'foo': 'bar', 'test': 'me'}
env = blag.environment_factory(globals_=globals_)
assert env.globals['foo'] == 'bar'
assert env.globals['test'] == 'me'
@@ -217,11 +221,7 @@ foo bar
convertibles.append((str(i), str(i)))
articles, pages = blag.process_markdown(
- convertibles,
- 'content',
- 'build',
- page_template,
- article_template
+ convertibles, 'content', 'build', page_template, article_template
)
assert isinstance(articles, list)
diff --git a/tests/test_devserver.py b/tests/test_devserver.py
index 9699f91..4b66b38 100644
--- a/tests/test_devserver.py
+++ b/tests/test_devserver.py
@@ -32,9 +32,11 @@ def test_autoreload_builds_immediately(args: Namespace) -> None:
with open('content/test.md', 'w') as fh:
fh.write('boo')
- t = threading.Thread(target=devserver.autoreload,
- args=(args, ),
- daemon=True,)
+ t = threading.Thread(
+ target=devserver.autoreload,
+ args=(args,),
+ daemon=True,
+ )
t0 = devserver.get_last_modified(['build'])
t.start()
# try for 5 seconds...
@@ -47,11 +49,15 @@ def test_autoreload_builds_immediately(args: Namespace) -> None:
assert t1 > t0
-@pytest.mark.filterwarnings("ignore::pytest.PytestUnhandledThreadExceptionWarning") # noqa
+@pytest.mark.filterwarnings(
+ "ignore::pytest.PytestUnhandledThreadExceptionWarning"
+)
def test_autoreload(args: Namespace) -> None:
- t = threading.Thread(target=devserver.autoreload,
- args=(args, ),
- daemon=True,)
+ t = threading.Thread(
+ target=devserver.autoreload,
+ args=(args,),
+ daemon=True,
+ )
t.start()
t0 = devserver.get_last_modified(['build'])
diff --git a/tests/test_markdown.py b/tests/test_markdown.py
index 670a4e1..816f310 100644
--- a/tests/test_markdown.py
+++ b/tests/test_markdown.py
@@ -9,54 +9,65 @@ import markdown
from blag.markdown import convert_markdown, markdown_factory
-@pytest.mark.parametrize("input_, expected", [
- # inline
- ('[test](test.md)', 'test.html'),
- ('[test](test.md "test")', 'test.html'),
- ('[test](a/test.md)', 'a/test.html'),
- ('[test](a/test.md "test")', 'a/test.html'),
- ('[test](/test.md)', '/test.html'),
- ('[test](/test.md "test")', '/test.html'),
- ('[test](/a/test.md)', '/a/test.html'),
- ('[test](/a/test.md "test")', '/a/test.html'),
- # reference
- ('[test][]\n[test]: test.md ''', 'test.html'),
- ('[test][]\n[test]: test.md "test"', 'test.html'),
- ('[test][]\n[test]: a/test.md', 'a/test.html'),
- ('[test][]\n[test]: a/test.md "test"', 'a/test.html'),
- ('[test][]\n[test]: /test.md', '/test.html'),
- ('[test][]\n[test]: /test.md "test"', '/test.html'),
- ('[test][]\n[test]: /a/test.md', '/a/test.html'),
- ('[test][]\n[test]: /a/test.md "test"', '/a/test.html'),
-])
+@pytest.mark.parametrize(
+ "input_, expected",
+ [
+ # inline
+ ('[test](test.md)', 'test.html'),
+ ('[test](test.md "test")', 'test.html'),
+ ('[test](a/test.md)', 'a/test.html'),
+ ('[test](a/test.md "test")', 'a/test.html'),
+ ('[test](/test.md)', '/test.html'),
+ ('[test](/test.md "test")', '/test.html'),
+ ('[test](/a/test.md)', '/a/test.html'),
+ ('[test](/a/test.md "test")', '/a/test.html'),
+ # reference
+ ('[test][]\n[test]: test.md ' '', 'test.html'),
+ ('[test][]\n[test]: test.md "test"', 'test.html'),
+ ('[test][]\n[test]: a/test.md', 'a/test.html'),
+ ('[test][]\n[test]: a/test.md "test"', 'a/test.html'),
+ ('[test][]\n[test]: /test.md', '/test.html'),
+ ('[test][]\n[test]: /test.md "test"', '/test.html'),
+ ('[test][]\n[test]: /a/test.md', '/a/test.html'),
+ ('[test][]\n[test]: /a/test.md "test"', '/a/test.html'),
+ ],
+)
def test_convert_markdown_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
-@pytest.mark.parametrize("input_, expected", [
- # scheme
- ('[test](https://)', 'https://'),
- # netloc
- ('[test](//test.md)', '//test.md'),
- # no path
- ('[test]()', ''),
-])
+@pytest.mark.parametrize(
+ "input_, expected",
+ [
+ # scheme
+ ('[test](https://)', 'https://'),
+ # netloc
+ ('[test](//test.md)', '//test.md'),
+ # no path
+ ('[test]()', ''),
+ ],
+)
def test_dont_convert_normal_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
-@pytest.mark.parametrize("input_, expected", [
- ('foo: bar', {'foo': 'bar'}),
- ('foo: those are several words', {'foo': 'those are several words'}),
- ('tags: this, is, a, test\n', {'tags': ['this', 'is', 'a', 'test']}),
- ('tags: this, IS, a, test', {'tags': ['this', 'is', 'a', 'test']}),
- ('date: 2020-01-01 12:10', {'date':
- datetime(2020, 1, 1, 12, 10).astimezone()}),
-])
+@pytest.mark.parametrize(
+ "input_, expected",
+ [
+ ('foo: bar', {'foo': 'bar'}),
+ ('foo: those are several words', {'foo': 'those are several words'}),
+ ('tags: this, is, a, test\n', {'tags': ['this', 'is', 'a', 'test']}),
+ ('tags: this, IS, a, test', {'tags': ['this', 'is', 'a', 'test']}),
+ (
+ 'date: 2020-01-01 12:10',
+ {'date': datetime(2020, 1, 1, 12, 10).astimezone()},
+ ),
+ ],
+)
def test_convert_metadata(input_: str, expected: dict[str, Any]) -> None:
md = markdown_factory()
_, meta = convert_markdown(md, input_)
From 01507e9de6e56ad3b59861f581aaf95702d40966 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 18:51:53 +0200
Subject: [PATCH 012/123] updated changelog
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3009093..307bf2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## unreleased
+* added type hints and mypy --strict to test suite
* improved default template
* updated dependencies:
* markdown 3.4.1
From a224840b28d3b64ae0699df7e9540de0cf1aa94a Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 19:03:07 +0200
Subject: [PATCH 013/123] added .mypy_cache to .gitignore
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 4780a71..1f8d906 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,5 +10,6 @@ docs/api/
htmlcov/
.coverage
+.mypy_cache
venv/
From fc4eb0f463a457fb7983f93bae3d8fe20b27081b Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 19:03:27 +0200
Subject: [PATCH 014/123] delete .mypy_cache on clean
---
Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile b/Makefile
index 87cec44..d6242d0 100644
--- a/Makefile
+++ b/Makefile
@@ -55,3 +55,4 @@ clean:
find . -type d -name __pycache__ -delete
# coverage
rm -rf htmlcov .coverage
+ rm -rf .mypy_cache
From 73672598e5f143dfaddf8b8c419daaf4e2a2ca9a Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Sep 2022 19:03:43 +0200
Subject: [PATCH 015/123] bumped version to prepare a new release
---
CHANGELOG.md | 2 +-
blag/version.py | 2 +-
debian/changelog | 7 +++++++
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7b4dcf..82294ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## unreleased
+## [1.4.0] - 2022-09-01
* added type hints and mypy --strict to test suite
* improved default template
diff --git a/blag/version.py b/blag/version.py
index 41c78c8..dec3ec6 100644
--- a/blag/version.py
+++ b/blag/version.py
@@ -1 +1 @@
-__VERSION__ = '1.3.2'
+__VERSION__ = '1.4.0'
diff --git a/debian/changelog b/debian/changelog
index 8f252c0..81c5e65 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+blag (1.4.0) unstable; urgency=medium
+
+ * added type hints and mypy --strict to test suite
+ * improved default template
+
+ -- Bastian Venthur Thu, 01 Sep 2022 18:59:11 +0200
+
blag (1.3.2) unstable; urgency=medium
* Added --version option
From a4aa8045ebc4fa54ae3e0a3b96e07d97807edda7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 12 Sep 2022 14:15:31 +0000
Subject: [PATCH 016/123] Bump pytest from 7.1.2 to 7.1.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.2 to 7.1.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.2...7.1.3)
---
updated-dependencies:
- dependency-name: pytest
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 86eea69..3b8eed5 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,7 +1,7 @@
sphinx==5.1.1
twine==4.0.1
wheel==0.37.1
-pytest==7.1.2
+pytest==7.1.3
pytest-cov==3.0.0
flake8==5.0.4
mypy==0.971
From 118b20ef33113ffb6079ddba02d30ea628d8082c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 19 Sep 2022 14:10:38 +0000
Subject: [PATCH 017/123] Bump types-markdown from 3.4.1 to 3.4.2
Bumps [types-markdown](https://github.com/python/typeshed) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)
---
updated-dependencies:
- dependency-name: types-markdown
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 86eea69..35123b9 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -5,4 +5,4 @@ pytest==7.1.2
pytest-cov==3.0.0
flake8==5.0.4
mypy==0.971
-types-markdown==3.4.1
+types-markdown==3.4.2
From 2d4f3334cf5e0b3b9c6a13e50b68241cc938bd57 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 26 Sep 2022 14:15:49 +0000
Subject: [PATCH 018/123] Bump sphinx from 5.1.1 to 5.2.1
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.1.1 to 5.2.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.1.1...v5.2.1)
---
updated-dependencies:
- dependency-name: sphinx
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 86eea69..2aec96e 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,4 +1,4 @@
-sphinx==5.1.1
+sphinx==5.2.1
twine==4.0.1
wheel==0.37.1
pytest==7.1.2
From 31fc3d688bffc779b9dd338ec7fa32a4ced57c15 Mon Sep 17 00:00:00 2001
From: Debian Janitor
Date: Thu, 29 Sep 2022 01:12:53 +0000
Subject: [PATCH 019/123] Apply multi-arch hints. + blag-doc: Add Multi-Arch:
foreign.
Changes-By: apply-multiarch-hints
---
debian/control | 1 +
1 file changed, 1 insertion(+)
diff --git a/debian/control b/debian/control
index 390a92a..485140f 100644
--- a/debian/control
+++ b/debian/control
@@ -46,6 +46,7 @@ Architecture: all
Depends:
${sphinxdoc:Depends},
${misc:Depends},
+Multi-Arch: foreign
Description: Blog-aware, static site generator (documentation)
Blag is a blog-aware, static site generator, written in Python. It supports
the following features:
From c06424cfdf9cd331f567b2acc8c9860bc6a04b05 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 29 Sep 2022 20:43:40 +0200
Subject: [PATCH 020/123] bumped version, updated changelogs
---
CHANGELOG.md | 4 ++++
blag/version.py | 2 +-
debian/changelog | 6 ++++++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 82294ed..52b622a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## [1.4.1] - 2022-09-29
+
+* applied multi-arch fix by debian-janitor
+
## [1.4.0] - 2022-09-01
* added type hints and mypy --strict to test suite
diff --git a/blag/version.py b/blag/version.py
index dec3ec6..6c9ba3b 100644
--- a/blag/version.py
+++ b/blag/version.py
@@ -1 +1 @@
-__VERSION__ = '1.4.0'
+__VERSION__ = '1.4.1'
diff --git a/debian/changelog b/debian/changelog
index 81c5e65..e840a6d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+blag (1.4.1) unstable; urgency=medium
+
+ * Applied multi-arch fix by debian-janitor
+
+ -- Bastian Venthur Thu, 29 Sep 2022 20:41:28 +0200
+
blag (1.4.0) unstable; urgency=medium
* added type hints and mypy --strict to test suite
From 34eb413434d83b249d20df326f02a932993959af Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 29 Sep 2022 20:47:14 +0200
Subject: [PATCH 021/123] updated changelog
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52b622a..36db670 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
## [1.4.1] - 2022-09-29
* applied multi-arch fix by debian-janitor
+* updated dependencies:
+ * pytest 7.1.3
## [1.4.0] - 2022-09-01
From a960db495297c641fe7986b163813881405a0d91 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 3 Oct 2022 14:13:26 +0000
Subject: [PATCH 022/123] Bump pytest-cov from 3.0.0 to 4.0.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0)
---
updated-dependencies:
- dependency-name: pytest-cov
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 4d08133..6390bdd 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -2,7 +2,7 @@ sphinx==5.2.1
twine==4.0.1
wheel==0.37.1
pytest==7.1.3
-pytest-cov==3.0.0
+pytest-cov==4.0.0
flake8==5.0.4
mypy==0.971
types-markdown==3.4.2
From e317f80d1cfd96b55e8bc0bcb1e1e0f837008d4a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Oct 2022 15:07:12 +0000
Subject: [PATCH 023/123] Bump types-markdown from 3.4.2 to 3.4.2.1
Bumps [types-markdown](https://github.com/python/typeshed) from 3.4.2 to 3.4.2.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)
---
updated-dependencies:
- dependency-name: types-markdown
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 4d08133..c51b0e1 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -5,4 +5,4 @@ pytest==7.1.3
pytest-cov==3.0.0
flake8==5.0.4
mypy==0.971
-types-markdown==3.4.2
+types-markdown==3.4.2.1
From 642e31c357c363f94e1376b22ff00d82891c4d34 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Oct 2022 15:07:18 +0000
Subject: [PATCH 024/123] Bump mypy from 0.971 to 0.982
Bumps [mypy](https://github.com/python/mypy) from 0.971 to 0.982.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.971...v0.982)
---
updated-dependencies:
- dependency-name: mypy
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 4d08133..e834b41 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -4,5 +4,5 @@ wheel==0.37.1
pytest==7.1.3
pytest-cov==3.0.0
flake8==5.0.4
-mypy==0.971
+mypy==0.982
types-markdown==3.4.2
From e45e59d5684512319b857b5fdb7170c964556cd8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Oct 2022 14:38:34 +0000
Subject: [PATCH 025/123] Bump sphinx from 5.2.1 to 5.3.0
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.2.1 to 5.3.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.2.1...v5.3.0)
---
updated-dependencies:
- dependency-name: sphinx
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 4d08133..375a4f4 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,4 +1,4 @@
-sphinx==5.2.1
+sphinx==5.3.0
twine==4.0.1
wheel==0.37.1
pytest==7.1.3
From d8d2f4f5d64964ab193885f05ec5029e58a454e0 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sat, 29 Oct 2022 13:26:42 +0200
Subject: [PATCH 026/123] added python 3.11 to test suite
---
.github/workflows/python-package.yaml | 1 +
CHANGELOG.md | 1 +
2 files changed, 2 insertions(+)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index cb0b346..3a4ed80 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -20,6 +20,7 @@ jobs:
- "3.8"
- "3.9"
- "3.10"
+ - "3.11"
steps:
- uses: actions/checkout@v2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 454493d..240b9ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## [unreleased]
+* added python 3.11 to test suite
* updated dependencies:
* mypy 0.982
* types-markdown 3.4.2.1
From c3993f5111459d9e078b07d78e35616067db1008 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:11:15 +0100
Subject: [PATCH 027/123] split mypy and lint from tests and run them only on
linux/latest stable python
---
.github/workflows/python-package.yaml | 32 ++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index 3a4ed80..58ec755 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -34,10 +34,40 @@ jobs:
run: |
make test
+ lint:
+ name: Lint
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.x"
+
- name: Run linter
run: |
make lint
+ mypy:
+ name: mypy
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.x"
+
- name: Run mypy
run: |
make mypy
From e168a0e0d3f6c1a239727dc35cf028fd5f9ae313 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:21:03 +0100
Subject: [PATCH 028/123] remove fail-fast for non-matrix, seperate setup venv
---
.github/workflows/python-package.yaml | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index 58ec755..1e9ea0c 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -30,17 +30,17 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
+ - name: Setup virtual environment
+ run: |
+ make venv
+
- name: Run tests
run: |
make test
lint:
- name: Lint
runs-on: ubuntu-latest
- strategy:
- fail-fast: false
-
steps:
- uses: actions/checkout@v2
@@ -49,17 +49,17 @@ jobs:
with:
python-version: "3.x"
+ - name: Setup virtual environment
+ run: |
+ make venv
+
- name: Run linter
run: |
make lint
mypy:
- name: mypy
runs-on: ubuntu-latest
- strategy:
- fail-fast: false
-
steps:
- uses: actions/checkout@v2
@@ -68,6 +68,10 @@ jobs:
with:
python-version: "3.x"
+ - name: Setup virtual environment
+ run: |
+ make venv
+
- name: Run mypy
run: |
make mypy
From 5902582c471efc28cf1e19eb70d0e8dd1890f4b3 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:30:27 +0100
Subject: [PATCH 029/123] added gh-actions check for dependabot
---
.github/dependabot.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 6a7695c..4776211 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,3 +4,8 @@ updates:
directory: "/"
schedule:
interval: "weekly"
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
From 470bfba2bf2c013b53146e83869c6af960ffb4ce Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:39:24 +0100
Subject: [PATCH 030/123] test
---
.github/workflows/python-package.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index 1e9ea0c..83c22d5 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -75,3 +75,6 @@ jobs:
- name: Run mypy
run: |
make mypy
+
+ - run: |
+ make mypy
From fcfa1bf06e60be5c632755d2ffd8ec8e466c4c8e Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:42:58 +0100
Subject: [PATCH 031/123] removed most names
---
.github/workflows/python-package.yaml | 34 +++++++--------------------
1 file changed, 8 insertions(+), 26 deletions(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index 83c22d5..b5356ea 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -24,18 +24,13 @@ jobs:
steps:
- uses: actions/checkout@v2
-
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
+ - uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- - name: Setup virtual environment
- run: |
+ - run: |
make venv
-
- - name: Run tests
- run: |
+ - run: |
make test
lint:
@@ -43,18 +38,13 @@ jobs:
steps:
- uses: actions/checkout@v2
-
- - name: Set up Python
- uses: actions/setup-python@v4
+ - name: actions/setup-python@v4
with:
python-version: "3.x"
- - name: Setup virtual environment
- run: |
+ - run: |
make venv
-
- - name: Run linter
- run: |
+ - run: |
make lint
mypy:
@@ -62,19 +52,11 @@ jobs:
steps:
- uses: actions/checkout@v2
-
- - name: Set up Python
- uses: actions/setup-python@v4
+ - uses: actions/setup-python@v4
with:
python-version: "3.x"
- - name: Setup virtual environment
- run: |
+ - run: |
make venv
-
- - name: Run mypy
- run: |
- make mypy
-
- run: |
make mypy
From f1e122cd239c39572700611ab58a87d74a6010bb Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:43:43 +0100
Subject: [PATCH 032/123] fix
---
.github/workflows/python-package.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index b5356ea..b4f0250 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -38,7 +38,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: actions/setup-python@v4
+ - uses: actions/setup-python@v4
with:
python-version: "3.x"
From 4c41d1429fe7e5d2c5b217a27272af1bce97cdf2 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 15 Nov 2022 21:47:52 +0100
Subject: [PATCH 033/123] added changelog
---
CHANGELOG.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 240b9ea..b82e388 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,9 @@
## [unreleased]
* added python 3.11 to test suite
+* break out lint and mypy from test matrix and only run on linux- and latest
+ stable python to make it a bit more efficient
+* added dependabot check for github actions
* updated dependencies:
* mypy 0.982
* types-markdown 3.4.2.1
From 33728ce713583a8b28190f261ab971bd9266d440 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 15 Nov 2022 20:48:40 +0000
Subject: [PATCH 034/123] Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
.github/workflows/python-package.yaml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index b4f0250..ac4c312 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -23,7 +23,7 @@ jobs:
- "3.11"
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.x"
@@ -51,7 +51,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.x"
From 6243552de11873b6a11fa13371acae1cd2332dce Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 28 Nov 2022 14:02:34 +0000
Subject: [PATCH 035/123] Bump flake8 from 5.0.4 to 6.0.0
Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0)
---
updated-dependencies:
- dependency-name: flake8
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..ae5ab28 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,6 +3,6 @@ twine==4.0.1
wheel==0.37.1
pytest==7.1.3
pytest-cov==4.0.0
-flake8==5.0.4
+flake8==6.0.0
mypy==0.982
types-markdown==3.4.2.1
From 0ca248ede3012e1f8a9a8287bcc7a0587d1d5533 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 5 Dec 2022 14:02:57 +0000
Subject: [PATCH 036/123] Bump twine from 4.0.1 to 4.0.2
Bumps [twine](https://github.com/pypa/twine) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/pypa/twine/releases)
- [Changelog](https://github.com/pypa/twine/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pypa/twine/compare/4.0.1...4.0.2)
---
updated-dependencies:
- dependency-name: twine
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..3a74eb3 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,5 +1,5 @@
sphinx==5.3.0
-twine==4.0.1
+twine==4.0.2
wheel==0.37.1
pytest==7.1.3
pytest-cov==4.0.0
From 352c37045a7080e4aee73b37db87fd4ed83a4912 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Fri, 9 Dec 2022 20:57:11 +0100
Subject: [PATCH 037/123] moved to pyproject toml
---
.flake8 | 2 ++
CHANGELOG.md | 1 +
Makefile | 19 +++++++++----
pyproject.toml | 67 ++++++++++++++++++++++++++++++++++++++++++++
requirements-dev.txt | 1 +
setup.cfg | 16 -----------
setup.py | 42 ---------------------------
7 files changed, 84 insertions(+), 64 deletions(-)
create mode 100644 .flake8
create mode 100644 pyproject.toml
delete mode 100644 setup.cfg
delete mode 100644 setup.py
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..2882809
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+exclude = venv,build,docs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b82e388..18951a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## [unreleased]
+* moved to pyproject.toml
* added python 3.11 to test suite
* break out lint and mypy from test matrix and only run on linux- and latest
stable python to make it a bit more efficient
diff --git a/Makefile b/Makefile
index d6242d0..5731772 100644
--- a/Makefile
+++ b/Makefile
@@ -14,13 +14,13 @@ endif
.PHONY: all
-all: lint mypy test
+all: lint mypy test test-release
-$(VENV): requirements.txt requirements-dev.txt setup.py
+$(VENV): requirements.txt requirements-dev.txt pyproject.toml
$(PY) -m venv $(VENV)
$(BIN)/pip install --upgrade -r requirements.txt
$(BIN)/pip install --upgrade -r requirements-dev.txt
- $(BIN)/pip install -e .
+ $(BIN)/pip install -e .['dev']
touch $(VENV)
.PHONY: test
@@ -35,10 +35,17 @@ mypy: $(VENV)
lint: $(VENV)
$(BIN)/flake8
-.PHONY: release
-release: $(VENV)
+.PHONY: build
+build: $(VENV)
rm -rf dist
- $(BIN)/python setup.py sdist bdist_wheel
+ $(BIN)/python3 -m build
+
+.PHONY: test-release
+test-release: $(VENV) build
+ $(BIN)/twine check dist/*
+
+.PHONY: release
+release: $(VENV) build
$(BIN)/twine upload dist/*
.PHONY: docs
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..836afe1
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,67 @@
+[build-system]
+requires = ["setuptools>=64.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "blag"
+authors = [
+ { name="Bastian Venthur", email="mail@venthur.de" },
+]
+description = "blog-aware, static site generator"
+keywords = ["markdown", "blag", "blog", "static site generator", "cli"]
+readme = "README.md"
+license = { file="LICENSE" }
+requires-python = ">=3.8"
+dynamic = ["version"]
+dependencies = [
+ "markdown",
+ "feedgenerator",
+ "jinja2",
+ "pygments",
+]
+
+[project.scripts]
+blag = "blag.blag:main"
+
+[project.urls]
+'Documentation' = 'https://blag.readthedocs.io/'
+'Source' = 'https://github.com/venthur/blag'
+'Changelog' = 'https://github.com/venthur/blag/blob/master/CHANGELOG.md'
+
+[project.optional-dependencies]
+dev = [
+ "build",
+ "sphinx",
+ "twine",
+ "wheel",
+ "pytest",
+ "pytest-cov",
+ "flake8",
+ "mypy",
+ "types-markdown",
+]
+
+[tool.setuptools.dynamic]
+version = {attr = "blag.__VERSION__" }
+
+[tool.setuptools]
+packages = ["blag"]
+
+[tool.setuptools.package-data]
+blag = ["templates/*"]
+
+[tool.pytest.ini_options]
+addopts = """
+ --cov=blag
+ --cov=tests
+ --cov-report=html
+ --cov-report=term-missing:skip-covered
+"""
+
+[tool.mypy]
+files = "blag,tests"
+strict = true
+
+[[tool.mypy.overrides]]
+module = "feedgenerator.*"
+ignore_missing_imports = true
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..16ac3e3 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,3 +1,4 @@
+build==0.9.0
sphinx==5.3.0
twine==4.0.1
wheel==0.37.1
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 94d778c..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-[tool:pytest]
-addopts =
- --cov=blag
- --cov=tests
- --cov-report=html
- --cov-report=term-missing:skip-covered
-
-[flake8]
-exclude = venv,build,docs
-
-[mypy]
-files = blag,tests
-strict = True
-
-[mypy-feedgenerator.*]
-ignore_missing_imports = True
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 2f275fa..0000000
--- a/setup.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-
-from setuptools import setup
-
-meta = {}
-exec(open('./blag/version.py').read(), meta)
-meta['long_description'] = open('./README.md').read()
-
-setup(
- name='blag',
- version=meta['__VERSION__'],
- description='blog-aware, static site generator',
- long_description=meta['long_description'],
- long_description_content_type='text/markdown',
- keywords='markdown blag blog static site generator cli',
- author='Bastian Venthur',
- author_email='mail@venthur.de',
- url='https://github.com/venthur/blag',
- project_urls={
- 'Documentation': 'https://blag.readthedocs.io/',
- 'Source': 'https://github.com/venthur/blag',
- 'Changelog':
- 'https://github.com/venthur/blag/blob/master/CHANGELOG.md',
- },
- python_requires='>=3.8',
- package_data={
- 'blag': ['templates/*'],
- },
- install_requires=[
- 'markdown',
- 'feedgenerator',
- 'jinja2',
- 'pygments',
- ],
- packages=['blag'],
- entry_points={
- 'console_scripts': [
- 'blag = blag.blag:main'
- ]
- },
- license='MIT',
-)
From fe43288c8c6f8cfa6af83c14ae2af105bbccd14f Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Fri, 9 Dec 2022 21:03:46 +0100
Subject: [PATCH 038/123] added debian dependency and test-release target for
gh action
---
.github/workflows/python-package.yaml | 15 +++++++++++++++
debian/control | 1 +
2 files changed, 16 insertions(+)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index ac4c312..6191d28 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -60,3 +60,18 @@ jobs:
make venv
- run: |
make mypy
+
+
+ test-release:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: "3.x"
+
+ - run: |
+ make venv
+ - run: |
+ make test-release
diff --git a/debian/control b/debian/control
index 485140f..32a11f6 100644
--- a/debian/control
+++ b/debian/control
@@ -8,6 +8,7 @@ Build-Depends:
dh-sequence-sphinxdoc,
dh-sequence-python3,
dh-python,
+ pybuild-plugin-pyproject,
python3-setuptools,
python3-all,
python3-markdown,
From f6c18d381983e787aa58a652f31d91843b94d577 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 20 Mar 2023 14:58:58 +0000
Subject: [PATCH 039/123] Bump wheel from 0.37.1 to 0.40.0
Bumps [wheel](https://github.com/pypa/wheel) from 0.37.1 to 0.40.0.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.37.1...0.40.0)
---
updated-dependencies:
- dependency-name: wheel
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..c7978eb 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,6 +1,6 @@
sphinx==5.3.0
twine==4.0.1
-wheel==0.37.1
+wheel==0.40.0
pytest==7.1.3
pytest-cov==4.0.0
flake8==5.0.4
From c3f0dffd11147f25d28b6f901c1c703e7f04ea25 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Apr 2023 14:57:48 +0000
Subject: [PATCH 040/123] Bump mypy from 0.982 to 1.2.0
Bumps [mypy](https://github.com/python/mypy) from 0.982 to 1.2.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.982...v1.2.0)
---
updated-dependencies:
- dependency-name: mypy
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..77404a2 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -4,5 +4,5 @@ wheel==0.37.1
pytest==7.1.3
pytest-cov==4.0.0
flake8==5.0.4
-mypy==0.982
+mypy==1.2.0
types-markdown==3.4.2.1
From 06d8623dd7dae992c3cdefec1267e5f4fed7b4f1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 10 Apr 2023 14:58:07 +0000
Subject: [PATCH 041/123] Bump pytest from 7.1.3 to 7.3.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.3 to 7.3.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.3...7.3.0)
---
updated-dependencies:
- dependency-name: pytest
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
requirements-dev.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements-dev.txt b/requirements-dev.txt
index cb925c4..de71638 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,7 +1,7 @@
sphinx==5.3.0
twine==4.0.1
wheel==0.37.1
-pytest==7.1.3
+pytest==7.3.0
pytest-cov==4.0.0
flake8==5.0.4
mypy==0.982
From 169f0f2e0bb98fd7bc969e32f9278e7322f1ed47 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sun, 16 Apr 2023 10:30:53 +0200
Subject: [PATCH 042/123] WIP
---
Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile b/Makefile
index 5731772..13ccdc8 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,7 @@ all: lint mypy test test-release
$(VENV): requirements.txt requirements-dev.txt pyproject.toml
$(PY) -m venv $(VENV)
+ $(BIN)/pip install --upgrade pip
$(BIN)/pip install --upgrade -r requirements.txt
$(BIN)/pip install --upgrade -r requirements-dev.txt
$(BIN)/pip install -e .['dev']
From d8ff4afddbf3a273d0914f5536dc09619339cc14 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sun, 16 Apr 2023 10:32:04 +0200
Subject: [PATCH 043/123] Revert "WIP"
This reverts commit 169f0f2e0bb98fd7bc969e32f9278e7322f1ed47.
---
Makefile | 1 -
1 file changed, 1 deletion(-)
diff --git a/Makefile b/Makefile
index 13ccdc8..5731772 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,6 @@ all: lint mypy test test-release
$(VENV): requirements.txt requirements-dev.txt pyproject.toml
$(PY) -m venv $(VENV)
- $(BIN)/pip install --upgrade pip
$(BIN)/pip install --upgrade -r requirements.txt
$(BIN)/pip install --upgrade -r requirements-dev.txt
$(BIN)/pip install -e .['dev']
From e765d6b7172677960760dbd2ad9961848559fb52 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sun, 16 Apr 2023 10:37:06 +0200
Subject: [PATCH 044/123] eclude py38 on windows
---
.github/workflows/python-package.yaml | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/python-package.yaml b/.github/workflows/python-package.yaml
index 6191d28..b10540f 100644
--- a/.github/workflows/python-package.yaml
+++ b/.github/workflows/python-package.yaml
@@ -21,6 +21,10 @@ jobs:
- "3.9"
- "3.10"
- "3.11"
+ exclude:
+ # 3.8 on windows fails due to some pip issue
+ - os: windows-latest
+ python-version: "3.8"
steps:
- uses: actions/checkout@v3
@@ -40,7 +44,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
- python-version: "3.x"
+ python-version: "3.x"
- run: |
make venv
@@ -54,7 +58,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
- python-version: "3.x"
+ python-version: "3.x"
- run: |
make venv
@@ -69,7 +73,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
- python-version: "3.x"
+ python-version: "3.x"
- run: |
make venv
From 128d3f032d75807bfea995e36e7c425e2a0dbb0f Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sun, 16 Apr 2023 10:49:06 +0200
Subject: [PATCH 045/123] updated changelog
---
CHANGELOG.md | 2 +-
blag/version.py | 2 +-
debian/changelog | 20 ++++++++++++++++++++
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12361db..21bb927 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## [unreleased]
+## [1.5.0] - 2023-04-16
* moved to pyproject.toml
* added python 3.11 to test suite
diff --git a/blag/version.py b/blag/version.py
index 6c9ba3b..3fe4bea 100644
--- a/blag/version.py
+++ b/blag/version.py
@@ -1 +1 @@
-__VERSION__ = '1.4.1'
+__VERSION__ = '1.5.0'
diff --git a/debian/changelog b/debian/changelog
index e840a6d..fcf6839 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,23 @@
+blag (1.5.0) unstable; urgency=medium
+
+ * new upstream version
+ * moved to pyproject.toml
+ * added python 3.11 to test suite
+ * break out lint and mypy from test matrix and only run on linux- and latest
+ stable python to make it a bit more efficient
+ * added dependabot check for github actions
+ * updated dependencies:
+ * mypy 1.2.0
+ * types-markdown 3.4.2.1
+ * pytest-cov 4.0.0
+ * sphinx 5.3.0
+ * pytest 7.3.0
+ * flake8 6.0.0
+ * twine 4.0.2
+ * wheel 0.40.0
+
+ -- Bastian Venthur Sun, 16 Apr 2023 10:48:18 +0200
+
blag (1.4.1) unstable; urgency=medium
* Applied multi-arch fix by debian-janitor
From a3572d414fdcd61df47da540ce5b6ff8321cbf7f Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Sun, 16 Apr 2023 10:57:44 +0200
Subject: [PATCH 046/123] added blag.templates to packages
---
pyproject.toml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 836afe1..85dbb8e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -45,7 +45,10 @@ dev = [
version = {attr = "blag.__VERSION__" }
[tool.setuptools]
-packages = ["blag"]
+packages = [
+ "blag",
+ "blag.templates",
+]
[tool.setuptools.package-data]
blag = ["templates/*"]
From 362e721d8820978cc96a3b6d803666d4a3f81cb7 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Wed, 31 May 2023 15:53:49 +0200
Subject: [PATCH 047/123] Split Archive into Index and Archive
---
CHANGELOG.md | 13 +++++++++++
blag/blag.py | 43 +++++++++++++++++++++++++++++++++----
blag/templates/archive.html | 2 +-
blag/templates/base.html | 1 +
blag/templates/index.html | 23 ++++++++++++++++++++
docs/blag.rst | 3 ++-
tests/conftest.py | 5 +++++
tests/test_blag.py | 4 +++-
tests/test_templates.py | 22 ++++++++++++++++++-
9 files changed, 108 insertions(+), 8 deletions(-)
create mode 100644 blag/templates/index.html
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21bb927..80015bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## [unreleased]
+
+* **Breaking Change**: Split former archive page which served as index.html
+ into "index" and "archive", each with their own template, respectively. Index
+ is the landing page and shows by default only the latest 10 articles. Archive
+ shows the full list of articles.
+
+ If you used custom templates,
+ * you should create an "index.html"-template (take blag's default one as a
+ starting point)
+ * you may want to include the new "/archive.html" link somewhere in your
+ navigation
+
## [1.5.0] - 2023-04-16
* moved to pyproject.toml
diff --git a/blag/blag.py b/blag/blag.py
index 490348b..f402357 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -263,6 +263,7 @@ def build(args: argparse.Namespace) -> None:
page_template = env.get_template('page.html')
article_template = env.get_template('article.html')
+ index_template = env.get_template('index.html')
archive_template = env.get_template('archive.html')
tags_template = env.get_template('tags.html')
tag_template = env.get_template('tag.html')
@@ -283,6 +284,7 @@ def build(args: argparse.Namespace) -> None:
blog_description=config['description'],
blog_author=config['author'],
)
+ generate_index(articles, index_template, args.output_dir)
generate_archive(articles, archive_template, args.output_dir)
generate_tags(articles, tags_template, tag_template, args.output_dir)
@@ -302,6 +304,8 @@ def process_markdown(
If a markdown file has a `date` metadata field it will be recognized
as article otherwise as page.
+ Articles are sorted by date in descending order.
+
Parameters
----------
convertibles
@@ -309,12 +313,12 @@ def process_markdown(
input_dir
output_dir
page_template, archive_template
- templats for pages and articles
+ templates for pages and articles
Returns
-------
list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str, Any]]]
- articles and pages
+ articles and pages, articles are sorted by date in descending order.
"""
logger.info("Converting Markdown files...")
@@ -401,12 +405,14 @@ def generate_feed(
feed.write(fh, encoding='utf8')
-def generate_archive(
+def generate_index(
articles: list[tuple[str, dict[str, Any]]],
template: Template,
output_dir: str,
) -> None:
- """Generate the archive page.
+ """Generate the index page.
+
+ This is used for the index (i.e. landing) page.
Parameters
----------
@@ -428,6 +434,35 @@ def generate_archive(
fh.write(result)
+def generate_archive(
+ articles: list[tuple[str, dict[str, Any]]],
+ template: Template,
+ output_dir: str,
+) -> None:
+ """Generate the archive page.
+
+ This is used for the full archive.
+
+ Parameters
+ ----------
+ articles
+ List of articles. Each article has the destination path and a
+ dictionary with the content.
+ template
+ output_dir
+
+ """
+ archive = []
+ for dst, context in articles:
+ entry = context.copy()
+ entry['dst'] = dst
+ archive.append(entry)
+
+ result = template.render(dict(archive=archive))
+ with open(f'{output_dir}/archive.html', 'w') as fh:
+ fh.write(result)
+
+
def generate_tags(
articles: list[tuple[str, dict[str, Any]]],
tags_template: Template,
diff --git a/blag/templates/archive.html b/blag/templates/archive.html
index e8f9cca..af8c122 100644
--- a/blag/templates/archive.html
+++ b/blag/templates/archive.html
@@ -1,6 +1,6 @@
{% extends "base.html" %}
-{% block title %}{{ site.title }}{% endblock %}
+{% block title %}Archive{% endblock %}
{% block content %}
{% for entry in archive %}
diff --git a/blag/templates/base.html b/blag/templates/base.html
index fc6f822..5e952b3 100644
--- a/blag/templates/base.html
+++ b/blag/templates/base.html
@@ -20,6 +20,7 @@
{{ site.description }}
diff --git a/blag/templates/index.html b/blag/templates/index.html
new file mode 100644
index 0000000..a88a011
--- /dev/null
+++ b/blag/templates/index.html
@@ -0,0 +1,23 @@
+{% extends "base.html" %}
+
+{% block title %}{{ site.title }}{% endblock %}
+
+{% block content %}
+{% for entry in archive[:10] %}
+
+ {% if entry.title %}
+
+
+ {% if entry.description %}
+ — {{ entry.description }}
+ {% endif %}
+
+ {% endif %}
+
+ Written on {{ entry.date.date() }}.
+
+{% endfor %}
+
+all articles...
+
+{% endblock %}
diff --git a/docs/blag.rst b/docs/blag.rst
index b00450e..05b5263 100644
--- a/docs/blag.rst
+++ b/docs/blag.rst
@@ -195,7 +195,8 @@ Template Used For Variables
============ ====================================== ===================
page.html pages (i.e. non-articles) site, content, meta
article.html articles (i.e. blog posts) site, content, meta
-archive.html archive- and landing page of the blog site, archive
+index.html landing page of the blog site, archive
+archive.html archive page of the blog site, archive
tags.html list of tags site, tags
tag.html archive of Articles with a certain tag site, archive, tag
============ ====================================== ===================
diff --git a/tests/conftest.py b/tests/conftest.py
index da40e05..00a0c11 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -33,6 +33,11 @@ def article_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('article.html')
+@pytest.fixture
+def index_template(environment: Environment) -> Iterator[Template]:
+ yield environment.get_template('index.html')
+
+
@pytest.fixture
def archive_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('archive.html')
diff --git a/tests/test_blag.py b/tests/test_blag.py
index 74e8512..17f840b 100644
--- a/tests/test_blag.py
+++ b/tests/test_blag.py
@@ -291,8 +291,10 @@ foo bar
assert os.path.exists(f'{args.output_dir}/testdir/test')
# ... feed
assert os.path.exists(f'{args.output_dir}/atom.xml')
- # ... archive
+ # ... index
assert os.path.exists(f'{args.output_dir}/index.html')
+ # ... archive
+ assert os.path.exists(f'{args.output_dir}/archive.html')
# ... tags
assert os.path.exists(f'{args.output_dir}/tags/index.html')
assert os.path.exists(f'{args.output_dir}/tags/foo.html')
diff --git a/tests/test_templates.py b/tests/test_templates.py
index b25388e..99a3890 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -27,6 +27,26 @@ def test_article(article_template: Template) -> None:
assert '1980-05-09' in result
+def test_index(index_template: Template) -> None:
+ entry = {
+ 'title': 'this is a title',
+ 'dst': 'https://example.com/link',
+ 'date': datetime.datetime(1980, 5, 9),
+ }
+ archive = [entry]
+ ctx = {
+ 'archive': archive,
+ }
+ result = index_template.render(ctx)
+ assert 'site title' in result
+
+ assert 'this is a title' in result
+ assert '1980-05-09' in result
+ assert 'https://example.com/link' in result
+
+ assert '/archive.html' in result
+
+
def test_archive(archive_template: Template) -> None:
entry = {
'title': 'this is a title',
@@ -38,7 +58,7 @@ def test_archive(archive_template: Template) -> None:
'archive': archive,
}
result = archive_template.render(ctx)
- assert 'site title' in result
+ assert 'Archive' in result
assert 'this is a title' in result
assert '1980-05-09' in result
From c952c574b71dbcc872f6b017f962e58007aea960 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Jun 2023 13:35:33 +0200
Subject: [PATCH 048/123] Don't use internal templates anymore.
Blag will throw an error if a template is not found locally. The error
message contains an explanation for the user on where to get the missing
templates.
Quickstart will generate templates for the user in the working
directory.
Updated tests appropriately.
---
CHANGELOG.md | 15 +++++++++++++++
blag/blag.py | 43 +++++++++++++++++++++++--------------------
blag/quickstart.py | 22 ++++++++++++++++++++++
docs/blag.rst | 10 ++++------
tests/conftest.py | 11 ++++++-----
tests/test_blag.py | 20 ++++++++++++++++++--
6 files changed, 88 insertions(+), 33 deletions(-)
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'])
From f97e641bd8ad8f7ba8ecef654252a8d68aca616a Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Thu, 1 Jun 2023 14:02:04 +0200
Subject: [PATCH 049/123] added test for quickstart creating the templates
---
tests/test_quickstart.py | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index ac6ccaf..95b54c1 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -1,5 +1,6 @@
# remove when we don't support py38 anymore
from __future__ import annotations
+import os
from pytest import MonkeyPatch
@@ -27,3 +28,13 @@ def test_quickstart(cleandir: str, monkeypatch: MonkeyPatch) -> None:
assert 'title = foo' in data
assert 'description = foo' in data
assert 'author = foo' in data
+
+ for template in (
+ "archive.html",
+ "article.html",
+ "base.html",
+ "page.html",
+ "tag.html",
+ "tags.html",
+ ):
+ assert os.path.exists(f'templates/{template}')
From fe268516e30310a2a9abb439af9f9bb1da53bf71 Mon Sep 17 00:00:00 2001
From: Bastian Venthur
Date: Tue, 13 Jun 2023 16:29:44 +0200
Subject: [PATCH 050/123] Improved the default theme.
Closes: #48
---
CHANGELOG.md | 5 ++
blag/content/about.md | 8 ++
blag/content/hello-world.md | 51 +++++++++++
blag/content/second-post.md | 9 ++
blag/content/testpage.md | 46 ++++++++++
blag/quickstart.py | 27 +++---
blag/static/code-dark.css | 83 ++++++++++++++++++
blag/static/code-light.css | 73 ++++++++++++++++
blag/static/favicon.ico | Bin 0 -> 15406 bytes
blag/static/style.css | 166 ++++++++++++++++++++++++++++++++++++
blag/templates/archive.html | 23 ++---
blag/templates/article.html | 1 -
blag/templates/base.html | 20 ++++-
blag/templates/page.html | 4 +-
blag/templates/tag.html | 27 +++---
pyproject.toml | 8 +-
tests/conftest.py | 5 +-
tests/test_templates.py | 2 +-
18 files changed, 515 insertions(+), 43 deletions(-)
create mode 100644 blag/content/about.md
create mode 100644 blag/content/hello-world.md
create mode 100644 blag/content/second-post.md
create mode 100644 blag/content/testpage.md
create mode 100644 blag/static/code-dark.css
create mode 100644 blag/static/code-light.css
create mode 100644 blag/static/favicon.ico
create mode 100644 blag/static/style.css
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb9cf8d..adbbe72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,11 @@
New users are not affected as `blag quickstart` will generate the needed
templates.
+### Changed
+
+* blag comes now with a simple yet good looking default theme that supports
+ syntax highlighting and a light- and dark theme.
+
## [1.5.0] - 2023-04-16
diff --git a/blag/content/about.md b/blag/content/about.md
new file mode 100644
index 0000000..4f01ccf
--- /dev/null
+++ b/blag/content/about.md
@@ -0,0 +1,8 @@
+title: About Me
+description: Short description of this page.
+
+
+## About Me
+
+This is a regular page, i.e. not a blog post. Feel free to delete this page,
+populate it with more content or generate more [pages like this](testpage.md).
diff --git a/blag/content/hello-world.md b/blag/content/hello-world.md
new file mode 100644
index 0000000..7039dd9
--- /dev/null
+++ b/blag/content/hello-world.md
@@ -0,0 +1,51 @@
+Title: Hello World!
+Description: Hello there, this is the first blog post. You should read me first.
+Date: 2023-01-01 12:00
+Tags: blag, pygments
+
+
+## Hello World
+
+This is an example blog post. Internally, blag differentiates between **pages**
+and **articles**. Intuitively, pages are simple pages and articles are blog
+posts. The decision whether a document is a page or an article is made
+depending on the presence of the `date` metadata element: Any document that
+contains the `date` metadata element is an article, everything else a page.
+
+This differentiation has consequences:
+
+* blag uses different templates: `page.html` and `article.html`
+* only articles are collected in the Atom feed
+* only articles are aggregated in the tag pages
+
+For more detailed information, please refer to the [documentation][doc]
+
+[doc]: https://blag.readthedocs.io
+
+
+### Syntax Highlighting
+
+```python
+def foo(bar):
+ """This is a docstring.
+
+ """
+ # comment
+ return bar
+```
+
+Syntax highlighting is done via [Pygments][pygments]. For code blocks, blag
+generates the necessary CSS classes by default, which you can use to style your
+code using CSS. It provides you with a default light- and dark theme, for more
+information on how to generate a different theme, please refer to [Pygments'
+documentation][pygments].
+
+[pygments]: https://pygments.org
+
+
+### Next Steps
+
+* Adapt the files in `templates` to your needs
+* Check out the files in `static` and modify as needed
+* Add some content
+* Change the [favicon.ico](favicon.ico)
diff --git a/blag/content/second-post.md b/blag/content/second-post.md
new file mode 100644
index 0000000..5a35d4b
--- /dev/null
+++ b/blag/content/second-post.md
@@ -0,0 +1,9 @@
+Title: Second Post
+Description: This is the second blog post, so you can see how it looks like on the front page.
+Date: 2023-01-02 12:00
+Tags: blag
+
+
+## Second Post
+
+This page serves no purpose :)
diff --git a/blag/content/testpage.md b/blag/content/testpage.md
new file mode 100644
index 0000000..24fe02b
--- /dev/null
+++ b/blag/content/testpage.md
@@ -0,0 +1,46 @@
+# This Is A Headline
+
+This is some **bold text** with some `code` inside. This is _some_underlined_
+text with some `code` inside. This is some text with some `code` inside. This
+is some text with some `code` inside. This is some text with some `code`
+inside. This is some text with some `code` inside. This is some text with some
+`code` inside. This is some text with some `code` inside.
+
+This is some [link](https://example.com) inside the text -- it does not really
+lead anywhere! This is some [link](https://example.com) inside the text -- it
+does not really lead anywhere! This is some [link](https://example.com) inside
+the text -- it does not really lead anywhere!
+
+
+* some bullets
+* some other
+ * bullets
+ * foo
+
+```python
+# this is some python code
+
+class Foo:
+
+ def __init__(self, foo, bar):
+ self.foo = foo
+ self.bar = bar
+
+ def do_something():
+ """This is the docstring of this method.
+
+ """
+ return foo
+```
+
+
+## Some other headline
+
+This is some other text
+
+```makefile
+
+# some comment
+foo:
+ ls -lh
+```
diff --git a/blag/quickstart.py b/blag/quickstart.py
index aee73e1..4d12af8 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -37,20 +37,25 @@ def get_input(question: str, default: str) -> str:
return reply
-def copy_templates() -> None:
- """Copy templates into current directory.
+def copy_default_theme() -> None:
+ """Copy default theme into current directory.
+
+ The default theme contains the 'templates', 'content' and 'static'
+ directories shipped with blag.
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.")
+ print("Copying default theme...")
+ for dir_ in 'templates', 'content', 'static':
+ print(f" Copying {dir_}...")
+ try:
+ shutil.copytree(
+ os.path.join(blag.__path__[0], dir_),
+ dir_,
+ )
+ except FileExistsError:
+ print(f" {dir_} already exist. Skipping.")
def quickstart(args: argparse.Namespace | None) -> None:
@@ -92,4 +97,4 @@ def quickstart(args: argparse.Namespace | None) -> None:
with open('config.ini', 'w') as fh:
config.write(fh)
- copy_templates()
+ copy_default_theme()
diff --git a/blag/static/code-dark.css b/blag/static/code-dark.css
new file mode 100644
index 0000000..a2af57e
--- /dev/null
+++ b/blag/static/code-dark.css
@@ -0,0 +1,83 @@
+pre { line-height: 125%; }
+td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+.hll { background-color: #49483e }
+.c { color: #75715e } /* Comment */
+.err { color: #960050; background-color: #1e0010 } /* Error */
+.esc { color: #f8f8f2 } /* Escape */
+.g { color: #f8f8f2 } /* Generic */
+.k { color: #66d9ef } /* Keyword */
+.l { color: #ae81ff } /* Literal */
+.n { color: #f8f8f2 } /* Name */
+.o { color: #f92672 } /* Operator */
+.x { color: #f8f8f2 } /* Other */
+.p { color: #f8f8f2 } /* Punctuation */
+.ch { color: #75715e } /* Comment.Hashbang */
+.cm { color: #75715e } /* Comment.Multiline */
+.cp { color: #75715e } /* Comment.Preproc */
+.cpf { color: #75715e } /* Comment.PreprocFile */
+.c1 { color: #75715e } /* Comment.Single */
+.cs { color: #75715e } /* Comment.Special */
+.gd { color: #f92672 } /* Generic.Deleted */
+.ge { color: #f8f8f2; font-style: italic } /* Generic.Emph */
+.gr { color: #f8f8f2 } /* Generic.Error */
+.gh { color: #f8f8f2 } /* Generic.Heading */
+.gi { color: #a6e22e } /* Generic.Inserted */
+.go { color: #66d9ef } /* Generic.Output */
+.gp { color: #f92672; font-weight: bold } /* Generic.Prompt */
+.gs { color: #f8f8f2; font-weight: bold } /* Generic.Strong */
+.gu { color: #75715e } /* Generic.Subheading */
+.gt { color: #f8f8f2 } /* Generic.Traceback */
+.kc { color: #66d9ef } /* Keyword.Constant */
+.kd { color: #66d9ef } /* Keyword.Declaration */
+.kn { color: #f92672 } /* Keyword.Namespace */
+.kp { color: #66d9ef } /* Keyword.Pseudo */
+.kr { color: #66d9ef } /* Keyword.Reserved */
+.kt { color: #66d9ef } /* Keyword.Type */
+.ld { color: #e6db74 } /* Literal.Date */
+.m { color: #ae81ff } /* Literal.Number */
+.s { color: #e6db74 } /* Literal.String */
+.na { color: #a6e22e } /* Name.Attribute */
+.nb { color: #f8f8f2 } /* Name.Builtin */
+.nc { color: #a6e22e } /* Name.Class */
+.no { color: #66d9ef } /* Name.Constant */
+.nd { color: #a6e22e } /* Name.Decorator */
+.ni { color: #f8f8f2 } /* Name.Entity */
+.ne { color: #a6e22e } /* Name.Exception */
+.nf { color: #a6e22e } /* Name.Function */
+.nl { color: #f8f8f2 } /* Name.Label */
+.nn { color: #f8f8f2 } /* Name.Namespace */
+.nx { color: #a6e22e } /* Name.Other */
+.py { color: #f8f8f2 } /* Name.Property */
+.nt { color: #f92672 } /* Name.Tag */
+.nv { color: #f8f8f2 } /* Name.Variable */
+.ow { color: #f92672 } /* Operator.Word */
+.pm { color: #f8f8f2 } /* Punctuation.Marker */
+.w { color: #f8f8f2 } /* Text.Whitespace */
+.mb { color: #ae81ff } /* Literal.Number.Bin */
+.mf { color: #ae81ff } /* Literal.Number.Float */
+.mh { color: #ae81ff } /* Literal.Number.Hex */
+.mi { color: #ae81ff } /* Literal.Number.Integer */
+.mo { color: #ae81ff } /* Literal.Number.Oct */
+.sa { color: #e6db74 } /* Literal.String.Affix */
+.sb { color: #e6db74 } /* Literal.String.Backtick */
+.sc { color: #e6db74 } /* Literal.String.Char */
+.dl { color: #e6db74 } /* Literal.String.Delimiter */
+.sd { color: #e6db74 } /* Literal.String.Doc */
+.s2 { color: #e6db74 } /* Literal.String.Double */
+.se { color: #ae81ff } /* Literal.String.Escape */
+.sh { color: #e6db74 } /* Literal.String.Heredoc */
+.si { color: #e6db74 } /* Literal.String.Interpol */
+.sx { color: #e6db74 } /* Literal.String.Other */
+.sr { color: #e6db74 } /* Literal.String.Regex */
+.s1 { color: #e6db74 } /* Literal.String.Single */
+.ss { color: #e6db74 } /* Literal.String.Symbol */
+.bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
+.fm { color: #a6e22e } /* Name.Function.Magic */
+.vc { color: #f8f8f2 } /* Name.Variable.Class */
+.vg { color: #f8f8f2 } /* Name.Variable.Global */
+.vi { color: #f8f8f2 } /* Name.Variable.Instance */
+.vm { color: #f8f8f2 } /* Name.Variable.Magic */
+.il { color: #ae81ff } /* Literal.Number.Integer.Long */
diff --git a/blag/static/code-light.css b/blag/static/code-light.css
new file mode 100644
index 0000000..e2cc7b8
--- /dev/null
+++ b/blag/static/code-light.css
@@ -0,0 +1,73 @@
+pre { line-height: 125%; }
+td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+.hll { background-color: #ffffcc }
+.c { color: #3D7B7B; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #008000; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
+.cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
+.cp { color: #9C6500 } /* Comment.Preproc */
+.cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
+.c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
+.cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #E40000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #008400 } /* Generic.Inserted */
+.go { color: #717171 } /* Generic.Output */
+.gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0044DD } /* Generic.Traceback */
+.kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.kp { color: #008000 } /* Keyword.Pseudo */
+.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #B00040 } /* Keyword.Type */
+.m { color: #666666 } /* Literal.Number */
+.s { color: #BA2121 } /* Literal.String */
+.na { color: #687822 } /* Name.Attribute */
+.nb { color: #008000 } /* Name.Builtin */
+.nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.no { color: #880000 } /* Name.Constant */
+.nd { color: #AA22FF } /* Name.Decorator */
+.ni { color: #717171; font-weight: bold } /* Name.Entity */
+.ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
+.nf { color: #0000FF } /* Name.Function */
+.nl { color: #767600 } /* Name.Label */
+.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.nt { color: #008000; font-weight: bold } /* Name.Tag */
+.nv { color: #19177C } /* Name.Variable */
+.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mb { color: #666666 } /* Literal.Number.Bin */
+.mf { color: #666666 } /* Literal.Number.Float */
+.mh { color: #666666 } /* Literal.Number.Hex */
+.mi { color: #666666 } /* Literal.Number.Integer */
+.mo { color: #666666 } /* Literal.Number.Oct */
+.sa { color: #BA2121 } /* Literal.String.Affix */
+.sb { color: #BA2121 } /* Literal.String.Backtick */
+.sc { color: #BA2121 } /* Literal.String.Char */
+.dl { color: #BA2121 } /* Literal.String.Delimiter */
+.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #BA2121 } /* Literal.String.Double */
+.se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #BA2121 } /* Literal.String.Heredoc */
+.si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
+.sx { color: #008000 } /* Literal.String.Other */
+.sr { color: #A45A77 } /* Literal.String.Regex */
+.s1 { color: #BA2121 } /* Literal.String.Single */
+.ss { color: #19177C } /* Literal.String.Symbol */
+.bp { color: #008000 } /* Name.Builtin.Pseudo */
+.fm { color: #0000FF } /* Name.Function.Magic */
+.vc { color: #19177C } /* Name.Variable.Class */
+.vg { color: #19177C } /* Name.Variable.Global */
+.vi { color: #19177C } /* Name.Variable.Instance */
+.vm { color: #19177C } /* Name.Variable.Magic */
+.il { color: #666666 } /* Literal.Number.Integer.Long */
diff --git a/blag/static/favicon.ico b/blag/static/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..6175ffc0c98d3eb8736a322197f8d335bd4c669e
GIT binary patch
literal 15406
zcmeHO33OD|8J@JZr}o%Z+tbb3BR#F?;j}`SMO&$;Ra{6iGYGh~DxwxE+F}LVN0}`l
z1SoshBBBDRV2H|&vWud!NEQT?gg_t(WFZS^<@Wn-@?KtE-kW)ECdg@zbI!|q_uhZ`
z{(Jv>?|+v#94U@(I?g}efp<5@uyY&^kHg{U)~z*t*#!>AT;%oY)mGl!;n?zHhvPEP
zfCU__`FL6SjmdDOM*W`Yc=kkmo>P3n{PugMg}iQPG5+NYyy#re%*1m#I^YUn`1n0v
zhQ03GK;MhMqm?p(ygtu*LmmTJ(6LS{gL?J6Q|?a_8y3tIuLd4A#6ldz&}Q$Kdj9pV
z&Jd?sn#9TGM)A)4shwrO7S@NXD+7$%-drf&D|}VtNB$}5sw>4S&;6~F4B(!|de-Y^
zx_I+yu_8B1^5lmf69-FncH(EdMA1G*{8eT9#OvdpRCy})d@NoZHAGF5N4Bru{e_-?
z$^+@r?z~a=s`MKd%@&*fJx5JTe!r&$820M^u6Z^lwcKiBETIRnwBk
z?~-uZ*f0q#2^
ze)sIC-~9n_*Pu?mKpXR^#k>td-FG0(`CZtUL;Ec2)!_l}=fE*`#FZDFYe#?9fL@oN9(O0ISI-9=yMjLF
zudQGRr8#?pzFIFM*)(KU!Cz#*Hp4N7cAo*=3iikV&r!2_V0+uC^PIb`731!>Mjdw)
z9r51qhh0Yg5c0Xl$KzGXSI@~2ElnrnTu@%LT`UUz-4>3p&z-Gp1B{v7BmOHsSLDZf
zXWn|HXgF3S$8yfY%3Qo*L9S&CXyeZ#>8Za_FaXcoSUR<3lZM{XLAQc|?=^W7ZD4TE
zrhblVz+-uA$sImOwfW5{LGi|<7sTOx#WJs@sX@$pVyIONO&ljVrfThr_f7eUfp$8+7d6^mza)+nh*Kj-J%b)Bdx-!IEpC$VHG
zWpaMUT%x3{yw~JSkUA>&mvqv>*n)L)8UM7?Wz^(P_)KuP%@}_HTdJ
zQ2wD$cFS_3xKb;J-<(6y2LI9L$4b*~+PHIVp`rd&i1Aqd(aI%;MzK7+E_N)y|J!F
z(&de8kCTn$!uOA0?Ac*dW|X&Q>pE3G?KGlco-!V+oRw`#BYFLvt*C=MGdbG)X~X>D
zB*uK&UR!lIrhk|1{!r4z^8v=nm=ph^)noR(eO0U9Q$PEF86ER0N_R>9W_?8AMcog6
zqW|wMKpnIwc}DLg*-xr|NBs-OJZh?6J3kqX5sG~1Y|P5I^n08G;DawJ`TFgJCzF4Bf^W_i&^syxap82^l^Ok#g~-ei@&
zykv(lt>1G>9|xf=Cg^Qv`lToD7c~{1p$_WA#{AjF@<6BXPPqF9QM_rjY%jAh0{t$l
z)$;bgGXCkCLKP|_Iq(y8oCz
zX?`&M@?V`P6T<1g{VD2fB>M3QJ%+AI!-o2h*Eu?H!{tAL9bM*E!8B(dj6*9?--dhN
zU4>uDk?rAL7R+#8-34utf-(LfxgN8z9!l08_7C{zv2cd#;Y4i+^yu;Jh}ZQvWSud8
ziDxHtHv_{z%;KsTwqaa!4hR3ScskB>xomsb5CdzcBDCEw+J2_7S(Q&LR(&a);k*{(
zfUWUdkArKivA6XRc4KqB9BrEYA()ZMK5aTK1-w1a=Qsm}ub?}?#M(bXgj#!f8x1qTKYh~Cl?oRvX16oY*rTN6H*bqr`xsg|<
zrLp@xc5ol@;quoy)w|vX`qPRTt>@f!btv?}S~bSk+u4Rc1#L1q+1P-4-Q4>mUiv-v
zST-!2B{nb469-Foil&BI)wZVkT08sko%{{>zhEpDa5%mZ7}VoDqze_>5`FW`sCd&V
z6+iDYDEp+7hxQk1=S`A(`$~J17jGAnapsYzKCCmAa{UmUBSFRBktK(tS7MzD1eD
zMgQiWxRH!$!+fH=ct>kH;aqC@^r#`75wAWEHbl{H-_YkLlAivMU$itfNL-DzHR83*
zk*2s7XN{J0Y=fGL10rjXwR0^!E{yprU_+@sKasR@#zag!2Q|CLBxNH$;{70{FE2%m
zk%&(C|0lp-n+UI-XH)(h6;EANrI`Ep-7zt}p7V@4*X{pki{SjBml-dOF{lnU*gEGj
zld1SL>y-DArv5c{zvP%o-yuEEO&Ir?$u`T!+R)ZHnVFo4LvB*faEPZG=cU=Vx8KDw
z;$sX^vSqEr--Nh=XU;}+vGU+MEqIz@(O4-fnDDIXJH-F#&iCVD;e4=V@r%-jIA8Pb
z-Pqgy7?)3r2iURi;@PLoOXRzF%bE`Ow-&r?2?y`{F{Y!2@=$B*
zt^Cjkc~_HsJOh3C*@x`m_qu}NbmtB6Fq)N*yYpI6^6px793+l1#ARmm`uv42JSysr
z9#(yC1@27hY0T2_`_mzB?;9Dv;X9%DZT`~_ibllq#4YO({qXJiQ!Haxq^W=MbIojq
zSDz2eWxVUdvsSFx-_n=IOHX+q4RdH~9HZc;FXxTC$1(<lZ
zmTbqkb0nOedbzUxebDLr7V_p;!O#0>yd$UJR^By-4hY`ivLb^t+!LxjQqe)qKEy#*
z_%ZI!8>Bn$2=(vz3)m2M|Kxq#Q&%u+-^*uYLU;VTO$t87M_eapW$ajEe0NCU;T!$7
zHgJpkXG+~`-;oUGqbQGgUyypaZsHn?^FI6Rwzn2psy8hT?l1C=JKKPAC{KIeTT82a
z1KTO?M{6-_zqx;iwpj(bnEQvhj|>*P!^1T?@1P{QpTj+i1(*YPAA)xjIW8zz^>1S0
zI2pdF7yets{D=D+ebARH^!#Tu%{z5`;2&lW@K?h>t}sX5UV?MQ`#>MJFPQ1->U?4e
zd!0ku5yt)cpFY2!b*+1%@(kwewFB?#XSj#uVtkKVOOzEf9hG>Ml6u1~!XYqnV!6F$R}{CPI#B*en}|F+;QsTU`X%sMCgw){V=*7IT8
z_cz#nz+A~aWEuM+e$<{vSVxjHWeWG-L;l`B4|<)~;QxW1!=B7i#8E}ScMK2z&xZFi
k_+5fNR7jd&dhhGV6X@IHJRmSVPfQx!*8;w-fjBkrU%?5uXaE2J
literal 0
HcmV?d00001
diff --git a/blag/static/style.css b/blag/static/style.css
new file mode 100644
index 0000000..416284a
--- /dev/null
+++ b/blag/static/style.css
@@ -0,0 +1,166 @@
+@import "code-light.css" (prefers-color-scheme: light);
+@import "code-dark.css" (prefers-color-scheme: dark);
+
+@media (prefers-color-scheme: light) {
+ :root {
+ --background: #FFFFFF;
+ --background-dim: #f5f7f9;
+
+ --foreground: #2B303A;
+ --foreground-dim: #576379;
+ --foreground-heavy: #191C22;
+
+ --primary-color: #375287;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --background: #2B363B;
+ --background-dim: #2F3C42;
+
+ --foreground: #f0f2f3;
+ --foreground-dim: #d5d5d5;
+ --foreground-heavy: #f2f4f5;
+
+ --primary-color: #A1C5FF;
+ }
+}
+
+
+html {
+ font-size: 18px;
+ font-family: serif;
+}
+
+body {
+ margin: 0 auto;
+ max-width: 50rem;
+ background: var(--background);
+ color: var(--foreground);
+ line-height: 1.5;
+ padding: 0rem 0.5rem;
+}
+
+aside {
+ font-size: smaller;
+ font-style: italic;
+ color: var(--foreground-dim);
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+strong {
+ color: var(--foreground-heavy);
+}
+
+a {
+ color: var(--primary-color);
+}
+
+h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
+ text-decoration: none;
+}
+
+h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover {
+ text-decoration: underline;
+}
+
+nav ul {
+ list-style: none;
+}
+
+nav li {
+ display: inline;
+}
+
+nav li + li:before {
+ content: " · ";
+ margin: 0 0.5ex;
+}
+
+article header {
+ display: flex;
+ flex-direction: row;
+ margin: 1rem 0;
+}
+
+article header time {
+ white-space: nowrap;
+ color: var(--foreground-dim);
+ font-style: italic;
+ flex: 0 0 12ex;
+}
+
+article header h2,
+article header p {
+ font-size: 1rem;
+ display: inline;
+}
+
+code,
+pre {
+ background: var(--background-dim);
+ border-radius: 0.3rem;
+ font-family: monospace;
+}
+
+pre {
+ padding: 1rem;
+ border-left: 2px solid var(--primary-color);
+ overflow: auto;
+}
+
+code {
+ padding: 0.1rem 0.2rem;
+}
+
+/* reset the padding for code inside pre */
+pre code {
+ padding: 0;
+}
+
+blockquote {
+ background: var(--background-dim);
+ border-radius: 0 0.3rem 0.3rem 0;
+ font-style: italic;
+ border-left: 2px solid var(--primary-color);
+ margin: 0;
+ padding: 1rem;
+}
+
+/* reset the margin for p inside blockquotes */
+blockquote p {
+ margin: 0;
+}
+
+body > header {
+ padding: 2rem 0;
+}
+
+body footer {
+ margin: 3rem 0;
+ color: var(--foreground-dim);
+ font-size: smaller;
+ text-align: center;
+}
+
+header nav {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+header h1 {
+ margin: 0 auto;
+ color: var(--primary-color);
+}
+
+header h2 {
+ display: inline;
+ font-size: 1.2rem;
+}
diff --git a/blag/templates/archive.html b/blag/templates/archive.html
index e8f9cca..1c1e62c 100644
--- a/blag/templates/archive.html
+++ b/blag/templates/archive.html
@@ -3,18 +3,21 @@
{% block title %}{{ site.title }}{% endblock %}
{% block content %}
+
{% for entry in archive %}
- {% if entry.title %}
-
-
- {% if entry.description %}
- — {{ entry.description }}
- {% endif %}
-
- {% endif %}
-
- Written on {{ entry.date.date() }}.
+
+
+
{% endfor %}
+
{% endblock %}
diff --git a/blag/templates/article.html b/blag/templates/article.html
index 4080c36..889186d 100644
--- a/blag/templates/article.html
+++ b/blag/templates/article.html
@@ -22,7 +22,6 @@
-
{{ content }}
{% endblock %}
diff --git a/blag/templates/base.html b/blag/templates/base.html
index fc6f822..de1f6af 100644
--- a/blag/templates/base.html
+++ b/blag/templates/base.html
@@ -4,12 +4,15 @@
+
{%- if description %}
{%- else %}
{%- endif %}
+
+
{% block title %}{% endblock %} | {{ site.description }}
@@ -19,9 +22,10 @@
@@ -31,7 +35,15 @@
{% endblock %}
+